msm@nucleus.mi.org (Michael S. Mattone) (04/07/90)
I've noticed a few bugs in MINIX 1.5.5. I'm posting this in case any of these haven't been noticed before. Maybe they will make it into official 1.5.6 changes to be posted in April. 1. Pipe limit 7K. The following fails if 'fd' is a pipe: write(fd, buf, 8000); This bug (feature?) has been annoying me since 1.2. Anyone else? I posted my modifications to make this problem go away 2 1/2 times before. Should I try for 3 1/2? Or is this something POSIX requires? 2. Named Pipes. I was playing with named pipes and ran into a few problems. Since a named pipe doesn't disappear like a normal pipe until it is unlinked, the trick being used to allow de(1) to recover deleted files causes problems. The message: FS freeing unused block of inode, bit = # ^^ - typo? should this be "or" is displayed when rm'ing a named pipe, and messes up the filesystem. This appears easy to fix in fs/link.c by calling wipe_inode() in truncate() if the inode is associated with a pipe. Cdiff included below. 3. Incompatible mknod(). The V7 UNIX mknod(2) takes three arguments, mknod(name, mode, addr) but MINIX requires a fourth arg to specify the size of a device. For portability and compatibility with UNIX, could the MINIX mknod() be renamed to something like mknodx() and a UNIX compatible mknod() that calls mknodx() with a 0 for the size argument? MINIX programs that need to would use mknodx(), ported programs wouldn't need to know mknod() was different. 4. Shell read built-in. The shell doesn't handle: read arg1 arg2 ... argN properly if fewer than N words are entered by the user. As delivered the shell forces the user to type a return for each of the left over arguments that there aren't words for. Another cdiff for commands/sh/sh3.c is included. --------------------------------cut here-------------------------------- echo x - link.cdif sed '/^X/s///' > link.cdif << '/' X*** link.c.old Fri Apr 6 16:47:47 1990 X--- link.c Fri Apr 6 16:47:47 1990 X*************** X*** 310,316 **** X register zone_nr z, *iz; X off_t position; X zone_type zone_size; X! int scale, file_type; X struct buf *bp; X dev_t dev; X X--- 310,316 ---- X register zone_nr z, *iz; X off_t position; X zone_type zone_size; X! int scale, file_type, waspipe; X struct buf *bp; X dev_t dev; X X*************** X*** 319,325 **** X dev = rip->i_dev; /* device on which inode resides */ X scale = scale_factor(rip); X zone_size = (zone_type) BLOCK_SIZE << scale; X! if (rip->i_pipe == I_PIPE) rip->i_size = PIPE_SIZE; /* pipes can shrink */ X X /* Step through the file a zone at a time, finding and freeing the zones. */ X for (position = 0; position < rip->i_size; position += zone_size) { X--- 319,326 ---- X dev = rip->i_dev; /* device on which inode resides */ X scale = scale_factor(rip); X zone_size = (zone_type) BLOCK_SIZE << scale; X! if (waspipe = (rip->i_pipe == I_PIPE)) X! rip->i_size = PIPE_SIZE; /* pipes can shrink */ X X /* Step through the file a zone at a time, finding and freeing the zones. */ X for (position = 0; position < rip->i_size; position += zone_size) { X*************** X*** 344,348 **** X } X X /* Leave zone numbers for de(1) to recover file after an unlink(2). */ X! rip->i_dirt = DIRTY; X } X--- 345,351 ---- X } X X /* Leave zone numbers for de(1) to recover file after an unlink(2). */ X! if (waspipe) X! wipe_inode(rip); /* clear out inode for pipes */ X! rip->i_dirt = DIRTY; X } / echo x - sh3.cdif sed '/^X/s///' > sh3.cdif << '/' X*** sh3.c.old Tue Feb 20 04:26:37 1990 X--- sh3.c Tue Feb 20 12:29:01 1990 X*************** X*** 776,790 **** X { X register char *cp, **wp; X register nb; X X if (t->words[1] == NULL) { X err("Usage: read name ..."); X return(1); X } X for (wp = t->words+1; *wp; wp++) { X! for (cp = e.linep; cp < elinep-1; cp++) X! if ((nb = read(0, cp, sizeof(*cp))) != sizeof(*cp) || X! *cp == '\n' || X wp[1] && any(*cp, ifs->value)) X break; X *cp = 0; X--- 776,791 ---- X { X register char *cp, **wp; X register nb; X+ register int nl = 0; X X if (t->words[1] == NULL) { X err("Usage: read name ..."); X return(1); X } X for (wp = t->words+1; *wp; wp++) { X! for (cp = e.linep; !nl && cp < elinep-1; cp++) X! if ((nb = read(0, cp, sizeof(*cp))) != sizeof(*cp) || X! (nl = (*cp == '\n')) || X wp[1] && any(*cp, ifs->value)) X break; X *cp = 0; / exit 0
archer%segin4.segin.fr@prime.com (Vincent Archer) (04/09/90)
Michael S. Mattone <msm@NUCLEUS.MI.ORG> says: MSM>1. Pipe limit 7K. The following fails if 'fd' is a pipe: MSM> write(fd, buf, 8000); MSM> This bug (feature?) has been annoying me since 1.2. Anyone else? MSM> I posted my modifications to make this problem go away 2 1/2 times MSM> before. Should I try for 3 1/2? Or is this something POSIX requires? Better yet, it fails with a specific error code saying that it's too big (8000 that is). That's because Unix requires writes to be atomic. Otherwise, you could find (assuming two processes writing onto the same pipe) the following situation: P1 says: write(8000) the pipe accepts 7K, and P1 waits P1 gets: signal -9 and is killed. FS notices this and purges the remaining 1K P2 says: read(8000) and gets the 7K, but never the 1K (missing) In that situation, you get a partial block of data. If you're using your pipe as a formatted packet stream, you wind up with a non-terminated packet. This can get annoying sometimes, and Unix therefore tries to forbid a write to be done in two (or more) chunks. Do not correct this behaviour, it's standard practice on Unix. Vincent Archer Email: archer%segin4.segin.fr@prime.com (Yes, indirect address required!)