bug-coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] Rebasing on Padraig's gnulib fallocate module and cleaning up


From: Matěj Cepl
Subject: [PATCH] Rebasing on Padraig's gnulib fallocate module and cleaning up
Date: Sat, 13 Jun 2009 01:50:12 +0200

* 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
 
address@hidden -a
address@hidden --allocate
address@hidden -a
address@hidden --allocate
address@hidden 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 address@hidden
+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"
+
address@hidden@/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 <address@hidden>
 
    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 <address@hidden>
+
+# 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 <address@hidden>
+
+# 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





reply via email to

[Prev in Thread] Current Thread [Next in Thread]