blob: af0bc946d2787ba9072fb4d045e9844a24c55167
1 | /* |
2 | * Mini blkdiscard implementation for busybox |
3 | * |
4 | * Copyright (C) 2015 by Ari Sundholm <ari@tuxera.com> and Tuxera Inc. |
5 | * |
6 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
7 | */ |
8 | //config:config BLKDISCARD |
9 | //config: bool "blkdiscard" |
10 | //config: default y |
11 | //config: help |
12 | //config: blkdiscard discards sectors on a given device. |
13 | |
14 | //kbuild:lib-$(CONFIG_BLKDISCARD) += blkdiscard.o |
15 | //applet:IF_BLKDISCARD(APPLET(blkdiscard, BB_DIR_USR_BIN, BB_SUID_DROP)) |
16 | |
17 | //usage:#define blkdiscard_trivial_usage |
18 | //usage: "[-o OFS] [-l LEN] [-s] DEVICE" |
19 | //usage:#define blkdiscard_full_usage "\n\n" |
20 | //usage: "Discard sectors on DEVICE\n" |
21 | //usage: "\n -o OFS Byte offset into device" |
22 | //usage: "\n -l LEN Number of bytes to discard" |
23 | //usage: "\n -s Perform a secure discard" |
24 | //usage: |
25 | //usage:#define blkdiscard_example_usage |
26 | //usage: "$ blkdiscard -o 0 -l 1G /dev/sdb" |
27 | |
28 | #include "libbb.h" |
29 | #include <linux/fs.h> |
30 | |
31 | int blkdiscard_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
32 | int blkdiscard_main(int argc UNUSED_PARAM, char **argv) |
33 | { |
34 | unsigned opts; |
35 | const char *offset_str = "0"; |
36 | const char *length_str; |
37 | uint64_t offset; /* Leaving these two variables out does not */ |
38 | uint64_t length; /* shrink code size and hampers readability. */ |
39 | uint64_t range[2]; |
40 | // struct stat st; |
41 | int fd; |
42 | |
43 | enum { |
44 | OPT_OFFSET = (1 << 0), |
45 | OPT_LENGTH = (1 << 1), |
46 | OPT_SECURE = (1 << 2), |
47 | }; |
48 | |
49 | opt_complementary = "=1"; |
50 | opts = getopt32(argv, "o:l:s", &offset_str, &length_str); |
51 | argv += optind; |
52 | |
53 | fd = xopen(argv[0], O_RDWR|O_EXCL); |
54 | //Why bother, BLK[SEC]DISCARD will fail on non-blockdevs anyway? |
55 | // xfstat(fd, &st); |
56 | // if (!S_ISBLK(st.st_mode)) |
57 | // bb_error_msg_and_die("%s: not a block device", argv[0]); |
58 | |
59 | offset = xatoull_sfx(offset_str, kMG_suffixes); |
60 | |
61 | if (opts & OPT_LENGTH) |
62 | length = xatoull_sfx(length_str, kMG_suffixes); |
63 | else { |
64 | xioctl(fd, BLKGETSIZE64, &length); |
65 | length -= offset; |
66 | } |
67 | |
68 | range[0] = offset; |
69 | range[1] = length; |
70 | ioctl_or_perror_and_die(fd, |
71 | (opts & OPT_SECURE) ? BLKSECDISCARD : BLKDISCARD, |
72 | &range, |
73 | "%s: %s failed", |
74 | argv[0], |
75 | (opts & OPT_SECURE) ? "BLKSECDISCARD" : "BLKDISCARD" |
76 | ); |
77 | |
78 | if (ENABLE_FEATURE_CLEAN_UP) |
79 | close(fd); |
80 | |
81 | return EXIT_SUCCESS; |
82 | } |
83 |