1/*
2 * Copyright (C) 2011, 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdlib.h>
18#include <stdio.h>
19#include <string.h>
20#include <sys/types.h>
21#include <sys/stat.h>
22#include <fcntl.h>
23#include <unistd.h>
24#include <sys/ioctl.h>
25#include <linux/fs.h>
26#include <errno.h>
27
28typedef unsigned long long u64;
29
30#ifndef BLKDISCARD
31#define BLKDISCARD _IO(0x12,119)
32#endif
33
34#ifndef BLKSECDISCARD
35#define BLKSECDISCARD _IO(0x12,125)
36#endif
37
38static u64 get_block_device_size(int fd)
39{
40        u64 size = 0;
41        int ret;
42
43        ret = ioctl(fd, BLKGETSIZE64, &size);
44
45        if (ret)
46                return 0;
47
48        return size;
49}
50
51static int wipe_block_device(int fd, u64 len, int secure)
52{
53    u64 range[2];
54    int ret;
55    int req;
56
57    range[0] = 0;
58    range[1] = len;
59    if (secure) {
60       req = BLKSECDISCARD;
61    } else {
62       req = BLKDISCARD;
63    }
64
65    ret = ioctl(fd, req, &range);
66    if (ret < 0) {
67        fprintf(stderr, "%s discard failed, errno = %d\n",
68                secure ? "Secure" : "Nonsecure", errno);
69    }
70
71    return ret;
72}
73
74static void usage(void)
75{
76    fprintf(stderr, "Usage: wipe_blkdev [-s] <partition>\n");
77    exit(1);
78}
79
80int main(int argc, char *argv[])
81{
82    int secure = 0;
83    char *devname;
84    int fd;
85    u64 len;
86    struct stat statbuf;
87    int ret;
88
89    if ((argc != 2) && (argc != 3)) {
90        usage();
91    }
92
93    if (argc == 3) {
94        if (!strcmp(argv[1], "-s")) {
95            secure = 1;
96            devname = argv[2];
97        } else {
98            usage();
99        }
100    } else {
101        devname = argv[1];
102    }
103
104    fd = open(devname, O_RDWR);
105    if (fd < 0) {
106        fprintf(stderr, "Cannot open device %s\n", devname);
107        exit(1);
108    }
109
110    if (fstat(fd, &statbuf) < 0) {
111        fprintf(stderr, "Cannot stat %s\n", devname);
112        exit(1);
113    }
114
115    if (!S_ISBLK(statbuf.st_mode)) {
116        fprintf(stderr, "%s is not a block device\n", devname);
117        exit(1);
118    }
119
120    len = get_block_device_size(fd);
121
122    if (! len) {
123        fprintf(stderr, "Cannot get size of block device %s\n", devname);
124        exit(1);
125    }
126
127    ret = wipe_block_device(fd, len, secure);
128
129    close(fd);
130
131    return ret;
132}
133