How do I truncate a file?

How do I truncate a file?

The BSD function ftruncate() sets the length of a file.
(But not all versions behave identically.) Other Unix variants
all seem to support some version of truncation as well.

For systems which support the ftruncate function, there are
three known behaviours:

BSD 4.2 - Ultrix, SGI, LynxOS
- truncation doesn't grow file
- truncation doesn't move file pointer


BSD 4.3 - SunOS, Solaris, OSF/1, HP/UX, Amiga
- truncation can grow file
- truncation doesn't move file pointer

Cray - UniCOS 7, UniCOS 8
- truncation doesn't grow file
- truncation changes file pointer

Other systems come in four varieties:

F_CHSIZE - Only SCO
- some systems define F_CHSIZE but don't support it
- behaves like BSD 4.3

F_FREESP - Only Interative Unix
- some systems (eg. Interactive Unix) define F_FREESP but
don't support it
- behaves like BSD 4.3

chsize() - QNX and SCO
- some systems (eg. Interactive Unix) have chsize() but
don't support it
- behaves like BSD 4.3

nothing - no known systems
- there will be systems that don't support truncate at all


Moderator's Note: I grabbed the functions below a few years back.
I can no longer identify the original author.
S. Spencer Sun has also
contributed a version for F_FREESP.

functions for each non-native ftruncate follow

/* ftruncate emulations that work on some System V's.
This file is in the public domain. */

#include
#include

#ifdef F_CHSIZE
int
ftruncate (fd, length)
int fd;
off_t length;
{
return fcntl (fd, F_CHSIZE, length);
}
#else
#ifdef F_FREESP
/* The following function was written by
kucharsk@Solbourne.com (William Kucharski) */

#include
#include
#include

int
ftruncate (fd, length)
int fd;
off_t length;
{
struct flock fl;
struct stat filebuf;

if (fstat (fd, &filebuf) < 0)
return -1;

if (filebuf.st_size < length)
{
/* Extend file length. */
if (lseek (fd, (length - 1), SEEK_SET) < 0)
return -1;

/* Write a "0" byte. */
if (write (fd, "", 1) != 1)
return -1;
}
else
{
/* Truncate length. */
fl.l_whence = 0;
fl.l_len = 0;
fl.l_start = length;
fl.l_type = F_WRLCK; /* Write lock on file space. */

/* This relies on the UNDOCUMENTED F_FREESP argument to
fcntl, which truncates the file so that it ends at the
position indicated by fl.l_start.
Will minor miracles never cease? */
if (fcntl (fd, F_FREESP, &fl) < 0)
return -1;
}

return 0;
}
#else
int
ftruncate (fd, length)
int fd;
off_t length;
{
return chsize (fd, length);
}
#endif
#endif



Home FAQ