kevin@msa3b.UUCP (Kevin P. Kleinfelter) (08/10/89)
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. If you know, thanks! -- Kevin Kleinfelter @ Management Science America, Inc (404) 239-2347 gatech!nanovx!msa3b!kevin
gwyn@smoke.BRL.MIL (Doug Gwyn) (08/13/89)
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. Not possible in UNIX System V through SVR3.2, probably supported in SVR4.0. You can simulate this operation by snarfing the intended ultimate file contents somewhere safe (like an in-memory array, if it will fit, or a temp file), then use creat() to truncate the file to 0 length, then write back the desired final contents.
kucharsk@uts.amdahl.com (William Kucharski) (08/13/89)
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 <sys/types.h> #include <sys/stat.h> #include <errno.h> #include <fcntl.h> #include <unistd.h> #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 <fcntl.h> or * <sys/fcntl.h>, 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.
dougm@queso.ico.isc.com (Doug McCallum) (08/14/89)
In article <10723@smoke.BRL.MIL> gwyn@smoke.BRL.MIL (Doug Gwyn) writes: 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. Not possible in UNIX System V through SVR3.2, probably supported in SVR4.0. You can simulate this operation by snarfing the intended ultimate file contents somewhere safe (like an in-memory array, if it will fit, or a temp file), then use creat() to truncate the file to 0 length, then write back the desired final contents. While not documented in the fcntl man page or listed in the fcntl man page with 386/ix, the XENIX compatibility of V.3.2 provides the "chsize" call in the XENIX compatibility library (-lx) and the F_CHSIZE fcntl function which are basically "ftruncate". using chsize(fd, size) does what ftruncate would do. #define ftruncate(fd,size) fcntl(fd, F_CHSIZE, size) will work if you don't want to load the XENIX library. So, from V.3.2 on there is likely to be something equivalent to ftruncate. Doug McCallum Interactive Systems Corp. dougm@ico.isc.com
chris@mimsy.UUCP (Chris Torek) (08/15/89)
In article <18lG02Em4aQn01@amdahl.uts.amdahl.com> kucharsk@uts.amdahl.com (William Kucharski) writes: >int >ftruncate(fd, length) [much deleted] > if (filebuf.st_size < length) { > /* extend file length */ The 4BSD ftruncate() call will not extend files. (If it did, it would probably have been called `fsetsize'; and a function like this one should probably be so called.) -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
kucharsk@uts.amdahl.com (William Kucharski) (08/15/89)
In article <19072@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes: >In article <18lG02Em4aQn01@amdahl.uts.amdahl.com> kucharsk@uts.amdahl.com >(William Kucharski) writes: >>int >>ftruncate(fd, length) >[much deleted] >> if (filebuf.st_size < length) { >> /* extend file length */ > >The 4BSD ftruncate() call will not extend files. (If it did, >it would probably have been called `fsetsize'; and a function >like this one should probably be so called.) Well, it may not be a good porting guide, but my SunOS 4.0 man page says: DESCRIPTION truncate() causes the file referred to by path (or for ftruncate() the object referred to by fd) to have a size equal to length bytes. If the file was previously longer than length, the extra bytes are removed from the file. If it was shorter, bytes between the old and new lengths are read as zeroes. [...] -- 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.