xref: /csrg-svn/sys/kern/vfs_lookup.c (revision 2275)
1*2275Swnj /*	vfs_lookup.c	4.3	01/26/81	*/
230Sbill 
330Sbill #include "../h/param.h"
430Sbill #include "../h/systm.h"
530Sbill #include "../h/inode.h"
630Sbill #include "../h/mount.h"
730Sbill #include "../h/dir.h"
830Sbill #include "../h/user.h"
930Sbill #include "../h/buf.h"
10*2275Swnj #include "../h/conf.h"
1130Sbill 
1230Sbill /*
1330Sbill  * Convert a pathname into a pointer to
1430Sbill  * an inode. Note that the inode is locked.
1530Sbill  *
1630Sbill  * func = function called to get next char of name
1730Sbill  *	&uchar if name is in user space
1830Sbill  *	&schar if name is in system space
1930Sbill  * flag = 0 if name is sought
2030Sbill  *	1 if name is to be created
2130Sbill  *	2 if name is to be deleted
2230Sbill  */
2330Sbill struct inode *
2430Sbill namei(func, flag)
2530Sbill int (*func)();
2630Sbill {
2730Sbill 	register struct inode *dp;
2830Sbill 	register c;
2930Sbill 	register char *cp;
3030Sbill 	struct buf *bp;
31194Sbill 	register struct direct *ep;
3230Sbill 	int i;
3330Sbill 	dev_t d;
3430Sbill 	off_t eo;
3530Sbill 
3630Sbill 	/*
3730Sbill 	 * If name starts with '/' start from
3830Sbill 	 * root; otherwise start from current dir.
3930Sbill 	 */
4030Sbill 
4130Sbill 	dp = u.u_cdir;
4230Sbill 	if((c=(*func)()) == '/')
4330Sbill 		if ((dp = u.u_rdir) == NULL)
4430Sbill 			dp = rootdir;
45194Sbill 	(void) iget(dp->i_dev, dp->i_number);
4630Sbill 	while(c == '/')
4730Sbill 		c = (*func)();
4830Sbill 	if(c == '\0' && flag != 0)
4930Sbill 		u.u_error = ENOENT;
5030Sbill 
5130Sbill cloop:
5230Sbill 	/*
5330Sbill 	 * Here dp contains pointer
5430Sbill 	 * to last component matched.
5530Sbill 	 */
5630Sbill 
5730Sbill 	if(u.u_error)
5830Sbill 		goto out;
5930Sbill 	if(c == '\0')
6030Sbill 		return(dp);
6130Sbill 
62*2275Swnj #ifdef CHAOS
63*2275Swnj 	if((dp->i_mode&IFMT) == IFCHR && cdevpath & (1 << major(dp->i_un.i_rdev)) ) {
64*2275Swnj 		u.u_dirp--;
65*2275Swnj 		return(dp);
66*2275Swnj 	}
67*2275Swnj #endif
68*2275Swnj 
6930Sbill 	/*
7030Sbill 	 * If there is another component,
7130Sbill 	 * Gather up name into
7230Sbill 	 * users' dir buffer.
7330Sbill 	 */
7430Sbill 
7530Sbill 	cp = &u.u_dbuf[0];
7630Sbill 	while (c != '/' && c != '\0' && u.u_error == 0 ) {
7730Sbill 		if (mpxip!=NULL && c=='!')
7830Sbill 			break;
791777Sbill 		if (flag==1 && c == ('/'|0200)) {
801777Sbill 			u.u_error = ENOENT;
811777Sbill 			goto out;
821777Sbill 		}
83194Sbill 		if (cp < &u.u_dbuf[DIRSIZ])
8430Sbill 			*cp++ = c;
8530Sbill 		c = (*func)();
8630Sbill 	}
8730Sbill 	while(cp < &u.u_dbuf[DIRSIZ])
8830Sbill 		*cp++ = '\0';
8930Sbill 	while(c == '/')
9030Sbill 		c = (*func)();
9130Sbill 	if (c == '!' && mpxip != NULL) {
9230Sbill 		iput(dp);
9330Sbill 		plock(mpxip);
9430Sbill 		mpxip->i_count++;
9530Sbill 		return(mpxip);
9630Sbill 	}
9730Sbill 
9830Sbill seloop:
9930Sbill 	/*
10030Sbill 	 * dp must be a directory and
10130Sbill 	 * must have X permission.
10230Sbill 	 */
10330Sbill 
10430Sbill 	if((dp->i_mode&IFMT) != IFDIR)
10530Sbill 		u.u_error = ENOTDIR;
106194Sbill 	(void) access(dp, IEXEC);
10730Sbill 	if(u.u_error)
10830Sbill 		goto out;
10930Sbill 
11030Sbill 	/*
11130Sbill 	 * set up to search a directory
11230Sbill 	 */
11330Sbill 	u.u_offset = 0;
11430Sbill 	u.u_segflg = 1;
11530Sbill 	eo = 0;
11630Sbill 	bp = NULL;
11730Sbill 
11830Sbill eloop:
11930Sbill 
12030Sbill 	/*
12130Sbill 	 * If at the end of the directory,
12230Sbill 	 * the search failed. Report what
12330Sbill 	 * is appropriate as per flag.
12430Sbill 	 */
12530Sbill 
12630Sbill 	if(u.u_offset >= dp->i_size) {
12730Sbill 		if(bp != NULL)
12830Sbill 			brelse(bp);
129265Sbill 		if(flag==1 && c=='\0' && dp->i_nlink) {
13030Sbill 			if(access(dp, IWRITE))
13130Sbill 				goto out;
13230Sbill 			u.u_pdir = dp;
13330Sbill 			if(eo)
13430Sbill 				u.u_offset = eo-sizeof(struct direct);
13530Sbill 			else
13630Sbill 				dp->i_flag |= IUPD|ICHG;
13730Sbill 			return(NULL);
13830Sbill 		}
13930Sbill 		u.u_error = ENOENT;
14030Sbill 		goto out;
14130Sbill 	}
14230Sbill 
14330Sbill 	/*
14430Sbill 	 * If offset is on a block boundary,
14530Sbill 	 * read the next directory block.
14630Sbill 	 * Release previous if it exists.
14730Sbill 	 */
14830Sbill 
14930Sbill 	if((u.u_offset&BMASK) == 0) {
15030Sbill 		if(bp != NULL)
15130Sbill 			brelse(bp);
15230Sbill 		bp = bread(dp->i_dev,
15330Sbill 			bmap(dp, (daddr_t)(u.u_offset>>BSHIFT), B_READ));
15430Sbill 		if (bp->b_flags & B_ERROR) {
15530Sbill 			brelse(bp);
15630Sbill 			goto out;
15730Sbill 		}
158194Sbill 		ep = (struct direct *)bp->b_un.b_addr;
159194Sbill 	} else
160194Sbill 		ep++;
16130Sbill 
16230Sbill 	/*
16330Sbill 	 * Note first empty directory slot
16430Sbill 	 * in eo for possible creat.
16530Sbill 	 * String compare the directory entry
16630Sbill 	 * and the current component.
16730Sbill 	 * If they do not match, go back to eloop.
16830Sbill 	 */
16930Sbill 
17030Sbill 	u.u_offset += sizeof(struct direct);
171194Sbill 	if(ep->d_ino == 0) {
17230Sbill 		if(eo == 0)
17330Sbill 			eo = u.u_offset;
17430Sbill 		goto eloop;
17530Sbill 	}
17630Sbill 	for(i=0; i<DIRSIZ; i++) {
177194Sbill 		if(u.u_dbuf[i] != ep->d_name[i])
17830Sbill 			goto eloop;
17930Sbill 		if(u.u_dbuf[i] == 0)
18030Sbill 			break;
18130Sbill 	}
18230Sbill 
18330Sbill 	/*
18430Sbill 	 * Here a component matched in a directory.
18530Sbill 	 * If there is more pathname, go back to
18630Sbill 	 * cloop, otherwise return.
18730Sbill 	 */
188194Sbill 	bcopy((caddr_t)ep, (caddr_t)&u.u_dent, sizeof(struct direct));
18930Sbill 	if(bp != NULL)
19030Sbill 		brelse(bp);
19130Sbill 	if(flag==2 && c=='\0') {
19230Sbill 		if(access(dp, IWRITE))
19330Sbill 			goto out;
19430Sbill 		return(dp);
19530Sbill 	}
19630Sbill 	d = dp->i_dev;
19730Sbill 	if(u.u_dent.d_ino == ROOTINO)
19830Sbill 	if(dp->i_number == ROOTINO)
19930Sbill 	if(u.u_dent.d_name[1] == '.')
20030Sbill 		for(i=1; i<NMOUNT; i++)
20130Sbill 			if(mount[i].m_bufp != NULL)
20230Sbill 			if(mount[i].m_dev == d) {
20330Sbill 				iput(dp);
20430Sbill 				dp = mount[i].m_inodp;
20530Sbill 				dp->i_count++;
20630Sbill 				plock(dp);
20730Sbill 				goto seloop;
20830Sbill 			}
20930Sbill 	iput(dp);
21030Sbill 	dp = iget(d, u.u_dent.d_ino);
21130Sbill 	if(dp == NULL)
21230Sbill 		return(NULL);
21330Sbill 	goto cloop;
21430Sbill 
21530Sbill out:
21630Sbill 	iput(dp);
21730Sbill 	return(NULL);
21830Sbill }
21930Sbill 
22030Sbill /*
22130Sbill  * Return the next character from the
22230Sbill  * kernel string pointed at by dirp.
22330Sbill  */
22430Sbill schar()
22530Sbill {
22630Sbill 
22730Sbill 	return(*u.u_dirp++ & 0377);
22830Sbill }
22930Sbill 
23030Sbill /*
23130Sbill  * Return the next character from the
23230Sbill  * user string pointed at by dirp.
23330Sbill  */
23430Sbill uchar()
23530Sbill {
23630Sbill 	register c;
23730Sbill 
23830Sbill 	c = fubyte(u.u_dirp++);
23930Sbill 	if(c == -1)
24030Sbill 		u.u_error = EFAULT;
24130Sbill 	return(c);
24230Sbill }
243