/* vfs_lookup.c 4.13 82/03/13 */
* Convert a pathname into a pointer to
* 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
* follow = 1 if links are to be followed at the end of the name
namei(func
, flag
, follow
)
int (*func
)(), flag
, follow
;
register struct inode
*dp
;
register struct buf
*bp
, *nbp
;
register struct direct
*ep
;
* allocate name buffer; copy name
for (i
=0, cp
= nbp
->b_un
.b_addr
; *cp
= (*func
)(); i
++) {
if ((*cp
&0377) == ('/'|0200)) {
if (*cp
++&0200 && flag
==1 || cp
>= nbp
->b_un
.b_addr
+BSIZE
) {
if (cp
>= nbp
->b_un
.b_addr
+BSIZE
) {
* If name starts with '/' start from
* root; otherwise start from current dir.
if ((dp
= u
.u_rdir
) == NULL
)
* dp must be a directory and
* must have X permission.
* cp is a path name relative to that directory.
if ((dp
->i_mode
&IFMT
) != IFDIR
)
(void) access(dp
, IEXEC
);
for (i
=0; *cp
!='\0' && *cp
!='/'; i
++) {
if (u
.u_dbuf
[0] == '\0') { /* null name, e.g. "/" or "" */
for (u
.u_offset
=0; u
.u_offset
< dp
->i_size
;
u
.u_offset
+= sizeof(struct direct
), ep
++) {
* If offset is on a block boundary,
* read the next directory block.
* Release previous if it exists.
if ((u
.u_offset
&BMASK
) == 0) {
bmap(dp
,(daddr_t
)(u
.u_offset
>>BSHIFT
), B_READ
));
if (bp
->b_flags
& B_ERROR
) {
ep
= (struct direct
*)bp
->b_un
.b_addr
;
* Note first empty directory slot
* in eo for possible creat.
* String compare the directory entry
* and the current component.
if (strncmp(u
.u_dbuf
, ep
->d_name
, DIRSIZ
) != 0)
* Here a component matched in a directory.
* If there is more pathname, go back to
* dirloop, otherwise return.
bcopy((caddr_t
)ep
, (caddr_t
)&u
.u_dent
, sizeof(struct direct
));
if (flag
==2 && *cp
=='\0') {
u
.u_offset
+= sizeof(struct direct
);
* Special handling for ".."
if (u
.u_dent
.d_name
[0]=='.' && u
.u_dent
.d_name
[1]=='.' &&
u
.u_dent
.d_name
[2]=='\0') {
u
.u_dent
.d_ino
= dp
->i_number
;
else if (u
.u_dent
.d_ino
==ROOTINO
&&
dp
->i_number
== ROOTINO
) {
if (mount
[i
].m_bufp
!= NULL
&&
mount
[i
].m_dev
== dp
->i_dev
) {
cp
-= 2; /* back over .. */
dp
= iget(d
, u
.u_dent
.d_ino
);
* Check for symbolic link
if ((dp
->i_mode
&IFMT
)==IFLNK
&& (follow
|| *cp
=='/')) {
if (dp
->i_size
+ (cp
-ocp
) >= BSIZE
-1 || ++nlink
>8) {
bcopy(ocp
, nbp
->b_un
.b_addr
+dp
->i_size
,
bp
= bread(dp
->i_dev
, bmap(dp
, (daddr_t
)0, B_READ
));
if (bp
->b_flags
& B_ERROR
) {
bcopy(bp
->b_un
.b_addr
, nbp
->b_un
.b_addr
,
if ((dp
= u
.u_rdir
) == NULL
)
if (flag
==1 && *cp
=='\0' && dp
->i_nlink
) {
* Return the next character from the
* kernel string pointed at by dirp.
return (*u
.u_dirp
++ & 0377);
* Return the next character from the
* user string pointed at by dirp.