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