Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!cornell!uw-beaver!uw-june!ka From: ka@june.cs.washington.edu (Kenneth Almquist) Newsgroups: comp.unix.wizards Subject: Re: getcwd() and friends. Message-ID: <7882@june.cs.washington.edu> Date: 15 Apr 89 22:26:22 GMT References: <3675@ficc.uu.net> <14689@rpp386.Dallas.TX.US> <811@mtxinu.UUCP> <3746@ficc.uu.net> Organization: U of Washington, Computer Science, Seattle Lines: 70 peter@ficc.uu.net (Peter da Silva) writes: > [Suggestion for O_TOKEN.] > > Do this cleverly enough and almost all the regular calls can actually use > the new calls... you just need to keep 'open' around so you can get the > fd in the first place: > > link(name, newname) > char *name, *newname; > { > int fd; > > fd = open(name, O_TOKEN); > if(fd >= 0) > { > retval = fd_link(fd, newname); > close(fd); > } > else > return -1; > } A good idea in principle, but the code you present here contains three rather obscure bugs which are worth pointing out in case someone decides to implement this. First, the open can fail because of a lack of open file descriptors, and EMFILE isn't one of the error codes that link is supposed to return. Second, there is no guarantee that the open system call will ever return; for example an open of a tty device blocks until carrier is present, and it may never be. Third, if a signal arrives between the open and the close, and the signal handler does a longjmp out of the link routine, the file descriptor will never be closed. The second problem is easily fixed by adding the O_NDELAY flag to the open call. The other two are harder. The third can be solved by blocking all signals before the open, and unblocking them after the close. The main problem with this is that, with a networked file system, you may want link to be interruptable. The first problem can be fixed by reserving the last file descriptor for routines like link. To do this, make the system calls refuse to allocate the last file descriptor under ordinary circumstances. Then allow the open call to allocate the last file descriptor if the O_USELAST flag is set. By convention, user code should not use O_USELAST. Putting this all together gives: link(name, newname) char *name, *newname; { int fd; int savemask; savemask = sigblock(~0); /* block all signals */ fd = open(name, O_TOKEN|O_NDELAY|O_USELAST); if(fd >= 0) { retval = fd_link(fd, newname); close(fd); sigblock(savemask); /* unblock signals */ return 0; } else { sigblock(savemask); return -1; } } Kenneth Almquist