unc-enable-fs-20040601
[openafs.git] / src / WINNT / afsd / cm_ioctl.c
index 9125589..ebafa91 100644 (file)
@@ -28,6 +28,7 @@
 #include "afsd_init.h"
 
 #include "smb.h"
+#include "cm_server.h"
 
 #ifndef DJGPP
 #include <rx/rxkad.h>
@@ -48,9 +49,6 @@
 #define MAX_PATH 260
 
 osi_mutex_t cm_Afsdsbmt_Lock;
-#ifdef AFS_FREELANCE_CLIENT
-extern osi_mutex_t cm_Freelance_Lock;
-#endif
 
 extern afs_int32 cryptall;
 
@@ -137,30 +135,62 @@ void TranslateExtendedChars(char *str)
 long cm_ParseIoctlPath(smb_ioctl_t *ioctlp, cm_user_t *userp, cm_req_t *reqp,
        cm_scache_t **scpp)
 {
+    extern char cm_NetbiosName[];
        long code;
        cm_scache_t *substRootp;
-
-        /* This is usually the file name, but for StatMountPoint it is the path. */
-       TranslateExtendedChars(ioctlp->inDatap);
-
-       code = cm_NameI(cm_rootSCachep, ioctlp->prefix->data,
-               CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
-               userp, ioctlp->tidPathp, reqp, &substRootp);
-       if (code) return code;
+    char * relativePath = ioctlp->inDatap;
+
+    /* This is usually the file name, but for StatMountPoint it is the path. */
+    /* ioctlp->inDatap can be either of the form:
+     *    \path\.
+     *    \path\file
+     *    \\netbios-name\submount\path\.
+     *    \\netbios-name\submount\path\file
+     */
+       TranslateExtendedChars(relativePath);
+
+    if (relativePath[0] == relativePath[1] &&
+         relativePath[1] == '\\' && 
+         !_strnicmp(cm_NetbiosName,relativePath+2,strlen(cm_NetbiosName))) 
+    {
+        /* We may have found a UNC path. 
+         * If the first component is the NetbiosName,
+         * then throw out the second component (the submount)
+         * since it had better expand into the value of ioctl->tidPathp
+         */
+        char * p;
+        p = relativePath + 2 + strlen(cm_NetbiosName) + 1;
+        if ( !_strnicmp("all", p, 3) )
+            p += 4;
+
+        code = cm_NameI(cm_rootSCachep, ioctlp->prefix->data,
+                         CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
+                         userp, p, reqp, &substRootp);
+        if (code) return code;
         
-        code = cm_NameI(substRootp, ioctlp->inDatap, CM_FLAG_FOLLOW,
-               userp, NULL, reqp, scpp);
-       if (code) return code;
+        code = cm_NameI(substRootp, ".", CM_FLAG_FOLLOW,
+                         userp, NULL, reqp, scpp);
+        if (code) return code;
+    } else {
+        code = cm_NameI(cm_rootSCachep, ioctlp->prefix->data,
+                         CM_FLAG_CASEFOLD | CM_FLAG_FOLLOW,
+                         userp, ioctlp->tidPathp, reqp, &substRootp);
+        if (code) return code;
         
+        code = cm_NameI(substRootp, relativePath, CM_FLAG_FOLLOW,
+                         userp, NULL, reqp, scpp);
+        if (code) return code;
+    }
+
        /* # of bytes of path */
-        code = strlen(ioctlp->inDatap) + 1;
-        ioctlp->inDatap += code;
+    code = strlen(ioctlp->inDatap) + 1;
+    ioctlp->inDatap += code;
 
-        /* This is usually nothing, but for StatMountPoint it is the file name. */
-        TranslateExtendedChars(ioctlp->inDatap);
+    /* This is usually nothing, but for StatMountPoint it is the file name. */
+    TranslateExtendedChars(ioctlp->inDatap);
 
        /* and return success */
-        return 0;
+    return 0;
 }
 
 void cm_SkipIoctlPath(smb_ioctl_t *ioctlp)
@@ -941,18 +971,55 @@ long cm_IoctlNewCell(struct smb_ioctl *ioctlp, struct cm_user *userp)
      * cell list will be cm_CellLock and cm_ServerLock will be held for write.
     */  
   
-    cm_cell_t *tcellp;
+    cm_cell_t *cp;
+    cm_cell_t *tcp;
   
     cm_SkipIoctlPath(ioctlp);
     lock_ObtainWrite(&cm_cellLock);
   
