rommel@Informatik.TU-Muenchen.DE (Kai-Uwe Rommel) (06/23/91)
I have fixed a serious bug in the symlink package posted here recently. I know there is a better implementation but it is not (yet) available and I want at least to fix the code posted here in case anyone uses it. The two diffs below replace two files in the original posting. Kai Uwe Rommel /* Kai Uwe Rommel, Munich ----- rommel@lan.informatik.tu-muenchen.dbp.de */ DOS ... is still a real mode only non-reentrant interrupt handler, and always will be. -Russell Williams - inode.c.cdif *** inode.orig Sun May 26 19:57:02 1991 --- inode.c Sun May 26 19:56:40 1991 *************** *** 78,83 **** --- 78,84 ---- if (rip == NIL_INODE) return; /* checking here is easier than in caller */ if (--rip->i_count == 0) { /* i_count == 0 means no one is using it now */ + if ((rip->i_mode & I_TYPE) != I_SLINK) { /* don't truncate symbolic links */ if ((rip->i_nlinks & BYTE) == 0) { /* i_nlinks == 0 means free the inode. */ truncate(rip); /* return all the disk blocks */ *************** *** 86,91 **** --- 87,93 ---- } else if (rip->i_pipe == I_PIPE) truncate(rip); rip->i_pipe = NO_PIPE; /* should always be cleared */ + } if (rip->i_dirt == DIRTY) rw_inode(rip, WRITING); } - stadir.c.cdif *** stadir.orig Sun May 26 19:57:06 1991 --- stadir.c Sun May 26 19:57:40 1991 *************** *** 6,11 **** --- 6,13 ---- * do_chroot: perform the CHROOT system call * do_stat: perform the STAT system call * do_fstat: perform the FSTAT system call + * do_lstat: perform the LSTAT system call + * do_rdlink: perform the RDLNK system call */ #include "fs.h" *************** *** 114,119 **** --- 116,189 ---- return(r); } + /*===========================================================================* + * do_lstat * + *===========================================================================*/ + PUBLIC int do_lstat() + { + /* Perform the lstat(name, buf) system call. */ + + register struct inode *ldip, *rip; + register int r; + char string[NAME_MAX]; + register char *p; + + if (fetch_name(name1, name1_length, M1) != OK) return(err_code); + + /* can't use eat_path() since it will traverse the link */ + + if ( (ldip = last_dir(user_path, string)) == NIL_INODE) return(err_code); + + /* Get final component of the path. */ + rip = advance(ldip, string); + put_inode(ldip); + + if (rip == NIL_INODE) return(err_code); + + r = stat_inode(rip, NIL_FILP, name2); /* work just like stat */ + + put_inode(rip); /* release the inode */ + return(r); + } + + + /*===========================================================================* + * do_rdlink * + *===========================================================================*/ + PUBLIC int do_rdlink() + { + /* Perform the readlink(name, buf) system call. */ + + register struct inode *ldip, *rip; + register int r; + char string[NAME_MAX]; + register char *p; + vir_bytes v; + + if (fetch_name(name1, name1_length, M1) != OK) return(err_code); + if ( (ldip = last_dir(user_path, string)) == NIL_INODE) return(err_code); + + /* Get final component of the path. */ + rip = advance(ldip, string); + put_inode(ldip); + + if (rip == NIL_INODE) return(err_code); + + if ((rip->i_mode & I_TYPE) == I_SLINK) { + /* copy last 30 bytes from inode into buf */ + p = (char *) rip; + p += 2; + + v = (vir_bytes) name2; + + /* Copy the name pointed to into user space. */ + r = rw_user(D, who, v, (vir_bytes) 30, p, TO_USER); + } else { + r = ENOTSLNK; + } + put_inode(rip); /* release the inode */ + return(r); + } /*===========================================================================* * do_fstat * /* Kai Uwe Rommel, Munich ----- rommel@lan.informatik.tu-muenchen.dbp.de */ DOS ... is still a real mode only non-reentrant interrupt handler, and always will be. -Russell Williams