* src/truncate.c: fixing parameters of fallocate call to fit the gnulib module. New option is called --allocate (nobody is interested in the implementation of the option). Doesn't use posix_fallocate but fallocate directly (relying on gnulib). * src/mkfile.in: script version of mkfile from other Unix systems using truncate (@bindir@ is filled in). * configure.ac: add necessary changes (by ./bootstrap) * doc/coreutils.texi: explanation of the -a feature of truncate together with its benefits. * man/mkfile.x: template for coreutils-style manpage * tests/Makefile.am: run new tests * tests/misc/truncate-fallocate: tests for -a option of truncate * tests/misc/truncate-mkfile: tests for mkfile --- configure.ac | 1 + doc/coreutils.texi | 11 ++++++ man/mkfile.x | 9 +++++ src/mkfile.in | 77 +++++++++++++++++++++++++++++++++++++++++ src/truncate.c | 36 +++++++++++++++---- tests/Makefile.am | 4 ++- tests/misc/truncate-fallocate | 61 ++++++++++++++++++++++++++++++++ tests/misc/truncate-mkfile | 76 ++++++++++++++++++++++++++++++++++++++++ 8 files changed, 267 insertions(+), 8 deletions(-) create mode 100644 man/mkfile.x create mode 100755 src/mkfile.in create mode 100755 tests/misc/truncate-fallocate create mode 100755 tests/misc/truncate-mkfile
diff --git a/configure.ac b/configure.ac index 4eb640e..90e589f 100644 --- a/configure.ac +++ b/configure.ac @@ -417,6 +417,7 @@ AC_CONFIG_FILES( man/Makefile po/Makefile.in src/Makefile + src/mkfile tests/Makefile gnulib-tests/Makefile ) diff --git a/doc/coreutils.texi b/doc/coreutils.texi index 155858b..afb817c 100644 --- a/doc/coreutils.texi +++ b/doc/coreutils.texi @@ -10565,6 +10565,17 @@ The program accepts the following options. Also see @ref{Common options}. @table @samp +...@item -a +...@itemx --allocate +...@opindex -a +...@opindex --allocate +...@opindex extents +When extending file use system call @command{fallocate}, which +ensures that disk space is allocated for @var{file} and ensure +that allocated blocks are contiguous. After a successful +call subsequent writes in the specified files are guaranteed +not to fail because of lack of disk space. + @item -c @itemx --no-create @opindex -c diff --git a/man/mkfile.x b/man/mkfile.x new file mode 100644 index 0000000..bf1655b --- /dev/null +++ b/man/mkfile.x @@ -0,0 +1,9 @@ +[NAME] +mkfile \- create a new file +[DESCRIPTION] +.\" Add any additional description here +[SEE ALSO] +swapon(8), dd(1), truncate(2), ftruncate(2) + +[HISTORY] +A command first appeared in SunOS. diff --git a/src/mkfile.in b/src/mkfile.in new file mode 100755 index 0000000..6f4ad48 --- /dev/null +++ b/src/mkfile.in @@ -0,0 +1,77 @@ +#!/bin/bash +# the original manpage is on +# http://developer.apple.com/documentation/Darwin/Reference\ +# /ManPages/man8/mkfile.8.html +# and +# http://docs.sun.com/app/docs/doc/819-2240/6n4htdnbv?a=view +SPARSE=0 +VERBOSE=0 +OPTFLAGS="" +VERSION="1.0" +COMMANDNAME="$0" + +function usage() { + cat - <<\EOF +Usage: mkfile OPTION... SIZE FILE +Create a new FILE of the specified size (possibly with sparse file) that is +suitable for use as NFS-mounted swap areas, or as local swap areas. + +A FILE argument that does exist is overwritten. + +Mandatory arguments to long options are mandatory for short options too. + -n create a sparse file (the size is noted, but disk blocks are not + allocated until data is written to them) + -v be verbose (report the size of the file created) + -h display this help and exit + +SIZE is a number which may be followed by one of the following suffixes: +KB 1000, K 1024, MB 1000*1000, M 1024*1024, and so on for G, T, P, E, Z, Y. + +SIZE may also be prefixed by one of the following modifying characters: +`+' extend by, `-' reduce by, `<' at most, `>' at least, +`/' round down to multiple of, `%' round up to multiple of. + +Report truncate bugs to bug-coreutils@gnu.org +GNU coreutils home page: <http://www.gnu.org/software/coreutils/> +General help using GNU software: <http://www.gnu.org/gethelp/> +Report mkfile translation bugs to <http://translationproject.org/team/> +EOF +} + +while getopts ":vnh" OPTION ; do + case $OPTION in + v) + VERBOSE=1 + ;; + n) + SPARSE=1 + ;; + h) + usage + exit 0 + ;; + *) + usage + exit 1 + ;; + esac +done + +if [ $SPARSE -eq 0 ] ; then + OPTFLAGS=$OPTFLAGS"-a " +fi + +shift $(($OPTIND - 1)) +SIZE="$1" + +shift 1 +FILE="$1" + +...@bindir@/truncate $OPTFLAGS $SIZE $FILE +# should I use http://tinyurl.com/amkydq ??? +/usr/bin/truncate $OPTFLAGS $SIZE $FILE +RET=$? + +if [ $RET -eq 0 ] && [ $VERBOSE -eq 1 ] ; then + echo >&2 "Created file $FILE of the size "$(stat --format="%s" $FILE)"." +fi diff --git a/src/truncate.c b/src/truncate.c index 31b3aa6..1bf72c2 100644 --- a/src/truncate.c +++ b/src/truncate.c @@ -15,6 +15,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ /* Written by Pádraig Brady + Extended to use fallocate by MatÄj Cepl <mc...@redhat.com> This is backwards compatible with the FreeBSD utility, but is more flexible wrt the size specifications and the use of long options, @@ -35,6 +36,7 @@ #include "posixver.h" #include "quote.h" #include "xstrtol.h" +#include "fallocate.h" /* The official name of this program (e.g., no `g' prefix). */ #define PROGRAM_NAME "truncate" @@ -50,10 +52,13 @@ static bool block_mode; /* (-r) Reference file to use size from */ static char const *ref_file; -static struct option const longopts[] = -{ +/* (-a) Use fallocate to create a file */ +static bool fallocate_mode; + +static struct option const longopts[] = { {"no-create", no_argument, NULL, 'c'}, {"io-blocks", no_argument, NULL, 'o'}, + {"allocate", no_argument, NULL, 'a'}, {"reference", required_argument, NULL, 'r'}, {"size", required_argument, NULL, 's'}, {GETOPT_HELP_OPTION_DECL}, @@ -77,7 +82,7 @@ parse_len (char const *str, off_t *size) intmax_t tmp_size; e = xstrtoimax (str, NULL, 10, &tmp_size, "EgGkKmMPtTYZ0"); if (e == LONGINT_OK - && !(OFF_T_MIN <= tmp_size && tmp_size <= OFF_T_MAX)) + && !(OFF_T_MIN <= tmp_size && tmp_size <= OFF_T_MAX)) e = LONGINT_OVERFLOW; if (e == LONGINT_OK) @@ -114,6 +119,9 @@ reads as zero bytes.\n\ Mandatory arguments to long options are mandatory for short options too.\n\ "), stdout); fputs (_("\ + -a, --allocate when extending a file use fallocate.\n\ +"), stdout); + fputs (_("\ -c, --no-create do not create any files\n\ "), stdout); fputs (_("\ @@ -224,6 +232,17 @@ do_ftruncate (int fd, char const *fname, off_t ssize, rel_mode_t rel_mode) if (nsize < 0) nsize = 0; + if (fallocate_mode) + { + int ret = 0; + if ((ret = fallocate (fd, 0, 0, nsize)) != 0) + { + error (0, ret, _("cannot allocate size %d for file %s"), nsize, + quote (fname)); + return 1; + } + } + if (ftruncate (fd, nsize) == -1) /* note updates mtime & ctime */ { /* Complain only when ftruncate fails on a regular file, a @@ -269,10 +288,14 @@ main (int argc, char **argv) atexit (close_stdout); - while ((c = getopt_long (argc, argv, "cor:s:", longopts, NULL)) != -1) + while ((c = getopt_long (argc, argv, "acor:s:", longopts, NULL)) != -1) { switch (c) { + case 'a': + fallocate_mode = true; + break; + case 'c': no_create = true; break; @@ -330,9 +353,9 @@ main (int argc, char **argv) got_size = true; break; - case_GETOPT_HELP_CHAR; + case_GETOPT_HELP_CHAR; - case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS); + case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS); default: usage (EXIT_FAILURE); @@ -402,7 +425,6 @@ main (int argc, char **argv) continue; } - if (fd != -1) { errors += do_ftruncate (fd, fname, size, rel_mode); diff --git a/tests/Makefile.am b/tests/Makefile.am index 2405ce4..c4781e3 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -234,10 +234,12 @@ TESTS = \ misc/truncate-dir-fail \ misc/truncate-fail-diag \ misc/truncate-fifo \ - misc/truncate-no-create-missing \ + misc/truncate-mkfile \ + misc/truncate-no-create-missing \ misc/truncate-overflow \ misc/truncate-parameters \ misc/truncate-relative \ + misc/truncate-fallocate \ misc/tsort \ misc/tty-eof \ misc/unexpand \ diff --git a/tests/misc/truncate-fallocate b/tests/misc/truncate-fallocate new file mode 100755 index 0000000..f1adab0 --- /dev/null +++ b/tests/misc/truncate-fallocate @@ -0,0 +1,61 @@ +#!/bin/sh + +# Copyright (C) 2008 Free Software Foundation, Inc. +# Written by MatÄj Cepl <mc...@redhat.com> + +# 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/>. + +export LANG=C +TESTSIZE=200k +TESTFILE=testfile + +cleartestfile () { + rm -f $TESTFILE +} + +if test "$VERBOSE" = yes; then + set -x + truncate --version +fi + +. $srcdir/lang-default +. $srcdir/test-lib.sh +skip_if_root_ + +trap cleartestfile EXIT + +fail=0 + +[ -f $TESTFILE ] && rm -f $TESTFILE +truncate -a -s $TESTSIZE $TESTFILE || fail=1 + +if [ ! $fail -eq 1 ] ; then + size=$(stat --format="%s" $TESTFILE) + if [ "$(($size - 204800))" -gt 1024 ] ; then + echo "Cannot create file $TESTFILE of $TESTSIZE size." + fail=1 + fi +fi + +[ -f $TESTFILE ] && rm -f $TESTFILE +if [ ! $fail -eq 1 ] ; then + truncate -a $TESTFILE && fail=1 +fi + +[ -f $TESTFILE ] && rm -f $TESTFILE +if [ ! $fail -eq 1 ] ; then + truncate -s && fail=1 +fi + +Exit $fail diff --git a/tests/misc/truncate-mkfile b/tests/misc/truncate-mkfile new file mode 100755 index 0000000..e482d64 --- /dev/null +++ b/tests/misc/truncate-mkfile @@ -0,0 +1,76 @@ +#!/bin/sh +# make sure truncate gives reasonable diagnostics + +# Copyright (C) 2008 Free Software Foundation, Inc. +# Written by MatÄj Cepl <mc...@redhat.com> + +# 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/>. + +export LANG=C +TESTSIZE=200k +TESTFILE=testfile + +cleartestfile () { + rm -f $TESTFILE +} + +if test "$VERBOSE" = yes; then + set -x + truncate --version +fi + +. $srcdir/lang-default +. $srcdir/test-lib.sh +skip_if_root_ + +trap cleartestfile EXIT + +fail=0 + +[ -f $TESTFILE ] && rm -f $TESTFILE +sh mkfile $TESTSIZE $TESTFILE || fail=1 + +if [ ! $fail -eq 1 ] ; then + size=$(stat --format="%s" $TESTFILE) + if [ "$(($size - 204800))" -gt 1024 ] ; then + echo "Cannot create file $TESTFILE of $TESTSIZE size." + fail=1 + fi +fi + +# Sparse file creation +[ -f $TESTFILE ] && rm -f $TESTFILE +sh mkfile -n $TESTSIZE $TESTFILE || fail=1 + +if [ ! $fail -eq 1 ] ; then + size=$(stat --format="%s" $TESTFILE) + blocks=$(stat --format="%s" $TESTFILE) + if [ "$(($size - 204800))" -gt 1024 ] ; then + echo "Cannot create file $TESTFILE of $TESTSIZE size." + fail=1 + fi +fi + +# Non-sensical option +[ -f $TESTFILE ] && rm -f $TESTFILE +if [ ! $fail -eq 1 ] ; then + truncate -s $TESTFILE && fail=1 +fi + +[ -f $TESTFILE ] && rm -f $TESTFILE +if [ ! $fail -eq 1 ] ; then + truncate -s && fail=1 +fi + +Exit $fail -- 1.6.2.2 _______________________________________________ Bug-coreutils mailing list Bug-coreutils@gnu.org http://lists.gnu.org/mailman/listinfo/bug-coreutils