From owner-freebsd-bugs@FreeBSD.ORG Tue Jan 4 00:40:25 2005 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id C133716A4CE for ; Tue, 4 Jan 2005 00:40:25 +0000 (GMT) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id 8DFCD43D48 for ; Tue, 4 Jan 2005 00:40:25 +0000 (GMT) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.13.1/8.13.1) with ESMTP id j040ePbo008099 for ; Tue, 4 Jan 2005 00:40:25 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.13.1/8.13.1/Submit) id j040ePmV008098; Tue, 4 Jan 2005 00:40:25 GMT (envelope-from gnats) Date: Tue, 4 Jan 2005 00:40:25 GMT Message-Id: <200501040040.j040ePmV008098@freefall.freebsd.org> To: freebsd-bugs@FreeBSD.org From: Giorgos Keramidas Subject: Re: bin/75767: WANTED: "fdclose" function in libc X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list Reply-To: Giorgos Keramidas List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 04 Jan 2005 00:40:26 -0000 The following reply was made to PR bin/75767; it has been noted by GNATS. From: Giorgos Keramidas To: "Ronald F.Guilmette" Cc: bug-followup@freebsd.org Subject: Re: bin/75767: WANTED: "fdclose" function in libc Date: Tue, 4 Jan 2005 02:38:13 +0200 On 2005-01-03 13:50, "Ronald F.Guilmette" wrote: > In certain contexts, and when using certain programming styles, it is > important to be able to symmetrically "undo" the effects of various > calls to various standard library (libc) routines. > > At present, due to the lack of an "fdclose" primitive in libc, it is > not easily possible to symmetrically undo the effects of a call to the > "fdopen" function. One may call fclose on an open stdio file pointer, > however the fclose function actually has two effects, i.e.: > > 1) recycling the stdio file descriptor that was allocated by the prior > call to fdopen() into the pool of available stdio file descriptors > and... > > 2) calling close(2) on the underlying UNIX file descriptor. > > Unfortunately, only the first of these two effects actually > constitutes a symmetric undo-ing of the actions performed by a call to > fdopen. The second effect is an unfortunate (and undesirable) > side-effect of fclose in some instances. > > Thus, it would be useful to have a new function in libc, i.e. an > "fdclose" function whose only effect would be to recycle a stdio file > descriptor into the pool of free/available stdio file descriptors > *without* also closing the underlying UNIX file descriptor. I believe there is no easy way to fdclose() a FILE object _and_ do it in a way that would satisfy all the potential uses of such a function. Some of the problems that an implementation would have to face are immediate results of the buffered nature of FILE streams: a) Should any pending writes be flushed out before the FILE object is destroyed? b) What should the implementation do with any data that has been "read-ahead" and cannot be pushed back to an input stream? I don't think there is a Right Thing(TM) for all the possible cases. Especially if the FILE object is attached to a device node, which may or may not support data read-ahead, pushing back of input data, rewinding on every open(), etc. > Add a new "fdclose" function to libc. This should have the same > effects as fclose, except that it should *not* close the underlying > UNIX file descriptor. You can probably emulate most of the behavior of fdclose() when such a need arises with something like this: % #include % #include % #include % % int % fdclose(FILE *fp) % { % int fd, nfd; % int status; % % if (fp == NULL || (fd = fileno(fp)) < 0) % goto out; % if ((nfd = dup(fd)) < 0 || (status = fclose(fp)) != 0 || % dup2(nfd, fd) < 0 || close(nfd) < 0) % goto syserr; % return (0); % % out: % errno = EINVAL; % syserr: % return (-1); % }