2006-04-22
Perhaps the most critical part of ImageIngester (link at left) is the copy loop that copies image files from a flash card to disk. Because the data is irreplaceable, this loop has to be coded carefully, with particular attention to error checking. But unlike other situations where programming is critical, the impact of an error is minor, as long as it's reported. The image is still on the card, so the ingestion can simply be restarted.
I was going to write an entry on how I designed this loop, using techniques explained in Advanced UNIX Programming (link at right), but then I started day-dreaming about a time back in 1973 or 1974 when I used the UNIX cat command to write a file, something like this:
% cat f1 f2 >f3
(My recollection is that the shell prompt was a percent sign in those days.)
Well, file f3 was short, and I eventually figured out that the file system was out of space. I was surprised at the time that the cat command gave no error message.
(Back then a friend of mine complained to Ken Thompson about a bug in the echo command. Thompson's response was, "Did you fix it?" Had I complained about cat, I'm sure I would have gotten the same answer.)
There are at least two reasons why cat didn't give me an error message:
- Looking at some source for Version 5 (available for all to see at minnie.tuhs.org/TUHS/archive_sites.html), which I think was what I was using back then, I don't see any commands that write diagnostics to file descriptor 2, which is what we now call the standard error output. Of course, UNIX had a file descriptor 2, but the convention that it would be opened to the terminal and stay directed to the terminal hadn't yet been adopted. Since I had redirected cat's standard output, I wouldn't have seen the diagnostic even if there had been one, although it would have been at the end of file f3.
-
But there wasn't any error message, anywhere.
In those days cat hadn't yet been recoded into C (other commands, such as cp, had been).
The relevant part of the code was:
Even if you don't remember your PDP-11 assembler, you can see that there's no code to check the error return from the write system call.putc: movb r0,(r2)+ cmp r2,$obuf+512. blo 1f mov $1,r0 sys write; obuf; 512. mov $obuf,r2 1: rts pc
So, in Version 5, the cat command was programmed somewhat casually.
In Version 6, the cat command was still in assembler, and it still didn't check for write errors. But, standard error output had arrived, as indicated by this code from the grep command, rewritten in C for Version 6:
printf2(s, a)
{
extern fout;
flush();
fout = 2;
printf(s, a);
flush();
exit(2);
}
Here's an example call to printf2 in grep.c:
printf2("RE error\n");
Then in Version 7, cat got recoded into C and started to make use of the standard error output, using Dennis Ritchie's new Standard I/O Library:
fprintf(stderr, "cat: can't open %s\n", *argv);
The copy loop was recoded to use Standard I/O as well, but, unfortunately, still didn't do any error checking:
while ((c = getc(fi)) != EOF)
putchar(c);
So, when did cat start checking for write errors? I don't actually know, but I think it was fixed in System III, which I used in 1984. In the mid-1970s I worked on the Programmer's Workbench version of UNIX, which was combined with the UNIX Support Group version (both based on Version 7) to form System III, but I don't remember when the cat command got fixed, or even if it was fixed before I left the PWB project.
If anyone out there knows when cat was fixed, and by whom, would you send me an email?