[comp.unix.wizards] How can a file be truncated on System V??

kemnitz@mitisft.Convergent.COM (Gregory Kemnitz) (04/29/89)

There is an ULTRIX (I think) function

ftruncate(fd, length)
int fd, length;

that takes a file pointed at by fd and truncates the file to length bytes.
The file descriptor may be only open for writing (which rules out dumping
length bytes to a temporary file and copying them back, which involves
read access).  How would one implement such a function in System V (I have
tried the obvious ways, ie fcntl(), etc).  Do you have to write something
to edit the inode to do this??

--Greg

bill@twwells.uucp (T. William Wells) (04/30/89)

In article <651@mitisft.Convergent.COM> kemnitz@mitisft.Convergent.COM (Gregory Kemnitz) writes:
: There is an ULTRIX (I think) function
:
: ftruncate(fd, length)
: int fd, length;

(Actually, BSD)

: that takes a file pointed at by fd and truncates the file to length bytes.
: The file descriptor may be only open for writing (which rules out dumping
: length bytes to a temporary file and copying them back, which involves
: read access).  How would one implement such a function in System V (I have
: tried the obvious ways, ie fcntl(), etc).  Do you have to write something
: to edit the inode to do this??

You don't do it with a standard system call. I once had occasion to
look long and hard for this and didn't find it.

---
Bill                            { uunet | novavax } !twwells!bill

davidsen@steinmetz.ge.com (Wm. E. Davidsen Jr) (05/03/89)

  There was a method in wizards a few years ago I believe. It had to do
with using O_TRUNC, which seems to truncate to the position of the
current file pointer. There was a trick with reopen or dup or ??? which
allowed opening of an already open file. Does this jog anyone's memory?

  I think the question at that time was "how do I do ftruncate?"
-- 
	bill davidsen		(wedu@crd.GE.COM)
  {uunet | philabs}!steinmetz!crdos1!davidsen
"Stupidity, like virtue, is its own reward" -me

guy@auspex.auspex.com (Guy Harris) (05/03/89)

>  There was a method in wizards a few years ago I believe. It had to do
>with using O_TRUNC, which seems to truncate to the position of the
>current file pointer.

Not on S5R3.1, and not on 4.3BSD.  O_TRUNC is used *only* on "open", and
since the whole point of "open" is to *create* a file pointer, there
*is* no current file pointer....  O_TRUNC isn't used on "fcntl".

>There was a trick with reopen or dup or ??? which
>allowed opening of an already open file.

Well, "dup" will give you a second file descriptor that refers to an
already-open file, but there's no trick that lets you open an
already-open file with "open", unless you have something like the
"/dev/fd" mechanism.

stevea@laidbak.UUCP (Steve Alexander) (05/04/89)

/*
 * This works only on System V 3.1 and 3.2, and relies on an
 * undocumented fcntl.  Use this at your own risk.  There are no guarantees
 * that this will remain in V.4, especially since I could find no commands
 * that use it.
 */

#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>

extern void exit();

main(argc, argv)
	int	argc;
	char	**argv;
{
	int		f, i, r;
	int		trunclen, maxlen;
	char		buf[1024];

	if (argc < 4)
		error("usage: f file maxlen trunclen");

	maxlen = atoi(argv[2]);	
	maxlen /= sizeof(buf);

	trunclen = atoi(argv[3]);	

	f = open(argv[1], O_RDWR|O_CREAT, 0644);
	if (f < 0)
		error("open");

	/* write maxlen * 1024 bytes */

	for (i = 0; i < maxlen; i++)
		if (write(f, buf, sizeof(buf)) < 0)
			error("write");

	/* truncate to trunclen */
	r = ftruncate(f, trunclen);
	if (r < 0)
		error("ftruncate");
	
	r = close(f);
	if (r < 0)
		error("close");

	exit(0);
/*NOTREACHED*/
}

int
ftruncate(f, l)
	int	f;
	int	l;
{
	struct	flock	fl;

	fl.l_whence = 0;
	fl.l_len = 0;
	fl.l_start = l;

	return fcntl(f, F_FREESP, &fl);
}

error(s)
	char	*s;
{
	extern void perror();
	if (errno)
		perror(s);
	else
		(void)fprintf(stderr,"%s\n",s);
	exit(1);
}

-- 
Steve Alexander, TCP/IP Development | stevea%laidbak@sun.com
Lachman Associates, Inc.            | ...!sun!laidbak!stevea

allbery@ncoast.ORG (Brandon S. Allbery) (05/06/89)

As quoted from <887@twwells.uucp> by bill@twwells.uucp (T. William Wells):
+---------------
| In article <651@mitisft.Convergent.COM> kemnitz@mitisft.Convergent.COM (Gregory Kemnitz) writes:
| : There is an ULTRIX (I think) function
| :
| : ftruncate(fd, length)
| : int fd, length;
| 
| (Actually, BSD)
| 
| You don't do it with a standard system call. I once had occasion to
| look long and hard for this and didn't find it.
+---------------

Standard System V (except perhaps 3.2) doesn't have this.  Xenix System V
may use one of two methods:

(1) zero-length write at point of truncation
(2) a system call whose name I've forgotten which truncates the file at
    the current lseek() position

SysV 3.2 probably uses the latter method.  I can look up the syscall if
you're desperate.

++Brandon
-- 
Brandon S. Allbery, moderator of comp.sources.misc	     allbery@ncoast.org
uunet!hal.cwru.edu!ncoast!allbery		    ncoast!allbery@hal.cwru.edu
      Send comp.sources.misc submissions to comp-sources-misc@<backbone>
NCoast Public Access UN*X - (216) 781-6201, 300/1200/2400 baud, login: makeuser

allbery@ncoast.ORG (Brandon S. Allbery) (05/06/89)

As quoted from <13619@ncoast.ORG> by allbery@ncoast.ORG (Brandon S. Allbery):
+---------------
| Standard System V (except perhaps 3.2) doesn't have this.  Xenix System V
| may use one of two methods:
+---------------

I forgot to mention that different versions of Xenix use one or the other,
never both.  The zero-length write trick is pretty much obsolete.

+---------------
| (1) zero-length write at point of truncation
| (2) a system call whose name I've forgotten which truncates the file at
|     the current lseek() position
+---------------

I remembered it:  chsize(fd).  It will also "grow" the file if you've
lseek()'ed past EOF.  (I don't know whether it uses "holes" where possible
or always allocates disk space.)

++Brandon
-- 
Brandon S. Allbery, moderator of comp.sources.misc	     allbery@ncoast.org
uunet!hal.cwru.edu!ncoast!allbery		    ncoast!allbery@hal.cwru.edu
      Send comp.sources.misc submissions to comp-sources-misc@<backbone>
NCoast Public Access UN*X - (216) 781-6201, 300/1200/2400 baud, login: makeuser

cs411s03@uhccux.uhcc.hawaii.edu (Cs411s03) (05/13/89)

The Xenix function chsize(S) can be found in /lib/libx.a under System V 3.2.
It functions similarly to the BSD ftruncate() function:

	int chsize(fildes, size)
	int fildes;
	long size;

The chsize function will change the file associated with fildes to be
exactly size bytes in length ...

cs411s03!uhccux