Proposed truncate command attached
>From 34b9bc72ffe70ec83710b12021e889d5ae65e508 Mon Sep 17 00:00:00 2001 From: =?utf-8?q?P=C3=A1draig=20Brady?= <[EMAIL PROTECTED]> Date: Wed, 26 Mar 2008 14:03:31 +0000 Subject: [PATCH] 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 * 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 * tests/misc/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
Signed-off-by: Pádraig Brady <[EMAIL PROTECTED]> --- AUTHORS | 1 + ChangeLog-2008 | 24 ++- NEWS | 4 + README | 3 +- doc/coreutils.texi | 80 +++++++- man/Makefile.am | 1 + man/truncate.x | 6 + src/Makefile.am | 2 +- src/truncate.c | 371 +++++++++++++++++++++++++++++++++ tests/misc/Makefile.am | 9 + tests/misc/help-version | 1 + tests/misc/truncate-dangling-symlink | 35 +++ tests/misc/truncate-dir-fail | 14 ++ tests/misc/truncate-fail-diag | 52 +++++ tests/misc/truncate-fifo | 38 ++++ tests/misc/truncate-no-create-missing | 31 +++ tests/misc/truncate-overflow | 52 +++++ tests/misc/truncate-owned-by-other | 40 ++++ tests/misc/truncate-parameters | 43 ++++ tests/misc/truncate-relative | 40 ++++ 20 files changed, 841 insertions(+), 6 deletions(-) create mode 100644 man/truncate.x create mode 100644 src/truncate.c create mode 100755 tests/misc/truncate-dangling-symlink create mode 100755 tests/misc/truncate-dir-fail create mode 100755 tests/misc/truncate-fail-diag create mode 100755 tests/misc/truncate-fifo create mode 100755 tests/misc/truncate-no-create-missing create mode 100755 tests/misc/truncate-overflow create mode 100755 tests/misc/truncate-owned-by-other create mode 100755 tests/misc/truncate-parameters create mode 100755 tests/misc/truncate-relative diff --git a/AUTHORS b/AUTHORS index 807857f..8b33318 100644 --- a/AUTHORS +++ b/AUTHORS @@ -87,6 +87,7 @@ test: Kevin Braunsdorf, Matthew Bradburn 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 diff --git a/ChangeLog-2008 b/ChangeLog-2008 index 279530a..d692adb 100644 --- a/ChangeLog-2008 +++ b/ChangeLog-2008 @@ -0,0 +1,25 @@ +2008-03-26 Pádraig Brady <[EMAIL PROTECTED]> + 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 + * 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 + * tests/misc/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 2008-02-07 Jim Meyering <[EMAIL PROTECTED]> diff --git a/NEWS b/NEWS index 948bced..e3d059d 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,10 @@ GNU coreutils NEWS -*- outline -*- * Noteworthy changes in release 6.?? (2008-??-??) [stable] +** New programs + + truncate: Set the size of a file to a specified size. + ** Bug fixes configure --enable-no-install-program=groups now works. diff --git a/README b/README index 7a608f4..c42c594 100644 --- a/README +++ b/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 touch tr true - tsort tty uname unexpand uniq unlink uptime users vdir wc who whoami yes + 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. diff --git a/doc/coreutils.texi b/doc/coreutils.texi index f161c4d..a687ebc 100644 --- a/doc/coreutils.texi +++ b/doc/coreutils.texi @@ -114,6 +114,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. Set the size of a file. * tsort: (coreutils)tsort invocation. Topological sort. * tty: (coreutils)tty invocation. Print terminal name. * uname: (coreutils)uname invocation. Print system information. @@ -182,7 +183,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 @@ -330,6 +331,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:: Set the size of a file Printing text @@ -9459,6 +9461,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:: Set the size of a file. @end menu @@ -10110,6 +10113,81 @@ Any arguments are ignored, except for a lone @option{--help} or @exitstatus [EMAIL PROTECTED] truncate invocation [EMAIL PROTECTED] @command{truncate}: Set the size of a file + [EMAIL PROTECTED] truncate [EMAIL PROTECTED] truncating, file sizes + [EMAIL PROTECTED] sets the size of each @var{file} to the specified size. +Synopsis: + [EMAIL PROTECTED] +truncate @[EMAIL PROTECTED] @[EMAIL PROTECTED] [EMAIL PROTECTED] example + [EMAIL PROTECTED] files, creating +Any @var{file} that does not exist is created. + [EMAIL PROTECTED] sparse files, creating [EMAIL PROTECTED] 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}. + [EMAIL PROTECTED] @samp + [EMAIL PROTECTED] -c [EMAIL PROTECTED] --no-create [EMAIL PROTECTED] -c [EMAIL PROTECTED] --no-create +Do not create files that do not exist. + [EMAIL PROTECTED] -o [EMAIL PROTECTED] --io-blocks [EMAIL PROTECTED] -o [EMAIL PROTECTED] --io-blocks +Treat @var{size} as number of I/O blocks of the @var{FILE} rather than bytes. + [EMAIL PROTECTED] -r @var{rfile} [EMAIL PROTECTED] [EMAIL PROTECTED] [EMAIL PROTECTED] -r [EMAIL PROTECTED] --reference +Set the size of each @var{file} to the same size as @var{rfile}. + [EMAIL PROTECTED] -s @var{size} [EMAIL PROTECTED] [EMAIL PROTECTED] [EMAIL PROTECTED] -s [EMAIL PROTECTED] --size +Set the size of each @var{file} to this @var{size}. [EMAIL PROTECTED] is a number which may be followed by one of these +multiplicative suffixes: [EMAIL PROTECTED] [EMAIL PROTECTED] => 1000 (KiloBytes) [EMAIL PROTECTED] => 1024 (KibiBytes) [EMAIL PROTECTED] => 1000*1000 (MegaBytes) [EMAIL PROTECTED] => 1024*1024 (MebiBytes) [EMAIL PROTECTED] example +and so on for @samp{G}, @samp{T}, @samp{P}, @samp{E}, @samp{Z}, and @samp{Y}. + [EMAIL PROTECTED] may also be prefixed by one of the following to adjust +the size of each @var{file} based on their current size: [EMAIL PROTECTED] [EMAIL PROTECTED] => extend by [EMAIL PROTECTED] => reduce by [EMAIL PROTECTED]<} => at most [EMAIL PROTECTED]>} => at least [EMAIL PROTECTED]/} => round down to multiple of [EMAIL PROTECTED] => tound up to multiple of [EMAIL PROTECTED] example + [EMAIL PROTECTED] table + [EMAIL PROTECTED] + + @node Printing text @chapter Printing text diff --git a/man/Makefile.am b/man/Makefile.am index 9076afc..da3309e 100644 --- a/man/Makefile.am +++ b/man/Makefile.am @@ -116,6 +116,7 @@ test.1: $(common_dep) $(srcdir)/test.x ../src/test.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 diff --git a/man/truncate.x b/man/truncate.x new file mode 100644 index 0000000..85524eb --- /dev/null +++ b/man/truncate.x @@ -0,0 +1,6 @@ +[NAME] +truncate \- set the size of a file to the specifed size +[DESCRIPTION] +.\" Add any additional description here +[SEE ALSO] +dd(1), truncate(2), ftruncate(2) diff --git a/src/Makefile.am b/src/Makefile.am index 44d802e..65f209c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 true tty whoami yes \ + test true truncate tty whoami yes \ base64 bin_PROGRAMS = $(OPTIONAL_BIN_PROGS) diff --git a/src/truncate.c b/src/truncate.c new file mode 100644 index 0000000..8fd505b --- /dev/null +++ b/src/truncate.c @@ -0,0 +1,371 @@ +/* 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 "argmatch.h" +#include "error.h" +#include "posixver.h" +#include "quote.h" +#include "safe-read.h" +#include "xstrtol.h" + + +/* The official name of this program (e.g., no `g' prefix). */ +#define PROGRAM_NAME "truncate" + +#define AUTHORS "Padraig Brady" + +static int parse_len (const char *str, off_t * size); +static void usage (int); + +/* The name by which this program was run. */ +char *program_name; + +/* (-c) If true, don't create if not already there. */ +static bool no_create; + +/* (-r) Reference file to use size from */ +static char *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; + +int +main (int argc, char **argv) +{ + bool got_size = false; + rel_mode_t rel_mode = rm_abs; + struct stat sb; + off_t size; + bool blocks = false; + mode_t omode; + int c, errors = 0, fd = -1, oflags; + char *fname; + + initialize_main (&argc, &argv); + 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': + blocks = 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) + usage (EXIT_FAILURE); + rel_mode = rm_rel; + } + if (parse_len (optarg, &size) == -1) + error (EXIT_FAILURE, errno, "%s ", quote (optarg)); + /* Rounding to multiple of 0 is nonsensical */ + if ((rel_mode == rm_rup || rel_mode == rm_rdn) && size == 0) + error (EXIT_FAILURE, EINVAL, "%s ", quote (optarg)); + 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)) + usage (EXIT_FAILURE); + /* blocks without size is not valid */ + if (blocks && !got_size) + usage (EXIT_FAILURE); + /* must specify at least 1 file */ + if (argc < 1) + usage (EXIT_FAILURE); + + if (ref_file) + { + if (stat (ref_file, &sb) != 0) + error (EXIT_FAILURE, errno, "%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) + { + off_t ssize = size; /* specifed size */ + off_t nsize; /* new size */ + + if (fd != -1) + close (fd); + 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 open_errno = errno; + 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, "%s", quote (fname)); + errors++; + } + continue; + } + if ((blocks || rel_mode) && fstat (fd, &sb) != 0) + { + error (0, errno, _("cannot fstat %s"), quote (fname)); + errors++; + continue; + } + if (blocks) + { + size_t blksize = ST_BLKSIZE (sb); + if (size < OFF_T_MIN / blksize || size > OFF_T_MAX / blksize) + { + error (0, EOVERFLOW, " %" PRIdMAX " * %zu", size, blksize); + errors++; + continue; + } + ssize *= blksize; + } + if (rel_mode) + { + uintmax_t 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, EOVERFLOW, "%s", quote (fname)); + errors++; + } + continue; + } + + 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 overflow = ((fsize + ssize - 1) / ssize) * ssize; + if (overflow > OFF_T_MAX) + { + error (0, EOVERFLOW, "%s", quote (fname)); + errors++; + continue; + } + nsize = overflow; + } + else + { + if (ssize > OFF_T_MAX - fsize) + { + error (0, EOVERFLOW, "%s", quote (fname)); + errors++; + continue; + } + 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 ftruncate_errno = errno; + if (fstat (fd, &sb) != 0) + { + error (0, errno, _("cannot fstat %s"), quote (fname)); + errors++; + } + else if (S_ISREG (sb.st_mode) || S_ISDIR (sb.st_mode) + || S_TYPEISSHM (&sb)) + { + error (0, ftruncate_errno, "%s", quote (fname)); + errors++; + } + continue; + } + } + if (fd != -1) + close (fd); + + return errors ? EXIT_FAILURE : EXIT_SUCCESS; +} + +/* 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 (const char *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 : EINVAL; + 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 (_("\ +Set 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); +} diff --git a/tests/misc/Makefile.am b/tests/misc/Makefile.am index 2be132f..f60e303 100644 --- a/tests/misc/Makefile.am +++ b/tests/misc/Makefile.am @@ -113,6 +113,15 @@ TESTS = \ tee \ tee-dash \ test-diag \ + truncate-dangling-symlink \ + truncate-dir-fail \ + truncate-fail-diag \ + truncate-fifo \ + truncate-no-create-missing \ + truncate-overflow \ + truncate-owned-by-other \ + truncate-parameters \ + truncate-relative \ tsort \ tty-eof \ unexpand diff --git a/tests/misc/help-version b/tests/misc/help-version index b54a7d8..7a14129 100755 --- a/tests/misc/help-version +++ b/tests/misc/help-version @@ -132,6 +132,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 diff --git a/tests/misc/truncate-dangling-symlink b/tests/misc/truncate-dangling-symlink new file mode 100755 index 0000000..8935361 --- /dev/null +++ b/tests/misc/truncate-dangling-symlink @@ -0,0 +1,35 @@ +#!/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 + +rm -f truncate-target t-symlink +ln -s truncate-target t-symlink +fail=0 + +truncate -s0 t-symlink || fail=1 + +test -f truncate-target || fail=1 +rm -f truncate-target t-symlink + +exit $fail diff --git a/tests/misc/truncate-dir-fail b/tests/misc/truncate-dir-fail new file mode 100755 index 0000000..a677f4a --- /dev/null +++ b/tests/misc/truncate-dir-fail @@ -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 diff --git a/tests/misc/truncate-fail-diag b/tests/misc/truncate-fail-diag new file mode 100755 index 0000000..7631724 --- /dev/null +++ b/tests/misc/truncate-fail-diag @@ -0,0 +1,52 @@ +#!/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_ + +d1=no-$$ +# Ensure that $d1 doesn't already exist. +[ -e $d1 ] && framework_failure + +fail=0 + +dir=/$d1/such-dir +truncate -s0 $dir > out 2>&1 && fail=1 +cat <<EOF > exp +truncate: \`$dir': 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: \`$dir': Is a directory +EOF +compare out exp || fail=1 + +(exit $fail); exit $fail diff --git a/tests/misc/truncate-fifo b/tests/misc/truncate-fifo new file mode 100755 index 0000000..88308ff --- /dev/null +++ b/tests/misc/truncate-fifo @@ -0,0 +1,38 @@ +#!/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 + +if ! mkfifo fifo; then + # Make an exception of this case -- usually we interpret framework-creation + # failure as a test failure. However, in this case, when running on a SunOS + # system using a disk NFS mounted from OpenBSD, the above fails like this: + # mkfifo: cannot make fifo `fifo-10558': Not owner + skip_test_ 'NOTICE: unable to create test prerequisites' +fi + +fail=0 + +truncate -s0 fifo || fail=1 + +exit $fail diff --git a/tests/misc/truncate-no-create-missing b/tests/misc/truncate-no-create-missing new file mode 100755 index 0000000..183d77e --- /dev/null +++ b/tests/misc/truncate-no-create-missing @@ -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 diff --git a/tests/misc/truncate-overflow b/tests/misc/truncate-overflow new file mode 100755 index 0000000..91bb48e --- /dev/null +++ b/tests/misc/truncate-overflow @@ -0,0 +1,52 @@ +#!/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 + +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 diff --git a/tests/misc/truncate-owned-by-other b/tests/misc/truncate-owned-by-other new file mode 100755 index 0000000..2c78712 --- /dev/null +++ b/tests/misc/truncate-owned-by-other @@ -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 diff --git a/tests/misc/truncate-parameters b/tests/misc/truncate-parameters new file mode 100755 index 0000000..4d2273f --- /dev/null +++ b/tests/misc/truncate-parameters @@ -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 diff --git a/tests/misc/truncate-relative b/tests/misc/truncate-relative new file mode 100755 index 0000000..37f6cfc --- /dev/null +++ b/tests/misc/truncate-relative @@ -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 -- 1.5.3.6