]>
Commit | Line | Data |
---|---|---|
3c67a9f7 TT |
1 | /* |
2 | * fallocate - utility to use the fallocate system call | |
3 | * | |
4 | * Copyright (C) 2008 Red Hat, Inc. All rights reserved. | |
5 | * Written by Eric Sandeen <sandeen@redhat.com> | |
6 | * | |
7 | * cvtnum routine taken from xfsprogs, | |
8 | * Copyright (c) 2003-2005 Silicon Graphics, Inc. | |
9 | * | |
10 | * This program is free software; you can redistribute it and/or | |
11 | * modify it under the terms of the GNU General Public License as | |
12 | * published by the Free Software Foundation. | |
13 | * | |
14 | * This program is distributed in the hope that it would be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | * GNU General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU General Public License | |
20 | * along with this program; if not, write to the Free Software Foundation, | |
21 | * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
22 | */ | |
23 | ||
3c67a9f7 TT |
24 | #define _LARGEFILE_SOURCE |
25 | #define _LARGEFILE64_SOURCE | |
26 | ||
27 | #include <sys/stat.h> | |
28 | #include <sys/syscall.h> | |
29 | #include <sys/types.h> | |
30 | #include <fcntl.h> | |
31 | #include <stdio.h> | |
32 | #include <stdlib.h> | |
33 | #include <unistd.h> | |
34 | #include <ctype.h> | |
35 | ||
36 | // #include <linux/falloc.h> | |
37 | #define FALLOC_FL_KEEP_SIZE 0x01 | |
2658b961 | 38 | #define FALLOC_FL_PUNCH_HOLE 0x02 /* de-allocates range */ |
8467b3be DW |
39 | #define FALLOC_FL_COLLAPSE_RANGE 0x08 |
40 | #define FALLOC_FL_ZERO_RANGE 0x10 | |
3c67a9f7 TT |
41 | |
42 | void usage(void) | |
43 | { | |
dc18a3b3 | 44 | printf("Usage: fallocate [-npt] [-o offset] -l length filename\n"); |
3c67a9f7 TT |
45 | exit(EXIT_FAILURE); |
46 | } | |
47 | ||
48 | #define EXABYTES(x) ((long long)(x) << 60) | |
49 | #define PETABYTES(x) ((long long)(x) << 50) | |
50 | #define TERABYTES(x) ((long long)(x) << 40) | |
51 | #define GIGABYTES(x) ((long long)(x) << 30) | |
52 | #define MEGABYTES(x) ((long long)(x) << 20) | |
53 | #define KILOBYTES(x) ((long long)(x) << 10) | |
54 | ||
55 | long long | |
56 | cvtnum(char *s) | |
57 | { | |
58 | long long i; | |
59 | char *sp; | |
60 | int c; | |
61 | ||
62 | i = strtoll(s, &sp, 0); | |
63 | if (i == 0 && sp == s) | |
64 | return -1LL; | |
65 | if (*sp == '\0') | |
66 | return i; | |
67 | if (sp[1] != '\0') | |
68 | return -1LL; | |
69 | ||
70 | c = tolower(*sp); | |
71 | switch (c) { | |
72 | case 'k': | |
73 | return KILOBYTES(i); | |
74 | case 'm': | |
75 | return MEGABYTES(i); | |
76 | case 'g': | |
77 | return GIGABYTES(i); | |
78 | case 't': | |
79 | return TERABYTES(i); | |
80 | case 'p': | |
81 | return PETABYTES(i); | |
82 | case 'e': | |
83 | return EXABYTES(i); | |
84 | } | |
85 | ||
86 | return -1LL; | |
87 | } | |
88 | ||
89 | int main(int argc, char **argv) | |
90 | { | |
91 | int fd; | |
92 | char *fname; | |
93 | int opt; | |
94 | loff_t length = -2LL; | |
95 | loff_t offset = 0; | |
96 | int falloc_mode = 0; | |
97 | int error; | |
c561e751 | 98 | int tflag = 0; |
3c67a9f7 | 99 | |
8467b3be | 100 | while ((opt = getopt(argc, argv, "npl:o:tzc")) != -1) { |
3c67a9f7 TT |
101 | switch(opt) { |
102 | case 'n': | |
103 | /* do not change filesize */ | |
104 | falloc_mode = FALLOC_FL_KEEP_SIZE; | |
105 | break; | |
2658b961 TT |
106 | case 'p': |
107 | /* punch mode */ | |
108 | falloc_mode = (FALLOC_FL_PUNCH_HOLE | | |
109 | FALLOC_FL_KEEP_SIZE); | |
110 | break; | |
8467b3be DW |
111 | case 'c': |
112 | /* collapse range mode */ | |
113 | falloc_mode = (FALLOC_FL_COLLAPSE_RANGE | | |
114 | FALLOC_FL_KEEP_SIZE); | |
115 | break; | |
116 | case 'z': | |
117 | /* zero range mode */ | |
118 | falloc_mode = (FALLOC_FL_ZERO_RANGE | | |
119 | FALLOC_FL_KEEP_SIZE); | |
120 | break; | |
3c67a9f7 TT |
121 | case 'l': |
122 | length = cvtnum(optarg); | |
123 | break; | |
124 | case 'o': | |
125 | offset = cvtnum(optarg); | |
126 | break; | |
c561e751 TT |
127 | case 't': |
128 | tflag++; | |
129 | break; | |
3c67a9f7 TT |
130 | default: |
131 | usage(); | |
132 | } | |
133 | } | |
134 | ||
135 | if (length == -2LL) { | |
136 | printf("Error: no length argument specified\n"); | |
137 | usage(); | |
138 | } | |
139 | ||
140 | if (length <= 0) { | |
141 | printf("Error: invalid length value specified\n"); | |
142 | usage(); | |
143 | } | |
144 | ||
145 | if (offset < 0) { | |
146 | printf("Error: invalid offset value specified\n"); | |
147 | usage(); | |
148 | } | |
149 | ||
c561e751 TT |
150 | if (tflag && (falloc_mode & FALLOC_FL_KEEP_SIZE)) { |
151 | printf("-n and -t options incompatible\n"); | |
152 | usage(); | |
153 | } | |
154 | ||
155 | if (tflag && offset) { | |
156 | printf("-n and -o options incompatible\n"); | |
157 | usage(); | |
158 | } | |
159 | ||
3c67a9f7 TT |
160 | if (optind == argc) { |
161 | printf("Error: no filename specified\n"); | |
162 | usage(); | |
163 | } | |
164 | ||
165 | fname = argv[optind++]; | |
166 | ||
167 | /* Should we create the file if it doesn't already exist? */ | |
c561e751 | 168 | fd = open(fname, O_WRONLY|O_LARGEFILE); |
3c67a9f7 TT |
169 | if (fd < 0) { |
170 | perror("Error opening file"); | |
171 | exit(EXIT_FAILURE); | |
172 | } | |
173 | ||
c561e751 TT |
174 | if (tflag) |
175 | error = ftruncate(fd, length); | |
176 | else | |
177 | error = syscall(SYS_fallocate, fd, falloc_mode, offset, length); | |
3c67a9f7 TT |
178 | |
179 | if (error < 0) { | |
180 | perror("fallocate failed"); | |
181 | exit(EXIT_FAILURE); | |
182 | } | |
183 | ||
184 | close(fd); | |
185 | return 0; | |
186 | } |