/* * fallocate - utility to use the fallocate system call * * Copyright (C) 2008 Red Hat, Inc. All rights reserved. * Written by Eric Sandeen <sandeen@redhat.com> * * cvtnum routine taken from xfsprogs, * Copyright (c) 2003-2005 Silicon Graphics, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it would be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _LARGEFILE_SOURCE #define _LARGEFILE_SOURCE #endif #ifndef _LARGEFILE64_SOURCE #define _LARGEFILE64_SOURCE #endif #include <sys/stat.h> #include <sys/syscall.h> #include <sys/types.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <ctype.h> // #include <linux/falloc.h> #define FALLOC_FL_KEEP_SIZE 0x01 #define FALLOC_FL_PUNCH_HOLE 0x02 /* de-allocates range */ #define FALLOC_FL_COLLAPSE_RANGE 0x08 #define FALLOC_FL_ZERO_RANGE 0x10 void usage(void) { printf("Usage: fallocate [-npt] [-o offset] -l length filename\n"); exit(EXIT_FAILURE); } #define EXABYTES(x) ((long long)(x) << 60) #define PETABYTES(x) ((long long)(x) << 50) #define TERABYTES(x) ((long long)(x) << 40) #define GIGABYTES(x) ((long long)(x) << 30) #define MEGABYTES(x) ((long long)(x) << 20) #define KILOBYTES(x) ((long long)(x) << 10) long long cvtnum(char *s) { long long i; char *sp; int c; i = strtoll(s, &sp, 0); if (i == 0 && sp == s) return -1LL; if (*sp == '\0') return i; if (sp[1] != '\0') return -1LL; c = tolower(*sp); switch (c) { case 'k': return KILOBYTES(i); case 'm': return MEGABYTES(i); case 'g': return GIGABYTES(i); case 't': return TERABYTES(i); case 'p': return PETABYTES(i); case 'e': return EXABYTES(i); } return -1LL; } int main(int argc, char **argv) { int fd; char *fname; int opt; loff_t length = -2LL; loff_t offset = 0; int falloc_mode = 0; int error; int tflag = 0; while ((opt = getopt(argc, argv, "npl:o:tzc")) != -1) { switch(opt) { case 'n': /* do not change filesize */ falloc_mode = FALLOC_FL_KEEP_SIZE; break; case 'p': /* punch mode */ falloc_mode = (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE); break; case 'c': /* collapse range mode */ falloc_mode = (FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_KEEP_SIZE); break; case 'z': /* zero range mode */ falloc_mode = (FALLOC_FL_ZERO_RANGE | FALLOC_FL_KEEP_SIZE); break; case 'l': length = cvtnum(optarg); break; case 'o': offset = cvtnum(optarg); break; case 't': tflag++; break; default: usage(); } } if (length == -2LL) { printf("Error: no length argument specified\n"); usage(); } if (length <= 0) { printf("Error: invalid length value specified\n"); usage(); } if (offset < 0) { printf("Error: invalid offset value specified\n"); usage(); } if (tflag && (falloc_mode & FALLOC_FL_KEEP_SIZE)) { printf("-n and -t options incompatible\n"); usage(); } if (tflag && offset) { printf("-n and -o options incompatible\n"); usage(); } if (optind == argc) { printf("Error: no filename specified\n"); usage(); } fname = argv[optind++]; /* Should we create the file if it doesn't already exist? */ fd = open(fname, O_WRONLY|O_LARGEFILE); if (fd < 0) { perror("Error opening file"); exit(EXIT_FAILURE); } if (tflag) error = ftruncate(fd, length); else error = syscall(SYS_fallocate, fd, falloc_mode, offset, length); if (error < 0) { perror("fallocate failed"); exit(EXIT_FAILURE); } close(fd); return 0; }