* Lookup the target of a symbolic link
* Call VN_HOLD on the output vnode if successful.
* Returns zero on success, error code on failure.
+ * If provided, use a path for confirming we are not linked to ourself.
*
* Note: Caller must hold the AFS global lock.
*/
-int
-uafs_LookupLink(struct usr_vnode *vp, struct usr_vnode *parentVp,
- struct usr_vnode **vpp)
+static int
+uafs_LookupLinkPath(struct usr_vnode *vp, struct usr_vnode *parentVp,
+ char *ppathP, struct usr_vnode **vpp)
{
int code;
int len;
len = MAX_OSI_PATH + 1 - uio.uio_resid;
pathP[len] = '\0';
+ /* are we linked to ourname or ./ourname? ELOOP */
+ if (ppathP) {
+ if ((strcmp(pathP, ppathP) == 0) ||
+ ((pathP[0] == '.') &&
+ (pathP[1] == '/') &&
+ (strcmp(&(pathP[2]), ppathP) == 0))) {
+ return ELOOP;
+ }
+ }
+
/*
* Find the target of the symbolic link
*/
afs_osi_Free(tmpPath, strlen(path) + 1);
return code;
}
- code = uafs_LookupLink(nextVp, vp, &linkVp);
+ code = uafs_LookupLinkPath(nextVp, vp, NULL, &linkVp);
if (code) {
VN_RELE(vp);
VN_RELE(nextVp);
return 0;
}
+int
+uafs_LookupLink(struct usr_vnode *vp, struct usr_vnode *parentVp,
+ struct usr_vnode **vpp)
+{
+ return uafs_LookupLinkPath(vp, parentVp, NULL, vpp);
+}
+
/*
* Lookup the parent of a file or directory given its path
* Call VN_HOLD on the output vnode if successful.