hua@cmu-cs-edu1.ARPA (Ernest Hua) (06/07/85)
___________________________________________________________________________ Does anyone have any idea how to truncate a file at the current point in writing if it is opened by open()? I cannot use creat() because the file is being used by another process, and I cannot use unlink() it is likely that it is linked. If the updated contents is longer than the original, it is not a problem because the file length is just extended. But if the updated contents is shorter, the file does not shrink. We have 4.1BSD on several 780's and 750's. Any help would be greatly appreciated. ARPA: (see below) UUCP: seismo!hua@cmu-cs-gandalf.arpa CSNET: hua%cmu-cs-gandalf.csnet@csnet.arpa ___________________________________________________________________________ Live long and prosper. Keebler { hua@cmu-cs-gandalf.arpa }
ken@turtlevax.UUCP (Ken Turkowski) (06/11/85)
In article <340@cmu-cs-edu1.ARPA> hua@cmu-cs-edu1.ARPA (Ernest Hua) writes: >Does anyone have any idea how to truncate a file at the current point in >writing if it is opened by open()? I cannot use creat() because the file >is being used by another process, and I cannot use unlink() it is likely >that it is linked. If the updated contents is longer than the original, >it is not a problem because the file length is just extended. But if the >updated contents is shorter, the file does not shrink. We have 4.1BSD on >several 780's and 750's. try size = lseek(fd, 0L, 1); /* tell(fd) */ ftruncate(fd, size); /* int fd, size; */ It's yet another undocumented feature on 4.2. -- Ken Turkowski @ CADLINC, Menlo Park, CA UUCP: {amd,decwrl,hplabs,nsc,seismo,spar}!turtlevax!ken ARPA: turtlevax!ken@DECWRL.ARPA
steven@luke.UUCP (Steven List) (06/13/85)
In article <786@turtlevax.UUCP> ken@turtlevax.UUCP (Ken Turkowski) writes: >In article <340@cmu-cs-edu1.ARPA> hua@cmu-cs-edu1.ARPA (Ernest Hua) writes: >>Does anyone have any idea how to truncate a file at the current point in >>writing if it is opened by open()? > >size = lseek(fd, 0L, 1); /* tell(fd) */ >ftruncate(fd, size); /* int fd, size; */ > >It's yet another undocumented feature on 4.2. OK, how about System III? That's my problem. Someone out there posted a program that uses ftruncate, and we don't have it. Solutions are welcome! -- *** * Steven List @ Benetics Corporation * (415) 940-6300 * {cdp,greipa,idi,oliveb,sun,tolerant}!bene!luke!steven ***
guy@sun.uucp (Guy Harris) (06/17/85)
> In article <786@turtlevax.UUCP> ken@turtlevax.UUCP (Ken Turkowski) writes: > >In article <340@cmu-cs-edu1.ARPA> hua@cmu-cs-edu1.ARPA (Ernest Hua) writes: > >>Does anyone have any idea how to truncate a file at the current point in > >>writing if it is opened by open()? > > > >size = lseek(fd, 0L, 1); /* tell(fd) */ > >ftruncate(fd, size); /* int fd, size; */ > > > >It's yet another undocumented feature on 4.2. Undocumented? Hardly. See TRUNCATE(2) in the UNIX Programmer's Manual. > OK, how about System III? That's my problem. Someone out there posted > a program that uses ftruncate, and we don't have it. Solutions are > welcome! There are precisely two solutions for non-4.2BSD systems: 1) implement (f)truncate on your system. Any implementation on a non-4.2BSD version of UNIX will probably move to any other non-4.2BSD version with little difficulty. 2) Copy the entire file, up to the point of truncation, to a temporary file, then copy it back to the original file. The "f77" support library uses solution 2), except under 4.2BSD where it uses solution 1); I believe "truncate" was introduced for the benefit of "f77". A comparision of solutions 1) and 2) may indicate why the Berkeley people added "truncate". Solution 2) is slow and ugly. Guy Harris
gwyn@brl-tgr.ARPA (Doug Gwyn <gwyn>) (06/18/85)
UNIX System III/V do not have any way to truncate a file. The best kludge is to recopy the whole file up to the point of truncation (yuck).
campbell@maynard.UUCP (Larry Campbell) (06/19/85)
> > >In article <340@cmu-cs-edu1.ARPA> hua@cmu-cs-edu1.ARPA (Ernest Hua) writes: > > >>Does anyone have any idea how to truncate a file at the current point in > > >>writing if it is opened by open()? > > There are precisely two solutions for non-4.2BSD systems: > 1) implement (f)truncate on your system... Kind of tough for people without source licenses (I know, I'm whining). > 2) Copy the entire file, up to the point of truncation, to a temporary file, > then copy it back to the original file. > > Guy Harris I don't see how this works unless you unlink the file and then re-creat it before writing it back. But the original question implied you only had a descriptor for the file, not a name... so you can't unlink or re-creat it. And even if you knew the name, other links wouldn't get truncated. Sounds like it's pretty tough to fake this one ... sigh ... - Larry Campbell The Boston Software Works, Inc., 120 Fulton St., Boston MA 02109 UUCP: {decvax, security, linus, mit-eddie}!genrad!enmasse!maynard!campbell ARPA: decvax!genrad!enmasse!maynard!campbell@DECWRL.ARPA
guy@sun.uucp (Guy Harris) (06/20/85)
> > There are precisely two solutions for non-4.2BSD systems: > > 1) implement (f)truncate on your system... > > Kind of tough for people without source licenses (I know, I'm whining). Actually, it was meant as a hint to various vendors, some of whom may be long-distance carriers... > > 2) Copy the entire file, up to the point of truncation, to a temporary > > file, then copy it back to the original file. > I don't see how this works unless you unlink the file and then re-creat > it before writing it back. Why unlink it? Re-"creat"ing will do the job - it truncates the file to zero length (unless you don't have write permission, which is unlikely unless the file is newly created and you created it without giving yourself write permission). Guy Harris
smk@axiom.UUCP (Steven M. Kramer) (06/22/85)
I wrote a few routines for non-4.2 machines that mimicked the 4.2 routines. Ftruncate was one of them. I probably missed some wierd conditions (like file descriptors refering to non-reg files, ..., and errno's), but my ftruncate works OK in a pinch. I posted the source to net.sources. -- --steve kramer {allegra,genrad,ihnp4,utzoo,philabs,uw-beaver}!linus!axiom!smk (UUCP) linus!axiom!smk@mitre-bedford (MIL)
mts@ms.UUCP (Martin Stanley) (06/24/85)
> > > >In article <340@cmu-cs-edu1.ARPA> hua@cmu-cs-edu1.ARPA (Ernest Hua) writes: > > > >>Does anyone have any idea how to truncate a file at the current point in > > > >>writing if it is opened by open()? > > > > There are precisely two solutions for non-4.2BSD systems: > > 1) implement (f)truncate on your system... > > Kind of tough for people without source licenses (I know, I'm whining). > > > 2) Copy the entire file, up to the point of truncation, to a temporary file, > > then copy it back to the original file. > > > > Guy Harris > > I don't see how this works unless you unlink the file and then re-creat > it before writing it back. But the original question implied you only had > a descriptor for the file, not a name... so you can't unlink or re-creat > it. And even if you knew the name, other links wouldn't get truncated. > Sounds like it's pretty tough to fake this one ... sigh ... > > - Larry Campbell > The Boston Software Works, Inc., 120 Fulton St., Boston MA 02109 > UUCP: {decvax, security, linus, mit-eddie}!genrad!enmasse!maynard!campbell > ARPA: decvax!genrad!enmasse!maynard!campbell@DECWRL.ARPA There's also another problem: In order to properly simulate the ftruncate() call from 4.2 BSD, you must leave the file open in the same mode it was originally opened in. In order to copy, link, etc. the file you need to fclose() it so you will need to reopen it later. The catch is that you do not know in what mode it was originally opened. (Also, if the file was originally opened in write-only mode you will not be able to read it to copy it to the temporary, so you must fclose() the file to begin with and then re-open for read/write). I wrote a substitute ftruncate() call that takes two arguments: the file pointer and the file name. (Instead of a file pointer and the length desired). It truncates the file at the position of the current file pointer. After the copy and/or re-linking, I reopen the file in "a+" mode and hope for the best. I do not take care of multiple links at all, since that was not necessary for my application. (If anyone wants my code, drop me a line and I'll send it along. It works, but certainly can be made more efficient). -- Martin Stanley Department of Computer Science University of Toronto Toronto, ON M5S 1A4 USENET: {decvax,ihnp4,linus,uw-beaver}!utcsri!utai!ms!mts CSNET: mts@toronto ARPANET: mts.toronto@csnet-relay
guy@sun.uucp (Guy Harris) (06/27/85)
> In order to properly simulate the ftruncate() call from 4.2 BSD, > you must leave the file open in the same mode it was originally opened in. > In order to copy, link, etc. the file you need to fclose() it... Huh? You only have to "fclose" it if you don't have enough file descriptors or if, as you mention, the FD wasn't open for reading and writing. I also don't understand why so much is made of links. You don't have to unlink the file unless you don't have write permission on it; if you have write permission, a "creat" will do the truncation to zero length quite well. (If you have to do the "unlink" and don't have write permission on the containing directory, you're out of luck.) All this is slightly beside the point, as the guy wasn't asking for an "ftruncate()" routine for non-4.2BSD systems, he was just asking for a way to truncate a file to a particular length. In some cases (such as in the F77 support library, which is where both the two-copy scheme and, I believe, the motivation of "(f)truncate" came from) you know what mode the file was opened in. Furthermore, given how slow "ftruncate" are, it's probably best to rewrite the code to use some other technique, if possible, rather than to simulate "ftruncate" by brute force. Then again, since "ftruncate" is useful and can't be nicely built out of other operations (it can be built out of other operations but the result is not pretty), it should probably become a part of standard UNIX. (Remember V6, the UNIX that stored the seek pointer for a file in the kernel and didn't let a program get the value, no matter now politely it asked? "tell" was added to V6, and the V7 "lseek" returned the seek pointer, so that you didn't have to use a kludge like counting all the characters you wrote - which also didn't always work, since you didn't necessarily know where the seek pointer was then the program started.) Guy Harris