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