Windows: Prevent cm_FreelanceAddSymlink from creating a symlink ending in a dot
[openafs.git] / src / WINNT / afsd / cm_freelance.c
index f512a1d..115daaa 100644 (file)
@@ -75,7 +75,7 @@ void cm_FreelanceChangeNotifier(void * parmp) {
                 hFreelanceChangeEvent = 0;         
                 return;                            
             }                                      
-            cm_noteLocalMountPointChange();
+            cm_noteLocalMountPointChange(FALSE);
         }
     }
 }
@@ -120,7 +120,7 @@ void cm_FreelanceSymlinkChangeNotifier(void * parmp) {
                 hFreelanceSymlinkChangeEvent = 0;         
                 return;                            
             }                                      
-            cm_noteLocalMountPointChange();
+            cm_noteLocalMountPointChange(FALSE);
         }
     }
 }
@@ -219,7 +219,7 @@ void cm_InitFakeRootDir() {
     if (cm_fakeDirSize != dirSize) {
         if (cm_FakeRootDir)
             free(cm_FakeRootDir);
-        cm_FakeRootDir = malloc(dirSize);
+        cm_FakeRootDir = calloc(dirSize, 1);
         cm_fakeDirSize = dirSize;
     }
 
@@ -358,11 +358,13 @@ int cm_FakeRootFid(cm_fid_t *fidp)
   
 /* called directly from ioctl */
 /* called while not holding freelance lock */
-int cm_noteLocalMountPointChange(void) {
-    lock_ObtainMutex(&cm_Freelance_Lock);
+int cm_noteLocalMountPointChange(afs_int32 locked) {
+    if (!locked)
+        lock_ObtainMutex(&cm_Freelance_Lock);
     cm_data.fakeDirVersion++;
     cm_localMountPointChangeFlag = 1;
-    lock_ReleaseMutex(&cm_Freelance_Lock);
+    if (!locked)
+        lock_ReleaseMutex(&cm_Freelance_Lock);
     return 1;
 }
 
@@ -971,6 +973,7 @@ long cm_FreelanceAddMount(char *filename, char *cellname, char *volume, int rw,
     DWORD dwType, dwSize;
     DWORD dwMountPoints;
     DWORD dwIndex;
+    afs_uint32 code = 0;
 
     /* before adding, verify the cell name; if it is not a valid cell,
        don't add the mount point.
@@ -983,19 +986,21 @@ long cm_FreelanceAddMount(char *filename, char *cellname, char *volume, int rw,
               rw ? "rw" : "ro");
 
     if ( filename[0] == '\0' || cellname[0] == '\0' || volume[0] == '\0' )
-        return -1;
+        return CM_ERROR_INVAL;
 
     if (cellname[0] == '.') {
         if (!cm_GetCell_Gen(&cellname[1], fullname, CM_FLAG_CREATE))
-            return -1;
+            return CM_ERROR_INVAL;
     } else {
         if (!cm_GetCell_Gen(cellname, fullname, CM_FLAG_CREATE))
-            return -1;
+            return CM_ERROR_INVAL;
     }
 
     if ( cm_FreelanceMountPointExists(filename, 0) ||
-         cm_FreelanceSymlinkExists(filename, 0) )
-        return -1;
+         cm_FreelanceSymlinkExists(filename, 0) ) {
+        code = CM_ERROR_EXISTS;
+        goto done;
+    }
     
     osi_Log1(afsd_logp,"Freelance Adding Mount for Cell: %s", 
               osi_LogSaveString(afsd_logp,cellname));
@@ -1076,13 +1081,12 @@ long cm_FreelanceAddMount(char *filename, char *cellname, char *volume, int rw,
     }
 
     /* Do this while we are holding the lock */
-    cm_data.fakeDirVersion++;
-    cm_localMountPointChangeFlag = 1;
+    cm_noteLocalMountPointChange(TRUE);
     lock_ReleaseMutex(&cm_Freelance_Lock);
 
+  done:
     if (fidp) {
         cm_req_t req;
-        afs_uint32 code;
         cm_scache_t *scp;
         clientchar_t *cpath;
 
@@ -1091,6 +1095,12 @@ long cm_FreelanceAddMount(char *filename, char *cellname, char *volume, int rw,
         cpath = cm_FsStringToClientStringAlloc(filename, -1, NULL);        
         if (!cpath)
             return CM_ERROR_NOSUCHPATH;
+
+        if (cm_getLocalMountPointChange()) {   // check for changes
+            cm_clearLocalMountPointChange();    // clear the changefile
+            cm_reInitLocalMountPoints();       // start reinit
+        }
+
         code = cm_NameI(cm_data.rootSCachep, cpath,
                         CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD | CM_FLAG_DFS_REFERRAL,
                         cm_rootUserp, NULL, &req, &scp);
@@ -1101,7 +1111,7 @@ long cm_FreelanceAddMount(char *filename, char *cellname, char *volume, int rw,
         cm_ReleaseSCache(scp);
     }
     
-    return 0;
+    return code;
 }
 
 long cm_FreelanceRemoveMount(char *toremove)
@@ -1205,8 +1215,7 @@ long cm_FreelanceRemoveMount(char *toremove)
 
     if (found) {
         /* Do this while we are holding the lock */
-        cm_data.fakeDirVersion++;
-        cm_localMountPointChangeFlag = 1;
+        cm_noteLocalMountPointChange(TRUE);
     }
     lock_ReleaseMutex(&cm_Freelance_Lock);
     return (found ? 0 : CM_ERROR_NOSUCHFILE);
@@ -1221,8 +1230,10 @@ long cm_FreelanceAddSymlink(char *filename, char *destination, cm_fid_t *fidp)
     DWORD dwType, dwSize;
     DWORD dwSymlinks;
     DWORD dwIndex;
+    afs_uint32 code = 0;
 
-    /* before adding, verify the filename.  If it is already in use, either as 
+    /*
+     * before adding, verify the filename.  If it is already in use, either as
      * as mount point or a cellname, do not permit the creation of the symlink.
      */
     osi_Log2(afsd_logp,"Freelance Add Symlink request: filename=%s destination=%s",
@@ -1232,20 +1243,30 @@ long cm_FreelanceAddSymlink(char *filename, char *destination, cm_fid_t *fidp)
     if ( filename[0] == '\0' || destination[0] == '\0' )
         return CM_ERROR_INVAL;
 
+    /* Do not create the symlink if the name ends in a dot */
+    if ( filename[strlen(filename)-1] == '.')
+        return CM_ERROR_INVAL;
+
     fullname[0] = '\0';
     if (filename[0] == '.') {
         cm_GetCell_Gen(&filename[1], fullname, CM_FLAG_CREATE);
-        if (cm_stricmp_utf8(&filename[1],fullname) == 0)
-            return CM_ERROR_EXISTS;
+        if (cm_stricmp_utf8(&filename[1],fullname) == 0) {
+            code = CM_ERROR_EXISTS;
+            goto done;
+        }
     } else {
         cm_GetCell_Gen(filename, fullname, CM_FLAG_CREATE);
-        if (cm_stricmp_utf8(filename,fullname) == 0)
-            return CM_ERROR_EXISTS;
+        if (cm_stricmp_utf8(filename,fullname) == 0) {
+            code = CM_ERROR_EXISTS;
+            goto done;
+        }
     }
 
     if ( cm_FreelanceMountPointExists(filename, 0) ||
-         cm_FreelanceSymlinkExists(filename, 0) )
-        return CM_ERROR_EXISTS;
+         cm_FreelanceSymlinkExists(filename, 0) ) {
+        code = CM_ERROR_EXISTS;
+        goto done;
+    }
 
     lock_ObtainMutex(&cm_Freelance_Lock);
 
@@ -1305,32 +1326,38 @@ long cm_FreelanceAddSymlink(char *filename, char *destination, cm_fid_t *fidp)
     } 
 
     /* Do this while we are holding the lock */
-    cm_data.fakeDirVersion++;
-    cm_localMountPointChangeFlag = 1;
+    cm_noteLocalMountPointChange(TRUE);
     lock_ReleaseMutex(&cm_Freelance_Lock);
 
+  done:
     if (fidp) {
         cm_req_t req;
-        afs_uint32 code;
         cm_scache_t *scp;
         clientchar_t *cpath;
 
         cm_InitReq(&req);
 
         cpath = cm_FsStringToClientStringAlloc(filename, -1, NULL);        
-        if (!cpath)
-            return CM_ERROR_NOSUCHPATH;
-        code = cm_NameI(cm_data.rootSCachep, cpath,
-                        CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD | CM_FLAG_DFS_REFERRAL,
-                        cm_rootUserp, NULL, &req, &scp);
-        free(cpath);
-        if (code)
-            return code;
-        *fidp = scp->fid;
-        cm_ReleaseSCache(scp);
+        if (!cpath) {
+            code = CM_ERROR_NOSUCHPATH;
+        } else {
+            if (cm_getLocalMountPointChange()) {       // check for changes
+                cm_clearLocalMountPointChange();    // clear the changefile
+                cm_reInitLocalMountPoints();   // start reinit
+            }
+
+            code = cm_NameI(cm_data.rootSCachep, cpath,
+                             CM_FLAG_FOLLOW | CM_FLAG_CASEFOLD | CM_FLAG_DFS_REFERRAL,
+                             cm_rootUserp, NULL, &req, &scp);
+            free(cpath);
+            if (code == 0) {
+                *fidp = scp->fid;
+                cm_ReleaseSCache(scp);
+            }
+        }
     }
 
-    return 0;
+    return code;
 }
 
 long cm_FreelanceRemoveSymlink(char *toremove)
@@ -1388,8 +1415,7 @@ long cm_FreelanceRemoveSymlink(char *toremove)
     
     if (found) {
         /* Do this while we are holding the lock */
-        cm_data.fakeDirVersion++;
-        cm_localMountPointChangeFlag = 1;
+        cm_noteLocalMountPointChange(TRUE);
     }
     lock_ReleaseMutex(&cm_Freelance_Lock);
     return (found ? 0 : CM_ERROR_NOSUCHFILE);