X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=libsysio%2Fsrc%2Fnamei.c;h=63e610ec16819208dcc901ffff16de715c64015f;hb=7b6aaef15a6547550c99cdaa538ea8b1d4d87c88;hp=b4d856997ef05a6d4afb0e7e400846f66cdfac2a;hpb=8692f4651696ff4324db3ad738d3fa62f68d7347;p=fs%2Flustre-release.git diff --git a/libsysio/src/namei.c b/libsysio/src/namei.c index b4d8569..63e610e 100644 --- a/libsysio/src/namei.c +++ b/libsysio/src/namei.c @@ -9,7 +9,7 @@ * terms of the GNU Lesser General Public License * (see cit/LGPL or http://www.gnu.org/licenses/lgpl.html) * - * Cplant(TM) Copyright 1998-2003 Sandia Corporation. + * Cplant(TM) Copyright 1998-2006 Sandia Corporation. * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive * license for use of this work by or on behalf of the US Government. * Export of this program may require a license from the United States @@ -41,14 +41,11 @@ * lee@sandia.gov */ -#if defined(AUTOMOUNT_FILE_NAME) && defined(__linux__) -#define _BSD_SOURCE -#endif - #include #include #include #include +#include #include #include #include @@ -87,15 +84,26 @@ lookup(struct pnode *parent, struct qstr *name, struct pnode **pnop, struct intent *intnt, - const char *path) + const char *path, + int check_permissions) { - struct pnode *pno; int err; + struct pnode *pno; if (!parent->p_base->pb_ino) return -ENOTDIR; /* + * Sometimes we don't want to check permissions. At initialization + * time, for instance. + */ + if (check_permissions) { + err = _sysio_permitted(parent, X_OK); + if (err) + return err; + } + + /* * Short-circuit `.' and `..'; We don't cache those. */ pno = NULL; @@ -146,6 +154,7 @@ lookup(struct pnode *parent, * ND_NOFOLLOW symbolic links are not followed * ND_NEGOK if terminal/leaf does not exist, return * path node (alias) anyway. + * ND_NOPERMCHECK do not check permissions */ int _sysio_path_walk(struct pnode *parent, struct nameidata *nd) @@ -177,6 +186,30 @@ _sysio_path_walk(struct pnode *parent, struct nameidata *nd) parent = nd->nd_root; } +#ifdef DEFER_INIT_CWD + if (!parent) { + const char *icwd; + + if (!_sysio_init_cwd && !nd->nd_root) + abort(); + + /* + * Finally have to set the current working directory. We can + * not tolerate errors here or else risk leaving the process + * in a very unexpected location. We abort then unless all goes + * well. + */ + icwd = _sysio_init_cwd; + _sysio_init_cwd = NULL; + parent = nd->nd_root; + if (!parent) + abort(); + (void )_sysio_namei(nd->nd_root, icwd, 0, NULL, &parent); + if (_sysio_p_chdir(parent) != 0) + abort(); + } +#endif + /* * (Re)Validate the parent. */ @@ -200,7 +233,7 @@ _sysio_path_walk(struct pnode *parent, struct nameidata *nd) */ for (;;) { ino = nd->nd_pno->p_base->pb_ino; - if (S_ISLNK(ino->i_mode) && + if (S_ISLNK(ino->i_stbuf.st_mode) && (next.len || !(nd->nd_flags & ND_NOFOLLOW))) { char *lpath; ssize_t cc; @@ -231,12 +264,14 @@ _sysio_path_walk(struct pnode *parent, struct nameidata *nd) lpath[cc] = '\0'; /* NUL term */ /* * Handle symbolic links with recursion. Yuck! + * Pass the NULL intent for recursive symlink + * except the last component. */ ND_INIT(&nameidata, - (nd->nd_flags | ND_NEGOK), + nd->nd_flags, lpath, nd->nd_root, - nd->nd_intent); + !next.len ? nd->nd_intent : NULL); nameidata.nd_slicnt = nd->nd_slicnt + 1; err = _sysio_path_walk(nd->nd_pno->p_parent, &nameidata); @@ -249,10 +284,10 @@ _sysio_path_walk(struct pnode *parent, struct nameidata *nd) } #ifdef AUTOMOUNT_FILE_NAME else if (ino && - S_ISDIR(ino->i_mode) && + S_ISDIR(ino->i_stbuf.st_mode) && (nd->nd_pno->p_mount->mnt_flags & MOUNT_F_AUTO) && nd->nd_amcnt < MAX_MOUNT_DEPTH && - ino->i_mode & S_ISUID) { + ino->i_stbuf.st_mode & S_ISUID) { struct pnode *pno; /* @@ -266,7 +301,8 @@ _sysio_path_walk(struct pnode *parent, struct nameidata *nd) &_sysio_mount_file_name, &pno, NULL, - NULL); + NULL, + 1); if (pno) P_RELE(pno); if (!err && _sysio_automount(pno) == 0) { @@ -336,7 +372,7 @@ _sysio_path_walk(struct pnode *parent, struct nameidata *nd) /* * Parent must be a directory. */ - if (ino && !S_ISDIR(ino->i_mode)) { + if (ino && !S_ISDIR(ino->i_stbuf.st_mode)) { err = -ENOTDIR; break; } @@ -379,7 +415,8 @@ _sysio_path_walk(struct pnode *parent, struct nameidata *nd) (path || !next.len) ? nd->nd_intent : NULL, - (path && next.len) ? path : NULL); + (path && next.len) ? path : NULL, + !(nd->nd_flags & ND_NOPERMCHECK)); if (err) { if (err == -ENOENT && !next.len && @@ -415,7 +452,8 @@ _sysio_path_walk(struct pnode *parent, struct nameidata *nd) * Make sure the last processed component was a directory. The * trailing slashes are illegal behind anything else. */ - if (!(err || S_ISDIR(nd->nd_pno->p_base->pb_ino->i_mode))) + if (!(err || + S_ISDIR(nd->nd_pno->p_base->pb_ino->i_stbuf.st_mode))) err = -ENOTDIR; }