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.