FreeBSD Bugzilla – Attachment 150961 Details for
Bug 196273
truncate(1) adding posix_fallocate(2) support to /usr/bin/truncate -- diff with unit tests attached
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
patch -- you need to run one svn cp before you run patch
allocate_diff (text/plain), 20.73 KB, created by
Kirk Russell
on 2014-12-25 20:21:35 UTC
(
hide
)
Description:
patch -- you need to run one svn cp before you run patch
Filename:
MIME Type:
Creator:
Kirk Russell
Created:
2014-12-25 20:21:35 UTC
Size:
20.73 KB
patch
obsolete
>Index: tests/Makefile >=================================================================== >--- tests/Makefile (revision 267309) >+++ tests/Makefile (working copy) >@@ -1,6 +1,14 @@ > # $FreeBSD$ > > TESTSDIR= ${TESTSBASE}/usr.bin/truncate >-ATF_TESTS_SH= truncate_test >+ATF_TESTS_SH= allocate_test truncate_test >+ATF_TESTS_C= sparse_test >+CLEANFILES+= allocate_test.sh truncate_test.sh > >+allocate_test.sh: base_test.func allocate_test.func >+ cat ${.ALLSRC} > ${.TARGET} >+ >+truncate_test.sh: base_test.func truncate_test.func >+ cat ${.ALLSRC} > ${.TARGET} >+ > .include <bsd.test.mk> >Index: tests/allocate_test.func >=================================================================== >--- tests/allocate_test.func (revision 0) >+++ tests/allocate_test.func (working copy) >@@ -0,0 +1,21 @@ >+atf_init_test_cases() >+{ >+ TRUNC="truncate -a" >+ >+ atf_add_test_case illegal_option >+ atf_add_test_case illegal_size >+ atf_add_test_case too_large_size >+ atf_add_test_case opt_c >+ atf_add_test_case opt_rs >+ atf_add_test_case no_files >+ atf_add_test_case bad_refer >+ atf_add_test_case bad_truncate >+ atf_add_test_case cannot_open >+ atf_add_test_case new_absolute_grow >+ atf_add_test_case new_absolute_shrink >+ atf_add_test_case new_relative_grow >+ atf_add_test_case new_relative_shrink >+ atf_add_test_case reference >+ atf_add_test_case new_zero >+ atf_add_test_case negative >+} >Index: tests/base_test.func >=================================================================== >--- tests/base_test.func (revision 267309) >+++ tests/base_test.func (working copy) >@@ -57,8 +57,8 @@ > _custom_create_file creat > _custom_create_file print "${1}" > _custom_create_file print \ >- "usage: truncate [-c] -s [+|-]size[K|k|M|m|G|g|T|t] file ..." >- _custom_create_file print " truncate [-c] -r rfile file ..." >+ "usage: truncate [-ac] -s [+|-]size[K|k|M|m|G|g|T|t|P|p|E|e] file ..." >+ _custom_create_file print " truncate [-ac] -r rfile file ..." > } > > atf_test_case illegal_option >@@ -72,7 +72,7 @@ > create_stderr_usage_file 'truncate: illegal option -- 7' > > # We expect the error message, with no new files. >- atf_check -s not-exit:0 -e file:stderr.txt truncate -7 -s0 output.txt >+ atf_check -s not-exit:0 -e file:stderr.txt ${TRUNC} -7 -s0 output.txt > [ ! -e output.txt ] || atf_fail "output.txt should not exist" > } > >@@ -87,7 +87,7 @@ > create_stderr_file "truncate: invalid size argument \`+1L'" > > # We expect the error message, with no new files. >- atf_check -s not-exit:0 -e file:stderr.txt truncate -s+1L output.txt >+ atf_check -s not-exit:0 -e file:stderr.txt ${TRUNC} -s+1L output.txt > [ ! -e output.txt ] || atf_fail "output.txt should not exist" > } > >@@ -103,7 +103,7 @@ > > # We expect the error message, with no new files. > atf_check -s not-exit:0 -e file:stderr.txt \ >- truncate -s8388608t output.txt >+ ${TRUNC} -s8388608t output.txt > [ ! -e output.txt ] || atf_fail "output.txt should not exist" > } > >@@ -115,10 +115,10 @@ > opt_c_body() > { > # No new files and truncate returns 0 as if this is a success. >- atf_check truncate -c -s 0 doesnotexist.txt >+ atf_check ${TRUNC} -c -s 0 doesnotexist.txt > [ ! -e output.txt ] || atf_fail "doesnotexist.txt should not exist" > > reference >- atf_check truncate -c -r reference doesnotexist.txt >+ atf_check ${TRUNC} -c -r reference doesnotexist.txt > [ ! -e output.txt ] || atf_fail "doesnotexist.txt should not exist" > > create_stderr_file >@@ -125,7 +125,7 @@ > > # The existing file will be altered by truncate. > > exists.txt >- atf_check -e file:stderr.txt truncate -c -s1 exists.txt >+ atf_check -e file:stderr.txt ${TRUNC} -c -s1 exists.txt > [ -s exists.txt ] || atf_fail "exists.txt be larger than zero bytes" > } > >@@ -141,7 +141,7 @@ > > # Force an error due to the use of both -s and -r. > > afile >- atf_check -s not-exit:0 -e file:stderr.txt truncate -s0 -r afile afile >+ atf_check -s not-exit:0 -e file:stderr.txt ${TRUNC} -s0 -r afile afile > } > > atf_test_case no_files >@@ -155,7 +155,7 @@ > create_stderr_usage_file > > # A list of files must be present on the command line. >- atf_check -s not-exit:0 -e file:stderr.txt truncate -s1 >+ atf_check -s not-exit:0 -e file:stderr.txt ${TRUNC} -s1 > } > > atf_test_case bad_refer >@@ -169,7 +169,7 @@ > create_stderr_file "truncate: afile: No such file or directory" > > # The reference file must exist before you try to use it. >- atf_check -s not-exit:0 -e file:stderr.txt truncate -r afile afile >+ atf_check -s not-exit:0 -e file:stderr.txt ${TRUNC} -r afile afile > [ ! -e afile ] || atf_fail "afile should not exist" > } > >@@ -185,9 +185,9 @@ > > # Trying to get the ftruncate() call to return -1. > > exists.txt >- atf_check chflags uimmutable exists.txt >+ chflags schg exists.txt || atf_skip "expected immutable flag support" > >- atf_check -s not-exit:0 -e file:stderr.txt truncate -s1 exists.txt >+ atf_check -s not-exit:0 -e file:stderr.txt ${TRUNC} -s1 exists.txt > } > bad_truncate_cleanup() > { >@@ -204,7 +204,7 @@ > create_stderr_file > > # Create a new file and grow it to 1024 bytes. >- atf_check -s exit:0 -e file:stderr.txt truncate -s1k output.txt >+ atf_check -s exit:0 -e file:stderr.txt ${TRUNC} -s1k output.txt > atf_check -s exit:1 cmp -s output.txt /dev/zero > eval $(stat -s output.txt) > [ ${st_size} -eq 1024 ] || atf_fail "expected file size of 1k" >@@ -212,7 +212,7 @@ > create_stderr_file > > # Grow the existing file to 1M. We are using absolute sizes. >- atf_check -s exit:0 -e file:stderr.txt truncate -c -s1M output.txt >+ atf_check -s exit:0 -e file:stderr.txt ${TRUNC} -c -s1M output.txt > atf_check -s exit:1 cmp -s output.txt /dev/zero > eval $(stat -s output.txt) > [ ${st_size} -eq 1048576 ] || atf_fail "expected file size of 1m" >@@ -229,7 +229,7 @@ > create_stderr_file > > # Create a new file and grow it to 1048576 bytes. >- atf_check -s exit:0 -e file:stderr.txt truncate -s1M output.txt >+ atf_check -s exit:0 -e file:stderr.txt ${TRUNC} -s1M output.txt > atf_check -s exit:1 cmp -s output.txt /dev/zero > eval $(stat -s output.txt) > [ ${st_size} -eq 1048576 ] || atf_fail "expected file size of 1m" >@@ -237,7 +237,7 @@ > create_stderr_file > > # Shrink the existing file to 1k. We are using absolute sizes. >- atf_check -s exit:0 -e file:stderr.txt truncate -s1k output.txt >+ atf_check -s exit:0 -e file:stderr.txt ${TRUNC} -s1k output.txt > atf_check -s exit:1 cmp -s output.txt /dev/zero > eval $(stat -s output.txt) > [ ${st_size} -eq 1024 ] || atf_fail "expected file size of 1k" >@@ -254,7 +254,7 @@ > create_stderr_file > > # Create a new file and grow it to 1024 bytes. >- atf_check -s exit:0 -e file:stderr.txt truncate -s+1k output.txt >+ atf_check -s exit:0 -e file:stderr.txt ${TRUNC} -s+1k output.txt > atf_check -s exit:1 cmp -s output.txt /dev/zero > eval $(stat -s output.txt) > [ ${st_size} -eq 1024 ] || atf_fail "expected file size of 1k" >@@ -262,7 +262,7 @@ > create_stderr_file > > # Grow the existing file to 1M. We are using relative sizes. >- atf_check -s exit:0 -e file:stderr.txt truncate -s+1047552 output.txt >+ atf_check -s exit:0 -e file:stderr.txt ${TRUNC} -s+1047552 output.txt > atf_check -s exit:1 cmp -s output.txt /dev/zero > eval $(stat -s output.txt) > [ ${st_size} -eq 1048576 ] || atf_fail "expected file size of 1m" >@@ -279,7 +279,7 @@ > create_stderr_file > > # Create a new file and grow it to 1049600 bytes. >- atf_check -s exit:0 -e file:stderr.txt truncate -s+1049600 output.txt >+ atf_check -s exit:0 -e file:stderr.txt ${TRUNC} -s+1049600 output.txt > atf_check -s exit:1 cmp -s output.txt /dev/zero > eval $(stat -s output.txt) > [ ${st_size} -eq 1049600 ] || atf_fail "expected file size of 1m" >@@ -287,7 +287,7 @@ > create_stderr_file > > # Shrink the existing file to 1k. We are using relative sizes. >- atf_check -s exit:0 -e file:stderr.txt truncate -s-1M output.txt >+ atf_check -s exit:0 -e file:stderr.txt ${TRUNC} -s-1M output.txt > atf_check -s exit:1 cmp -s output.txt /dev/zero > eval $(stat -s output.txt) > [ ${st_size} -eq 1024 ] || atf_fail "expected file size of 1k" >@@ -312,7 +312,7 @@ > > # Create a new file and grow it to 1024 bytes. > atf_check -s not-exit:0 -e file:stderr.txt \ >- truncate -c -s1k before 0000 after >+ ${TRUNC} -c -s1k before 0000 after > eval $(stat -s before) > [ ${st_size} -eq 1024 ] || atf_fail "expected file size of 1k" > eval $(stat -s after) >@@ -336,7 +336,7 @@ > create_stderr_file > > # Create a new file and grow it to 4 bytes. >- atf_check -e file:stderr.txt truncate -r reference afile >+ atf_check -e file:stderr.txt ${TRUNC} -r reference afile > eval $(stat -s afile) > [ ${st_size} -eq 4 ] || atf_fail "new file should also be 4 bytes" > } >@@ -351,12 +351,12 @@ > create_stderr_file > > # Create a new file and grow it to zero bytes. >- atf_check -s exit:0 -e file:stderr.txt truncate -s0 output.txt >+ atf_check -s exit:0 -e file:stderr.txt ${TRUNC} -s0 output.txt > eval $(stat -s output.txt) > [ ${st_size} -eq 0 ] || atf_fail "expected file size of zero" > > # Pretend to grow the file. >- atf_check -s exit:0 -e file:stderr.txt truncate -s+0 output.txt >+ atf_check -s exit:0 -e file:stderr.txt ${TRUNC} -s+0 output.txt > eval $(stat -s output.txt) > [ ${st_size} -eq 0 ] || atf_fail "expected file size of zero" > } >@@ -376,27 +376,7 @@ > create_stderr_file > > # Create a new file and do a 100 byte negative relative shrink. >- atf_check -e file:stderr.txt truncate -s-100 afile >+ atf_check -e file:stderr.txt ${TRUNC} -s-100 afile > eval $(stat -s afile) > [ ${st_size} -eq 0 ] || atf_fail "new file should now be zero bytes" > } >- >-atf_init_test_cases() >-{ >- atf_add_test_case illegal_option >- atf_add_test_case illegal_size >- atf_add_test_case too_large_size >- atf_add_test_case opt_c >- atf_add_test_case opt_rs >- atf_add_test_case no_files >- atf_add_test_case bad_refer >- atf_add_test_case bad_truncate >- atf_add_test_case cannot_open >- atf_add_test_case new_absolute_grow >- atf_add_test_case new_absolute_shrink >- atf_add_test_case new_relative_grow >- atf_add_test_case new_relative_shrink >- atf_add_test_case reference >- atf_add_test_case new_zero >- atf_add_test_case negative >-} >Index: tests/sparse_test.c >=================================================================== >--- tests/sparse_test.c (revision 0) >+++ tests/sparse_test.c (working copy) >@@ -0,0 +1,198 @@ >+/*- >+ * Copyright 2014, Google Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * >+ * * Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * * 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. >+ * * Neither the name of Google nor the names of its contributors may >+ * be used to endorse or promote products derived from this software >+ * without specific prior written permission. >+ * >+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" >+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE >+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE >+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF >+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS >+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN >+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) >+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE >+ * POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#include <sys/cdefs.h> >+__FBSDID("$FreeBSD$"); >+ >+#include <sys/types.h> >+#include <sys/wait.h> >+ >+#include <assert.h> >+#include <errno.h> >+#include <fcntl.h> >+#include <spawn.h> >+#include <unistd.h> >+ >+#include <atf-c.h> >+ >+/* Create child process and block for successful termination. */ >+void >+run_truncate(const char *const *argv) >+{ >+ int status; >+ pid_t child; >+ extern char **environ; >+ >+ ATF_REQUIRE(posix_spawnp(&child, argv[0], NULL, NULL, >+ (char *const *)argv, environ) == 0); >+ ATF_REQUIRE(waitpid(child, &status, 0) == child); >+ ATF_REQUIRE(WIFEXITED(status)); >+ ATF_REQUIRE(WEXITSTATUS(status) == 0); >+} >+ >+/* Return the number of bytes used for holes or data in this file. */ >+off_t >+get_size(const char *path, int whence) >+{ >+ int fd, opposite; >+ off_t hstart, hend, total; >+ >+ assert(whence == SEEK_HOLE || whence == SEEK_DATA); >+ >+ /* We expect the file to exist and to have SEEK_HOLE support. */ >+ ATF_REQUIRE((fd = open(path, O_RDONLY)) != -1); >+ if (fpathconf(fd, _PC_MIN_HOLE_SIZE) <= 0) >+ atf_tc_skip("Require _PC_MIN_HOLE_SIZE support."); >+ >+ hstart = hend = total = 0; >+ opposite = (whence == SEEK_DATA) ? SEEK_HOLE : SEEK_DATA; >+ for (;;) { >+ if ((hstart = lseek(fd, hend, whence)) == -1) { >+ ATF_REQUIRE(errno == ENXIO); >+ break; >+ } >+ if ((hend = lseek(fd, hstart, opposite)) == -1) { >+ ATF_REQUIRE(errno == ENXIO); >+ ATF_REQUIRE((hend = lseek(fd, 0, SEEK_END)) != -1); >+ } >+ total += hend - hstart; >+ } >+ >+ ATF_REQUIRE(close(fd) == 0); >+ return (total); >+} >+ >+/* Return the number of bytes used for holes in this sparse file. */ >+off_t >+get_hole_size(const char *path) >+{ >+ >+ return (get_size(path, SEEK_HOLE)); >+} >+ >+/* Return the number of bytes actually allocated in this file. */ >+off_t >+get_allocated_size(const char *path) >+{ >+ >+ return (get_size(path, SEEK_DATA)); >+} >+ >+ATF_TC_WITHOUT_HEAD(default_absolute_file_is_sparse); >+ATF_TC_BODY(default_absolute_file_is_sparse, tc) >+{ >+ off_t hole, data, expected; >+ const char *filename = "afile"; >+ const char *const cmd[] = { "truncate", "-s", "5m", filename, NULL }; >+ >+ run_truncate(cmd); >+ >+ expected = 5242880; >+ hole = get_hole_size(filename); >+ data = get_allocated_size(filename); >+ >+ if (hole + data != expected) >+ atf_tc_fail("Expected size of %jd, but got %jd + %jd.", >+ expected, hole, data); >+ else if (hole <= 0) >+ atf_tc_fail("Expected a sparse file, but got %jd of data.", >+ data); >+} >+ >+ATF_TC_WITHOUT_HEAD(default_relative_file_is_sparse); >+ATF_TC_BODY(default_relative_file_is_sparse, tc) >+{ >+ off_t hole, data, expected; >+ const char *const before[] = { "truncate", "-s", "1", "afile", NULL }; >+ const char *const after[] = { "truncate", "-cs", "+5242879", "afile", >+ NULL }; >+ >+ run_truncate(before); >+ run_truncate(after); >+ >+ expected = 5242880; >+ hole = get_hole_size(before[3]); >+ data = get_allocated_size(before[3]); >+ >+ if (hole + data != expected) >+ atf_tc_fail("Expected size of %jd, but got %jd + %jd.", >+ expected, hole, data); >+ else if (hole <= 0) >+ atf_tc_fail("Expected a sparse file, but got %jd of data.", >+ data); >+} >+ >+ATF_TC_WITHOUT_HEAD(allocate_absolute_file); >+ATF_TC_BODY(allocate_absolute_file, tc) >+{ >+ off_t hole, data, expected; >+ const char *filename = "afile"; >+ const char *const cmd[] = { "truncate", "-as", "5m", filename, NULL }; >+ >+ run_truncate(cmd); >+ >+ expected = 5242880; >+ hole = get_hole_size(filename); >+ data = get_allocated_size(filename); >+ >+ if (hole != 0 || data != expected) >+ atf_tc_fail("Expected size of %jd, but got %jd + %jd.", >+ expected, hole, data); >+} >+ >+ATF_TC_WITHOUT_HEAD(allocate_relative_file); >+ATF_TC_BODY(allocate_relative_file, tc) >+{ >+ off_t hole, data, expected; >+ const char *filename = "afile"; >+ const char *const before[] = { "truncate", "-s1m", filename, NULL }; >+ const char *const after[] = { "truncate", "-acs+4m", filename, NULL }; >+ >+ run_truncate(before); >+ run_truncate(after); >+ >+ expected = 5242880; >+ hole = get_hole_size(filename); >+ data = get_allocated_size(filename); >+ >+ if (hole + data != expected) >+ atf_tc_fail("Expected size of %jd, but got %jd + %jd.", >+ expected, hole, data); >+ else if (hole <= 0 || data < 4194304) >+ atf_tc_fail("got hole=%jd and data=%jd.", hole, data); >+} >+ >+ATF_TP_ADD_TCS(tp) >+{ >+ ATF_TP_ADD_TC(tp, default_absolute_file_is_sparse); >+ ATF_TP_ADD_TC(tp, default_relative_file_is_sparse); >+ ATF_TP_ADD_TC(tp, allocate_absolute_file); >+ ATF_TP_ADD_TC(tp, allocate_relative_file); >+ return atf_no_error(); >+} >Index: tests/truncate_test.func >=================================================================== >--- tests/truncate_test.func (revision 0) >+++ tests/truncate_test.func (working copy) >@@ -0,0 +1,21 @@ >+atf_init_test_cases() >+{ >+ TRUNC="truncate" >+ >+ atf_add_test_case illegal_option >+ atf_add_test_case illegal_size >+ atf_add_test_case too_large_size >+ atf_add_test_case opt_c >+ atf_add_test_case opt_rs >+ atf_add_test_case no_files >+ atf_add_test_case bad_refer >+ atf_add_test_case bad_truncate >+ atf_add_test_case cannot_open >+ atf_add_test_case new_absolute_grow >+ atf_add_test_case new_absolute_shrink >+ atf_add_test_case new_relative_grow >+ atf_add_test_case new_relative_shrink >+ atf_add_test_case reference >+ atf_add_test_case new_zero >+ atf_add_test_case negative >+} >Index: truncate.1 >=================================================================== >--- truncate.1 (revision 268016) >+++ truncate.1 (working copy) >@@ -33,6 +33,7 @@ > .Nd truncate or extend the length of files > .Sh SYNOPSIS > .Nm >+.Op Fl a > .Op Fl c > .Bk -words > .Fl s Xo >@@ -39,12 +40,13 @@ > .Sm off > .Op Cm + | - > .Ar size >-.Op Cm K | k | M | m | G | g | T | t >+.Op Cm K | k | M | m | G | g | T | t | P | p | E | e > .Sm on > .Xc > .Ek > .Ar > .Nm >+.Op Fl a > .Op Fl c > .Bk -words > .Fl r Ar rfile >@@ -57,6 +59,10 @@ > .Pp > The following options are available: > .Bl -tag -width indent >+.It Fl a >+When increasing the size of a file, >+allocate the required disk storage instead of using a >+.Qq hole. > .It Fl c > Do not create files if they do not exist. > The >@@ -71,7 +77,7 @@ > .Sm off > .Op Cm + | - > .Ar size >-.Op Cm K | k | M | m | G | g | T | t >+.Op Cm K | k | M | m | G | g | T | t | P | p | E | e > .Sm on > .Xc > If the >@@ -119,13 +125,11 @@ > .Pp > Note that, > while truncating a file causes space on disk to be freed, >-extending a file does not cause space to be allocated. >-To extend a file and actually allocate the space, >-it is necessary to explicitly write data to it, >-using (for example) the shell's >-.Ql >> >-redirection syntax, or >-.Xr dd 1 . >+extending a file does not cause space to be allocated on disk. >+To extend a file and actually allocate the disk space, >+it is necessary to to specify the >+.Fl a >+option. > .Sh EXIT STATUS > .Ex -std > If the operation fails for an argument, >@@ -132,9 +136,24 @@ > .Nm > will issue a diagnostic > and continue processing the remaining arguments. >+.Sh EXAMPLES >+The following commands: >+.Dl rm -f rz35.dsk >+.Dl truncate -s 852m rz35.dsk >+creates a sparse file that can be used as an emulated disk image. >+Future writes to the sparse file could fail to the a lack of free space >+on the base file system storage. >+.Pp >+The following commands: >+.Dl rm -f rz28.dsk >+.Dl truncate -a -s 2100m rz28.dsk >+creates a file that can be used as an emulated disk image. >+The required disk space should have been reserved on the storage media. >+We do not expect future writes to fail due to lack of free space on the >+base file system storage. > .Sh SEE ALSO >-.Xr dd 1 , >-.Xr touch 1 , >+.Xr lseek 2 , >+.Xr posix_fallocate 2 , > .Xr truncate 2 > .Sh STANDARDS > The >Index: truncate.c >=================================================================== >--- truncate.c (revision 267309) >+++ truncate.c (working copy) >@@ -45,6 +45,7 @@ > static void usage(void); > > static int no_create; >+static int do_allocate; > static int do_relative; > static int do_refer; > static int got_size; >@@ -63,8 +64,11 @@ > rsize = tsize = sz = 0; > error = 0; > rname = NULL; >- while ((ch = getopt(argc, argv, "cr:s:")) != -1) >+ while ((ch = getopt(argc, argv, "acr:s:")) != -1) > switch (ch) { >+ case 'a': >+ do_allocate = 1; >+ break; > case 'c': > no_create = 1; > break; >@@ -122,12 +126,12 @@ > } > continue; > } >+ if (fstat(fd, &sb) == -1) { >+ warn("%s", fname); >+ error++; >+ continue; >+ } > if (do_relative) { >- if (fstat(fd, &sb) == -1) { >- warn("%s", fname); >- error++; >- continue; >- } > oflow = sb.st_size + rsize; > if (oflow < (sb.st_size + rsize)) { > errno = EFBIG; >@@ -135,12 +139,19 @@ > error++; > continue; > } >- tsize = oflow; >+ tsize = oflow < 0 ? 0 : oflow; >+ } else { >+ rsize = tsize - sb.st_size; > } >- if (tsize < 0) >- tsize = 0; > >- if (ftruncate(fd, tsize) == -1) { >+ /* >+ * Use posix_fallocate() when we need to grow the file with >+ * the required on-disk storage. In all other cases, use >+ * ftruncate(). >+ */ >+ if (((do_allocate && rsize > 0) ? >+ posix_fallocate(fd, sb.st_size, rsize) : >+ ftruncate(fd, tsize)) == -1) { > warn("%s", fname); > error++; > continue; >@@ -155,8 +166,8 @@ > static void > usage(void) > { >- fprintf(stderr, "%s\n%s\n", >- "usage: truncate [-c] -s [+|-]size[K|k|M|m|G|g|T|t] file ...", >- " truncate [-c] -r rfile file ..."); >+ fprintf(stderr, "usage: %s\n %s\n", >+ "truncate [-ac] -s [+|-]size[K|k|M|m|G|g|T|t|P|p|E|e] file ...", >+ "truncate [-ac] -r rfile file ..."); > exit(EXIT_FAILURE); > }
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 196273
: 150961