blob: 0e8319fea7a08e90b79d0bc740da5a61d341c385 [file] [log] [blame]
Theodore Ts'o3c67a9f2010-03-22 21:53:41 -04001/*
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
Theodore Ts'o3c67a9f2010-03-22 21:53:41 -040024#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
38
39void usage(void)
40{
Theodore Ts'oc561e752010-03-22 22:03:53 -040041 printf("Usage: fallocate [-nt] [-o offset] -l length filename\n");
Theodore Ts'o3c67a9f2010-03-22 21:53:41 -040042 exit(EXIT_FAILURE);
43}
44
45#define EXABYTES(x) ((long long)(x) << 60)
46#define PETABYTES(x) ((long long)(x) << 50)
47#define TERABYTES(x) ((long long)(x) << 40)
48#define GIGABYTES(x) ((long long)(x) << 30)
49#define MEGABYTES(x) ((long long)(x) << 20)
50#define KILOBYTES(x) ((long long)(x) << 10)
51
52long long
53cvtnum(char *s)
54{
55 long long i;
56 char *sp;
57 int c;
58
59 i = strtoll(s, &sp, 0);
60 if (i == 0 && sp == s)
61 return -1LL;
62 if (*sp == '\0')
63 return i;
64 if (sp[1] != '\0')
65 return -1LL;
66
67 c = tolower(*sp);
68 switch (c) {
69 case 'k':
70 return KILOBYTES(i);
71 case 'm':
72 return MEGABYTES(i);
73 case 'g':
74 return GIGABYTES(i);
75 case 't':
76 return TERABYTES(i);
77 case 'p':
78 return PETABYTES(i);
79 case 'e':
80 return EXABYTES(i);
81 }
82
83 return -1LL;
84}
85
86int main(int argc, char **argv)
87{
88 int fd;
89 char *fname;
90 int opt;
91 loff_t length = -2LL;
92 loff_t offset = 0;
93 int falloc_mode = 0;
94 int error;
Theodore Ts'oc561e752010-03-22 22:03:53 -040095 int tflag = 0;
Theodore Ts'o3c67a9f2010-03-22 21:53:41 -040096
Theodore Ts'oc561e752010-03-22 22:03:53 -040097 while ((opt = getopt(argc, argv, "nl:ot")) != -1) {
Theodore Ts'o3c67a9f2010-03-22 21:53:41 -040098 switch(opt) {
99 case 'n':
100 /* do not change filesize */
101 falloc_mode = FALLOC_FL_KEEP_SIZE;
102 break;
103 case 'l':
104 length = cvtnum(optarg);
105 break;
106 case 'o':
107 offset = cvtnum(optarg);
108 break;
Theodore Ts'oc561e752010-03-22 22:03:53 -0400109 case 't':
110 tflag++;
111 break;
Theodore Ts'o3c67a9f2010-03-22 21:53:41 -0400112 default:
113 usage();
114 }
115 }
116
117 if (length == -2LL) {
118 printf("Error: no length argument specified\n");
119 usage();
120 }
121
122 if (length <= 0) {
123 printf("Error: invalid length value specified\n");
124 usage();
125 }
126
127 if (offset < 0) {
128 printf("Error: invalid offset value specified\n");
129 usage();
130 }
131
Theodore Ts'oc561e752010-03-22 22:03:53 -0400132 if (tflag && (falloc_mode & FALLOC_FL_KEEP_SIZE)) {
133 printf("-n and -t options incompatible\n");
134 usage();
135 }
136
137 if (tflag && offset) {
138 printf("-n and -o options incompatible\n");
139 usage();
140 }
141
Theodore Ts'o3c67a9f2010-03-22 21:53:41 -0400142 if (optind == argc) {
143 printf("Error: no filename specified\n");
144 usage();
145 }
146
147 fname = argv[optind++];
148
149 /* Should we create the file if it doesn't already exist? */
Theodore Ts'oc561e752010-03-22 22:03:53 -0400150 fd = open(fname, O_WRONLY|O_LARGEFILE);
Theodore Ts'o3c67a9f2010-03-22 21:53:41 -0400151 if (fd < 0) {
152 perror("Error opening file");
153 exit(EXIT_FAILURE);
154 }
155
Theodore Ts'oc561e752010-03-22 22:03:53 -0400156 if (tflag)
157 error = ftruncate(fd, length);
158 else
159 error = syscall(SYS_fallocate, fd, falloc_mode, offset, length);
Theodore Ts'o3c67a9f2010-03-22 21:53:41 -0400160
161 if (error < 0) {
162 perror("fallocate failed");
163 exit(EXIT_FAILURE);
164 }
165
166 close(fd);
167 return 0;
168}