-    for(tcellp = cm_allCellsp; tcellp; tcellp=tcellp->nextp) 
+    for(cp = cm_allCellsp; cp; cp=cp->nextp) 
     {
+        long code;
+      top:
         /* delete all previous server lists - cm_FreeServerList will ask for write on cm_ServerLock*/
-        cm_FreeServerList(&tcellp->vlServersp);
-        tcellp->vlServersp = NULL;
-        cm_SearchCellFile(tcellp->namep, tcellp->namep, cm_AddCellProc, tcellp);
-        cm_RandomizeServer(&tcellp->vlServersp);
+        cm_FreeServerList(&cp->vlServersp);
+        cp->vlServersp = NULL;
+        code = cm_SearchCellFile(cp->namep, cp->namep, cm_AddCellProc, cp);
+               if (code) {
+#ifdef AFS_AFSDB_ENV
+            if (cm_dnsEnabled) {
+                int ttl;
+                code = cm_SearchCellByDNS(cp->namep, cp->namep, &ttl, cm_AddCellProc, cp);
+                if ( code ) {
+                    if ( cm_allCellsp == cp )
+                        cm_allCellsp = cp->nextp;
+                    else {
+                        for(tcp = cm_allCellsp; tcp->nextp; tcp=tcp->nextp) {
+                            if ( tcp->nextp == cp ) {
+                                tcp->nextp = cp->nextp;
+                                break;
+                            }
+                        }
+                    }   
+                    
+                    lock_FinalizeMutex(&cp->mx);
+                    free(cp->namep);
+                }
+                else {   /* got cell from DNS */
+                    cp->flags |= CM_CELLFLAG_DNS;
+                    cp->timeout = time(0) + ttl;
+                }
+            }
+#endif /* AFS_AFSDB_ENV */
+        }
+        if (code) {
+            tcp = cp;
+            cp = cp->nextp;
+            free(tcp);
+            goto top;
+        }
+        else
+            cm_RandomizeServer(&cp->vlServersp);
     }
     
     lock_ReleaseWrite(&cm_cellLock);
@@ -1063,7 +1130,8 @@ long cm_IoctlSetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp)
        vlonly     = spin->flags;
        if ( vlonly )
                type = CM_SERVER_VLDB;
-       else    type = CM_SERVER_FILE;
+       else    
+        type = CM_SERVER_FILE;
 
        for ( i=0; i < noServers; i++) 
        {
@@ -1073,7 +1141,7 @@ long cm_IoctlSetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp)
                tmp.sin_family = AF_INET;
 
                tsp = cm_FindServer(&tmp, type);
-               if ( tsp )              /* an existing server */
+               if ( tsp )              /* an existing server - ref count increased */
                {
                        tsp->ipRank = rank; /* no need to protect by mutex*/
 
@@ -1089,13 +1157,13 @@ long cm_IoctlSetSPrefs(struct smb_ioctl *ioctlp, struct cm_user *userp)
                            /* set preferences for an existing vlserver */
                            cm_ChangeRankCellVLServer(tsp);
                        }
+            cm_PutServer(tsp);  /* decrease refcount */
                }
-               else                    /* add a new server without a cell*/
+               else    /* add a new server without a cell */
                {
-                       tsp = cm_NewServer(&tmp, type, NULL);
+                       tsp = cm_NewServer(&tmp, type, NULL); /* refcount = 1 */
                        tsp->ipRank = rank;
                }
-               cm_PutServer(tsp);
        }
        return 0;
 }
@@ -1157,53 +1225,53 @@ long cm_IoctlStoreBehind(struct smb_ioctl *ioctlp, struct cm_user *userp)
 long cm_IoctlCreateMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
 {
        char leaf[256];
-        long code;
-        cm_scache_t *dscp;
-        cm_attr_t tattr;
-        char *cp;
+    long code;
+    cm_scache_t *dscp;
+    cm_attr_t tattr;
+    char *cp;
        cm_req_t req;
-        char mpInfo[256];
-        char fullCell[256];
+    char mpInfo[256];
+    char fullCell[256];
        char volume[256];
        char cell[256];
        int ttl;
 
        cm_InitReq(&req);
         
-        code = cm_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf);
-        if (code) return code;
+    code = cm_ParseIoctlParent(ioctlp, userp, &req, &dscp, leaf);
+    if (code) return code;
 
