Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > truncate() file function and EOF problem

Reply
Thread Tools

truncate() file function and EOF problem

 
 
Davy
Guest
Posts: n/a
 
      12-24-2009
truncate() file function and EOF problem

Hi all,

I am trying to do some C programming on Linux (exercise in Linux
Programming by example)and encounter a problem of write EOF to file
(the exercise is write a truncate() function).

For example, I have a file with length 20, and I want to truncate it
to 16, my method is use write() to write to offset 16 a EOF char. But
"cat
file" shows the method is wrong. I guess my understanding of EOF maybe
wrong, because EOF is a status signal provided by some function like
read(), but
how to do it?

my wrong code:
//-----------------------
else if (newendpos < endpos) {
/* remove content */
lseek(fd, newendpos, SEEK_SET);
char eof = EOF;
write(fd, &eof, sizeof(char));
}
//-----------------------

Best regards,
Davy
 
Reply With Quote
 
 
 
 
Alan Curry
Guest
Posts: n/a
 
      12-24-2009
In article <(E-Mail Removed)>,
Davy <(E-Mail Removed)> wrote:
>
>Hi all,
>
>I am trying to do some C programming on Linux (exercise in Linux
>Programming by example)and encounter a problem of write EOF to file
>(the exercise is write a truncate() function).


The exercise is misconceived. The only sensible way to do file truncation
(other than "truncate to 0 size") is with the truncate() and ftruncate()
POSIX functions. They have no equivalents in stdio, and there's no way to
build them up from operations that do exist in stdio.

>
>For example, I have a file with length 20, and I want to truncate it
>to 16, my method is use write() to write to offset 16 a EOF char. But


There is no such thing as an EOF character. EOF is a value that indicates the
absence of any character.

>file" shows the method is wrong. I guess my understanding of EOF maybe
>wrong, because EOF is a status signal provided by some function like
>read(), but


Not read(), since read isn't a stdio function. The macro EOF is associated
mainly with stdio functions.

>how to do it?


If you want to shorten a file witout losing the beginning part, you have
truncate() and ftruncate() from <unistd.h>, or you have a disgusting hack:
make a copy of the data you want to keep in the beginning, then open the file
destructively (fopen "w") and rewrite it all.

The other kind of "truncation" (making a file bigger without explicitly
writing all the data between the current end and the new end) may be
accomplished with seek and write, but you will have to write at least 1 byte
at the end to make it happen. Even here "just use the POSIX truncate
function" is still the best answer.

Here's a solution that'll work on almost any Linux system and quite a few
others. It doesn't call any functions that aren't in the C standard.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void truncate(const char *filename, size_t size)
{
char buf[strlen(filename)+100];
sprintf(buf, "perl -e 'truncate \"%s\", %zu'", filename, size);
system(buf);
}

Have we learned anything from this "exercise" in avoiding the right tool for
the job?

Sensible questions about the POSIX standard truncate() and ftruncate() may be
posted to comp.unix.programmer (although there's really not much to know
about them)

--
Alan Curry
 
Reply With Quote
 
 
 
 
Kaz Kylheku
Guest
Posts: n/a
 
      12-24-2009
On 2009-12-24, Davy <(E-Mail Removed)> wrote:
> truncate() file function and EOF problem
>
> Hi all,
>
> I am trying to do some C programming on Linux (exercise in Linux
> Programming by example)and encounter a problem of write EOF to file
> (the exercise is write a truncate() function).


This function cannot be written. Truncating an existing function
is a function that can only be done in the operating system.

The standard C language has no function for doing this.

truncate is a POSIX extension to C.

You cannot write truncate using any combination of functions in C, or
other POSIX functions (not including alternative API's like ftruncate of
course).

Of course, what you can do is copy the contents of the 20 byte file to
another file, retaining only the first 16 bytes. Then you can rename
that file to the original name (rename is even a standard C function).
You may have to remove the original with remove (remove is also a
standard C function). Not every operating system allows a rename to
an existing file.

Even if you take this approach, it's not maximally portable. C
imlementations can add null padding bytes to binary files. So what will
happen is that your truncate-by-copy program might not accurately
truncate files with byte precision.

See, the C standard I/O library can be implemented on operating systems
that don't track the exact length of binary files, but, say, only the
number of disk blocks occupied. So for instance if the block size is
512 bytes, then the creation of a 40 byte binary file actually results
in a 512 byte file; bytes 0-39 are the ones you write, and 40 through
511 are null padding bytes.

On such an implementation, it's likely that text files are either
a different kind of object at the filesystem level, so that they
can have a precise length, or they are given a precise length by
means of an end-of-text sentinel byte (but that has nothing to do with
the EOF number in ISO C; the text stream implementation in C will hide
the existence of such a byte from you).

> For example, I have a file with length 20, and I want to truncate it
> to 16, my method is use write() to write to offset 16 a EOF char.


Writing a byte at offset 16 will not shorten the file.

There is no EOF character; this is just the name of an integer constant
in ISO C, whose value is returned as an error indicator from several
functions.

How the length of a file is represented in ANSI C is up to the
implementation. Text files may in fact use a special character.
This is not possible in binary files, but note that binary files in C
are not required to have a precise length. As mentioned before,
implementations are allowed to add null padding bytes to binary files.

In the POSIX world files (binary or text; there is no representational
difference in this regard) have a length accurate down to the byte.
There is no EOF character. A 17 byte file consists of 17 bytes.
Of course, the filesystem allocates this in some larger block.
But the file object has a length field which reads 17.

Also note that, in POSIX, if you write a byte to offset 16 of an empty
file, you get a 17 byte file, not a 16 byte file. You can prove this by
induction. The base case is this: if you write a byte at position 0 (the
first position) of a file, you get a one byte file---true by inspection.
Inductively, if writing a byte at position k results in a k+1 length
file, it must be the case that writing another byte next to that byte at
position k+1 results in a k+2 length file.

> "cat
> file" shows the method is wrong.


Note that in your OS, you can check the length of the file without
dumping its contents by listing it with ls -l.

> wrong, because EOF is a status signal provided by some function like
> read(), but


The POSIX function read does not use EOF as a signal. It returns 0 when
a file (or other device) does not have any more bytes that can be read,
or a value smaller than the requested size, if the file or device has
fewer remaining bytes than the requested size.

The ISO C fread function also does not use EOF as a signal; it returns
size_t, which is an unsigned type that cannot represent EOF.
 
Reply With Quote
 
jmeisell jmeisell is offline
Junior Member
Join Date: Jan 2010
Posts: 1
 
      01-08-2010
Issue is this: your logfiles have filled up your storage space. You want to delete the old entries and retain the new ones. You have no working space in which to copy a portion of the logfile and then delete the big one. So either the file start or end pointer needs to be moved (depending on how the logfile is formatted). Maybe the source code for truncate () and/or logrotate have some ideas!
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
[Windows] Any way to distinguish ^C Induced EOF from ^Z EOF? Jan Burse Java 67 03-14-2012 12:21 AM
ifstream eof not reporting eof? SpreadTooThin C++ 10 06-15-2007 08:49 AM
getchar function and EOF problem.. broeisi C Programming 13 03-12-2006 08:06 AM
if EOF = -1, can't a valid character == EOF and cause problems? Kobu C Programming 10 03-04-2005 10:40 PM
How to check for EOF (End of file) when using StreamReader to parse text file Sacha Korell ASP .Net 2 09-06-2003 02:59 PM



Advertisments