mirror of
https://github.com/opnsense/src.git
synced 2026-06-11 09:41:03 -04:00
truncate(1): Add hole-punching support
This commit adds hole-punching support to the truncate(1) utility. If the option -d is specified, truncate(1) performs zeroing, and if possible hole-punching in case the operation is supported by the underlying file system of the specified files. Sponsored by: The FreeBSD Foundation Reviewed by: kib Differential Revision: https://reviews.freebsd.org/D31556
This commit is contained in:
parent
78267c2e70
commit
5ee2c35751
2 changed files with 115 additions and 27 deletions
|
|
@ -1,6 +1,10 @@
|
||||||
.\"
|
.\"
|
||||||
.\" Copyright (c) 2000 Sheldon Hearn <sheldonh@FreeBSD.org>.
|
.\" Copyright (c) 2000 Sheldon Hearn <sheldonh@FreeBSD.org>.
|
||||||
.\" All rights reserved.
|
.\" All rights reserved.
|
||||||
|
.\" Copyright (c) 2021 The FreeBSD Foundation
|
||||||
|
.\"
|
||||||
|
.\" Portions of this manual page were written by Ka Ho Ng <khng@FreeBSD.org>
|
||||||
|
.\" under sponsorship from the FreeBSD Foundation.
|
||||||
.\"
|
.\"
|
||||||
.\" Redistribution and use in source and binary forms, with or without
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
.\" modification, are permitted provided that the following conditions
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
|
@ -25,12 +29,12 @@
|
||||||
.\"
|
.\"
|
||||||
.\" $FreeBSD$
|
.\" $FreeBSD$
|
||||||
.\"
|
.\"
|
||||||
.Dd July 27, 2020
|
.Dd August 18, 2021
|
||||||
.Dt TRUNCATE 1
|
.Dt TRUNCATE 1
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
.Nm truncate
|
.Nm truncate
|
||||||
.Nd truncate or extend the length of files
|
.Nd truncate, extend the length of files, or perform space management in files
|
||||||
.Sh SYNOPSIS
|
.Sh SYNOPSIS
|
||||||
.Nm
|
.Nm
|
||||||
.Op Fl c
|
.Op Fl c
|
||||||
|
|
@ -39,7 +43,7 @@
|
||||||
.Sm off
|
.Sm off
|
||||||
.Op Cm + | - | % | /
|
.Op Cm + | - | % | /
|
||||||
.Ar size
|
.Ar size
|
||||||
.Op Cm K | k | M | m | G | g | T | t
|
.Op Cm SUFFIX
|
||||||
.Sm on
|
.Sm on
|
||||||
.Xc
|
.Xc
|
||||||
.Ek
|
.Ek
|
||||||
|
|
@ -50,10 +54,32 @@
|
||||||
.Fl r Ar rfile
|
.Fl r Ar rfile
|
||||||
.Ek
|
.Ek
|
||||||
.Ar
|
.Ar
|
||||||
|
.Nm
|
||||||
|
.Op Fl c
|
||||||
|
.Bk -words
|
||||||
|
.Fl d
|
||||||
|
.Oo
|
||||||
|
.Fl o Xo
|
||||||
|
.Sm off
|
||||||
|
.Ar offset
|
||||||
|
.Op Cm SUFFIX
|
||||||
|
.Sm on
|
||||||
|
.Xc
|
||||||
|
.Oc
|
||||||
|
.Fl l Xo
|
||||||
|
.Sm off
|
||||||
|
.Ar length
|
||||||
|
.Op Cm SUFFIX
|
||||||
|
.Sm on
|
||||||
|
.Xc
|
||||||
|
.Ek
|
||||||
|
.Ar
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
The
|
The
|
||||||
.Nm
|
.Nm
|
||||||
utility adjusts the length of each regular file given on the command-line.
|
utility adjusts the length of each regular file given on the command-line, or
|
||||||
|
performs space management with the given offset and the length over a regular
|
||||||
|
file given on the command-line.
|
||||||
.Pp
|
.Pp
|
||||||
The following options are available:
|
The following options are available:
|
||||||
.Bl -tag -width indent
|
.Bl -tag -width indent
|
||||||
|
|
@ -71,7 +97,7 @@ Truncate or extend files to the length of the file
|
||||||
.Sm off
|
.Sm off
|
||||||
.Op Cm + | - | % | /
|
.Op Cm + | - | % | /
|
||||||
.Ar size
|
.Ar size
|
||||||
.Op Cm K | k | M | m | G | g | T | t
|
.Op Cm SUFFIX
|
||||||
.Sm on
|
.Sm on
|
||||||
.Xc
|
.Xc
|
||||||
If the
|
If the
|
||||||
|
|
@ -100,10 +126,28 @@ Otherwise, the
|
||||||
.Ar size
|
.Ar size
|
||||||
argument specifies an absolute length to which all files
|
argument specifies an absolute length to which all files
|
||||||
should be extended or reduced as appropriate.
|
should be extended or reduced as appropriate.
|
||||||
|
.It Fl d
|
||||||
|
Zero a region in the specified file.
|
||||||
|
If the underlying file system of the given file supports hole-punching,
|
||||||
|
file system space deallocation may be performed in the operation region.
|
||||||
|
.It Fl o Ar offset
|
||||||
|
The space management operation is performed at the given
|
||||||
|
.Ar offset
|
||||||
|
bytes in the file.
|
||||||
|
If this option is not specified, the operation is performed at the beginning of the file.
|
||||||
|
.It Fl l Ar length
|
||||||
|
The length of the operation range in bytes.
|
||||||
|
This option must always be specified if option
|
||||||
|
.Fl d
|
||||||
|
is specified, and must be greater than 0.
|
||||||
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
The
|
The
|
||||||
.Ar size
|
.Ar size ,
|
||||||
argument may be suffixed with one of
|
.Ar offset
|
||||||
|
and
|
||||||
|
.Ar length
|
||||||
|
arguments may be suffixed with one of
|
||||||
.Cm K ,
|
.Cm K ,
|
||||||
.Cm M ,
|
.Cm M ,
|
||||||
.Cm G
|
.Cm G
|
||||||
|
|
@ -112,7 +156,6 @@ or
|
||||||
(either upper or lower case) to indicate a multiple of
|
(either upper or lower case) to indicate a multiple of
|
||||||
Kilobytes, Megabytes, Gigabytes or Terabytes
|
Kilobytes, Megabytes, Gigabytes or Terabytes
|
||||||
respectively.
|
respectively.
|
||||||
.El
|
|
||||||
.Pp
|
.Pp
|
||||||
Exactly one of the
|
Exactly one of the
|
||||||
.Fl r
|
.Fl r
|
||||||
|
|
@ -183,6 +226,7 @@ ls -l test_file*
|
||||||
.Sh SEE ALSO
|
.Sh SEE ALSO
|
||||||
.Xr dd 1 ,
|
.Xr dd 1 ,
|
||||||
.Xr touch 1 ,
|
.Xr touch 1 ,
|
||||||
|
.Xr fspacectl 2 ,
|
||||||
.Xr truncate 2
|
.Xr truncate 2
|
||||||
.Sh STANDARDS
|
.Sh STANDARDS
|
||||||
The
|
The
|
||||||
|
|
@ -198,3 +242,6 @@ The
|
||||||
.Nm
|
.Nm
|
||||||
utility was written by
|
utility was written by
|
||||||
.An Sheldon Hearn Aq Mt sheldonh@starjuice.net .
|
.An Sheldon Hearn Aq Mt sheldonh@starjuice.net .
|
||||||
|
Hole-punching support of this
|
||||||
|
utility was developed by
|
||||||
|
.An Ka Ho Ng Aq Mt khng@FreeBSD.org .
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,11 @@
|
||||||
* Copyright (c) 2000 Sheldon Hearn <sheldonh@FreeBSD.org>.
|
* Copyright (c) 2000 Sheldon Hearn <sheldonh@FreeBSD.org>.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
|
* Copyright (c) 2021 The FreeBSD Foundation
|
||||||
|
*
|
||||||
|
* Portions of this software were developed by Ka Ho Ng <khng@FreeBSD.org>
|
||||||
|
* under sponsorship from the FreeBSD Foundation.
|
||||||
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
* modification, are permitted provided that the following conditions
|
* modification, are permitted provided that the following conditions
|
||||||
* are met:
|
* are met:
|
||||||
|
|
@ -49,26 +54,36 @@ main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
mode_t omode;
|
mode_t omode;
|
||||||
off_t oflow, rsize, sz, tsize, round;
|
off_t oflow, rsize, sz, tsize, round, off, len;
|
||||||
uint64_t usz;
|
uint64_t usz;
|
||||||
int ch, error, fd, oflags;
|
int ch, error, fd, oflags, r;
|
||||||
|
int do_dealloc;
|
||||||
|
int do_truncate;
|
||||||
int no_create;
|
int no_create;
|
||||||
int do_relative;
|
int do_relative;
|
||||||
int do_round;
|
int do_round;
|
||||||
int do_refer;
|
int do_refer;
|
||||||
int got_size;
|
int got_size;
|
||||||
char *fname, *rname;
|
char *fname, *rname;
|
||||||
|
struct spacectl_range sr;
|
||||||
|
|
||||||
fd = -1;
|
fd = -1;
|
||||||
rsize = tsize = sz = 0;
|
rsize = tsize = sz = off = 0;
|
||||||
no_create = do_relative = do_round = do_refer = got_size = 0;
|
len = -1;
|
||||||
error = 0;
|
do_dealloc = no_create = do_relative = do_round = do_refer =
|
||||||
|
got_size = 0;
|
||||||
|
do_truncate = 1;
|
||||||
|
error = r = 0;
|
||||||
rname = NULL;
|
rname = NULL;
|
||||||
while ((ch = getopt(argc, argv, "cr:s:")) != -1)
|
while ((ch = getopt(argc, argv, "cdr:s:o:l:")) != -1)
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case 'c':
|
case 'c':
|
||||||
no_create = 1;
|
no_create = 1;
|
||||||
break;
|
break;
|
||||||
|
case 'd':
|
||||||
|
do_dealloc = 1;
|
||||||
|
do_truncate = 0;
|
||||||
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
do_refer = 1;
|
do_refer = 1;
|
||||||
rname = optarg;
|
rname = optarg;
|
||||||
|
|
@ -89,6 +104,22 @@ main(int argc, char **argv)
|
||||||
-(off_t)usz : (off_t)usz;
|
-(off_t)usz : (off_t)usz;
|
||||||
got_size = 1;
|
got_size = 1;
|
||||||
break;
|
break;
|
||||||
|
case 'o':
|
||||||
|
if (expand_number(optarg, &usz) == -1 ||
|
||||||
|
(off_t)usz < 0)
|
||||||
|
errx(EXIT_FAILURE,
|
||||||
|
"invalid offset argument `%s'", optarg);
|
||||||
|
|
||||||
|
off = usz;
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
if (expand_number(optarg, &usz) == -1 ||
|
||||||
|
(off_t)usz <= 0)
|
||||||
|
errx(EXIT_FAILURE,
|
||||||
|
"invalid length argument `%s'", optarg);
|
||||||
|
|
||||||
|
len = usz;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
usage();
|
usage();
|
||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
|
|
@ -98,19 +129,22 @@ main(int argc, char **argv)
|
||||||
argc -= optind;
|
argc -= optind;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Exactly one of do_refer or got_size must be specified. Since
|
* Exactly one of do_refer, got_size or do_dealloc must be specified.
|
||||||
* do_relative implies got_size, do_relative and do_refer are
|
* Since do_relative implies got_size, do_relative, do_refer and
|
||||||
* also mutually exclusive. See usage() for allowed invocations.
|
* do_dealloc are also mutually exclusive. If do_dealloc is specified,
|
||||||
|
* the length argument must be set. See usage() for allowed
|
||||||
|
* invocations.
|
||||||
*/
|
*/
|
||||||
if (do_refer + got_size != 1 || argc < 1)
|
if (argc < 1 || do_refer + got_size + do_dealloc != 1 ||
|
||||||
|
(do_dealloc == 1 && len == -1))
|
||||||
usage();
|
usage();
|
||||||
if (do_refer) {
|
if (do_refer == 1) {
|
||||||
if (stat(rname, &sb) == -1)
|
if (stat(rname, &sb) == -1)
|
||||||
err(EXIT_FAILURE, "%s", rname);
|
err(EXIT_FAILURE, "%s", rname);
|
||||||
tsize = sb.st_size;
|
tsize = sb.st_size;
|
||||||
} else if (do_relative || do_round)
|
} else if (do_relative == 1 || do_round == 1)
|
||||||
rsize = sz;
|
rsize = sz;
|
||||||
else
|
else if (do_dealloc == 0)
|
||||||
tsize = sz;
|
tsize = sz;
|
||||||
|
|
||||||
if (no_create)
|
if (no_create)
|
||||||
|
|
@ -129,7 +163,7 @@ main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (do_relative) {
|
if (do_relative == 1) {
|
||||||
if (fstat(fd, &sb) == -1) {
|
if (fstat(fd, &sb) == -1) {
|
||||||
warn("%s", fname);
|
warn("%s", fname);
|
||||||
error++;
|
error++;
|
||||||
|
|
@ -144,7 +178,7 @@ main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
tsize = oflow;
|
tsize = oflow;
|
||||||
}
|
}
|
||||||
if (do_round) {
|
if (do_round == 1) {
|
||||||
if (fstat(fd, &sb) == -1) {
|
if (fstat(fd, &sb) == -1) {
|
||||||
warn("%s", fname);
|
warn("%s", fname);
|
||||||
error++;
|
error++;
|
||||||
|
|
@ -166,10 +200,16 @@ main(int argc, char **argv)
|
||||||
if (tsize < 0)
|
if (tsize < 0)
|
||||||
tsize = 0;
|
tsize = 0;
|
||||||
|
|
||||||
if (ftruncate(fd, tsize) == -1) {
|
if (do_dealloc == 1) {
|
||||||
|
sr.r_offset = off;
|
||||||
|
sr.r_len = len;
|
||||||
|
r = fspacectl(fd, SPACECTL_DEALLOC, &sr, 0, &sr);
|
||||||
|
}
|
||||||
|
if (do_truncate == 1)
|
||||||
|
r = ftruncate(fd, tsize);
|
||||||
|
if (r == -1) {
|
||||||
warn("%s", fname);
|
warn("%s", fname);
|
||||||
error++;
|
error++;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fd != -1)
|
if (fd != -1)
|
||||||
|
|
@ -181,8 +221,9 @@ main(int argc, char **argv)
|
||||||
static void
|
static void
|
||||||
usage(void)
|
usage(void)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "%s\n%s\n",
|
fprintf(stderr, "%s\n%s\n%s\n",
|
||||||
"usage: truncate [-c] -s [+|-|%|/]size[K|k|M|m|G|g|T|t] file ...",
|
"usage: truncate [-c] -s [+|-|%|/]size[K|k|M|m|G|g|T|t] file ...",
|
||||||
" truncate [-c] -r rfile file ...");
|
" truncate [-c] -r rfile file ...",
|
||||||
|
" truncate [-c] -d [-o offset[K|k|M|m|G|g|T|t]] -l length[K|k|M|m|G|g|T|t] file ...");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue