Bug#467378: coreutils: Please include a program to truncate files

2008-03-26 Thread Pádraig Brady
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

2008-03-26 Thread Jim Meyering
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

2008-02-26 Thread Jim Meyering
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

2008-02-26 Thread Pádraig Brady
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

2008-02-26 Thread Pádraig Brady
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

2008-02-26 Thread Russell Coker
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

2008-02-25 Thread Pádraig Brady
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

2008-02-25 Thread Bob Proulx
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

2008-02-25 Thread Jim Meyering
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

2008-02-25 Thread Russell Coker
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

2008-02-25 Thread Michael Stone

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

2008-02-25 Thread Russell Coker
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

2008-02-25 Thread Jim Meyering
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

2008-02-25 Thread Paul Eggert
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

2008-02-25 Thread Russell Coker
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

2008-02-24 Thread Russell Coker
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

2008-02-24 Thread Bob Proulx
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

2008-02-24 Thread Russell Coker
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

2008-02-24 Thread Jim Meyering
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;