[net.sources] ftruncate library routine for non 4.

georg@unido.UUCP (07/03/85)

I tried to translate the routine ftruncate. The compiler said `name'
is undeclared. I took `name' as third parameter renamed the routine
to ftruncateName and now it works.

Georg Heeg, Informatik V, Univ. Dortmund, West-Germany

georg@unido.uucp

/***** unido:net.sources / axiom!smk /  2:24 am  Jun 23, 1985*/
/*Subject: ftruncate library routine for non 4.2bsd sites*/

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>

/*
 * This mimicks a 4.2BSD system call.  Here, we just make it
 * a lil ol' routine.  It expects a file descriptor, the NEW
 * size to truncate to, and the file name (which we use but 4.2
 * doesn't).  What we do simply is copy size bytes to a temporary
 * file, truncate the original file to zero (which we CAN do), and
 * then copy the second file back to the first.
 *
 * Steve Kramer    Copyright 1/18/84
 * Not to be used for profit without author's permission.
 * May be otherwise redistributed.
 *
 * Third Parameter added by Georg Heeg, Univ. Dortmund 85-07-02
 *
 */
ftruncateName(fr, size, name)
	int fr;
	long size;
	char *name;
{
	extern char     *mktemp();
	struct stat stat_buf;
	char    *tname;
	register int    tf;
	register int s, n;
	long int new_size;
	char buf[BUFSIZ];

	/*
	 * Get a temporary file to copy to.
	 */
	tname = mktemp("/tmp/sXXXXXX");
	close(creat(tname, 0600));
	tf = open(tname, 2);
	if(tf < 0) {
		unlink(tname);
		return (-1);
	}

	/*
	 * Copy the original to the temporary file.  Do it in increments
	 * of BUFSIZ for efficiency.
	 */
	new_size = size;
	lseek(fr, (long)0, 0);
	while(new_size != 0) {
		s = BUFSIZ;
		if(new_size < BUFSIZ)
			s = new_size;
		n = read(fr, buf, s);
		if(n != s) {
			close(tf);
			unlink(tname);
			return(-1);
		}
		n = write(tf, buf, s);
		if(n != s) {
			close(tf);
			unlink(tname);
			return(-1);
		}
		new_size -= s;
	}

	/*
	 * Truncate the original file no that the information is
	 * stuck tightly away in the temporary.
	 */
	lseek(fr, (long)0, 0);
	lseek(tf, (long)0, 0);
	if (fstat (fr, &stat_buf) == 0)
		close(creat(name, stat_buf.st_mode & 0777));
	else
		close(creat(name, 0755));

	/*
	 * Now, copy back.
	 */
	new_size = size;
	while(new_size != 0) {
		s = BUFSIZ;
		if(new_size < BUFSIZ)
			s = new_size;
		n = read(tf, buf, s);
		if(n != s) {
			close (tf);
			unlink(tname);
			return(-1);
		}
		n = write(fr, buf, s);
		if(n != s) {
			close (tf);
			unlink(tname);
			return(-1);
		}
		new_size -= s;
	}

	/*
	 * Close and remove the temporary file.  It's no longer needed.
	 */
	close(tf);
	unlink(tname);
	return(0);
}