Windows: cm_GetCell_Gen rework cell prefix matching
authorJeffrey Altman <jaltman@your-file-system.com>
Thu, 14 May 2015 22:29:45 +0000 (18:29 -0400)
committerJeffrey Altman <jaltman@your-file-system.com>
Thu, 24 Sep 2015 14:42:17 +0000 (10:42 -0400)
The cm_GetCell_Gen() function permits cells to be searched for by
prefix.  The idea is to permit "cs.cmu.edu" to be abbreviated "cs"
when at CMU.  There are two problems with the current behavior:

1. the existing match rules will accept "cs.c" and "cs.cmu.ed" as
   valid prefix matches.  By not restricting the prefix matching
   to full components the Freelance symlink list can become
   cluttered.

2. the existing match rules will accept the first cell that
   matches even if there are more than one cells that would match.
   this can result in unpredictable behavior since the ordering
   of the cells is not guaranteed.

Instead, fail requests for cell prefixes that are not full component
matches or that would be ambiguous.

Change-Id: I59fb5ea9bba4cebdd71808fc9fae9662456943e0
Reviewed-on: http://gerrit.openafs.org/11886
Reviewed-by: Jeffrey Altman <jaltman@your-file-system.com>
Tested-by: BuildBot <buildbot@rampaginggeek.com>

src/WINNT/afsd/cm_cell.c

index 7d37fed..149b46f 100644 (file)
@@ -168,6 +168,7 @@ cm_cell_t *cm_GetCell_Gen(char *namep, char *newnamep, afs_uint32 flags)
     afs_uint32 hash;
     cm_cell_rock_t rock;
     size_t len;
+    size_t namelen;
     afs_int32 cellID;
 
     if (namep == NULL || !namep[0] || !strcmp(namep,CM_IOCTL_FILENAME_NOSLASH))
@@ -186,6 +187,7 @@ cm_cell_t *cm_GetCell_Gen(char *namep, char *newnamep, afs_uint32 flags)
     if (len == 0)
         return NULL;
     namep = name;
+    namelen = strlen(namep);
 
     hash = CM_CELL_NAME_HASH(namep);
 
@@ -199,13 +201,32 @@ cm_cell_t *cm_GetCell_Gen(char *namep, char *newnamep, afs_uint32 flags)
     }
 
     if (!cp) {
-        for (cp = cm_data.allCellsp; cp; cp=cp->allNextp) {
-            if (strnicmp(namep, cp->name, strlen(namep)) == 0) {
-                strncpy(fullname, cp->name, CELL_MAXNAMELEN);
-                fullname[CELL_MAXNAMELEN-1] = '\0';
-                break;
-            }
-        }
+       /* the name wasn't found but it might be a matching prefix */
+       for (cp = cm_data.allCellsp, cp2 = NULL; cp; cp=cp->allNextp) {
+           if (strnicmp(namep, cp->name, namelen) == 0
+                && (namelen == strlen(cp->name) || cp->name[namelen] == '.')) {
+               if (cp2 != NULL) {
+                   osi_Log5(afsd_logp,
+                             "cm_GetCell_gen ambiguous prefix match: prefix %s matches (%u) %s and (%u) %s",
+                             osi_LogSaveString(afsd_logp,namep),
+                             cp->cellID,
+                             osi_LogSaveString(afsd_logp,cp->name),
+                             cp2->cellID,
+                             osi_LogSaveString(afsd_logp,cp2->name));
+                   cp = NULL;
+                   lock_ReleaseRead(&cm_cellLock);
+                   goto done;
+               }
+               cp2 = cp;
+           }
+       }
+
+       if (cp2 != NULL) {
+           /* an unambiguous prefix match was found */
+           cp = cp2;
+           strncpy(fullname, cp->name, CELL_MAXNAMELEN);
+           fullname[CELL_MAXNAMELEN-1] = '\0';
+       }
     }
 
     if (cp) {
@@ -222,30 +243,36 @@ cm_cell_t *cm_GetCell_Gen(char *namep, char *newnamep, afs_uint32 flags)
             if (cm_stricmp_utf8(namep, cp->name) == 0) {
                 strncpy(fullname, cp->name, CELL_MAXNAMELEN);
                 fullname[CELL_MAXNAMELEN-1] = '\0';
-                break;
+               goto done;
             }
         }
 
-        if (cp)
-            goto done;
-
-        for (cp = cm_data.allCellsp; cp; cp=cp->allNextp) {
-            if (strnicmp(namep, cp->name, strlen(namep)) == 0) {
-                strncpy(fullname, cp->name, CELL_MAXNAMELEN);
-                fullname[CELL_MAXNAMELEN-1] = '\0';
-                break;
-            }
-        }
+       /* the name wasn't found but it might be a matching prefix */
+       for (cp = cm_data.allCellsp, cp2 = NULL; cp; cp=cp->allNextp) {
+           if (strnicmp(namep, cp->name, namelen) == 0
+                && (namelen == strlen(cp->name) || cp->name[namelen] == '.')) {
+               if (cp2 != NULL) {
+                   osi_Log5(afsd_logp,
+                             "cm_GetCell_gen ambiguous prefix match: prefix %s matches (%u) %s and (%u) %s",
+                             osi_LogSaveString(afsd_logp,namep),
+                             cp->cellID,
+                             osi_LogSaveString(afsd_logp,cp->name),
+                             cp2->cellID,
+                             osi_LogSaveString(afsd_logp,cp2->name));
+                   cp = NULL;
+                   goto done;
+               }
+               cp2 = cp;
+           }
+       }
 
-        if (cp) {
-            lock_ReleaseWrite(&cm_cellLock);
-            lock_ObtainMutex(&cp->mx);
-            lock_ObtainWrite(&cm_cellLock);
-            cm_AddCellToNameHashTable(cp);
-            cm_AddCellToIDHashTable(cp);
-            lock_ReleaseMutex(&cp->mx);
-            goto done;
-        }
+       if (cp2 != NULL) {
+           /* an unambiguous prefix match was found */
+           cp = cp2;
+           strncpy(fullname, cp->name, CELL_MAXNAMELEN);
+           fullname[CELL_MAXNAMELEN-1] = '\0';
+           goto done;
+       }
 
         if ( cm_data.freeCellsp != NULL ) {
             cp = cm_data.freeCellsp;