118 }
119
120 startvp = vp;
121 next:
122 retry_with_kcred = B_FALSE;
123
124 /*
125 * Make sure we have a directory.
126 */
127 if (vp->v_type != VDIR) {
128 error = ENOTDIR;
129 goto bad;
130 }
131
132 if (rpnp && VN_CMP(vp, rootvp))
133 (void) pn_set(rpnp, "/");
134
135 /*
136 * Process the next component of the pathname.
137 */
138 if (error = pn_getcomponent(pnp, component)) {
139 goto bad;
140 }
141
142 /*
143 * Handle "..": two special cases.
144 * 1. If we're at the root directory (e.g. after chroot or
145 * zone_enter) then change ".." to "." so we can't get
146 * out of this subtree.
147 * 2. If this vnode is the root of a mounted file system,
148 * then replace it with the vnode that was mounted on
149 * so that we take the ".." in the other file system.
150 */
151 if (component[0] == '.' && component[1] == '.' && component[2] == 0) {
152 checkforroot:
153 if (VN_CMP(vp, rootvp)) {
154 component[1] = '\0';
155 } else if (vp->v_flag & VROOT) {
156 vfs_t *vfsp;
157 cvp = vp;
158
290 cvp = tvp;
291 goto bad;
292 }
293 cvp = tvp;
294 }
295
296 /*
297 * If we hit a symbolic link and there is more path to be
298 * translated or this operation does not wish to apply
299 * to a link, then place the contents of the link at the
300 * front of the remaining pathname.
301 */
302 if (cvp->v_type == VLNK && ((flags & FOLLOW) || pn_pathleft(pnp))) {
303 struct pathname linkpath;
304
305 if (++nlink > MAXSYMLINKS) {
306 error = ELOOP;
307 goto bad;
308 }
309 pn_alloc(&linkpath);
310 if (error = pn_getsymlink(cvp, &linkpath, cr)) {
311 pn_free(&linkpath);
312 goto bad;
313 }
314
315 if (pn_pathleft(&linkpath) == 0)
316 (void) pn_set(&linkpath, ".");
317 error = pn_insert(pnp, &linkpath, strlen(component));
318 pn_free(&linkpath);
319 if (error)
320 goto bad;
321 VN_RELE(cvp);
322 cvp = NULL;
323 if (pnp->pn_pathlen == 0) {
324 error = ENOENT;
325 goto bad;
326 }
327 if (pnp->pn_path[0] == '/') {
328 do {
329 pnp->pn_path++;
330 pnp->pn_pathlen--;
|
118 }
119
120 startvp = vp;
121 next:
122 retry_with_kcred = B_FALSE;
123
124 /*
125 * Make sure we have a directory.
126 */
127 if (vp->v_type != VDIR) {
128 error = ENOTDIR;
129 goto bad;
130 }
131
132 if (rpnp && VN_CMP(vp, rootvp))
133 (void) pn_set(rpnp, "/");
134
135 /*
136 * Process the next component of the pathname.
137 */
138 if ((error = pn_getcomponent(pnp, component)) != 0) {
139 goto bad;
140 }
141
142 /*
143 * Handle "..": two special cases.
144 * 1. If we're at the root directory (e.g. after chroot or
145 * zone_enter) then change ".." to "." so we can't get
146 * out of this subtree.
147 * 2. If this vnode is the root of a mounted file system,
148 * then replace it with the vnode that was mounted on
149 * so that we take the ".." in the other file system.
150 */
151 if (component[0] == '.' && component[1] == '.' && component[2] == 0) {
152 checkforroot:
153 if (VN_CMP(vp, rootvp)) {
154 component[1] = '\0';
155 } else if (vp->v_flag & VROOT) {
156 vfs_t *vfsp;
157 cvp = vp;
158
290 cvp = tvp;
291 goto bad;
292 }
293 cvp = tvp;
294 }
295
296 /*
297 * If we hit a symbolic link and there is more path to be
298 * translated or this operation does not wish to apply
299 * to a link, then place the contents of the link at the
300 * front of the remaining pathname.
301 */
302 if (cvp->v_type == VLNK && ((flags & FOLLOW) || pn_pathleft(pnp))) {
303 struct pathname linkpath;
304
305 if (++nlink > MAXSYMLINKS) {
306 error = ELOOP;
307 goto bad;
308 }
309 pn_alloc(&linkpath);
310 if ((error = pn_getsymlink(cvp, &linkpath, cr)) != 0) {
311 pn_free(&linkpath);
312 goto bad;
313 }
314
315 if (pn_pathleft(&linkpath) == 0)
316 (void) pn_set(&linkpath, ".");
317 error = pn_insert(pnp, &linkpath, strlen(component));
318 pn_free(&linkpath);
319 if (error)
320 goto bad;
321 VN_RELE(cvp);
322 cvp = NULL;
323 if (pnp->pn_pathlen == 0) {
324 error = ENOENT;
325 goto bad;
326 }
327 if (pnp->pn_path[0] == '/') {
328 do {
329 pnp->pn_path++;
330 pnp->pn_pathlen--;
|