svn commit: r273129 - head/sys/kern

Bruce Evans brde at optusnet.com.au
Mon Oct 27 17:28:46 UTC 2014


On Wed, 15 Oct 2014, Konstantin Belousov wrote:

> Log:
>  Implement FIODTYPE for master ptys.
>
>  Requested and reviewed by:	bde
>  Sponsored by:	The FreeBSD Foundation
>  MFC after:	1 week

Thanks. This allows dd to work on ptys again.  dd has the following bad code:

% static void
% getfdtype(IO *io)
% {
% 	struct stat sb;
% 	int type;
% 
% 	if (fstat(io->fd, &sb) == -1)
% 		err(1, "%s", io->name);

FIODTYPE should only be used as a hint, but dd makes its non-support fatal
in some cases.  Even fstat() failure for determining the hint shouldn't be
fatal.

% 	if (S_ISREG(sb.st_mode))
% 		io->flags |= ISTRUNC;
% 	if (S_ISCHR(sb.st_mode) || S_ISBLK(sb.st_mode)) { 
% 		if (ioctl(io->fd, FIODTYPE, &type) == -1) {
% 			err(1, "%s", io->name);
% 		} else {

dd only uses the dtype hint for devices.  Otherwise, it uses defaults.  It
might as well use the defaults for devices that don't support dtype too.

% 			if (type & D_TAPE)
% 				io->flags |= ISTAPE;
% 			else if (type & (D_DISK | D_MEM))
% 				io->flags |= ISSEEK;
% 			if (S_ISCHR(sb.st_mode) && (type & D_TAPE) == 0)
% 				io->flags |= ISCHR;
% 		}
% 		return;
% 	}
% 	errno = 0;
% 	if (lseek(io->fd, (off_t)0, SEEK_CUR) == -1 && errno == ESPIPE)
% 		io->flags |= ISPIPE;
% 	else
% 		io->flags |= ISSEEK;
% }

Not only the dtype check is bad.  dd still has to guess about seekability,
and does this not very well.  Guessing is not needed for pipes, but dd
guesses for them.  Pipes are not seekable, but the converse is false.
Tapes ar character devices, but ISCHR is not set for them.  I use the
following fixes (not complete -- at least the spelling change for ISSEEK
is mostly in other files).

@diff -u2 dd.c~ dd.c
@--- dd.c~	Wed Apr  7 20:20:48 2004
@+++ dd.c	Wed Apr  7 20:20:49 2004
@@@ -247,21 +245,18 @@
@ 		io->flags |= ISTRUNC;
@ 	if (S_ISCHR(sb.st_mode) || S_ISBLK(sb.st_mode)) { 
@-		if (ioctl(io->fd, FIODTYPE, &type) == -1) {
@+		if (ioctl(io->fd, FIODTYPE, &type) == -1)
@ 			err(1, "%s", io->name);
@-		} else {
@+		else {
@ 			if (type & D_TAPE)
@ 				io->flags |= ISTAPE;
@ 			else if (type & (D_DISK | D_MEM))
@-				io->flags |= ISSEEK;
@-			if (S_ISCHR(sb.st_mode) && (type & D_TAPE) == 0)
@+				io->flags |= ISSEEKABLE;
@+			if (S_ISCHR(sb.st_mode))
@ 				io->flags |= ISCHR;
@ 		}
@-		return;
@-	}
@-	errno = 0;
@-	if (lseek(io->fd, (off_t)0, SEEK_CUR) == -1 && errno == ESPIPE)
@-		io->flags |= ISPIPE;
@-	else
@-		io->flags |= ISSEEK;
@+	} else if (lseek(io->fd, (off_t)0, SEEK_CUR) == 0)
@+		io->flags |= ISSEEKABLE;
@+	else if (errno == ESPIPE)
@+		io->flags |= ISPIPE;		/* XXX fixed in 4.4BSD */
@ }
@

Bruce


More information about the svn-src-head mailing list