* man/mkfile.8.xml: temporarily example of manpage for mkfile * src/mkfile: script to use truncate to emulate mkfile(8) * src/truncate.c: add option -a to user posix_fallocate before creating a file * tests/misc/truncate-fallocate: test truncate fallocate functionality * tests/misc/truncate-mkfile: test mkfile(8)
Signed-off-by: Matej Cepl <[email protected]> --- doc/coreutils.texi | 9 ++++ man/mkfile.8.xml | 94 +++++++++++++++++++++++++++++++++++++++++ src/mkfile | 81 +++++++++++++++++++++++++++++++++++ src/truncate.c | 48 +++++++++++++++------ tests/Makefile.am | 1 + tests/misc/truncate-fallocate | 57 +++++++++++++++++++++++++ tests/misc/truncate-mkfile | 72 +++++++++++++++++++++++++++++++ 7 files changed, 349 insertions(+), 13 deletions(-) create mode 100644 man/mkfile.8.xml create mode 100755 src/mkfile create mode 100755 tests/misc/truncate-fallocate create mode 100755 tests/misc/truncate-mkfile diff --git a/doc/coreutils.texi b/doc/coreutils.texi index 2c1fae5..d318e8d 100644 --- a/doc/coreutils.texi +++ b/doc/coreutils.texi @@ -10491,6 +10491,15 @@ The program accepts the following options. Also see @ref{Common options}. @table @samp +...@item -a +...@itemx --fallocate +...@opindex -a +...@opindex --fallocate +When extending file use system call @command{fallocate}, which +ensures that disk space is allocated for @var{FILE}. 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.8.xml b/man/mkfile.8.xml new file mode 100644 index 0000000..ba3d0b4 --- /dev/null +++ b/man/mkfile.8.xml @@ -0,0 +1,94 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" + "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"> +<!-- lifted from troff+man by doclifter --> +<refentry id='mkfile8'> +<!-- Copyright (c) 2007 --> +<!-- MATEJ Cepl. All rights reserved. --> +<!-- Copyright (c) 2001, 2003, 2004 --> +<!-- HATANOU Tomomi. All rights reserved. --> + +<!-- Redistribution and use in source and binary forms, with or without --> +<!-- modification, are permitted provided that the following conditions --> +<!-- are met: --> +<!-- 1. Redistributions of source code must retain the above copyright --> +<!-- notice, this list of conditions and the following disclaimer. --> +<!-- 2. Redistributions in binary form must reproduce the above copyright --> +<!-- notice, this list of conditions and the following disclaimer in the --> +<!-- documentation and/or other materials provided with the distribution. --> +<!-- @(#)mkfile.8 1.3 (HATANOU Tomomi) 2004/01/21 --> + +<info> + <date>2007-09-03</date> + <author>MatÄj Cepl <[email protected]></author> +</info> +<refmeta> +<refentrytitle>MKFILE</refentrytitle> +<manvolnum>8</manvolnum> +<refmiscinfo class='date'>2007-09-03</refmiscinfo> +<refmiscinfo class='source'>GNU</refmiscinfo> +<refmiscinfo class='manual'>GNU</refmiscinfo> +</refmeta> +<refnamediv id='name'> +<refname>mkfile</refname> +<refpurpose>create a file</refpurpose> +</refnamediv> +<!-- body begins here --> +<refsynopsisdiv id='synopsis'> +<cmdsynopsis> + <command>mkfile</command> <arg choice='opt'>-n </arg> + <arg choice='opt'>-v </arg> + <arg choice='plain'><replaceable>size</replaceable></arg> + <group choice='plain'><arg choice='plain'><replaceable>e</replaceable></arg><arg choice='plain'><replaceable>p</replaceable></arg><arg choice='plain'><replaceable>t</replaceable></arg><arg choice='plain'><replaceable>g</replaceable></arg><arg choice='plain'><replaceable>m</replaceable></arg><arg choice='plain'><replaceable>k</replaceable></arg><arg choice='plain'><replaceable>b</replaceable></arg><arg choice='plain'><replaceable>filename</replaceable></arg></group> +</cmdsynopsis> +</refsynopsisdiv> + + +<refsect1 id='description'><title>DESCRIPTION</title> +<para>creates a file named +<emphasis remap='I'>filename</emphasis> +that are suitable for use as NFS-mounted swap areas, +or as local swap areas. +The file is padded with zeros by default. +The default +<emphasis remap='I'>size</emphasis> +is in bytes, but it can be flagged as exabytes, petabytes, terabytes, gigabytes, megabytes, kilobytes, or blocks, with the e, p, t, g, m, k, or b suffixes, respectively.</para> +</refsect1> + +<refsect1 id='options'><title>OPTIONS</title> +<para>The following options are available:</para> +<variablelist remap='TP'> + <varlistentry> + <term><option>-n</option></term> + <listitem> +<para>Create an empty file. +The size is noted, but disk blocks are not allocated +until data is written to them.</para> + </listitem> + </varlistentry> + <varlistentry> + <term><option>-v</option></term> + <listitem> +<para>Verbose. +Report the names and sizes of created files.</para> + + </listitem> + </varlistentry> +</variablelist> +</refsect1> + +<refsect1 id='see_also'><title>SEE ALSO</title> +<para><citerefentry><refentrytitle>swapon</refentrytitle><manvolnum>8</manvolnum></citerefentry>, +<citerefentry><refentrytitle>swapon</refentrytitle><manvolnum>8</manvolnum></citerefentry>,</para> +</refsect1> + +<refsect1 id='bugs'><title>BUGS</title> +<para>Option +<option>-n</option> +is not tested well.</para> +</refsect1> + +<refsect1 id='history'><title>HISTORY</title> +<para>A command first appeared in SunOS.</para> +</refsect1> +</refentry> diff --git a/src/mkfile b/src/mkfile new file mode 100755 index 0000000..0c020ad --- /dev/null +++ b/src/mkfile @@ -0,0 +1,81 @@ +#!/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. + +SEE ALSO +swapon(8) + +HISTORY +A command first appeared in SunOS. + +Report truncate bugs to [email protected] +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" + +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 c6f12b7..6eaeac0 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 posix_fallocate by MatÄj Cepl <[email protected]> This is backwards compatible with the FreeBSD utility, but is more flexible wrt the size specifications and the use of long options, @@ -50,10 +51,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'}, + {"fallocate", no_argument, NULL, 'a'}, {"reference", required_argument, NULL, 'r'}, {"size", required_argument, NULL, 's'}, {GETOPT_HELP_OPTION_DECL}, @@ -71,13 +75,12 @@ typedef enum 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) +parse_len (char const *str, off_t * size) { enum strtol_error e; 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)) + if (e == LONGINT_OK && !(OFF_T_MIN <= tmp_size && tmp_size <= OFF_T_MAX)) e = LONGINT_OVERFLOW; if (e == LONGINT_OK) @@ -114,6 +117,9 @@ reads as zero bytes.\n\ Mandatory arguments to long options are mandatory for short options too.\n\ "), stdout); fputs (_("\ + -a, --fallocate when extending a file use fallocate.\n\ +"), stdout); + fputs (_("\ -c, --no-create do not create any files\n\ "), stdout); fputs (_("\ @@ -161,8 +167,7 @@ do_ftruncate (int fd, char const *fname, off_t ssize, rel_mode_t rel_mode) error (0, 0, _("overflow in %" PRIdMAX " * %" PRIdMAX " byte blocks for file %s"), - (intmax_t) ssize, (intmax_t) blksize, - quote (fname)); + (intmax_t) ssize, (intmax_t) blksize, quote (fname)); return 1; } ssize *= blksize; @@ -210,7 +215,7 @@ do_ftruncate (int fd, char const *fname, off_t ssize, rel_mode_t rel_mode) } else { - if (ssize > OFF_T_MAX - (off_t)fsize) + if (ssize > OFF_T_MAX - (off_t) fsize) { error (0, 0, _("overflow extending size of file %s"), quote (fname)); @@ -224,6 +229,20 @@ do_ftruncate (int fd, char const *fname, off_t ssize, rel_mode_t rel_mode) if (nsize < 0) nsize = 0; + /* posix_fallocate() is available since glibc 2.1.94. + * fallocate is in Linux since kernel 2.6.23. + */ + if (fallocate_mode) + { + int ret = 0; + if ((ret = posix_fallocate (fd, 0, nsize)) != 0) + { + error (0, ret, _("cannot fallocate 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 @@ -255,7 +274,7 @@ int main (int argc, char **argv) { bool got_size = false; - off_t size IF_LINT (= 0); + off_t size IF_LINT ( = 0); rel_mode_t rel_mode = rm_abs; mode_t omode; int c, errors = 0, fd = -1, oflags; @@ -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 07e9473..d6e6426 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -231,6 +231,7 @@ TESTS = \ 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..bce4083 --- /dev/null +++ b/tests/misc/truncate-fallocate @@ -0,0 +1,57 @@ +#!/bin/sh + +# Copyright (C) 2008 Free Software Foundation, Inc. +# Written by MatÄj Cepl <[email protected]> + +# 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 + +if test "$VERBOSE" = yes; then + set -x + truncate --version +fi + +. $srcdir/lang-default +. $srcdir/test-lib.sh +skip_if_root_ + +trap EXIT rm -f $TESTFILE + +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..90531a6 --- /dev/null +++ b/tests/misc/truncate-mkfile @@ -0,0 +1,72 @@ +#!/bin/sh +# make sure truncate gives reasonable diagnostics + +# Copyright (C) 2008 Free Software Foundation, Inc. +# Written by MatÄj Cepl <[email protected]> + +# 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 + +if test "$VERBOSE" = yes; then + set -x + truncate --version +fi + +. $srcdir/lang-default +. $srcdir/test-lib.sh +skip_if_root_ + +trap EXIT rm -f $TESTFILE + +fail=0 + +[ -f $TESTFILE ] && rm -f $TESTFILE +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 +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.0.6 _______________________________________________ Bug-coreutils mailing list [email protected] http://lists.gnu.org/mailman/listinfo/bug-coreutils
