Bug#467378: coreutils: Please include a program to truncate files
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 + 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
Bug#467378: coreutils: Please include a program to truncate files
Pádraig Brady [EMAIL PROTECTED] wrote: Subject: [PATCH] Add new program: truncate Nice! Thanks for doing all that. Here's a first pass: - fix a typo s/tound/round/ : [EMAIL PROTECTED] = tound up to multiple of - please indent using only spaces (no TABs) and add this at the end of the file: /* * Local variables: * indent-tabs-mode: nil * End: */ - don't use a bare %s as a format string in a diagnostic; instead, always include some English text to say what failed or was unexpected. E.g., this + if (stat (ref_file, sb) != 0) + error (EXIT_FAILURE, errno, %s, quote (ref_file)); would become this: + if (stat (ref_file, sb) != 0) +error (EXIT_FAILURE, errno, _(cannot access %s), quote (ref_file)); - I noticed this spacing oddity in a couple of places (space after *): +static int parse_len (const char *str, off_t * size); You can fix that by adding this line to ~/.indent.pro: -Toff_t and rerunning GNU indent: - Remove trailing blanks in these format strings: (I see that it makes diagnostics a little more symmetric, but all other tools emit no space before the : strerror(error) string, so it's better for consistency. Another alternative: use quotearg_colon rather than just quote, since it's delimited on the right by a :, and most of the time, the quote()-supplied `...' delimiters are not useful) + 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)); - run make syntax-check: = The po-check failure would have told you that you need to add the file name, src/truncate.c to po/POTFILES.in. = Then, the sc_prohibit_safe_read_without_use failure would have told you to remove the unnecessary `#include safe-read.h' line. - Rather than relying on EOVERFLOW (which, as you note, may not apply), how about just saying you can't use that file because its size appears to be negative? + /* overflow is the only reason I can think +this would ever go negative for the above types */ + error (0, EOVERFLOW, %s, quote (fname)); E.g., error (0, 0, %s has unusable, apparently negative size, quote (fname)); - I've made a point of avoiding prototypes for static functions (defining usage before main, etc.), in most src/*.c files, so for consistency, it'd be nice, but with just two simple functions here, it's not a big deal. - when you amend that commit, please leave an empty line between the first line of the log message and all the remaining ones. Otherwise, some git tools end up using a *very* long (entire log concatenated) subject line.
Bug#467378: coreutils: Please include a program to truncate files
Paul Eggert [EMAIL PROTECTED] wrote: Jim Meyering [EMAIL PROTECTED] writes: If you don't mind truncating first, how about this? true /var/spool/whatever/foo dd bs=1 seek=2G of=/var/spool/whatever/foo /dev/null Also, the latter command works even if the former command is omitted. That is, by itself, that invocation of dd resizes /var/spool/whatever/foo to 2 GiB, discarding or extending the file as needed, which is what the original request asked for. Hi Paul, That depends on your definition of works. If you don't mind retaining the first 2GiB of content in a preexisting output file, then it works fine. But the initial truncation is required if you want to be sure it's a big sparse file with nothing but NUL bytes. Try this: echo foo k dd bs=1 seek=2G of=k /dev/null head -c4 k and note that it prints foo\n. -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of unsubscribe. Trouble? Contact [EMAIL PROTECTED]
Bug#467378: coreutils: Please include a program to truncate files
Jim Meyering wrote: Paul Eggert [EMAIL PROTECTED] wrote: Jim Meyering [EMAIL PROTECTED] writes: If you don't mind truncating first, how about this? true /var/spool/whatever/foo dd bs=1 seek=2G of=/var/spool/whatever/foo /dev/null Also, the latter command works even if the former command is omitted. That is, by itself, that invocation of dd resizes /var/spool/whatever/foo to 2 GiB, discarding or extending the file as needed, which is what the original request asked for. Hi Paul, That depends on your definition of works. If you don't mind retaining the first 2GiB of content in a preexisting output file, then it works fine. But the initial truncation is required if you want to be sure it's a big sparse file with nothing but NUL bytes. Try this: echo foo k dd bs=1 seek=2G of=k /dev/null head -c4 k and note that it prints foo\n. That's how I would expect it to work, and is how I'm currently implementing it. Given the name truncate I think this operation should be obvious to users. Pádraig. p.s. I'm going to push the timeout and truncate utils to util-linux-ng/misc-utils/ via Karel Zak within the next couple of days.
Bug#467378: coreutils: Please include a program to truncate files
Russell Coker wrote: On Tuesday 26 February 2008 21:03, Pádraig Brady [EMAIL PROTECTED] wrote: That depends on your definition of works. If you don't mind retaining the first 2GiB of content in a preexisting output file, then it works fine. But the initial truncation is required if you want to be sure it's a big sparse file with nothing but NUL bytes. Try this: echo foo k dd bs=1 seek=2G of=k /dev/null head -c4 k and note that it prints foo\n. That's how I would expect it to work, and is how I'm currently implementing it. Given the name truncate I think this operation should be obvious to users. What exactly do you mean by how I expect it to work, do you mean reducing the file size or removing all content and extending it to size N? The latter is not truncation, it's replacement. Exactly. I expect it to work as per Jim's example above. I.E. truncate rather than replace. Pádraig.
Bug#467378: coreutils: Please include a program to truncate files
On Tuesday 26 February 2008 21:03, Pádraig Brady [EMAIL PROTECTED] wrote: That depends on your definition of works. If you don't mind retaining the first 2GiB of content in a preexisting output file, then it works fine. But the initial truncation is required if you want to be sure it's a big sparse file with nothing but NUL bytes. Try this: echo foo k dd bs=1 seek=2G of=k /dev/null head -c4 k and note that it prints foo\n. That's how I would expect it to work, and is how I'm currently implementing it. Given the name truncate I think this operation should be obvious to users. What exactly do you mean by how I expect it to work, do you mean reducing the file size or removing all content and extending it to size N? The latter is not truncation, it's replacement.
Bug#467378: coreutils: Please include a program to truncate files
Jim Meyering wrote: Russell Coker [EMAIL PROTECTED] wrote: If I have a file that is 2G in size but wish to discard the last 1G of data then there seems to be no program available to do this. I think it would be ideal to have a program as part of coreutils that allows you to resize a file. If the new length is longer than the old length then it would either write zeros to the end or extend the file (with a hole) via the truncate() system call according to the wish of the user. If the new length is shorter then it would just call truncate(). I would be happy to contribute the code for this. This will require some discussion with upstream, but it seemed best to start the discussion here. That would be nice. If the mythical miscutils project were more concrete, I'd say this tool belongs there. I'm planning to push code to this very project very soon. As previously discussed I'm going to push this to the misc-utils directory of the util-linux-ng project. We can split that directory as a new project in future if ever deemed necessary. I'm not 100% sure it should be written in C, especially since I wrote it in Perl: And here's a shell version: http://www.pixelbeat.org/scripts/truncate I'm probably going to (re)write all miscutils in C though. Russell, if you want to write a C version and do the usual complete job (update coreutils.texi, NEWS, etc. and add tests), I'd probably go for it. The only reason not to would be if miscutils is now viable, and even then... One advantage of using C/coreutils/gnulib is that you'd get k, M, G, ... byte-count suffixes for free. Note I already got util-linux-ng using the coreutils suffixes, so this should be a good fit. Russell if you want to push code to me it's fine, but I was going to work on this tool anyway. thanks, Pádraig.
Bug#467378: coreutils: Please include a program to truncate files
Russell Coker wrote: Bob Proulx wrote: There is always 'head'. head --bytes=1024m That doesn't do what I want at all. I knew you wouldn't be happy with it. :-) I did mention that it copied the data twice for example. But it was an obvious program to mention because it could be used for the stated purpose. Yes, particularly when a program named truncate(1) would be a good complement to truncate(2). I see that Jim has come through with a perl program to do just that. Bob -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of unsubscribe. Trouble? Contact [EMAIL PROTECTED]
Bug#467378: coreutils: Please include a program to truncate files
Russell Coker [EMAIL PROTECTED] wrote: On Monday 25 February 2008 21:29, Pádraig Brady [EMAIL PROTECTED] wrote: Russell if you want to push code to me it's fine, but I was going to work on this tool anyway. I don't have any code (yet). If you are going to work on it then I would be more than happy to leave it to you. I would be very interested in testing it, but my coding time is unfortunately quite limited at the moment and I'd prefer to focus on the things that don't have someone else about to work on them. One non-obvious feature request that I have is for a truncate on a non-existant file to create it (similar to the way touch is commonly used to create files). The obvious question is then Why?
Bug#467378: coreutils: Please include a program to truncate files
On Monday 25 February 2008 21:29, Pádraig Brady [EMAIL PROTECTED] wrote: Russell if you want to push code to me it's fine, but I was going to work on this tool anyway. I don't have any code (yet). If you are going to work on it then I would be more than happy to leave it to you. I would be very interested in testing it, but my coding time is unfortunately quite limited at the moment and I'd prefer to focus on the things that don't have someone else about to work on them. One non-obvious feature request that I have is for a truncate on a non-existant file to create it (similar to the way touch is commonly used to create files).
Bug#467378: coreutils: Please include a program to truncate files
On Mon, Feb 25, 2008 at 11:28:41AM +1100, Russell Coker wrote: I would be happy to contribute the code for this. This will require some discussion with upstream, but it seemed best to start the discussion here. No, I'd start it upstream and try to solicit input from a wider base than the debian BTS. Mike Stone -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of unsubscribe. Trouble? Contact [EMAIL PROTECTED]
Bug#467378: coreutils: Please include a program to truncate files
On Monday 25 February 2008 22:11, Jim Meyering [EMAIL PROTECTED] wrote: One non-obvious feature request that I have is for a truncate on a non-existant file to create it (similar to the way touch is commonly used to create files). The obvious question is then Why? One specific case is where I want a large sparse file to exist - which may have been created previously. So truncate 2g /var/spool/whatever/foo would make that file exist and be 2g in size regardless of whether it was there before. Of course writing shell code to check for the existence of a file is not difficult, but the people who wrote touch(1) seemed to think this is a good idea. -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of unsubscribe. Trouble? Contact [EMAIL PROTECTED]
Bug#467378: coreutils: Please include a program to truncate files
Russell Coker [EMAIL PROTECTED] wrote: On Monday 25 February 2008 22:11, Jim Meyering [EMAIL PROTECTED] wrote: One non-obvious feature request that I have is for a truncate on a non-existant file to create it (similar to the way touch is commonly used to create files). The obvious question is then Why? One specific case is where I want a large sparse file to exist - which may have been created previously. So truncate 2g /var/spool/whatever/foo would make that file exist and be 2g in size regardless of whether it was there before. If you don't mind truncating first, how about this? true /var/spool/whatever/foo dd bs=1 seek=2G of=/var/spool/whatever/foo /dev/null -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of unsubscribe. Trouble? Contact [EMAIL PROTECTED]
Bug#467378: coreutils: Please include a program to truncate files
Jim Meyering [EMAIL PROTECTED] writes: If you don't mind truncating first, how about this? true /var/spool/whatever/foo dd bs=1 seek=2G of=/var/spool/whatever/foo /dev/null Also, the latter command works even if the former command is omitted. That is, by itself, that invocation of dd resizes /var/spool/whatever/foo to 2 GiB, discarding or extending the file as needed, which is what the original request asked for. -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of unsubscribe. Trouble? Contact [EMAIL PROTECTED]
Bug#467378: coreutils: Please include a program to truncate files
On Tuesday 26 February 2008 10:08, Paul Eggert [EMAIL PROTECTED] wrote: dd bs=1 seek=2G of=/var/spool/whatever/foo /dev/null Also, the latter command works even if the former command is omitted. That is, by itself, that invocation of dd resizes /var/spool/whatever/foo to 2 GiB, discarding or extending the file as needed, which is what the original request asked for. Yes, that does it. -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of unsubscribe. Trouble? Contact [EMAIL PROTECTED]
Bug#467378: coreutils: Please include a program to truncate files
Package: coreutils Version: 5.97-5.3 Severity: wishlist If I have a file that is 2G in size but wish to discard the last 1G of data then there seems to be no program available to do this. I think it would be ideal to have a program as part of coreutils that allows you to resize a file. If the new length is longer than the old length then it would either write zeros to the end or extend the file (with a hole) via the truncate() system call according to the wish of the user. If the new length is shorter then it would just call truncate(). I would be happy to contribute the code for this. This will require some discussion with upstream, but it seemed best to start the discussion here. -- System Information: Debian Release: 4.0 APT prefers stable APT policy: (500, 'stable') Architecture: i386 (i686) Shell: /bin/sh linked to /bin/bash Kernel: Linux 2.6.18-5-686 Locale: LANG=en_AU.UTF-8, LC_CTYPE=en_AU.UTF-8 (charmap=ANSI_X3.4-1968) (ignored: LC_ALL set to C) Versions of packages coreutils depends on: ii libacl12.2.41-1 Access control list shared library ii libc6 2.3.6.ds1-13etch5 GNU C Library: Shared libraries ii libselinux12.0.15-2.etch1SELinux shared libraries coreutils recommends no packages. -- no debconf information -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of unsubscribe. Trouble? Contact [EMAIL PROTECTED]
Bug#467378: coreutils: Please include a program to truncate files
Russell Coker wrote: If I have a file that is 2G in size but wish to discard the last 1G of data then there seems to be no program available to do this. There is always 'head'. head --bytes=1024m But that does still perform 1G x 2 of I/O. Let me guess. You have a partially downloaded image with a corrupted part at the end that you want to modify so that the download can resume from a known good state? I think it would be ideal to have a program as part of coreutils that allows you to resize a file. If the new length is longer than the old length then it would either write zeros to the end or extend the file (with a hole) via the truncate() system call according to the wish of the user. If the new length is shorter then it would just call truncate(). I think the functionality is interesting but don't know where the best place to locate it. The dd program actually does seem like a good place for this to go. I think I would favor putting it there. But otherwise a completely new program with general file handling features might not be a bad idea. Many of the existing programs already have a large amount of bloat and it is better not to keep dumping the kitchen sink of things into them. I would be happy to contribute the code for this. This will require some discussion with upstream, but it seemed best to start the discussion here. Actually the general consensus has been that Debian should try to avoid unique downstream patches as much as possible. Therefore I suggest that this discussion be taken upstream. Let me encourage you to discuss this upstream on the [EMAIL PROTECTED] mailing list. For upstream contribution the FSF will require a copyright assignment. If you can submit one then I am sure that patches and contributions would be both appreciated and seriously considered. But if you are unable to do that then it is much better simply to suggest ideas and to let someone else with a copyright assignment actually submit the code patches. I am sure you know this already but worst case is that someone submits an absolutely perfect bit of code that does exactly what is needed but without a copyright assignment it can't be used. It might even be necessary to even code things less well in order to avoid conflict with the submitted code which can't be used. It's a pain but recent court cases have shown that this diligence is needed to keep the clear trail so that free software can remain free. It is really more important now than ever. As I said I am sure that you already know all of that but I felt compelled to say it anyway. Bob -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of unsubscribe. Trouble? Contact [EMAIL PROTECTED]
Bug#467378: coreutils: Please include a program to truncate files
On Monday 25 February 2008 12:26, Bob Proulx [EMAIL PROTECTED] wrote: There is always 'head'. head --bytes=1024m That doesn't do what I want at all. It creates a new file, which is an entirely different thing, it uses temporary file space (in the above example it won't work unless there is 1G of free space), and it can't deal with holes and therefore won't work on sparse files for that reason alone. Also consider the case of a multi-terabyte sparse file, even if you have spare disk space the time taken to copy the file will be immense. Let me guess. You have a partially downloaded image with a corrupted part at the end that you want to modify so that the download can resume from a known good state? No. One thing I want to do is to resize Xen images. Another thing I want to do is to create large sparse files. I think the functionality is interesting but don't know where the best place to locate it. The dd program actually does seem like a good place for this to go. dd copies data, it doesn't adjust file sizes. Doing this correctly requires three system calls, open(), ftruncate(), and close() and no functionality that is currently in dd (which calls ftruncate() only for the purpose of setting the file size to the output size and only in some situations). dd can create large sparse files with the seek= option, but that's awkward, not obvious to casual users, and generally inconvenient. I think I would favor putting it there. But otherwise a completely new program with general file handling features might not be a bad idea. Many of the existing programs already have a large amount of bloat and it is better not to keep dumping the kitchen sink of things into them. Yes, particularly when a program named truncate(1) would be a good complement to truncate(2). -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of unsubscribe. Trouble? Contact [EMAIL PROTECTED]
Bug#467378: coreutils: Please include a program to truncate files
Russell Coker [EMAIL PROTECTED] wrote: If I have a file that is 2G in size but wish to discard the last 1G of data then there seems to be no program available to do this. I think it would be ideal to have a program as part of coreutils that allows you to resize a file. If the new length is longer than the old length then it would either write zeros to the end or extend the file (with a hole) via the truncate() system call according to the wish of the user. If the new length is shorter then it would just call truncate(). I would be happy to contribute the code for this. This will require some discussion with upstream, but it seemed best to start the discussion here. That would be nice. If the mythical miscutils project were more concrete, I'd say this tool belongs there. I'm not 100% sure it should be written in C, especially since I wrote it in Perl: $ truncate --help Usage: truncate [OPTIONS] FILE ... Modify FILE(s) in place, removing part from the end of each of them. As a safety measure, if you want to remove more than 10% of a FILE, then you must specify the --force option. OPTIONS: --bytes=-N remove N bytes from the end of each FILE --bytes=N truncate each FILE to have size N --force don't fail when asked to remove too much --help display this help and exit --version output version information and exit I used --bytes= to align with head and tail. If I were to do something official with this code, I would consider adding aliases, e.g., --from-end=N remove N bytes from the end of each FILE --to-size=N truncate each FILE to have size N Russell, if you want to write a C version and do the usual complete job (update coreutils.texi, NEWS, etc. and add tests), I'd probably go for it. The only reason not to would be if miscutils is now viable, and even then... One advantage of using C/coreutils/gnulib is that you'd get k, M, G, ... byte-count suffixes for free. Here's the script: #!/usr/bin/perl -w # Truncate file(s) in place by removing some bytes from the end. # Copyright (C) 2002, 2007-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 Jim Meyering use strict; use Getopt::Long; use File::stat; (my $VERSION = '$Revision: 1.13 $ ') =~ tr/[0-9].//cd; (my $ME = $0) =~ s|.*/||; # use File::Coda; # http://meyering.net/code/Coda/ END { defined fileno STDOUT or return; close STDOUT and return; warn $ME: failed to close standard output: $!\n; $? ||= 1; } my $debug = 0; # The maximum percentage size decrease. # If you try to truncate more than this amount, this program # will fail, unless you override with --force. But see below... my $max_percent_size_decrease = 10; # Even if the above percentage is exceeded, don't fail # if the number of bytes is smaller than this number. my $min_bytes_to_fail = 10; sub usage ($) { my ($exit_code) = @_; my $STREAM = ($exit_code == 0 ? *STDOUT : *STDERR); if ($exit_code != 0) { print $STREAM Try `$ME --help' for more information.\n; } else { my $p = $max_percent_size_decrease; print $STREAM EOF; Usage: $ME [OPTIONS] FILE ... Modify FILE(s) in place, removing part from the end of each of them. As a safety measure, if you want to remove more than $p% of a FILE, then you must specify the --force option. OPTIONS: --bytes=-N remove N bytes from the end of each FILE --bytes=N truncate each FILE to have size N --force don't fail when asked to remove too much --help display this help and exit --version output version information and exit EOF } #' exit $exit_code; } { my $n_bytes; my $force; GetOptions ( 'bytes=i' = \$n_bytes, force = \$force, debug = \$debug, help = sub { usage 0 }, version = sub { print $ME version $VERSION\n; exit }, ) or usage 1; # Make sure we have at least one non-option argument. @ARGV 1 and (warn $ME: missing FILE argument\n), usage 1; defined $n_bytes or (warn $ME: you must specify --bytes=N\n), usage 1; my $fail = 0; foreach my $arg (@ARGV) { open F, '+', $arg or (warn $ME: failed to open $arg for read/write\n), $fail = 1, next; my $st = stat ($arg) or (warn $ME: failed to stat $arg\n), $fail = 1, next; my $size = $st-size; my $new_size;