Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!uunet!husc6!hao!ames!aurora!labrea!decwrl!pyramid!prls!philabs!micomvax!musocs!mcgill-vision!mouse From: mouse@mcgill-vision.UUCP (der Mouse) Newsgroups: comp.sources.bugs Subject: copytape fix allowing network operation Message-ID: <922@mcgill-vision.UUCP> Date: Fri, 20-Nov-87 23:00:28 EST Article-I.D.: mcgill-v.922 Posted: Fri Nov 20 23:00:28 1987 Date-Received: Fri, 27-Nov-87 00:10:10 EST Organization: McGill University, Montreal Lines: 120 The copytape program posted to comp.sources.unix is a very nice and extremely useful program. However, when it was updated recently to fix some bugs, some other bugs were introduced. While it may be true that % copytape /dev/rmt8 /dev/rmt9 or % copytape /dev/rmt8 tempfile (switch tapes) % copytape tempfile /dev/rmt8 will work, it is not true that % copytape < /dev/rmt8 | rsh othermachine copytape \> /dev/rmt8 works. This is because an assumption about the nature of data files is made that is valid for real files but not for network connections or pipes.... When read(...,n,...) is done on a file, the system guarantees that if (at least) n bytes remain before end-of-file, the read will read all n. With a pipe or a network connection, this is not the case. Here is a fix to copytape to make it work across network connections or pipes: *** copytape.c.original Fri Nov 20 22:42:38 1987 --- copytape.c Fri Nov 20 22:30:01 1987 *************** *** 193,199 **** --- 193,234 ---- exit(0); } + /* When reading from a file, read(...,n,...) is guaranteed to return + n bytes if they are present. When reading from a pipe or a network + connection, this is not the case. Hence.... */ + int Read(fd,buf,n) + int fd; + char *buf; + int n; + { + int left; + char *bp; + int did; + int nr; + bp = buf; + left = n; + did = 0; + while (left > 0) + { nr = read(fd,bp,left); + if (nr < 0) + { if (did == 0) + { did = -1; + } + break; + } + else if (nr == 0) + { break; + } + else + { did += nr; + bp += nr; + left -= nr; + } + } + return(did); + } + /* * Input up to 256K from a file or tape. If input file is a tape, then * do markcount stuff. Input record length will be supplied by the *************** *** 229,249 **** }; } /* Input is really a data file. */ ! l2 = read(fd, header, 5); if (l2 != 5 || strncmp(header, "CPTP:", 5) != 0) return FORMAT_ERROR; ! l2 = read(fd, header, 4); if (strncmp(header, "BLK ", 4) == 0) { ! l2 = read(fd, header, 7); if (l2 != 7) return FORMAT_ERROR; header[6] = '\0'; len = atoi(header); ! l2 = read(fd, tapebuf, len); if (l2 != len) return FORMAT_ERROR; ! read(fd, header, 1); /* skip trailing newline */ } else if (strncmp(header, "MRK\n", 4) == 0) return TAPE_MARK; else if (strncmp(header, "EOT\n", 4) == 0) --- 264,284 ---- }; } /* Input is really a data file. */ ! l2 = Read(fd, header, 5); if (l2 != 5 || strncmp(header, "CPTP:", 5) != 0) return FORMAT_ERROR; ! l2 = Read(fd, header, 4); if (strncmp(header, "BLK ", 4) == 0) { ! l2 = Read(fd, header, 7); if (l2 != 7) return FORMAT_ERROR; header[6] = '\0'; len = atoi(header); ! l2 = Read(fd, tapebuf, len); if (l2 != len) return FORMAT_ERROR; ! Read(fd, header, 1); /* skip trailing newline */ } else if (strncmp(header, "MRK\n", 4) == 0) return TAPE_MARK; else if (strncmp(header, "EOT\n", 4) == 0) der Mouse (mouse@mcgill-vision.uucp)