From 5ac7a7db9a79ac81f83b61150e73bc7bf0f14d61 Mon Sep 17 00:00:00 2001 From: Asanka Herath Date: Wed, 13 Jun 2007 23:25:45 +0000 Subject: [PATCH] windows-magic-share-names-20070613 Access to AFS volumes via magic share names \\afs\ = cellname = % or # = volume name or id --- src/WINNT/afsd/cm_vnodeops.c | 169 +++++++++++++++++++++++++++++++++++++------ src/WINNT/afsd/cm_vnodeops.h | 16 +++- src/WINNT/afsd/smb.c | 30 ++++++++ 3 files changed, 191 insertions(+), 24 deletions(-) diff --git a/src/WINNT/afsd/cm_vnodeops.c b/src/WINNT/afsd/cm_vnodeops.c index 4b3921e..5c29700 100644 --- a/src/WINNT/afsd/cm_vnodeops.c +++ b/src/WINNT/afsd/cm_vnodeops.c @@ -1292,6 +1292,114 @@ int cm_ExpandSysName(char *inp, char *outp, long outSize, unsigned int index) return 1; } +long cm_EvaluateVolumeReference(char * namep, long flags, cm_user_t * userp, + cm_req_t *reqp, cm_scache_t ** outpScpp) +{ + long code = 0; + char cellName[CELL_MAXNAMELEN]; + char volumeName[VL_MAXNAMELEN]; + size_t len; + char * cp; + char * tp; + + cm_cell_t * cellp = NULL; + cm_volume_t * volp = NULL; + cm_fid_t fid; + int volType; + int mountType = RWVOL; + + osi_Log1(afsd_logp, "cm_EvaluateVolumeReference for string [%s]", + osi_LogSaveString(afsd_logp, namep)); + + if (strnicmp(namep, CM_PREFIX_VOL, CM_PREFIX_VOL_CCH) != 0) { + goto _exit_invalid_path; + } + + /* namep is assumed to look like the following: + + @vol:%\0 + or + @vol:#\0 + + */ + + cp = namep + CM_PREFIX_VOL_CCH; /* cp points to cell name, hopefully */ + tp = strchr(cp, '%'); + if (tp == NULL) + tp = strchr(cp, '#'); + if (tp == NULL || + (len = tp - cp) == 0 || + len > CELL_MAXNAMELEN) + goto _exit_invalid_path; + strncpy(cellName, cp, len); + cellName[len] = '\0'; + + if (*tp == '#') + mountType = ROVOL; + + cp = tp+1; /* cp now points to volume, supposedly */ + strncpy(volumeName, cp, VL_MAXNAMELEN-1); + volumeName[VL_MAXNAMELEN - 1] = 0; + + /* OK, now we have the cell and the volume */ + osi_Log2(afsd_logp, " Found cell [%s] and volume [%s]", + osi_LogSaveString(afsd_logp, cellName), + osi_LogSaveString(afsd_logp, volumeName)); + + cellp = cm_GetCell(cellName, CM_FLAG_CREATE); + if (cellp == NULL) { + goto _exit_invalid_path; + } + + len = strlen(volumeName); + if (len >= 8 && strcmp(volumeName + len - 7, ".backup") == 0) + volType = BACKVOL; + else if (len >= 10 && + strcmp(volumeName + len - 9, ".readonly") == 0) + volType = ROVOL; + else + volType = RWVOL; + + if (cm_VolNameIsID(volumeName)) { + code = cm_GetVolumeByID(cellp, atoi(volumeName), userp, reqp, + CM_GETVOL_FLAG_CREATE, &volp); + } else { + code = cm_GetVolumeByName(cellp, volumeName, userp, reqp, + CM_GETVOL_FLAG_CREATE, &volp); + } + + if (code != 0) + goto _exit_cleanup; + + fid.cell = cellp->cellID; + + if (volType == BACKVOL) + fid.volume = volp->bk.ID; + else if (volType == ROVOL || + (volType == RWVOL && mountType == ROVOL && volp->ro.ID != 0)) + fid.volume = volp->ro.ID; + else + fid.volume = volp->rw.ID; + + fid.vnode = 1; + fid.unique = 1; + + code = cm_GetSCache(&fid, outpScpp, userp, reqp); + + _exit_cleanup: + if (volp) + cm_PutVolume(volp); + + if (code == 0) + return code; + + _exit_invalid_path: + if (flags & CM_FLAG_CHECKPATH) + return CM_ERROR_NOSUCHPATH; + else + return CM_ERROR_NOSUCHFILE; +} + #ifdef DEBUG_REFCOUNT long cm_LookupDbg(cm_scache_t *dscp, char *namep, long flags, cm_user_t *userp, cm_req_t *reqp, cm_scache_t **outpScpp, char * file, long line) @@ -1317,32 +1425,47 @@ long cm_Lookup(cm_scache_t *dscp, char *namep, long flags, cm_user_t *userp, return CM_ERROR_NOSUCHFILE; } - for ( sysNameIndex = 0; sysNameIndex < MAXNUMSYSNAMES; sysNameIndex++) { - code = cm_ExpandSysName(namep, tname, sizeof(tname), sysNameIndex); - if (code > 0) { - code = cm_LookupInternal(dscp, tname, flags, userp, reqp, &scp); + if (dscp == cm_data.rootSCachep && + strnicmp(namep, CM_PREFIX_VOL, CM_PREFIX_VOL_CCH) == 0) { + return cm_EvaluateVolumeReference(namep, flags, userp, reqp, outpScpp); + } + + if (cm_ExpandSysName(namep, NULL, 0, 0) > 0) { + for ( sysNameIndex = 0; sysNameIndex < MAXNUMSYSNAMES; sysNameIndex++) { + code = cm_ExpandSysName(namep, tname, sizeof(tname), sysNameIndex); + if (code > 0) { + code = cm_LookupInternal(dscp, tname, flags, userp, reqp, &scp); #ifdef DEBUG_REFCOUNT - afsi_log("%s:%d cm_LookupInternal (1) code 0x%x dscp 0x%p ref %d scp 0x%p ref %d", file, line, code, dscp, dscp->refCount, scp, scp ? scp->refCount : 0); - osi_Log3(afsd_logp, "cm_LookupInternal (1) code 0x%x dscp 0x%p scp 0x%p", code, dscp, scp); + afsi_log("%s:%d cm_LookupInternal (1) code 0x%x dscp 0x%p ref %d scp 0x%p ref %d", file, line, code, dscp, dscp->refCount, scp, scp ? scp->refCount : 0); + osi_Log3(afsd_logp, "cm_LookupInternal (1) code 0x%x dscp 0x%p scp 0x%p", code, dscp, scp); #endif - if (code == 0) { + if (code == 0) { + *outpScpp = scp; + return 0; + } + if (scp) { + cm_ReleaseSCache(scp); + scp = NULL; + } + } else { + code = cm_LookupInternal(dscp, namep, flags, userp, reqp, &scp); +#ifdef DEBUG_REFCOUNT + afsi_log("%s:%d cm_LookupInternal (2) code 0x%x dscp 0x%p ref %d scp 0x%p ref %d", file, line, code, dscp, dscp->refCount, scp, scp ? scp->refCount : 0); + osi_Log3(afsd_logp, "cm_LookupInternal (2) code 0x%x dscp 0x%p scp 0x%p", code, dscp, scp); +#endif *outpScpp = scp; - return 0; - } - if (scp) { - cm_ReleaseSCache(scp); - scp = NULL; + return code; } - } else { - code = cm_LookupInternal(dscp, namep, flags, userp, reqp, &scp); + } + } else { + code = cm_LookupInternal(dscp, namep, flags, userp, reqp, &scp); #ifdef DEBUG_REFCOUNT - afsi_log("%s:%d cm_LookupInternal (2) code 0x%x dscp 0x%p ref %d scp 0x%p ref %d", file, line, code, dscp, dscp->refCount, scp, scp ? scp->refCount : 0); - osi_Log3(afsd_logp, "cm_LookupInternal (2) code 0x%x dscp 0x%p scp 0x%p", code, dscp, scp); + afsi_log("%s:%d cm_LookupInternal (2) code 0x%x dscp 0x%p ref %d scp 0x%p ref %d", file, line, code, dscp, dscp->refCount, scp, scp ? scp->refCount : 0); + osi_Log3(afsd_logp, "cm_LookupInternal (2) code 0x%x dscp 0x%p scp 0x%p", code, dscp, scp); #endif - *outpScpp = scp; - return code; - } + *outpScpp = scp; + return code; } /* None of the possible sysName expansions could be found */ @@ -3910,11 +4033,11 @@ long cm_Lock(cm_scache_t *scp, unsigned char sLockType, if (code != 0 && (scp->sharedLocks > 0 || scp->exclusiveLocks > 0) && - scp->serverLock == -1) { - /* Oops. We lost the lock. */ - cm_LockMarkSCacheLost(scp); - } + scp->serverLock == -1) { + /* Oops. We lost the lock. */ + cm_LockMarkSCacheLost(scp); } + } } else if (code == 0) { /* server locks not enabled */ osi_Log0(afsd_logp, " Skipping server lock for scp"); diff --git a/src/WINNT/afsd/cm_vnodeops.h b/src/WINNT/afsd/cm_vnodeops.h index 86a37db..96c41de 100644 --- a/src/WINNT/afsd/cm_vnodeops.h +++ b/src/WINNT/afsd/cm_vnodeops.h @@ -45,6 +45,17 @@ typedef struct cm_lookupSearch { typedef int (*cm_DirFuncp_t)(struct cm_scache *, struct cm_dirEntry *, void *, osi_hyper_t *entryOffsetp); +/* Special path syntax for direct references to volumes + + The syntax: @vol:{%,#} can be used to refer to a + specific volume in a specific cell, where: + + : name of the cell + : volume name or ID + */ +#define CM_PREFIX_VOL "@vol:" +#define CM_PREFIX_VOL_CCH 5 + /* arrays */ extern unsigned char cm_foldUpper[]; @@ -69,7 +80,10 @@ extern void cm_Gen8Dot3NameInt(const char * longname, cm_dirFid_t * pfid, char *shortName, char **shortNameEndp); extern long cm_ReadMountPoint(cm_scache_t *scp, cm_user_t *userp, - cm_req_t *reqp); + cm_req_t *reqp); + +extern long cm_EvaluateVolumeReference(char * namep, long flags, cm_user_t * userp, + cm_req_t *reqp, cm_scache_t ** outpScpp); #ifdef DEBUG_REFCOUNT extern long cm_NameIDbg(cm_scache_t *rootSCachep, char *pathp, long flags, diff --git a/src/WINNT/afsd/smb.c b/src/WINNT/afsd/smb.c index 8c877fa..ed99919 100644 --- a/src/WINNT/afsd/smb.c +++ b/src/WINNT/afsd/smb.c @@ -1634,6 +1634,36 @@ int smb_FindShare(smb_vc_t *vcp, smb_user_t *uidp, char *shareName, return 0; } + /* Check for volume references + * + * They look like {%,#} + */ + if (strchr(shareName, '%') != NULL || + strchr(shareName, '#') != NULL) { + char pathstr[CELL_MAXNAMELEN + VL_MAXNAMELEN + 1 + CM_PREFIX_VOL_CCH]; + /* make room for '/@vol:' + mountchar + NULL terminator*/ + + osi_Log1(smb_logp, "smb_FindShare found volume reference [%s]", + osi_LogSaveString(smb_logp, shareName)); + + snprintf(pathstr, sizeof(pathstr)/sizeof(char), + "/" CM_PREFIX_VOL "%s", shareName); + pathstr[sizeof(pathstr)/sizeof(char) - 1] = '\0'; + len = strlen(pathstr); + + *pathNamep = malloc(len); + if (*pathNamep) { + strcpy(*pathNamep, pathstr); + strlwr(*pathNamep); + osi_Log1(smb_logp, " returning pathname [%s]", + osi_LogSaveString(smb_logp, *pathNamep)); + + return 1; + } else { + return 0; + } + } + code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY "\\Submounts", 0, KEY_QUERY_VALUE, &parmKey); if (code == ERROR_SUCCESS) { -- 1.9.4