return 0;
}
sp->caseFold = casefold;
+ }
- /* see if we can find it using the directory hash tables.
- we can only do exact matches, since the hash is case
- sensitive. */
- {
- cm_dirOp_t dirop;
+ /*
+ * see if we can find it using the directory hash tables.
+ * we can only do exact matches, since the hash is case
+ * sensitive.
+ */
+ if (funcp != (cm_DirFuncp_t)cm_BPlusDirFoo)
+ {
+ cm_dirOp_t dirop;
#ifdef USE_BPLUS
- int usedBplus = 0;
+ int usedBplus = 0;
#endif
- code = ENOENT;
+ code = ENOENT;
- code = cm_BeginDirOp(scp, userp, reqp, CM_DIRLOCK_READ, &dirop);
- if (code == 0) {
+ code = cm_BeginDirOp(scp, userp, reqp, CM_DIRLOCK_READ, &dirop);
+ if (code == 0) {
#ifdef USE_BPLUS
- code = cm_BPlusDirLookup(&dirop, sp->nsearchNamep, &sp->fid);
- if (code != EINVAL)
- usedBplus = 1;
- else
+ code = cm_BPlusDirLookup(&dirop, sp->nsearchNamep, &sp->fid);
+ if (code != EINVAL)
+ usedBplus = 1;
+ else
#endif
- code = cm_DirLookup(&dirop, sp->searchNamep, &sp->fid);
+ code = cm_DirLookup(&dirop, sp->searchNamep, &sp->fid);
- cm_EndDirOp(&dirop);
- }
+ cm_EndDirOp(&dirop);
+ }
- if (code == 0) {
+ if (code == 0) {
+ /* found it */
+ sp->found = TRUE;
+ sp->ExactFound = TRUE;
+ *retscp = NULL; /* force caller to call cm_GetSCache() */
+ return 0;
+ }
+#ifdef USE_BPLUS
+ if (usedBplus) {
+ if (sp->caseFold && code == CM_ERROR_INEXACT_MATCH) {
/* found it */
sp->found = TRUE;
- sp->ExactFound = TRUE;
+ sp->ExactFound = FALSE;
*retscp = NULL; /* force caller to call cm_GetSCache() */
return 0;
}
-#ifdef USE_BPLUS
- if (usedBplus) {
- if (sp->caseFold && code == CM_ERROR_INEXACT_MATCH) {
- /* found it */
- sp->found = TRUE;
- sp->ExactFound = FALSE;
- *retscp = NULL; /* force caller to call cm_GetSCache() */
- return 0;
- }
-
- return CM_ERROR_BPLUS_NOMATCH;
- }
-#endif
+
+ return CM_ERROR_BPLUS_NOMATCH;
}
+#endif
}
}
{
fschar_t *cellNamep = NULL;
fschar_t *volNamep = NULL;
- int tlen;
afs_uint32 code;
fschar_t *cp;
fschar_t *mpNamep;
mpNamep = scp->mountPointStringp;
if (!mpNamep[0])
return CM_ERROR_NOSUCHPATH;
- tlen = cm_FsStrLen(scp->mountPointStringp);
mtType = *scp->mountPointStringp;
cp = cm_FsStrChr(mpNamep, _FS(':'));
int getroot;
normchar_t *nnamep = NULL;
fschar_t *fnamep = NULL;
+ size_t fnlen;
*outScpp = NULL;
goto done;
}
+retry_lookup:
if (flags & CM_FLAG_NOMOUNTCHASE) {
/* In this case, we should go and call cm_Dir* functions
directly since the following cm_ApplyDir() function will
goto haveFid;
}
- return CM_ERROR_BPLUS_NOMATCH;
+ code = CM_ERROR_BPLUS_NOMATCH;
+ goto notfound;
}
#endif
}
* that we stopped early, probably because we found the entry we're
* looking for. Any other non-zero code is an error.
*/
- if (code && code != CM_ERROR_STOPNOW) {
+ if (code && code != CM_ERROR_STOPNOW && code != CM_ERROR_BPLUS_NOMATCH) {
/* if the cm_scache_t we are searching in is not a directory
* we must return path not found because the error
* is to describe the final component not an intermediary
goto done;
}
+notfound:
getroot = (dscp==cm_data.rootSCachep) ;
if (!rock.found) {
if (!cm_freelanceEnabled || !getroot) {
/* nonexistent dir on freelance root, so add it */
fschar_t fullname[CELL_MAXNAMELEN + 1] = "."; /* +1 so that when we skip the . the size is still CELL_MAXNAMELEN */
int found = 0;
+ int retry = 0;
osi_Log1(afsd_logp,"cm_Lookup adding mount for non-existent directory: %S",
osi_LogSaveClientString(afsd_logp,cnamep));
*/
code = -1;
+ fnlen = strlen(fnamep);
+ if ( fnamep[fnlen-1] == '.') {
+ fnamep[fnlen-1] = '\0';
+ fnlen--;
+ retry = 1;
+ }
+
if (cnamep[0] == '.') {
if (cm_GetCell_Gen(&fnamep[1], &fullname[1], CM_FLAG_CREATE)) {
found = 1;
- if (!cm_FreelanceMountPointExists(fullname, 0))
- code = cm_FreelanceAddMount(fullname, &fullname[1], "root.cell.",
- 1, &rock.fid);
- if ( cm_FsStrCmpI(&fnamep[1], &fullname[1]) &&
- !cm_FreelanceMountPointExists(fnamep, flags & CM_FLAG_DFS_REFERRAL ? 1 : 0) &&
- !cm_FreelanceSymlinkExists(fnamep, flags & CM_FLAG_DFS_REFERRAL ? 1 : 0))
- code = cm_FreelanceAddSymlink(fnamep, fullname, &rock.fid);
+ code = cm_FreelanceAddMount(fullname, &fullname[1], "root.cell.", 1, &rock.fid);
+ if ( cm_FsStrCmpI(&fnamep[1], &fullname[1])) {
+ /*
+ * Do not permit symlinks that are one of:
+ * . the cellname followed by a dot
+ * . the cellname minus a single character
+ * . a substring of the cellname that does not consist of full components
+ */
+ if ( cm_strnicmp_utf8(&fnamep[1], fullname, (int)fnlen-1) == 0 &&
+ (fnlen-1 == strlen(fullname)-1 || fullname[fnlen-1] != '.'))
+ {
+ /* do not add; substitute fullname for the search */
+ free(fnamep);
+ fnamep = malloc(strlen(fullname)+2);
+ fnamep[0] = '.';
+ strncpy(&fnamep[1], fullname, strlen(fullname)+1);
+ retry = 1;
+ } else {
+ code = cm_FreelanceAddSymlink(fnamep, fullname, &rock.fid);
+ }
+ }
}
} else {
if (cm_GetCell_Gen(fnamep, fullname, CM_FLAG_CREATE)) {
found = 1;
- if (!cm_FreelanceMountPointExists(fullname, 0))
- code = cm_FreelanceAddMount(fullname, fullname, "root.cell.", 0, &rock.fid);
- if ( cm_FsStrCmpI(fnamep, fullname) &&
- !cm_FreelanceMountPointExists(fnamep, flags & CM_FLAG_DFS_REFERRAL ? 1 : 0) &&
- !cm_FreelanceSymlinkExists(fnamep, flags & CM_FLAG_DFS_REFERRAL ? 1 : 0))
- code = cm_FreelanceAddSymlink(fnamep, fullname, &rock.fid);
+ code = cm_FreelanceAddMount(fullname, fullname, "root.cell.", 0, &rock.fid);
+ if ( cm_FsStrCmpI(fnamep, fullname)) {
+ /*
+ * Do not permit symlinks that are one of:
+ * . the cellname followed by a dot
+ * . the cellname minus a single character
+ * . a substring of the cellname that does not consist of full components
+ */
+ if ( cm_strnicmp_utf8(fnamep, fullname, (int)fnlen-1) == 0 &&
+ (fnlen == strlen(fullname)-1 || fullname[fnlen] != '.'))
+ {
+ /* do not add; substitute fullname for the search */
+ free(fnamep);
+ fnamep = strdup(fullname);
+ code = 0;
+ retry = 1;
+ } else {
+ code = cm_FreelanceAddSymlink(fnamep, fullname, &rock.fid);
+ }
+ }
}
}
+
+ if (retry) {
+ if (nnamep)
+ free(nnamep);
+ nnamep = cm_FsStringToNormStringAlloc(fnamep, -1, NULL);
+ goto retry_lookup;
+ }
+
if (!found || code) { /* add mount point failed, so give up */
if (flags & CM_FLAG_CHECKPATH)
code = CM_ERROR_NOSUCHPATH;
}
}
- haveFid:
+ haveFid:
if ( !tscp ) /* we did not find it in the dnlc */
{
dnlcHit = 0;