Home | History | Annotate | Download | only in storage
      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 <sys/types.h>
     20 #include <sys/stat.h>
     21 #include <fcntl.h>
     22 #include <unistd.h>
     23 #include <sys/ioctl.h>
     24 #include <linux/fs.h>
     25 #include <errno.h>
     26 
     27 typedef unsigned long long u64;
     28 
     29 #ifndef BLKDISCARD
     30 #define BLKDISCARD _IO(0x12,119)
     31 #endif
     32 
     33 #ifndef BLKSECDISCARD
     34 #define BLKSECDISCARD _IO(0x12,125)
     35 #endif
     36 
     37 static u64 get_block_device_size(int fd)
     38 {
     39         u64 size = 0;
     40         int ret;
     41 
     42         ret = ioctl(fd, BLKGETSIZE64, &size);
     43 
     44         if (ret)
     45                 return 0;
     46 
     47         return size;
     48 }
     49 
     50 static int wipe_block_device(int fd, u64 len, int secure)
     51 {
     52     u64 range[2];
     53     int ret;
     54     int req;
     55 
     56     range[0] = 0;
     57     range[1] = len;
     58     if (secure) {
     59        req = BLKSECDISCARD;
     60     } else {
     61        req = BLKDISCARD;
     62     }
     63 
     64     ret = ioctl(fd, req, &range);
     65     if (ret < 0) {
     66         fprintf(stderr, "%s discard failed, errno = %d\n",
     67                 secure ? "Secure" : "Nonsecure", errno);
     68     }
     69 
     70     return ret;
     71 }
     72 
     73 static void usage(void)
     74 {
     75     fprintf(stderr, "Usage: wipe_blkdev [-s] <partition>\n");
     76     exit(1);
     77 }
     78 
     79 int main(int argc, char *argv[])
     80 {
     81     int secure = 0;
     82     char *devname;
     83     int fd;
     84     u64 len;
     85     struct stat statbuf;
     86     int ret;
     87 
     88     if ((argc != 2) && (argc != 3)) {
     89         usage();
     90     }
     91 
     92     if (argc == 3) {
     93         if (!strcmp(argv[1], "-s")) {
     94             secure = 1;
     95             devname = argv[2];
     96         } else {
     97             usage();
     98         }
     99     } else {
    100         devname = argv[1];
    101     }
    102 
    103     fd = open(devname, O_RDWR);
    104     if (fd < 0) {
    105         fprintf(stderr, "Cannot open device %s\n", devname);
    106         exit(1);
    107     }
    108 
    109     if (fstat(fd, &statbuf) < 0) {
    110         fprintf(stderr, "Cannot stat %s\n", devname);
    111         exit(1);
    112     }
    113 
    114     if (!S_ISBLK(statbuf.st_mode)) {
    115         fprintf(stderr, "%s is not a block device\n", devname);
    116         exit(1);
    117     }
    118 
    119     len = get_block_device_size(fd);
    120 
    121     if (! len) {
    122         fprintf(stderr, "Cannot get size of block device %s\n", devname);
    123         exit(1);
    124     }
    125 
    126     ret = wipe_block_device(fd, len, secure);
    127 
    128     close(fd);
    129 
    130     return ret;
    131 }
    132