Path: utzoo!attcan!uunet!amdahl!kucharsk
From: kucharsk@uts.amdahl.com (William Kucharski)
Newsgroups: comp.unix.questions
Subject: Re: Set file size in SYSV
Summary: Ah, time to answer the SYSV ftruncate question again...
Keywords: How
Message-ID: <18lG02Em4aQn01@amdahl.uts.amdahl.com>
Date: 13 Aug 89 01:20:07 GMT
References: <708@msa3b.UUCP>
Organization: Amdahl Coup, UTS Products Hen House
Lines: 101

In article <708@msa3b.UUCP>, kevin@msa3b.UUCP (Kevin P. Kleinfelter) writes:
> O.K. I give up.  How do you set the size of a file in SYSV.
> In particular, I want to take a file which is 1000 bytes, and truncate
> it to 500 bytes WITHOUT COPYING IT.

What you're looking for is a SYSV version of the BSD (f)truncate(3) call.

If you're lucky enough to be running a version of SVR3 which implements the
undocumented F_FREESP fcntl, the code below should do nicely...

#include 
#include 
#include 
#include 
#include 

#ifndef NULL
#define NULL	0
#endif

int
ftruncate(fd, length)
int	fd;	/* file descriptor */
off_t	length;	/* length to set file to */
{
	extern	long	lseek();

	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 = (off_t) 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(2), which truncates the file so that it ends at the
		 * position indicated by fl.l_start.
		 *
		 * If you can't find it listed in your  or 
		 * , chances are it isn't implemented in
		 * your kernel.
		 */

		if (fcntl(fd, F_FREESP, &fl) < 0)
			return(-1);
	}

	return(0);
}


int
truncate(path, length)
char	*path;
off_t	length;
{
	int	fd;	/* file descriptor */

	if ((path == NULL) || (*path == NULL)) {
		errno = EINVAL;
		return(-1);
	}

	if ((fd = open(path, O_WRONLY)) < 0)
		return(-1);

	if (ftruncate(fd, length) < 0) {
		(void) close(fd);
		return(-1);
	}

	(void) close(fd);
	return(0);
}
-- 
					William Kucharski

ARPA: kucharsk@uts.amdahl.com
UUCP: ...!{ames,apple,decwrl,sun,uunet}!amdahl!kucharsk

Disclaimer:  The opinions expressed above are my own, and may not agree with
	     those of any other sentient being, not to mention those of my 
	     employer.  So there.