mirror of
git://git.sv.gnu.org/coreutils.git
synced 2026-04-20 02:36:16 +02:00
Add new program: truncate
* AUTHORS: Register as the author * NEWS: Mention this change * README: Add truncate command to list * src/truncate.c: New command * src/Makefile.am: Add truncate command to list to build * src/.gitignore: Add truncate binary to list to ignore * doc/coreutils.texi (truncate invocation): Add truncate info * man/Makefile.am: Add truncate man page to list to build * man/truncate.x: Add truncate man page template * po/POTFILES.in: Add truncate to list to translate * tests/Makefile.am: Add truncate tests * tests/misc/help-version: Add support for new truncate command * tests/misc/truncate-dangling-symlink: check dangling link ok * tests/misc/truncate-dir-fail: ensure dirs fail * tests/misc/truncate-fail-diag: validate messages for missing paths * tests/misc/truncate-fifo: ensure fifos ignored * tests/misc/truncate-no-create-missing: ensure -c option honoured * tests/misc/truncate-overflow: check signed integer overflows * tests/misc/truncate-owned-by-other: root permissions check * tests/misc/truncate-parameters: check invalid parameter combinations * tests/misc/truncate-relative: check invalid relative sizes
This commit is contained in:
committed by
Jim Meyering
parent
74c0bfbc4c
commit
75e0047c4b
1
AUTHORS
1
AUTHORS
@@ -88,6 +88,7 @@ timeout: Pádraig Brady
|
||||
touch: Paul Rubin, Arnold Robbins, Jim Kingdon, David MacKenzie, Randy Smith
|
||||
tr: Jim Meyering
|
||||
true: Jim Meyering
|
||||
truncate: Pádraig Brady
|
||||
tsort: Mark Kettenis
|
||||
tty: David MacKenzie
|
||||
uname: David MacKenzie
|
||||
|
||||
1
NEWS
1
NEWS
@@ -5,6 +5,7 @@ GNU coreutils NEWS -*- outline -*-
|
||||
** New programs
|
||||
|
||||
timeout: Run a command with bounded time.
|
||||
truncate: Set the size of a file to a specified size.
|
||||
|
||||
** New features
|
||||
|
||||
|
||||
3
README
3
README
@@ -14,7 +14,8 @@ The programs that can be built with this package are:
|
||||
od paste pathchk pinky pr printenv printf ptx pwd readlink rm rmdir
|
||||
runcon seq sha1sum sha224sum sha256sum sha384sum sha512sum shred shuf
|
||||
sleep sort split stat stty su sum sync tac tail tee test timeout touch tr
|
||||
true tsort tty uname unexpand uniq unlink uptime users vdir wc who whoami yes
|
||||
true truncate tsort tty uname unexpand uniq unlink uptime users vdir wc who
|
||||
whoami yes
|
||||
|
||||
See the file NEWS for a list of major changes in the current release.
|
||||
|
||||
|
||||
@@ -117,6 +117,7 @@
|
||||
* touch: (coreutils)touch invocation. Change file timestamps.
|
||||
* tr: (coreutils)tr invocation. Translate characters.
|
||||
* true: (coreutils)true invocation. Do nothing, successfully.
|
||||
* truncate: (coreutils)truncate invocation. Shrink/extend size of a file.
|
||||
* tsort: (coreutils)tsort invocation. Topological sort.
|
||||
* tty: (coreutils)tty invocation. Print terminal name.
|
||||
* uname: (coreutils)uname invocation. Print system information.
|
||||
@@ -185,7 +186,7 @@ Free Documentation License''.
|
||||
* Basic operations:: cp dd install mv rm shred
|
||||
* Special file types:: ln mkdir rmdir mkfifo mknod
|
||||
* Changing file attributes:: chgrp chmod chown touch
|
||||
* Disk usage:: df du stat sync
|
||||
* Disk usage:: df du stat sync truncate
|
||||
* Printing text:: echo printf yes
|
||||
* Conditions:: false true test expr
|
||||
* Redirection:: tee
|
||||
@@ -334,6 +335,7 @@ Disk usage
|
||||
* du invocation:: Estimate file space usage
|
||||
* stat invocation:: Report file or file system status
|
||||
* sync invocation:: Synchronize data on disk with memory
|
||||
* truncate invocation:: Shrink or extend the size of a file
|
||||
|
||||
Printing text
|
||||
|
||||
@@ -9571,6 +9573,7 @@ file status information, and write buffers to disk.
|
||||
* du invocation:: Estimate file space usage.
|
||||
* stat invocation:: Report file or file system status.
|
||||
* sync invocation:: Synchronize memory and disk.
|
||||
* truncate invocation:: Shrink or extend the size of a file.
|
||||
@end menu
|
||||
|
||||
|
||||
@@ -10214,6 +10217,81 @@ Any arguments are ignored, except for a lone @option{--help} or
|
||||
@exitstatus
|
||||
|
||||
|
||||
@node truncate invocation
|
||||
@section @command{truncate}: Shrink or extend the size of a file
|
||||
|
||||
@pindex truncate
|
||||
@cindex truncating, file sizes
|
||||
|
||||
@command{truncate} shrinks or extends the size of each @var{file} to the
|
||||
specified size. Synopsis:
|
||||
|
||||
@example
|
||||
truncate @var{option}@dots{} @var{file}@dots{}
|
||||
@end example
|
||||
|
||||
@cindex files, creating
|
||||
Any @var{file} that does not exist is created.
|
||||
|
||||
@cindex sparse files, creating
|
||||
@cindex holes, creating files with
|
||||
If a @var{file} is larger than the specified size, the extra data is lost.
|
||||
If a @var{file} is shorter, it is extended and the extended part (or hole)
|
||||
reads as zero bytes.
|
||||
|
||||
The program accepts the following options. Also see @ref{Common options}.
|
||||
|
||||
@table @samp
|
||||
|
||||
@item -c
|
||||
@itemx --no-create
|
||||
@opindex -c
|
||||
@opindex --no-create
|
||||
Do not create files that do not exist.
|
||||
|
||||
@item -o
|
||||
@itemx --io-blocks
|
||||
@opindex -o
|
||||
@opindex --io-blocks
|
||||
Treat @var{size} as number of I/O blocks of the @var{FILE} rather than bytes.
|
||||
|
||||
@item -r @var{rfile}
|
||||
@itemx --reference=@var{rfile}
|
||||
@opindex -r
|
||||
@opindex --reference
|
||||
Set the size of each @var{file} to the same size as @var{rfile}.
|
||||
|
||||
@item -s @var{size}
|
||||
@itemx --size=@var{size}
|
||||
@opindex -s
|
||||
@opindex --size
|
||||
Set the size of each @var{file} to this @var{size}.
|
||||
@var{size} is a number which may be followed by one of these
|
||||
multiplicative suffixes:
|
||||
@example
|
||||
@samp{KB} => 1000 (KiloBytes)
|
||||
@samp{K} => 1024 (KibiBytes)
|
||||
@samp{MB} => 1000*1000 (MegaBytes)
|
||||
@samp{M} => 1024*1024 (MebiBytes)
|
||||
@end example
|
||||
and so on for @samp{G}, @samp{T}, @samp{P}, @samp{E}, @samp{Z}, and @samp{Y}.
|
||||
|
||||
@var{size} may also be prefixed by one of the following to adjust
|
||||
the size of each @var{file} based on their current size:
|
||||
@example
|
||||
@samp{+} => extend by
|
||||
@samp{-} => reduce by
|
||||
@samp{<} => at most
|
||||
@samp{>} => at least
|
||||
@samp{/} => round down to multiple of
|
||||
@samp{%} => round up to multiple of
|
||||
@end example
|
||||
|
||||
@end table
|
||||
|
||||
@exitstatus
|
||||
|
||||
|
||||
@node Printing text
|
||||
@chapter Printing text
|
||||
|
||||
|
||||
@@ -117,6 +117,7 @@ timeout.1: $(common_dep) $(srcdir)/timeout.x ../src/timeout.c
|
||||
touch.1: $(common_dep) $(srcdir)/touch.x ../src/touch.c
|
||||
tr.1: $(common_dep) $(srcdir)/tr.x ../src/tr.c
|
||||
true.1: $(common_dep) $(srcdir)/true.x ../src/true.c
|
||||
truncate.1: $(common_dep) $(srcdir)/truncate.x ../src/truncate.c
|
||||
tsort.1: $(common_dep) $(srcdir)/tsort.x ../src/tsort.c
|
||||
tty.1: $(common_dep) $(srcdir)/tty.x ../src/tty.c
|
||||
uname.1: $(common_dep) $(srcdir)/uname.x ../src/uname.c
|
||||
|
||||
6
man/truncate.x
Normal file
6
man/truncate.x
Normal file
@@ -0,0 +1,6 @@
|
||||
[NAME]
|
||||
truncate \- shrink or extend the size of a file to the specifed size
|
||||
[DESCRIPTION]
|
||||
.\" Add any additional description here
|
||||
[SEE ALSO]
|
||||
dd(1), truncate(2), ftruncate(2)
|
||||
@@ -120,6 +120,7 @@ src/timeout.c
|
||||
src/touch.c
|
||||
src/tr.c
|
||||
src/true.c
|
||||
src/truncate.c
|
||||
src/tsort.c
|
||||
src/tty.c
|
||||
src/uname.c
|
||||
|
||||
1
src/.gitignore
vendored
1
src/.gitignore
vendored
@@ -91,6 +91,7 @@ timeout
|
||||
touch
|
||||
tr
|
||||
true
|
||||
truncate
|
||||
tsort
|
||||
tty
|
||||
uname
|
||||
|
||||
@@ -39,7 +39,7 @@ EXTRA_PROGRAMS = \
|
||||
basename date dirname echo env expr factor false \
|
||||
id kill logname pathchk printenv printf pwd \
|
||||
runcon seq sleep tee \
|
||||
test timeout true tty whoami yes \
|
||||
test timeout true truncate tty whoami yes \
|
||||
base64
|
||||
|
||||
bin_PROGRAMS = $(OPTIONAL_BIN_PROGS)
|
||||
|
||||
405
src/truncate.c
Normal file
405
src/truncate.c
Normal file
@@ -0,0 +1,405 @@
|
||||
/* truncate -- truncate or extend the length of files.
|
||||
Copyright (C) 2008 Free Software Foundation, 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, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will 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, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* Written by Pádraig Brady
|
||||
|
||||
This is backwards compatible with the FreeBSD utility, but is more
|
||||
flexible wrt the size specifications and the use of long options,
|
||||
to better fit the "GNU" environment.
|
||||
|
||||
Note if !defined(HAVE_FTRUNCATE) then the --skip-ftruncate configure flag
|
||||
was specified or we're in a mingw environment. In these cases gnulib
|
||||
emulation will be used and GNULIB_FTRUNCATE is defined. Note if emulation
|
||||
can't even be provided ftruncate() will return EIO. */
|
||||
|
||||
#include <config.h> /* sets _FILE_OFFSET_BITS=64 etc. */
|
||||
#include <stdio.h>
|
||||
#include <getopt.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "system.h"
|
||||
#include "error.h"
|
||||
#include "posixver.h"
|
||||
#include "quote.h"
|
||||
#include "xstrtol.h"
|
||||
|
||||
/* The official name of this program (e.g., no `g' prefix). */
|
||||
#define PROGRAM_NAME "truncate"
|
||||
|
||||
#define AUTHORS proper_name_utf8 ("Padraig Brady", "P\303\241draig Brady")
|
||||
|
||||
/* (-c) If true, don't create if not already there */
|
||||
static bool no_create;
|
||||
|
||||
/* (-o) If true, --size refers to blocks not bytes */
|
||||
static bool block_mode;
|
||||
|
||||
/* (-r) Reference file to use size from */
|
||||
static char const *ref_file;
|
||||
|
||||
static struct option const longopts[] = {
|
||||
{"no-create", no_argument, NULL, 'c'},
|
||||
{"io-blocks", no_argument, NULL, 'o'},
|
||||
{"reference", required_argument, NULL, 'r'},
|
||||
{"size", required_argument, NULL, 's'},
|
||||
{GETOPT_HELP_OPTION_DECL},
|
||||
{GETOPT_VERSION_OPTION_DECL},
|
||||
{NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{ rm_abs = 0, rm_rel, rm_min, rm_max, rm_rdn, rm_rup } rel_mode_t;
|
||||
|
||||
/* Set size to the value of STR, interpreted as a decimal integer,
|
||||
optionally multiplied by various values.
|
||||
Return -1 on error, 0 on success.
|
||||
|
||||
This supports dd BLOCK size suffixes + lowercase g,t,m for bsd compat
|
||||
Note we don't support dd's b=512, c=1, w=2 or 21x512MiB formats. */
|
||||
static int
|
||||
parse_len (char const *str, off_t *size)
|
||||
{
|
||||
enum strtol_error e;
|
||||
/* OFF_T_MAX = INTMAX_MAX */
|
||||
e = xstrtoimax (str, NULL, 10, size, "EgGkKmMPtTYZ0");
|
||||
errno = (e == LONGINT_OVERFLOW) ? EOVERFLOW : 0;
|
||||
return (e == LONGINT_OK) ? 0 : -1;
|
||||
}
|
||||
|
||||
static void
|
||||
usage (int status)
|
||||
{
|
||||
if (status != EXIT_SUCCESS)
|
||||
fprintf (stderr, _("Try `%s --help' for more information.\n"),
|
||||
program_name);
|
||||
else
|
||||
{
|
||||
printf (_("Usage: %s OPTION... FILE...\n"), program_name);
|
||||
fputs (_("\
|
||||
Shrink or extend the size of each FILE to the specified size\n\
|
||||
\n\
|
||||
A FILE argument that does not exist is created.\n\
|
||||
\n\
|
||||
If a FILE is larger than the specified size, the extra data is lost.\n\
|
||||
If a FILE is shorter, it is extended and the extended part (hole)\n\
|
||||
reads as zero bytes.\n\
|
||||
\n\
|
||||
"), stdout);
|
||||
fputs (_("\
|
||||
Mandatory arguments to long options are mandatory for short options too.\n\
|
||||
"), stdout);
|
||||
fputs (_("\
|
||||
-c, --no-create do not create any files\n\
|
||||
"), stdout);
|
||||
fputs (_("\
|
||||
-o, --io-blocks Treat SIZE as number of IO blocks instead of bytes\n\
|
||||
"), stdout);
|
||||
fputs (_("\
|
||||
-r, --reference=FILE use this FILE's size\n\
|
||||
-s, --size=SIZE use this SIZE\n"), stdout);
|
||||
fputs (HELP_OPTION_DESCRIPTION, stdout);
|
||||
fputs (VERSION_OPTION_DESCRIPTION, stdout);
|
||||
fputs (_("\n\
|
||||
SIZE is a number which may be followed by one of the following suffixes:\n\
|
||||
KB 1000, K 1024, MB 1000*1000, M 1024*1024, and so on for G, T, P, E, Z, Y.\n\
|
||||
"), stdout);
|
||||
fputs (_("\n\
|
||||
SIZE may also be prefixed by one of the following modifying characters:\n\
|
||||
`+' extend by, `-' reduce by, `<' at most, `>' at least,\n\
|
||||
`/' round down to multiple of, `%' round up to multiple of.\n"), stdout);
|
||||
fputs (_("\
|
||||
\n\
|
||||
Note that the -r and -s options are mutually exclusive.\n\
|
||||
"), stdout);
|
||||
emit_bug_reporting_address ();
|
||||
}
|
||||
exit (status);
|
||||
}
|
||||
|
||||
/* return 1 on error, 0 on success */
|
||||
static int
|
||||
do_ftruncate (int fd, char const *fname, off_t ssize, rel_mode_t rel_mode)
|
||||
{
|
||||
struct stat sb;
|
||||
off_t nsize;
|
||||
|
||||
if ((block_mode || rel_mode) && fstat (fd, &sb) != 0)
|
||||
{
|
||||
error (0, errno, _("cannot fstat %s"), quote (fname));
|
||||
return 1;
|
||||
}
|
||||
if (block_mode)
|
||||
{
|
||||
size_t const blksize = ST_BLKSIZE (sb);
|
||||
if (ssize < OFF_T_MIN / blksize || ssize > OFF_T_MAX / blksize)
|
||||
{
|
||||
error (0, 0,
|
||||
_("overflow in %" PRIdMAX
|
||||
" * %zu byte blocks for file %s"), ssize, blksize,
|
||||
quote (fname));
|
||||
return 1;
|
||||
}
|
||||
ssize *= blksize;
|
||||
}
|
||||
if (rel_mode)
|
||||
{
|
||||
uintmax_t const fsize = sb.st_size;
|
||||
|
||||
if (sb.st_size < 0)
|
||||
{
|
||||
/* Complain only for a regular file, a directory,
|
||||
or a shared memory object, as POSIX 1003.1-2004 specifies
|
||||
ftruncate's behavior only for these file types. */
|
||||
if (S_ISREG (sb.st_mode) || S_ISDIR (sb.st_mode)
|
||||
|| S_TYPEISSHM (&sb))
|
||||
{
|
||||
/* overflow is the only reason I can think
|
||||
this would ever go negative for the above types */
|
||||
error (0, 0, _("%s has unusable, apparently negative size"),
|
||||
quote (fname));
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rel_mode == rm_min)
|
||||
nsize = MAX (fsize, ssize);
|
||||
else if (rel_mode == rm_max)
|
||||
nsize = MIN (fsize, ssize);
|
||||
else if (rel_mode == rm_rdn)
|
||||
/* 0..ssize-1 -> 0 */
|
||||
nsize = (fsize / ssize) * ssize;
|
||||
else if (rel_mode == rm_rup)
|
||||
/* 1..ssize -> ssize */
|
||||
{
|
||||
/* Here ssize>=1 && fsize>=0 */
|
||||
uintmax_t const overflow = ((fsize + ssize - 1) / ssize) * ssize;
|
||||
if (overflow > OFF_T_MAX)
|
||||
{
|
||||
error (0, 0, _("overflow rounding up size of file %s"),
|
||||
quote (fname));
|
||||
return 1;
|
||||
}
|
||||
nsize = overflow;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ssize > OFF_T_MAX - (off_t)fsize)
|
||||
{
|
||||
error (0, 0, _("overflow extending size of file %s"),
|
||||
quote (fname));
|
||||
return 1;
|
||||
}
|
||||
nsize = fsize + ssize;
|
||||
}
|
||||
}
|
||||
else
|
||||
nsize = ssize;
|
||||
if (nsize < 0)
|
||||
nsize = 0;
|
||||
|
||||
if (ftruncate (fd, nsize) == -1) /* note updates mtime & ctime */
|
||||
{
|
||||
/* Complain only when ftruncate fails on a regular file, a
|
||||
directory, or a shared memory object, as POSIX 1003.1-2004
|
||||
specifies ftruncate's behavior only for these file types.
|
||||
For example, do not complain when Linux 2.4 ftruncate
|
||||
fails on /dev/fd0. */
|
||||
int const ftruncate_errno = errno;
|
||||
if (fstat (fd, &sb) != 0)
|
||||
{
|
||||
error (0, errno, _("cannot fstat %s"), quote (fname));
|
||||
return 1;
|
||||
}
|
||||
else if (S_ISREG (sb.st_mode) || S_ISDIR (sb.st_mode)
|
||||
|| S_TYPEISSHM (&sb))
|
||||
{
|
||||
error (0, ftruncate_errno,
|
||||
_("truncating %s at %" PRIdMAX " bytes"), quote (fname),
|
||||
nsize);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
bool got_size = false;
|
||||
off_t size;
|
||||
rel_mode_t rel_mode = rm_abs;
|
||||
mode_t omode;
|
||||
int c, errors = 0, fd = -1, oflags;
|
||||
char const *fname;
|
||||
|
||||
initialize_main (&argc, &argv);
|
||||
set_program_name (argv[0]);
|
||||
setlocale (LC_ALL, "");
|
||||
bindtextdomain (PACKAGE, LOCALEDIR);
|
||||
textdomain (PACKAGE);
|
||||
|
||||
atexit (close_stdout);
|
||||
|
||||
while ((c = getopt_long (argc, argv, "cor:s:", longopts, NULL)) != -1)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case 'c':
|
||||
no_create = true;
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
block_mode = true;
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
ref_file = optarg;
|
||||
break;
|
||||
|
||||
case 's':
|
||||
switch (*optarg)
|
||||
{
|
||||
case '<':
|
||||
rel_mode = rm_max;
|
||||
optarg++;
|
||||
break;
|
||||
case '>':
|
||||
rel_mode = rm_min;
|
||||
optarg++;
|
||||
break;
|
||||
case '/':
|
||||
rel_mode = rm_rdn;
|
||||
optarg++;
|
||||
break;
|
||||
case '%':
|
||||
rel_mode = rm_rup;
|
||||
optarg++;
|
||||
break;
|
||||
}
|
||||
if (*optarg == '+' || *optarg == '-')
|
||||
{
|
||||
if (rel_mode)
|
||||
{
|
||||
error (0, 0, _("multiple relative modifiers specified"));
|
||||
/* Note other combinations are flagged as invalid numbers */
|
||||
usage (EXIT_FAILURE);
|
||||
}
|
||||
rel_mode = rm_rel;
|
||||
}
|
||||
if (parse_len (optarg, &size) == -1)
|
||||
error (EXIT_FAILURE, errno, _("invalid number %s"),
|
||||
quote (optarg));
|
||||
/* Rounding to multiple of 0 is nonsensical */
|
||||
if ((rel_mode == rm_rup || rel_mode == rm_rdn) && size == 0)
|
||||
error (EXIT_FAILURE, 0, _("division by zero"));
|
||||
got_size = true;
|
||||
break;
|
||||
|
||||
case_GETOPT_HELP_CHAR;
|
||||
|
||||
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
|
||||
|
||||
default:
|
||||
usage (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
argv += optind;
|
||||
argc -= optind;
|
||||
|
||||
/* must specify either size or reference file */
|
||||
if ((ref_file && got_size) || (!ref_file && !got_size))
|
||||
{
|
||||
error (0, 0, _("You must specify one of %s or %s"),
|
||||
quote_n (0, "--size"), quote_n (1, "--reference"));
|
||||
usage (EXIT_FAILURE);
|
||||
}
|
||||
/* block_mode without size is not valid */
|
||||
if (block_mode && !got_size)
|
||||
{
|
||||
error (0, 0, _("%s was specified but %s was not"),
|
||||
quote_n (0, "--io-blocks"), quote_n (1, "--size"));
|
||||
usage (EXIT_FAILURE);
|
||||
}
|
||||
/* must specify at least 1 file */
|
||||
if (argc < 1)
|
||||
{
|
||||
error (0, 0, _("missing file operand"));
|
||||
usage (EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (ref_file)
|
||||
{
|
||||
struct stat sb;
|
||||
if (stat (ref_file, &sb) != 0)
|
||||
error (EXIT_FAILURE, errno, _("cannot stat %s"), quote (ref_file));
|
||||
size = sb.st_size;
|
||||
}
|
||||
|
||||
oflags = O_WRONLY | (no_create ? 0 : O_CREAT) | O_NONBLOCK;
|
||||
omode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
|
||||
|
||||
while ((fname = *argv++) != NULL)
|
||||
{
|
||||
if ((fd = open (fname, oflags, omode)) == -1)
|
||||
{
|
||||
/* `truncate -s0 -c no-such-file` shouldn't gen error
|
||||
`truncate -s0 no-such-dir/file` should gen ENOENT error
|
||||
`truncate -s0 no-such-dir/` should gen EISDIR error
|
||||
`truncate -s0 .` should gen EISDIR error */
|
||||
if (!(no_create && errno == ENOENT))
|
||||
{
|
||||
int const open_errno = errno;
|
||||
struct stat sb;
|
||||
if (stat (fname, &sb) == 0)
|
||||
{
|
||||
/* Complain only for a regular file, a directory,
|
||||
or a shared memory object, as POSIX 1003.1-2004 specifies
|
||||
ftruncate's behavior only for these file types. */
|
||||
if (!S_ISREG (sb.st_mode) && !S_ISDIR (sb.st_mode)
|
||||
&& !S_TYPEISSHM (&sb))
|
||||
continue;
|
||||
}
|
||||
error (0, open_errno, _("cannot open %s for writing"),
|
||||
quote (fname));
|
||||
errors++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (fd != -1)
|
||||
{
|
||||
errors += do_ftruncate (fd, fname, size, rel_mode);
|
||||
if (close (fd) != 0)
|
||||
{
|
||||
error (0, errno, _("closing %s"), quote (fname));
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return errors ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||
@@ -28,6 +28,7 @@ root_tests = \
|
||||
ls/nameless-uid \
|
||||
misc/chcon \
|
||||
misc/selinux \
|
||||
misc/truncate-owned-by-other \
|
||||
mkdir/writable-under-readonly \
|
||||
mv/sticky-to-xpart \
|
||||
rm/fail-2eperm \
|
||||
@@ -212,6 +213,14 @@ TESTS = \
|
||||
misc/timeout \
|
||||
misc/timeout-parameters \
|
||||
misc/tr \
|
||||
misc/truncate-dangling-symlink \
|
||||
misc/truncate-dir-fail \
|
||||
misc/truncate-fail-diag \
|
||||
misc/truncate-fifo \
|
||||
misc/truncate-no-create-missing \
|
||||
misc/truncate-overflow \
|
||||
misc/truncate-parameters \
|
||||
misc/truncate-relative \
|
||||
misc/tsort \
|
||||
misc/tty-eof \
|
||||
misc/unexpand \
|
||||
|
||||
@@ -131,6 +131,7 @@ rmdir_args=$tmp_dir
|
||||
rm_args=$tmp_in
|
||||
shred_args=$tmp_in
|
||||
touch_args=$tmp_in2
|
||||
truncate_args="--reference=$tmp_in $tmp_in2"
|
||||
|
||||
basename_args=$tmp_in
|
||||
dirname_args=$tmp_in
|
||||
|
||||
33
tests/misc/truncate-dangling-symlink
Executable file
33
tests/misc/truncate-dangling-symlink
Executable file
@@ -0,0 +1,33 @@
|
||||
#!/bin/sh
|
||||
# Make sure truncate can create a file through a dangling symlink.
|
||||
|
||||
# Copyright (C) 2008 Free Software Foundation, 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, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
if test "$VERBOSE" = yes; then
|
||||
set -x
|
||||
truncate --version
|
||||
fi
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
ln -s truncate-target t-symlink
|
||||
fail=0
|
||||
|
||||
truncate -s0 t-symlink || fail=1
|
||||
|
||||
test -f truncate-target || fail=1
|
||||
|
||||
(exit $fail); exit $fail
|
||||
14
tests/misc/truncate-dir-fail
Executable file
14
tests/misc/truncate-dir-fail
Executable file
@@ -0,0 +1,14 @@
|
||||
#!/bin/sh
|
||||
# Make sure truncate fails for a directory.
|
||||
|
||||
if test "$VERBOSE" = yes; then
|
||||
set -x
|
||||
truncate --version
|
||||
fi
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
# truncate on dir not allowed
|
||||
truncate -s+0 . && fail=1 || fail=0
|
||||
|
||||
(exit $fail); exit $fail
|
||||
50
tests/misc/truncate-fail-diag
Executable file
50
tests/misc/truncate-fail-diag
Executable file
@@ -0,0 +1,50 @@
|
||||
#!/bin/sh
|
||||
# make sure truncate gives reasonable diagnostics
|
||||
# Note open() checks for trailing '/' before checking for existance
|
||||
# open (".", O_CREAT & (O_WRONLY | O_RDWR), ...) -> EISDIR
|
||||
# open ("missing/", O_CREAT & (O_WRONLY | O_RDWR), ...) -> EISDIR
|
||||
# open ("missing/file", O_CREAT & (O_WRONLY | O_RDWR), ...) -> ENOENT
|
||||
|
||||
# Copyright (C) 2008 Free Software Foundation, 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, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
if test "$VERBOSE" = yes; then
|
||||
set -x
|
||||
truncate --version
|
||||
fi
|
||||
|
||||
. $srcdir/lang-default
|
||||
. $srcdir/test-lib.sh
|
||||
skip_if_root_
|
||||
|
||||
fail=0
|
||||
|
||||
d1=no
|
||||
|
||||
dir=$d1/such-dir
|
||||
truncate -s0 $dir > out 2>&1 && fail=1
|
||||
cat <<EOF > exp
|
||||
truncate: cannot open \`$dir' for writing: No such file or directory
|
||||
EOF
|
||||
compare out exp || fail=1
|
||||
|
||||
dir=$d1/
|
||||
truncate -s0 $dir > out 2>&1 && fail=1
|
||||
cat <<EOF > exp
|
||||
truncate: cannot open \`$dir' for writing: Is a directory
|
||||
EOF
|
||||
compare out exp || fail=1
|
||||
|
||||
(exit $fail); exit $fail
|
||||
32
tests/misc/truncate-fifo
Executable file
32
tests/misc/truncate-fifo
Executable file
@@ -0,0 +1,32 @@
|
||||
#!/bin/sh
|
||||
# Make sure truncate works on fifos without hanging or errors
|
||||
|
||||
# Copyright (C) 2008 Free Software Foundation, 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, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
if test "$VERBOSE" = yes; then
|
||||
set -x
|
||||
truncate --version
|
||||
fi
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
mkfifo_or_skip_ "fifo"
|
||||
|
||||
fail=0
|
||||
|
||||
truncate -s0 "fifo" || fail=1
|
||||
|
||||
(exit $fail); exit $fail
|
||||
31
tests/misc/truncate-no-create-missing
Executable file
31
tests/misc/truncate-no-create-missing
Executable file
@@ -0,0 +1,31 @@
|
||||
#!/bin/sh
|
||||
# Ensure that truncate -c no-such-file doesn't fail.
|
||||
|
||||
# Copyright (C) 2008 Free Software Foundation, 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, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
if test "$VERBOSE" = yes; then
|
||||
set -x
|
||||
truncate --version
|
||||
fi
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
fail=0
|
||||
|
||||
# truncate -c no-such-file should not fail.
|
||||
truncate -s0 -c no-such-file || fail=1
|
||||
|
||||
(exit $fail); exit $fail
|
||||
55
tests/misc/truncate-overflow
Executable file
55
tests/misc/truncate-overflow
Executable file
@@ -0,0 +1,55 @@
|
||||
#!/bin/sh
|
||||
# Validate truncate integer overflow
|
||||
|
||||
# Copyright (C) 2008 Free Software Foundation, 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, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
if test "$VERBOSE" = yes; then
|
||||
set -x
|
||||
truncate --version
|
||||
fi
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
fail=0
|
||||
|
||||
# -= overflow
|
||||
truncate -s-1 create-zero-len-file || fail=1
|
||||
|
||||
echo > non-empty-file
|
||||
|
||||
truncate -s2147483648 -c no-such-file && _FILE_OFFSET_BITS=64
|
||||
|
||||
if [ $_FILE_OFFSET_BITS -eq 64 ]; then
|
||||
# signed overflow
|
||||
truncate -s9223372036854775808 file && fail=1
|
||||
|
||||
# *= signed overflow
|
||||
truncate --io-blocks --size="1E" file && fail=1
|
||||
|
||||
# += signed overflow
|
||||
truncate -s+9223372036854775807 non-empty-file && fail=1
|
||||
else
|
||||
# signed overflow
|
||||
truncate -s2147483648 file && fail=1
|
||||
|
||||
# *= signed overflow
|
||||
truncate --io-blocks --size="1G" file && fail=1
|
||||
|
||||
# += signed overflow
|
||||
truncate -s+2147483647 non-empty-file && fail=1
|
||||
fi
|
||||
|
||||
(exit $fail); exit $fail
|
||||
40
tests/misc/truncate-owned-by-other
Executable file
40
tests/misc/truncate-owned-by-other
Executable file
@@ -0,0 +1,40 @@
|
||||
#!/bin/sh
|
||||
# Demonstrate that "truncate -s0 writable-but-owned-by-other" works.
|
||||
|
||||
# Copyright (C) 2008 Free Software Foundation, 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, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
if test "$VERBOSE" = yes; then
|
||||
set -x
|
||||
truncate --version
|
||||
fi
|
||||
|
||||
. $srcdir/envvar-check
|
||||
. $srcdir/test-lib.sh
|
||||
require_root_
|
||||
|
||||
group_num=$(id -g $NON_ROOT_USERNAME)
|
||||
|
||||
# Create a file owned by root, and writable by $NON_ROOT_USERNAME.
|
||||
echo > root-owned || framework_failure
|
||||
chgrp +$group_num . root-owned || framework_failure
|
||||
chmod g+w root-owned
|
||||
|
||||
# Ensure that the current directory is searchable by $NON_ROOT_USERNAME.
|
||||
chmod g+x .
|
||||
|
||||
setuidgid $NON_ROOT_USERNAME env PATH="$PATH" truncate -s0 root-owned || fail=1
|
||||
|
||||
(exit $fail); exit $fail
|
||||
43
tests/misc/truncate-parameters
Executable file
43
tests/misc/truncate-parameters
Executable file
@@ -0,0 +1,43 @@
|
||||
#!/bin/sh
|
||||
# Validate truncate parameter combinations
|
||||
|
||||
# Copyright (C) 2008 Free Software Foundation, 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, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
if test "$VERBOSE" = yes; then
|
||||
set -x
|
||||
truncate --version
|
||||
fi
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
fail=0
|
||||
|
||||
# must specify at least 1 file
|
||||
truncate --size=0 && fail=1
|
||||
|
||||
# must specify size. don't default to 0
|
||||
truncate file && fail=1
|
||||
|
||||
# mixture of size & reference not allowed
|
||||
truncate --size=0 --reference=file file && fail=1
|
||||
|
||||
# blocks without size is not valid
|
||||
truncate --io-blocks --reference=file file && fail=1
|
||||
|
||||
# must specify valid numbers
|
||||
truncate --size="invalid" file && fail=1
|
||||
|
||||
(exit $fail); exit $fail
|
||||
40
tests/misc/truncate-relative
Executable file
40
tests/misc/truncate-relative
Executable file
@@ -0,0 +1,40 @@
|
||||
#!/bin/sh
|
||||
# Validate truncate relative sizes
|
||||
|
||||
# Copyright (C) 2008 Free Software Foundation, 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, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
|
||||
# This program is distributed in the hope that it will 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
if test "$VERBOSE" = yes; then
|
||||
set -x
|
||||
truncate --version
|
||||
fi
|
||||
|
||||
. $srcdir/test-lib.sh
|
||||
|
||||
fail=0
|
||||
|
||||
# mixture of relative modifiers not allowed
|
||||
truncate --size="+>0" file && fail=1
|
||||
|
||||
# mixture of relative modifiers not allowed
|
||||
truncate --size=">+0" file && fail=1
|
||||
|
||||
# division by zero
|
||||
truncate --size="/0" file && fail=1
|
||||
|
||||
# division by zero
|
||||
truncate --size="%0" file && fail=1
|
||||
|
||||
(exit $fail); exit $fail
|
||||
Reference in New Issue
Block a user