You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
191 lines
4.0 KiB
191 lines
4.0 KiB
4 months ago
|
/*
|
||
|
* 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;
|
||
|
}
|