fstrim: Indicate failure on error
[oweals/busybox.git] / util-linux / fstrim.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * fstrim.c - discard the part (or whole) of mounted filesystem.
4  *
5  * 03 March 2012 - Malek Degachi <malek-degachi@laposte.net>
6  * Adapted for busybox from util-linux-2.12a.
7  *
8  * Licensed under GPLv2 or later, see file LICENSE in this source tree.
9  */
10
11 //usage:#define fstrim_trivial_usage
12 //usage:       "[Options] <mountpoint>"
13 //usage:#define fstrim_full_usage "\n\n"
14 //usage:       "Options:"
15 //usage:        IF_LONG_OPTS(
16 //usage:     "\n        -o,--offset=offset      offset in bytes to discard from"
17 //usage:     "\n        -l,--length=length      length of bytes to discard from the offset"
18 //usage:     "\n        -m,--minimum=minimum    minimum extent length to discard"
19 //usage:     "\n        -v,--verbose            print number of discarded bytes"
20 //usage:        )
21 //usage:        IF_NOT_LONG_OPTS(
22 //usage:     "\n        -o offset       offset in bytes to discard from"
23 //usage:     "\n        -l length       length of bytes to discard from the offset"
24 //usage:     "\n        -m minimum      minimum extent length to discard"
25 //usage:     "\n        -v,             print number of discarded bytes"
26 //usage:        )
27
28 #include "libbb.h"
29 #include <linux/fs.h>
30
31 #ifndef FITRIM
32 struct fstrim_range {
33         uint64_t start;
34         uint64_t len;
35         uint64_t minlen;
36 };
37 #define FITRIM          _IOWR('X', 121, struct fstrim_range)
38 #endif
39
40 static const struct suffix_mult fstrim_sfx[] = {
41         { "KiB", 1024 },
42         { "kiB", 1024 },
43         { "K", 1024 },
44         { "k", 1024 },
45         { "MiB", 1048576 },
46         { "miB", 1048576 },
47         { "M", 1048576 },
48         { "m", 1048576 },
49         { "GiB", 1073741824 },
50         { "giB", 1073741824 },
51         { "G", 1073741824 },
52         { "g", 1073741824 },
53         { "KB", 1000 },
54         { "MB", 1000000 },
55         { "GB", 1000000000 },
56         { "", 0 }
57 };
58
59 int fstrim_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
60 int fstrim_main(int argc UNUSED_PARAM, char **argv)
61 {
62         struct fstrim_range range;
63         char *arg_o, *arg_l, *arg_m, *bd;
64         unsigned opts;
65         int fd;
66
67         enum {
68                 OPT_o = (1 << 0),
69                 OPT_l = (1 << 1),
70                 OPT_m = (1 << 2),
71                 OPT_v = (1 << 3),
72         };
73
74 #if ENABLE_LONG_OPTS
75         static const char getopt_longopts[] ALIGN1 =
76                 "offset\0"    Required_argument    "o"
77                 "length\0"    Required_argument    "l"
78                 "minimum\0"   Required_argument    "m"
79                 "verbose\0"   No_argument          "v"
80                 ;
81         applet_long_options = getopt_longopts;
82 #endif
83
84         opt_complementary = "=1"; /* exactly one non-option arg: the mountpoint */
85         opts = getopt32(argv, "o:l:m:v", &arg_o, &arg_l, &arg_m);
86
87         memset(&range, 0, sizeof(range));
88         range.len = ULLONG_MAX;
89
90         if (opts & OPT_o)
91                 range.start = xatoull_sfx(arg_o, fstrim_sfx);
92         if (opts & OPT_l)
93                 range.len = xatoull_sfx(arg_l, fstrim_sfx);
94         if (opts & OPT_m)
95                 range.minlen = xatoull_sfx(arg_m, fstrim_sfx);
96
97         bd = find_block_device(*(argv += optind));
98         if (bd) {
99                 fd = xopen_nonblocking(bd);
100                 xioctl(fd, FITRIM, &range);
101                 if (ENABLE_FEATURE_CLEAN_UP)
102                         close(fd);
103
104                 if (opts & OPT_v)
105                         printf("%s: %llu bytes were trimmed\n", bd, range.len);
106                 return EXIT_SUCCESS;
107         }
108         return EXIT_FAILURE;
109 }