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 <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 
     28 typedef 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 
     38 static 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 
     51 static 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 
     74 static void usage(void)
     75 {
     76     fprintf(stderr, "Usage: wipe_blkdev [-s] <partition>\n");
     77     exit(1);
     78 }
     79 
     80 int 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