08800 #include "../h/param.h" 08801 #include "../h/systm.h" 08802 #include "../h/inode.h" 08803 #include "../h/mount.h" 08804 #include "../h/dir.h" 08805 #include "../h/user.h" 08806 #include "../h/buf.h" 08807 08808 /* 08809 * Convert a pathname into a pointer to 08810 * an inode. Note that the inode is locked. 08811 * 08812 * func = function called to get next char of name 08813 * &uchar if name is in user space 08814 * &schar if name is in system space 08815 * flag = 0 if name is sought 08816 * 1 if name is to be created 08817 * 2 if name is to be deleted 08818 */ 08819 struct inode */ 08820 namei(func, flag) 08821 int (*func)(); 08822 { 08823 register struct inode *dp; 08824 register c; 08825 register char *cp; 08826 struct buf *bp; 08827 int i; 08828 dev_t d; 08829 off_t eo; 08830 08831 /* 08832 * If name starts with '/' start from 08833 * root; otherwise start from current dir. 08834 */ 08835 08836 dp = u.u_cdir; 08837 if((c=(*func)()) == '/') 08838 if ((dp = u.u_rdir) == NULL) 08839 dp = rootdir; 08840 iget(dp->i_dev, dp->i_number); 08841 while(c == '/') 08842 c = (*func)(); 08843 if(c == '\0' && flag != 0) 08844 u.u_error = ENOENT; 08845 08846 cloop: 08847 /* 08848 * Here dp contains pointer 08849 * to last component matched. 08850 */ 08851 08852 if(u.u_error) 08853 goto out; 08854 if(c == '\0') 08855 return(dp); 08856 08857 /* 08858 * If there is another component, 08859 * Gather up name into 08860 * users' dir buffer. 08861 */ 08862 08863 cp = &u.u_dbuf[0]; 08864 while (c != '/' && c != '\0' && u.u_error == 0 ) { 08865 if (mpxip!=NULL && c=='!') 08866 break; 08867 if(cp < &u.u_dbuf[DIRSIZ]) 08868 *cp++ = c; 08869 c = (*func)(); 08870 } 08871 while(cp < &u.u_dbuf[DIRSIZ]) 08872 *cp++ = '\0'; 08873 while(c == '/') 08874 c = (*func)(); 08875 if (c == '!' && mpxip != NULL) { 08876 iput(dp); 08877 plock(mpxip); 08878 mpxip->i_count++; 08879 return(mpxip); 08880 } 08881 08882 seloop: 08883 /* 08884 * dp must be a directory and 08885 * must have X permission. 08886 */ 08887 08888 if((dp->i_mode&IFMT) != IFDIR) 08889 u.u_error = ENOTDIR; 08890 access(dp, IEXEC); 08891 if(u.u_error) 08892 goto out; 08893 08894 /* 08895 * set up to search a directory 08896 */ 08897 u.u_offset = 0; 08898 u.u_segflg = 1; 08899 eo = 0; 08900 bp = NULL; 08901 08902 eloop: 08903 08904 /* 08905 * If at the end of the directory, 08906 * the search failed. Report what 08907 * is appropriate as per flag. 08908 */ 08909 08910 if(u.u_offset >= dp->i_size) { 08911 if(bp != NULL) 08912 brelse(bp); 08913 if(flag==1 && c=='\0') { 08914 if(access(dp, IWRITE)) 08915 goto out; 08916 u.u_pdir = dp; 08917 if(eo) 08918 u.u_offset = eo-sizeof(struct direct); 08919 else 08920 dp->i_flag |= IUPD|ICHG; 08921 return(NULL); 08922 } 08923 u.u_error = ENOENT; 08924 goto out; 08925 } 08926 08927 /* 08928 * If offset is on a block boundary, 08929 * read the next directory block. 08930 * Release previous if it exists. 08931 */ 08932 08933 if((u.u_offset&BMASK) == 0) { 08934 if(bp != NULL) 08935 brelse(bp); 08936 bp = bread(dp->i_dev, 08937 bmap(dp, (daddr_t)(u.u_offset>>BSHIFT), B_READ)); 08938 if (bp->b_flags & B_ERROR) { 08939 brelse(bp); 08940 goto out; 08941 } 08942 } 08943 08944 /* 08945 * Note first empty directory slot 08946 * in eo for possible creat. 08947 * String compare the directory entry 08948 * and the current component. 08949 * If they do not match, go back to eloop. 08950 */ 08951 08952 bcopy(bp->b_un.b_addr+(u.u_offset&BMASK), (caddr_t)&u.u_dent, 08953 sizeof(struct direct)); 08954 u.u_offset += sizeof(struct direct); 08955 if(u.u_dent.d_ino == 0) { 08956 if(eo == 0) 08957 eo = u.u_offset; 08958 goto eloop; 08959 } 08960 for(i=0; i08961 if(u.u_dbuf[i] != u.u_dent.d_name[i]) 08962 goto eloop; 08963 08964 /* 08965 * Here a component matched in a directory. 08966 * If there is more pathname, go back to 08967 * cloop, otherwise return. 08968 */ 08969 08970 if(bp != NULL) 08971 brelse(bp); 08972 if(flag==2 && c=='\0') { 08973 if(access(dp, IWRITE)) 08974 goto out; 08975 return(dp); 08976 } 08977 d = dp->i_dev; 08978 if(u.u_dent.d_ino == ROOTINO) 08979 if(dp->i_number == ROOTINO) 08980 if(u.u_dent.d_name[1] == '.') 08981 for(i=1; i08982 if(mount[i].m_bufp != NULL) 08983 if(mount[i].m_dev == d) { 08984 iput(dp); 08985 dp = mount[i].m_inodp; 08986 dp->i_count++; 08987 plock(dp); 08988 goto seloop; 08989 } 08990 iput(dp); 08991 dp = iget(d, u.u_dent.d_ino); 08992 if(dp == NULL) 08993 return(NULL); 08994 goto cloop; 08995 08996 out: 08997 iput(dp); 08998 return(NULL); 08999 } 09000 09001 /* 09002 * Return the next character from the 09003 * kernel string pointed at by dirp. 09004 */ 09005 schar() 09006 { 09007 09008 return(*u.u_dirp++ & 0377); 09009 } 09010 09011 /* 09012 * Return the next character from the 09013 * user string pointed at by dirp. 09014 */ 09015 uchar() 09016 { 09017 register c; 09018 09019 c = fubyte(u.u_dirp++); 09020 if(c == -1) 09021 u.u_error = EFAULT; 09022 return(c); 09023 } 09024 09025 09026 09027 09028 09029 09030 09031 09032 09033 09034 09035 09036 09037 09038 09039 09040 09041 09042 09043 09044 09045 09046 09047 09048 09049