-        /* Translate chars for the mount point name */
-        TranslateExtendedChars(leaf);
+    /* Translate chars for the mount point name */
+    TranslateExtendedChars(leaf);
 
-        /* 
-         * The fs command allows the user to specify partial cell names on NT.  These must
-         * be expanded to the full cell name for mount points so that the mount points will
-         * work on UNIX clients.
-         */
+    /* 
+     * The fs command allows the user to specify partial cell names on NT.  These must
+     * be expanded to the full cell name for mount points so that the mount points will
+     * work on UNIX clients.
+     */
 
        /* Extract the possibly partial cell name */
        strcpy(cell, ioctlp->inDatap + 1);      /* Skip the mp type character */
         
-        if (cp = strchr(cell, ':')) {
+    if (cp = strchr(cell, ':')) {
                /* Extract the volume name */
-               *cp = 0;
+        *cp = 0;
                strcpy(volume,  cp + 1);
        
-               /* Get the full name for this cell */
-               code = cm_SearchCellFile(cell, fullCell, 0, 0);
+        /* Get the full name for this cell */
+        code = cm_SearchCellFile(cell, fullCell, 0, 0);
 #ifdef AFS_AFSDB_ENV
                if (code && cm_dnsEnabled)
-                  code = cm_SearchCellByDNS(cell, fullCell, &ttl, 0, 0);
+            code = cm_SearchCellByDNS(cell, fullCell, &ttl, 0, 0);
 #endif
-                 if (code)
+        if (code)
                        return CM_ERROR_NOSUCHCELL;
        
-               sprintf(mpInfo, "%c%s:%s", *ioctlp->inDatap, fullCell, volume);
+        sprintf(mpInfo, "%c%s:%s", *ioctlp->inDatap, fullCell, volume);
        } else {
-               /* No cell name specified */
-               strcpy(mpInfo, ioctlp->inDatap);
-        }
+        /* No cell name specified */
+        strcpy(mpInfo, ioctlp->inDatap);
+    }
 
 #ifdef AFS_FREELANCE_CLIENT
        if (cm_freelanceEnabled && dscp == cm_rootSCachep) {
@@ -1214,21 +1282,20 @@ long cm_IoctlCreateMountPoint(struct smb_ioctl *ioctlp, struct cm_user *userp)
        }
 #endif
        /* create the symlink with mode 644.  The lack of X bits tells
-         * us that it is a mount point.
-         */
+     * us that it is a mount point.
+     */
        tattr.mask = CM_ATTRMASK_UNIXMODEBITS | CM_ATTRMASK_CLIENTMODTIME;
-        tattr.unixModeBits = 0644;
+    tattr.unixModeBits = 0644;
        tattr.clientModTime = time(NULL);
 
-        code = cm_SymLink(dscp, leaf, mpInfo, 0, &tattr, userp, &req);
+    code = cm_SymLink(dscp, leaf, mpInfo, 0, &tattr, userp, &req);
        if (code == 0 && (dscp->flags & CM_SCACHEFLAG_ANYWATCH))
                smb_NotifyChange(FILE_ACTION_ADDED,
-                                FILE_NOTIFY_CHANGE_DIR_NAME,
-                                dscp, leaf, NULL, TRUE);
-
-        cm_ReleaseSCache(dscp);
+                         FILE_NOTIFY_CHANGE_DIR_NAME,
+                         dscp, leaf, NULL, TRUE);
 
-        return code;
+    cm_ReleaseSCache(dscp);
+    return code;
 }
 
 long cm_IoctlSymlink(struct smb_ioctl *ioctlp, struct cm_user *userp)
@@ -1981,7 +2048,15 @@ long cm_IoctlMemoryDump(struct smb_ioctl *ioctlp, struct cm_user *userp)
     cm_SkipIoctlPath(ioctlp);
     memcpy(&inValue, ioctlp->inDatap, sizeof(long));
   
-    GetWindowsDirectory(logfileName, sizeof(logfileName));
+    if (getenv("TEMP"))
+    {
+        strncpy(logfileName, getenv("TEMP"), MAX_PATH);
+        logfileName[MAX_PATH] = '\0';
+    }
+    else
+    {
+        GetWindowsDirectory(logfileName, sizeof(logfileName));
+    }
     strncat(logfileName, "\\afsd_alloc.log", sizeof(logfileName));
 
     hLogFile = CreateFile(logfileName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);