[PATCH] support kernels without __ARCH_WANT_SYSCALL_NO_FLAGS

Mark Salter msalter at redhat.com
Thu Apr 26 23:44:37 UTC 2012


On Thu, 2012-04-26 at 17:04 -0400, Mark Salter wrote:
> On Thu, 2012-04-26 at 12:47 -0400, Rich Felker wrote:
> > On Thu, Apr 26, 2012 at 11:00:39AM -0400, Rich Felker wrote:
> > > On Thu, Apr 26, 2012 at 10:18:11AM -0400, Mark Salter wrote:
> > > > +#ifdef __NR_dup2
> > > >  _syscall2(int, dup2, int, oldfd, int, newfd)
> > > > +#elif defined __NR_dup3
> > > > +#include <fcntl.h>
> > > > +
> > > > +int
> > > > +dup2 (int fd, int fd2)
> > > > +{
> > > > +	/* For the degenerate case, check if the fd is valid (by trying to
> > > > +	   get the file status flags) and return it, or else return EBADF.  */
> > > > +	if (fd == fd2)
> > > > +		return __libc_fcntl(fd, F_GETFL, 0) < 0 ? -1 : fd;
> > > 
> > > Is there a reason this special case is necessary? Not questioning it,
> > > I just want to know.
> > 
> > OK, I'll answer my own question: it seems to be a workaround for a
> > kernel bug on 64-bit Linux:
> > 
> > http://old.nabble.com/-PATCH--dup2:-Fix-return-value-with-oldfd-%3D%3D-newfd-and-invalid-fd-td23488867.html
> > 
> 
> No that isn't it. There is a semantic difference in how dup2 and dup3
> handles the case of fd1 == fd2. dup3 unconditionally sets errno to
> EINVAL. dup2 checks if the fd is valid and sets EBADF if not, or returns
> the fd if it is valid. So the intent in that case is to let fcntl
> validate the fd in that case to emulate dup2 behavior.

Thinking about this some more, it'd probably be better to do something
like this so that fcntl is only in the error path:

int
dup2 (int fd, int fd2)
{
	int err = INLINE_SYSCALL(dup3, 3, fd, fd2, 0);

	/*
	 * dup3 returns -1 and sets errno to EINVAL when fd == fd2
	 * dup2 in that case will return fd if it is valid or set
	 * errno to EBADF and return -1 if fd is not valid
	 */	
	if (err < 0 && fd == fd2) {
		errno = 0;
		err = __libc_fcntl(fd, F_GETFL, 0) < 0 ? -1 : fd;
	}
	return err;
}






More information about the uClibc mailing list