/* #define HOWFAR */ /* @(#)nami.c 1.2 */ #include "sys/param.h" #include "sys/types.h" #include "sys/systm.h" #include "sys/sysinfo.h" #include "sys/inode.h" #include "sys/mount.h" #include "sys/dir.h" #include "sys/signal.h" #include "sys/user.h" #include "sys/errno.h" #include "sys/buf.h" #include "sys/var.h" /* * Convert a pathname into a pointer to * an inode. Note that the inode is locked. * * func = function called to get next char of name * &uchar if name is in user space * &schar if name is in system space * flag = 0 if name is sought * 1 if name is to be created * 2 if name is to be deleted */ struct inode * namei(func, flag) int (*func)(); { register struct user *up; register struct inode *dp; register c; register char *cp; register struct buf *bp; register i; dev_t d; off_t eo; /* * If name starts with '/' start from * root; otherwise start from current dir. */ up = &u; sysinfo.namei++; c = (*func)(); if (c == '\0') { up->u_error = ENOENT; return(NULL); } if (c == '/') { if ((dp = up->u_rdir) == NULL) dp = rootdir; while(c == '/') c = (*func)(); if(c == '\0' && flag != 0) { up->u_error = ENOENT; return(NULL); } } else dp = up->u_cdir; (void) iget(dp->i_dev, dp->i_number); cloop: /* * Here dp contains pointer * to last component matched. */ if(up->u_error) goto out; if(c == '\0') return(dp); /* * If there is another component, * gather up name into users' dir buffer. */ cp = &up->u_dent.d_name[0]; while(c != '/' && c != '\0' && up->u_error == 0) { if(cp < &up->u_dent.d_name[DIRSIZ]) *cp++ = c; c = (*func)(); } while(cp < &up->u_dent.d_name[DIRSIZ]) *cp++ = '\0'; #ifdef HOWFAR printf("nami:about to scan for '%s'\n", up->u_dent.d_name); #endif while(c == '/') c = (*func)(); seloop: /* * dp must be a directory and * must have X permission. */ #ifdef HOWFAR /* printf("nami:directory mode = 0%o\n", dp->i_mode&0xFFFF); */ #endif if ((dp->i_mode&IFMT) != IFDIR || dp->i_nlink==0) up->u_error = ENOTDIR; else (void) access(dp, IEXEC); if (up->u_error) goto out; /* * set up to search a directory */ up->u_offset = 0; up->u_count = dp->i_size; up->u_pbsize = 0; eo = 0; bp = NULL; if (dp == up->u_rdir) if (up->u_dent.d_name[0] == '.') if (up->u_dent.d_name[1] == '.') if (up->u_dent.d_name[2] == '\0') goto cloop; eloop: /* * If at the end of the directory, * the search failed. Report what * is appropriate as per flag. */ if (up->u_count == 0) { if(bp != NULL) brelse(bp); if(flag==1 && c=='\0') { if(access(dp, IWRITE)) goto out; up->u_pdir = dp; if (eo) up->u_offset = eo - sizeof(struct direct); up->u_count = sizeof(struct direct); (void) bmap(dp, B_WRITE); if (up->u_error) goto out; return(NULL); } up->u_error = ENOENT; goto out; } /* * If done with current block, * read the next directory block. * Release previous if it exists. */ if (up->u_pbsize == 0) { daddr_t bn; if(bp != NULL) brelse(bp); sysinfo.dirblk++; bn = bmap(dp, B_READ); if (up->u_error) goto out; if (bn < 0) { up->u_error = EIO; goto out; } bp = bread(dp->i_dev, bn); if (up->u_error) { brelse(bp); goto out; } } /* * Note first empty directory slot * in eo for possible creat. * String compare the directory entry * and the current component. * If they do not match, go back to eloop. */ cp = bp->b_un.b_addr + up->u_pboff; up->u_offset += sizeof(struct direct); up->u_pboff += sizeof(struct direct); up->u_pbsize -= sizeof(struct direct); up->u_count -= sizeof(struct direct); up->u_dent.d_ino = ((struct direct *)cp)->d_ino; if(up->u_dent.d_ino == 0) { if(eo == 0) eo = up->u_offset; goto eloop; } cp = &((struct direct *)cp)->d_name[0]; for(i=0; iu_dent.d_name[i]) goto eloop; /* * Here a component matched in a directory. * If there is more pathname, go back to * cloop, otherwise return. */ if(bp != NULL) brelse(bp); if(flag==2 && c=='\0') { if(access(dp, IWRITE)) goto out; return(dp); } d = dp->i_dev; if(up->u_dent.d_ino == ROOTINO) if(dp->i_number == ROOTINO) if(up->u_dent.d_name[1] == '.') for(i=1; ii_count++; plock(dp); goto seloop; } iput(dp); dp = iget(d, up->u_dent.d_ino); if(dp == NULL) return(NULL); goto cloop; out: iput(dp); return(NULL); } /* * Return the next character from the * kernel string pointed at by dirp. */ schar() { return(*u.u_dirp++ & 0377); } /* * Return the next character from the * user string pointed at by dirp. */ uchar() { register c; c = fubyte((caddr_t)u.u_dirp++); if(c == -1) u.u_error = EFAULT; return(c); }