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 (at) 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 24 #ifndef _LARGEFILE_SOURCE 25 #define _LARGEFILE_SOURCE 26 #endif 27 #ifndef _LARGEFILE64_SOURCE 28 #define _LARGEFILE64_SOURCE 29 #endif 30 31 #include <sys/stat.h> 32 #include <sys/syscall.h> 33 #include <sys/types.h> 34 #include <fcntl.h> 35 #include <stdio.h> 36 #include <stdlib.h> 37 #include <unistd.h> 38 #include <ctype.h> 39 40 // #include <linux/falloc.h> 41 #define FALLOC_FL_KEEP_SIZE 0x01 42 #define FALLOC_FL_PUNCH_HOLE 0x02 /* de-allocates range */ 43 #define FALLOC_FL_COLLAPSE_RANGE 0x08 44 #define FALLOC_FL_ZERO_RANGE 0x10 45 46 void usage(void) 47 { 48 printf("Usage: fallocate [-npt] [-o offset] -l length filename\n"); 49 exit(EXIT_FAILURE); 50 } 51 52 #define EXABYTES(x) ((long long)(x) << 60) 53 #define PETABYTES(x) ((long long)(x) << 50) 54 #define TERABYTES(x) ((long long)(x) << 40) 55 #define GIGABYTES(x) ((long long)(x) << 30) 56 #define MEGABYTES(x) ((long long)(x) << 20) 57 #define KILOBYTES(x) ((long long)(x) << 10) 58 59 long long 60 cvtnum(char *s) 61 { 62 long long i; 63 char *sp; 64 int c; 65 66 i = strtoll(s, &sp, 0); 67 if (i == 0 && sp == s) 68 return -1LL; 69 if (*sp == '\0') 70 return i; 71 if (sp[1] != '\0') 72 return -1LL; 73 74 c = tolower(*sp); 75 switch (c) { 76 case 'k': 77 return KILOBYTES(i); 78 case 'm': 79 return MEGABYTES(i); 80 case 'g': 81 return GIGABYTES(i); 82 case 't': 83 return TERABYTES(i); 84 case 'p': 85 return PETABYTES(i); 86 case 'e': 87 return EXABYTES(i); 88 } 89 90 return -1LL; 91 } 92 93 int main(int argc, char **argv) 94 { 95 int fd; 96 char *fname; 97 int opt; 98 loff_t length = -2LL; 99 loff_t offset = 0; 100 int falloc_mode = 0; 101 int error; 102 int tflag = 0; 103 104 while ((opt = getopt(argc, argv, "npl:o:tzc")) != -1) { 105 switch(opt) { 106 case 'n': 107 /* do not change filesize */ 108 falloc_mode = FALLOC_FL_KEEP_SIZE; 109 break; 110 case 'p': 111 /* punch mode */ 112 falloc_mode = (FALLOC_FL_PUNCH_HOLE | 113 FALLOC_FL_KEEP_SIZE); 114 break; 115 case 'c': 116 /* collapse range mode */ 117 falloc_mode = (FALLOC_FL_COLLAPSE_RANGE | 118 FALLOC_FL_KEEP_SIZE); 119 break; 120 case 'z': 121 /* zero range mode */ 122 falloc_mode = (FALLOC_FL_ZERO_RANGE | 123 FALLOC_FL_KEEP_SIZE); 124 break; 125 case 'l': 126 length = cvtnum(optarg); 127 break; 128 case 'o': 129 offset = cvtnum(optarg); 130 break; 131 case 't': 132 tflag++; 133 break; 134 default: 135 usage(); 136 } 137 } 138 139 if (length == -2LL) { 140 printf("Error: no length argument specified\n"); 141 usage(); 142 } 143 144 if (length <= 0) { 145 printf("Error: invalid length value specified\n"); 146 usage(); 147 } 148 149 if (offset < 0) { 150 printf("Error: invalid offset value specified\n"); 151 usage(); 152 } 153 154 if (tflag && (falloc_mode & FALLOC_FL_KEEP_SIZE)) { 155 printf("-n and -t options incompatible\n"); 156 usage(); 157 } 158 159 if (tflag && offset) { 160 printf("-n and -o options incompatible\n"); 161 usage(); 162 } 163 164 if (optind == argc) { 165 printf("Error: no filename specified\n"); 166 usage(); 167 } 168 169 fname = argv[optind++]; 170 171 /* Should we create the file if it doesn't already exist? */ 172 fd = open(fname, O_WRONLY|O_LARGEFILE); 173 if (fd < 0) { 174 perror("Error opening file"); 175 exit(EXIT_FAILURE); 176 } 177 178 if (tflag) 179 error = ftruncate(fd, length); 180 else 181 error = syscall(SYS_fallocate, fd, falloc_mode, offset, length); 182 183 if (error < 0) { 184 perror("fallocate failed"); 185 exit(EXIT_FAILURE); 186 } 187 188 close(fd); 189 return 0; 190 } 191