]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
Windows: refactor fs, symlink and fs_utils
authorJeffrey Altman <jaltman@your-file-system.com>
Fri, 3 Jun 2011 18:19:27 +0000 (14:19 -0400)
committerJeffrey Altman <jaltman@openafs.org>
Tue, 7 Jun 2011 13:25:27 +0000 (06:25 -0700)
over the years a large number of duplicated functionality
has been added to symlink.c and fs.c.  Refactor both so all
common functionality is implemented within fs_utils.c.

Ensure that all functionality migrated to fs_utils.c and
symlink.c uses the SafeString library functions.

Update the build rules for afs_shl_ext.dll, afscreds.exe
and afsconfig.exe to support the changes to fs_utils.c.

Remove non-windows components from symlink.c.

Change-Id: Ia7709235600f48c09282246e23b1f13d26f54e28
Reviewed-on: http://gerrit.openafs.org/4777
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Jeffrey Altman <jaltman@openafs.org>
Tested-by: Jeffrey Altman <jaltman@openafs.org>
src/WINNT/afsd/NTMakefile
src/WINNT/afsd/fs.c
src/WINNT/afsd/fs_utils.c
src/WINNT/afsd/fs_utils.h
src/WINNT/afsd/parsemode.c
src/WINNT/afsd/symlink.c
src/WINNT/client_config/NTMakefile
src/WINNT/client_creds/NTMakefile
src/WINNT/client_exp/NTMakefile

index 36016b02443e0f6866be260dc1268724e87e2802..cd00e13395e4d392e2088f612c58cba8c265ccc0 100644 (file)
@@ -173,7 +173,9 @@ AFSIOOBJS=$(OUT)\afsio.obj
 $(AFSIOOBJS): $(AFSROOT)\src\venus\afsio.c
        $(C2OBJ) -DAFS_PTHREAD_ENV /Fo$@ $**
 
-SLOBJS=$(OUT)\symlink.obj $(OUT)\fs_utils.obj
+SLOBJS= $(OUT)\symlink.obj \
+        $(OUT)\fs_utils.obj \
+        $(OUT)\cm_nls.obj
 
 ILIBDIR = $(DESTDIR)\lib
 
index 9363e6ce35379661e82b2bce239012b53e5b48d8..b3d3e1332746b689279d3c3c8008ed2f2ec48fdd 100644 (file)
@@ -50,8 +50,9 @@
 #define CELL_MAXNAMELEN                256
 #define MAXHOSTCHARS           64
 
+static char pn[] = "fs";
+
 static char space[AFS_PIOCTL_MAXSIZE];
-static char tspace[1024];
 
 static struct ubik_client *uclient;
 
@@ -77,7 +78,6 @@ static int MemDumpCmd(struct cmd_syndesc *asp, void *arock);
 static int CSCPolicyCmd(struct cmd_syndesc *asp, void *arock);
 static int MiniDumpCmd(struct cmd_syndesc *asp, void *arock);
 
-static char pn[] = "fs";
 static int rxInitDone = 0;
 
 /*
@@ -255,77 +255,6 @@ PRights(afs_int32 arights, int dfs)
     return 0;
 }
 
-/* this function returns TRUE (1) if the file is in AFS, otherwise false (0) */
-static int
-InAFS(char *apath)
-{
-    struct ViceIoctl blob;
-    cm_ioctlQueryOptions_t options;
-    cm_fid_t fid;
-    afs_int32 code;
-
-    memset(&options, 0, sizeof(options));
-    options.size = sizeof(options);
-    options.field_flags |= CM_IOCTL_QOPTS_FIELD_LITERAL;
-    options.literal = 1;
-    blob.in_size = options.size;    /* no variable length data */
-    blob.in = &options;
-    blob.out_size = sizeof(cm_fid_t);
-    blob.out = (char *) &fid;
-
-    code = pioctl_utf8(apath, VIOCGETFID, &blob, 1);
-    if (code) {
-       if ((errno == EINVAL) || (errno == ENOENT))
-            return 0;
-    }
-    return 1;
-}
-
-static int
-IsFreelanceRoot(char *apath)
-{
-    struct ViceIoctl blob;
-    afs_int32 code;
-
-    blob.in_size = 0;
-    blob.out_size = AFS_PIOCTL_MAXSIZE;
-    blob.out = space;
-
-    code = pioctl_utf8(apath, VIOC_FILE_CELL_NAME, &blob, 1);
-    if (code == 0) {
-        return !cm_strnicmp_utf8N("Freelance.Local.Root",space, blob.out_size);
-    }
-    return 1;   /* assume it is because it is more restrictive that way */
-}
-
-/* return a static pointer to a buffer */
-static char *
-Parent(char *apath)
-{
-    char *tp;
-    if( FAILED(StringCbCopy(tspace, sizeof(tspace), apath))) {
-        fprintf (stderr, "tspace - not enough space");
-        exit(1);
-    }
-    tp = strrchr(tspace, '\\');
-    if (tp) {
-        if (tp - tspace > 2 &&
-            tspace[1] == ':' &&
-            &tspace[2] == tp)
-           *(tp+1) = 0;        /* lv trailing slash so Parent("k:\foo") is "k:\" not "k:" */
-        else
-            *tp = 0;
-    }
-    else {
-       fs_ExtractDriveLetter(apath, tspace);
-       if( FAILED(StringCbCat(tspace, sizeof(tspace), "."))) {
-           fprintf (stderr, "tspace - not enough space");
-           exit(1);
-       }
-    }
-    return tspace;
-}
-
                                 /* added relative add resp. delete    */
                                 /* (so old add really means to set)   */
 enum rtype { add, destroy, deny, reladd, reldel };
@@ -871,177 +800,6 @@ static DWORD IsFreelance(void)
     return enabled;
 }
 
-#define NETBIOSNAMESZ 1024
-static const char * NetbiosName(void)
-{
-    static char buffer[NETBIOSNAMESZ] = "AFS";
-    HKEY  parmKey;
-    DWORD code;
-    DWORD dummyLen;
-    DWORD enabled = 0;
-
-    code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
-                         0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
-    if (code == ERROR_SUCCESS) {
-        dummyLen = sizeof(buffer);
-        code = RegQueryValueEx(parmKey, "NetbiosName", NULL, NULL,
-                              buffer, &dummyLen);
-        RegCloseKey (parmKey);
-    } else {
-       if( FAILED(StringCbCopy(buffer, sizeof(buffer), "AFS"))) {
-           fprintf (stderr, "buffer - not enough space");
-            exit(1);
-       }
-    }
-    return buffer;
-}
-
-#define AFSCLIENT_ADMIN_GROUPNAME "AFS Client Admins"
-
-static BOOL IsAdmin (void)
-{
-    static BOOL fAdmin = FALSE;
-    static BOOL fTested = FALSE;
-
-    if (!fTested)
-    {
-        /* Obtain the SID for the AFS client admin group.  If the group does
-         * not exist, then assume we have AFS client admin privileges.
-         */
-        PSID psidAdmin = NULL;
-        DWORD dwSize, dwSize2;
-        char pszAdminGroup[ MAX_COMPUTERNAME_LENGTH + sizeof(AFSCLIENT_ADMIN_GROUPNAME) + 2 ];
-        char *pszRefDomain = NULL;
-        SID_NAME_USE snu = SidTypeGroup;
-
-        dwSize = sizeof(pszAdminGroup);
-
-        if (!GetComputerName(pszAdminGroup, &dwSize)) {
-            /* Can't get computer name.  We return false in this case.
-               Retain fAdmin and fTested. This shouldn't happen.*/
-            return FALSE;
-        }
-
-        dwSize = 0;
-        dwSize2 = 0;
-
-       if( FAILED(StringCbCat(pszAdminGroup, MAX_COMPUTERNAME_LENGTH + sizeof(AFSCLIENT_ADMIN_GROUPNAME) + 2,"\\"))) {
-           fprintf (stderr, "pszAdminGroup - not enough space");
-            exit(1);
-       }
-       if( FAILED(StringCbCat(pszAdminGroup, MAX_COMPUTERNAME_LENGTH +
-           sizeof(AFSCLIENT_ADMIN_GROUPNAME) + 2, AFSCLIENT_ADMIN_GROUPNAME))) {
-           fprintf (stderr, "pszAdminGroup - not enough space");
-            exit(1);
-       }
-
-        LookupAccountName(NULL, pszAdminGroup, NULL, &dwSize, NULL, &dwSize2, &snu);
-        /* that should always fail. */
-
-        if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
-            /* if we can't find the group, then we allow the operation */
-            fAdmin = TRUE;
-            return TRUE;
-        }
-
-        if (dwSize == 0 || dwSize2 == 0) {
-            /* Paranoia */
-            fAdmin = TRUE;
-            return TRUE;
-        }
-
-        psidAdmin = (PSID)malloc(dwSize); memset(psidAdmin,0,dwSize);
-        assert(psidAdmin);
-        pszRefDomain = (char *)malloc(dwSize2);
-        assert(pszRefDomain);
-
-        if (!LookupAccountName(NULL, pszAdminGroup, psidAdmin, &dwSize, pszRefDomain, &dwSize2, &snu)) {
-            /* We can't lookup the group now even though we looked it up earlier.
-               Could this happen? */
-            fAdmin = TRUE;
-        } else {
-            /* Then open our current ProcessToken */
-            HANDLE hToken;
-
-            if (OpenProcessToken (GetCurrentProcess(), TOKEN_QUERY, &hToken))
-            {
-
-                if (!CheckTokenMembership(hToken, psidAdmin, &fAdmin)) {
-                    /* We'll have to allocate a chunk of memory to store the list of
-                     * groups to which this user belongs; find out how much memory
-                     * we'll need.
-                     */
-                    DWORD dwSize = 0;
-                    PTOKEN_GROUPS pGroups;
-
-                    GetTokenInformation (hToken, TokenGroups, NULL, dwSize, &dwSize);
-
-                    pGroups = (PTOKEN_GROUPS)malloc(dwSize);
-                    assert(pGroups);
-
-                    /* Allocate that buffer, and read in the list of groups. */
-                    if (GetTokenInformation (hToken, TokenGroups, pGroups, dwSize, &dwSize))
-                    {
-                        /* Look through the list of group SIDs and see if any of them
-                         * matches the AFS Client Admin group SID.
-                         */
-                        size_t iGroup = 0;
-                        for (; (!fAdmin) && (iGroup < pGroups->GroupCount); ++iGroup)
-                        {
-                            if (EqualSid (psidAdmin, pGroups->Groups[ iGroup ].Sid)) {
-                                fAdmin = TRUE;
-                            }
-                        }
-                    }
-
-                    if (pGroups)
-                        free(pGroups);
-                }
-
-                /* if do not have permission because we were not explicitly listed
-                 * in the Admin Client Group let's see if we are the SYSTEM account
-                 */
-                if (!fAdmin) {
-                    PTOKEN_USER pTokenUser;
-                    SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY;
-                    PSID pSidLocalSystem = 0;
-                    DWORD gle;
-
-                    GetTokenInformation(hToken, TokenUser, NULL, 0, &dwSize);
-
-                    pTokenUser = (PTOKEN_USER)malloc(dwSize);
-                    assert(pTokenUser);
-
-                    if (!GetTokenInformation(hToken, TokenUser, pTokenUser, dwSize, &dwSize))
-                        gle = GetLastError();
-
-                    if (AllocateAndInitializeSid( &SIDAuth, 1,
-                                                  SECURITY_LOCAL_SYSTEM_RID,
-                                                  0, 0, 0, 0, 0, 0, 0,
-                                                  &pSidLocalSystem))
-                    {
-                        if (EqualSid(pTokenUser->User.Sid, pSidLocalSystem)) {
-                            fAdmin = TRUE;
-                        }
-
-                        FreeSid(pSidLocalSystem);
-                    }
-
-                    if ( pTokenUser )
-                        free(pTokenUser);
-                }
-            }
-        }
-
-        free(psidAdmin);
-        free(pszRefDomain);
-
-        fTested = TRUE;
-    }
-
-    return fAdmin;
-}
-
 static int
 SetACLCmd(struct cmd_syndesc *as, void *arock)
 {
@@ -1062,7 +820,7 @@ SetACLCmd(struct cmd_syndesc *as, void *arock)
         clear = 0;
     plusp = !(as->parms[3].items);
     for(ti=as->parms[0].items; ti;ti=ti->next) {
-        if ( IsFreelanceRoot(ti->data) ) {
+        if ( fs_IsFreelanceRoot(ti->data) ) {
             fprintf(stderr,"%s: ACLs cannot be set on the Freelance root.afs volume.\n", pn);
             error = 1;
             continue;
@@ -1072,7 +830,7 @@ SetACLCmd(struct cmd_syndesc *as, void *arock)
        blob.in = blob.out = space;
        code = pioctl_utf8(ti->data, VIOCGETAL, &blob, 1);
        if (code) {
-           Die(errno, ti->data);
+           fs_Die(errno, ti->data);
            error = 1;
             continue;
        }
@@ -1185,7 +943,7 @@ SetACLCmd(struct cmd_syndesc *as, void *arock)
                             "\t-Tried to add non-existent user to access control list\n");
                }
             } else {
-               Die(errno, ti->data);
+               fs_Die(errno, ti->data);
             }
             error = 1;
         }
@@ -1217,7 +975,7 @@ CopyACLCmd(struct cmd_syndesc *as, void *arock)
     blob.in = blob.out = space;
     code = pioctl_utf8(as->parms[0].items->data, VIOCGETAL, &blob, 1);
     if (code) {
-       Die(errno, as->parms[0].items->data);
+       fs_Die(errno, as->parms[0].items->data);
        return 1;
     }
     fa = ParseAcl(space, AFS_PIOCTL_MAXSIZE);
@@ -1234,7 +992,7 @@ CopyACLCmd(struct cmd_syndesc *as, void *arock)
        blob.in = blob.out = space;
        code = pioctl_utf8(ti->data, VIOCGETAL, &blob, 1);
        if (code) {
-           Die(errno, ti->data);
+           fs_Die(errno, ti->data);
            error = 1;
             continue;
        }
@@ -1290,7 +1048,7 @@ CopyACLCmd(struct cmd_syndesc *as, void *arock)
                         "%s: Invalid argument, possible reasons include:\n", pn);
                fprintf(stderr,"\t-File not in AFS\n");
            } else {
-               Die(errno, ti->data);
+               fs_Die(errno, ti->data);
            }
             error = 1;
        }
@@ -1416,7 +1174,7 @@ CleanACLCmd(struct cmd_syndesc *as, void *arock)
        blob.out = space;
        code = pioctl_utf8(ti->data, VIOCGETAL, &blob, 1);
        if (code) {
-           Die(errno, ti->data);
+           fs_Die(errno, ti->data);
             error = 1;
            continue;
        }
@@ -1460,7 +1218,7 @@ CleanACLCmd(struct cmd_syndesc *as, void *arock)
                             "%s: Too many users on access control list or\n",
                             pn);
                } else {
-                   Die(errno, ti->data);
+                   fs_Die(errno, ti->data);
                }
                 error = 1;
                 continue;
@@ -1510,7 +1268,7 @@ ListACLCmd(struct cmd_syndesc *as, void *arock)
     for(ti=as->parms[0].items; ti; ti=ti->next) {
        char separator;
 
-        if ( IsFreelanceRoot(ti->data) ) {
+        if ( fs_IsFreelanceRoot(ti->data) ) {
             fprintf(stderr,"%s: ACLs are not set on the Freelance root.afs volume.\n", pn);
             error = 1;
             continue;
@@ -1521,7 +1279,7 @@ ListACLCmd(struct cmd_syndesc *as, void *arock)
        blob.in = blob.out = space;
        code = pioctl_utf8(ti->data, VIOCGETAL, &blob, 1);
        if (code) {
-           Die(errno, ti->data);
+           fs_Die(errno, ti->data);
             error = 1;
            continue;
        }
@@ -1762,39 +1520,13 @@ SetVolCmd(struct cmd_syndesc *as, void *arock) {
         }
        code = pioctl_utf8(ti->data,VIOCSETVOLSTAT, &blob, 1);
        if (code) {
-           Die(errno, ti->data);
+           fs_Die(errno, ti->data);
            error = 1;
        }
     }
     return error;
 }
 
-/* values match cache manager File Types */
-static char *
-filetypestr(afs_uint32 type)
-{
-    char * s = "Object";
-
-    switch (type) {
-    case 1:     /* file */
-        s = "File";
-        break;
-    case 2:
-        s = "Directory";
-        break;
-    case 3:
-        s = "Symlink";
-        break;
-    case 4:
-        s = "Mountpoint";
-        break;
-    case 5:
-        s = "DfsLink";
-        break;
-    }
-    return s;
-}
-
 static int
 ExamineCmd(struct cmd_syndesc *as, void *arock)
 {
@@ -1836,7 +1568,7 @@ ExamineCmd(struct cmd_syndesc *as, void *arock)
             options.field_flags |= CM_IOCTL_QOPTS_FIELD_FID;
             options.fid = fid;
         } else {
-           Die(errno, ti->data);
+           fs_Die(errno, ti->data);
            error = 1;
            continue;
         }
@@ -1846,7 +1578,7 @@ ExamineCmd(struct cmd_syndesc *as, void *arock)
 
         code = pioctl_utf8(ti->data, VIOC_GETFILETYPE, &blob, 1);
         if (code || blob.out_size != sizeof(filetype)) {
-           Die(errno, ti->data);
+           fs_Die(errno, ti->data);
            error = 1;
            continue;
         }
@@ -1858,7 +1590,7 @@ ExamineCmd(struct cmd_syndesc *as, void *arock)
         if (code == 0)
             cell[blob.out_size-1] = '\0';
         printf("%s %s (%u.%u.%u) contained in cell %s\n",
-                filetypestr(filetype),
+                fs_filetypestr(filetype),
                 ti->data, fid.volume, fid.vnode, fid.unique,
                 code ? "unknown-cell" : cell);
 
@@ -1905,7 +1637,7 @@ ExamineCmd(struct cmd_syndesc *as, void *arock)
             motd = offmsg + len + 1;
             PrintStatus(status, name, motd, offmsg);
         } else {
-            Die(errno, ti->data);
+            fs_Die(errno, ti->data);
         }
 
         errno = 0;
@@ -1925,7 +1657,7 @@ ExamineCmd(struct cmd_syndesc *as, void *arock)
             break;
         default:
             printf("Unknown volume state\n");
-            Die(errno, ti->data);
+            fs_Die(errno, ti->data);
         }
         printf("\n");
     }
@@ -1953,7 +1685,7 @@ ListQuotaCmd(struct cmd_syndesc *as, void *arock)
        blob.out = space;
        code = pioctl_utf8(ti->data, VIOCGETVOLSTAT, &blob, 1);
        if (code) {
-           Die(errno, ti->data);
+           fs_Die(errno, ti->data);
             error = 1;
            continue;
        }
@@ -2003,7 +1735,7 @@ WhereIsCmd(struct cmd_syndesc *as, void *arock)
             options.field_flags |= CM_IOCTL_QOPTS_FIELD_FID;
             options.fid = fid;
         } else {
-           Die(errno, ti->data);
+           fs_Die(errno, ti->data);
            error = 1;
            continue;
         }
@@ -2013,7 +1745,7 @@ WhereIsCmd(struct cmd_syndesc *as, void *arock)
 
         code = pioctl_utf8(ti->data, VIOC_GETFILETYPE, &blob, 1);
         if (code || blob.out_size != sizeof(filetype)) {
-           Die(errno, ti->data);
+           fs_Die(errno, ti->data);
             error = 1;
            continue;
         }
@@ -2022,13 +1754,13 @@ WhereIsCmd(struct cmd_syndesc *as, void *arock)
        memset(space, 0, sizeof(space));
        code = pioctl_utf8(ti->data, VIOCWHEREIS, &blob, 1);
        if (code) {
-           Die(errno, ti->data);
+           fs_Die(errno, ti->data);
             error = 1;
            continue;
        }
         hosts = (afs_int32 *) space;
        printf("%s %s is on host%s ",
-                filetypestr(filetype),
+                fs_filetypestr(filetype),
                 ti->data,
                 (hosts[0] && !hosts[1]) ? "": "s");
        for(j=0; j<AFS_MAXHOSTS; j++) {
@@ -2063,7 +1795,7 @@ DiskFreeCmd(struct cmd_syndesc *as, void *arock)
        blob.out = space;
        code = pioctl_utf8(ti->data, VIOCGETVOLSTAT, &blob, 1);
        if (code) {
-           Die(errno, ti->data);
+           fs_Die(errno, ti->data);
             error = 1;
            continue;
        }
@@ -2096,7 +1828,7 @@ QuotaCmd(struct cmd_syndesc *as, void *arock)
          * The response is VolumeStatus, volume name, offline message, and motd
          */
        if (code || blob.out_size < sizeof(*status)) {
-           Die(errno, ti->data);
+           fs_Die(errno, ti->data);
             error = 1;
            continue;
        }
@@ -2231,8 +1963,8 @@ ListMountCmd(struct cmd_syndesc *as, void *arock)
            parent_dir[last_component - true_name + 1] = 0;
            last_component++;   /*Skip the slash*/
 #ifdef WIN32
-           if (!InAFS(parent_dir)) {
-               const char * nbname = NetbiosName();
+           if (!fs_InAFS(parent_dir)) {
+               const char * nbname = fs_NetbiosName();
                if( FAILED(StringCbLength(nbname, NETBIOSNAMESZ, &len))) {
                    fprintf (stderr, "StringCbLength failure on nbname");
                    exit(1);
@@ -2293,7 +2025,7 @@ ListMountCmd(struct cmd_syndesc *as, void *arock)
            if (errno == EINVAL) {
                fprintf(stderr,"'%s' is not a mount point.\n", ti->data);
            } else {
-               Die(errno, (ti->data ? ti->data : parent_dir));
+               fs_Die(errno, (ti->data ? ti->data : parent_dir));
            }
            error = 1;
        }
@@ -2342,10 +2074,10 @@ MakeMountCmd(struct cmd_syndesc *as, void *arock)
         volName = ++tmpName;
     }
 
-    parent = Parent(as->parms[0].items->data);
-    if (!InAFS(parent)) {
+    parent = fs_GetParent(as->parms[0].items->data);
+    if (!fs_InAFS(parent)) {
 #ifdef WIN32
-       const char * nbname = NetbiosName();
+       const char * nbname = fs_NetbiosName();
        if ( FAILED(StringCbLength(nbname, NETBIOSNAMESZ, &len))) {
            fprintf (stderr, "StringCbLength failure on nbname");
            exit(1);
@@ -2360,8 +2092,8 @@ MakeMountCmd(struct cmd_syndesc *as, void *arock)
                fprintf (stderr, "path - cannot be populated");
                 exit(1);
             }
-           parent = Parent(path);
-           if (!InAFS(parent)) {
+           parent = fs_GetParent(path);
+           if (!fs_InAFS(parent)) {
                fprintf(stderr,"%s: mount points must be created within the AFS file system\n", pn);
                return 1;
            }
@@ -2383,8 +2115,8 @@ MakeMountCmd(struct cmd_syndesc *as, void *arock)
             exit(1);
        }
     }
-    if ( IsFreelanceRoot(parent) ) {
-       if ( !IsAdmin() ) {
+    if ( fs_IsFreelanceRoot(parent) ) {
+       if ( !fs_IsAdmin() ) {
            fprintf(stderr,"%s: Only AFS Client Administrators may alter the Freelance root.afs volume\n", pn);
            return 1;
        }
@@ -2478,7 +2210,7 @@ MakeMountCmd(struct cmd_syndesc *as, void *arock)
         free(info.linkedCell);
 
     if (code) {
-       Die(errno, path);
+       fs_Die(errno, path);
        return 1;
     }
     return 0;
@@ -2514,8 +2246,8 @@ RemoveMountCmd(struct cmd_syndesc *as, void *arock) {
            tp++;   /* skip the slash */
 
 #ifdef WIN32
-           if (!InAFS(tbuffer)) {
-               const char * nbname = NetbiosName();
+           if (!fs_InAFS(tbuffer)) {
+               const char * nbname = fs_NetbiosName();
                if( FAILED(StringCbLength(nbname, NETBIOSNAMESZ, &len))) {
                    fprintf (stderr, "StringCbLength failure on nbname");
                    exit(1);
@@ -2540,7 +2272,7 @@ RemoveMountCmd(struct cmd_syndesc *as, void *arock) {
                 exit(1);
            }
            tp = ti->data;
-            fs_StripDriveLetter(tp, tp, 0);
+            fs_StripDriveLetter(tp, tp, strlen(tp) + 1);
        }
        blob.in = tp;
        if( FAILED(StringCbLength(tp, AFS_PIOCTL_MAXSIZE, &len))) {
@@ -2555,13 +2287,13 @@ RemoveMountCmd(struct cmd_syndesc *as, void *arock) {
            if (errno == EINVAL) {
                fprintf(stderr,"%s: '%s' is not a mount point.\n", pn, ti->data);
             } else {
-               Die(errno, ti->data);
+               fs_Die(errno, ti->data);
            }
             error = 1;
            continue;   /* don't bother trying */
        }
 
-        if ( IsFreelanceRoot(tbuffer) && !IsAdmin() ) {
+        if ( fs_IsFreelanceRoot(tbuffer) && !fs_IsAdmin() ) {
             fprintf(stderr,"%s: Only AFS Client Administrators may alter the Freelance root.afs volume\n", pn);
             error = 1;
             continue;   /* skip */
@@ -2576,7 +2308,7 @@ RemoveMountCmd(struct cmd_syndesc *as, void *arock) {
        blob.in_size = (long)len+1;
        code = pioctl_utf8(tbuffer, VIOC_AFS_DELETE_MT_PT, &blob, 0);
        if (code) {
-           Die(errno, ti->data);
+           fs_Die(errno, ti->data);
             error = 1;
        }
     }
@@ -2660,7 +2392,7 @@ CheckServersCmd(struct cmd_syndesc *as, void *arock)
 
     if ( checkserv.tinterval >= 0 ) {
 #ifdef WIN32
-        if ( !IsAdmin() ) {
+        if ( !fs_IsAdmin() ) {
             fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");
             return EACCES;
         }
@@ -2678,7 +2410,7 @@ CheckServersCmd(struct cmd_syndesc *as, void *arock)
            printf("Must be root to change -interval\n");
            return code;
        }
-       Die(errno, 0);
+       fs_Die(errno, 0);
         return 1;
     }
 #if _MSC_VER < 1400
@@ -2762,7 +2494,7 @@ MessagesCmd(struct cmd_syndesc *as, void *arock)
 
     code = pioctl_utf8(0, VIOC_GAG, &blob, 1);
     if (code) {
-       Die(errno, 0);
+       fs_Die(errno, 0);
         return 1;
     }
     return 0;
@@ -2778,7 +2510,7 @@ CheckVolumesCmd(struct cmd_syndesc *as, void *arock)
     blob.out_size = 0;
     code = pioctl_utf8(0, VIOCCKBACK, &blob, 1);
     if (code) {
-       Die(errno, 0);
+       fs_Die(errno, 0);
        return 1;
     }
     printf("All volumeID/name mappings checked.\n");
@@ -2794,7 +2526,7 @@ SetCacheSizeCmd(struct cmd_syndesc *as, void *arock)
     afs_int32 temp;
 
 #ifdef WIN32
-    if ( !IsAdmin() ) {
+    if ( !fs_IsAdmin() ) {
         fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");
         return EACCES;
     }
@@ -2822,7 +2554,7 @@ SetCacheSizeCmd(struct cmd_syndesc *as, void *arock)
     blob.out_size = 0;
     code = pioctl_utf8(0, VIOCSETCACHESIZE, &blob, 1);
     if (code) {
-       Die(errno, (char *) 0);
+       fs_Die(errno, (char *) 0);
         return 1;
     }
 
@@ -2844,7 +2576,7 @@ GetCacheParmsCmd(struct cmd_syndesc *as, void *arock)
     blob.out = (char *) &parms;
     code = pioctl_utf8(0, VIOCGETCACHEPARMS, &blob, 1);
     if (code || blob.out_size != sizeof(parms)) {
-       Die(errno, NULL);
+       fs_Die(errno, NULL);
         return 1;
     }
 
@@ -2891,7 +2623,7 @@ ListCellsCmd(struct cmd_syndesc *as, void *arock)
        if (code < 0) {
            if (errno == EDOM)
                 break; /* done with the list */
-            Die(errno, 0);
+            fs_Die(errno, 0);
             return 1;
        }
        tp = space;
@@ -2970,7 +2702,7 @@ ListAliasesCmd(struct cmd_syndesc *as, void *arock)
        if (code < 0) {
            if (errno == EDOM)
                break;          /* done with the list */
-           Die(errno, 0);
+           fs_Die(errno, 0);
            return 1;
        }
         space[blob.out_size - 1] = '\0';
@@ -3028,7 +2760,7 @@ CallBackRxConnCmd(struct cmd_syndesc *as, void *arock)
 
     code = pioctl_utf8(0, VIOC_CBADDR, &blob, 1);
     if (code < 0) {
-       Die(errno, 0);
+       fs_Die(errno, 0);
        return 1;
     }
     return 0;
@@ -3046,7 +2778,7 @@ NewCellCmd(struct cmd_syndesc *as, void *arock)
     afs_uint32 fsport = 0, vlport = 0;
     size_t destRemaining;
 
-    if ( !IsAdmin() ) {
+    if ( !fs_IsAdmin() ) {
         fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");
         return EACCES;
     }
@@ -3061,7 +2793,7 @@ NewCellCmd(struct cmd_syndesc *as, void *arock)
         code = pioctl_utf8((char *) 0, VIOCNEWCELL, &blob, 1);
 
         if (code) {
-            Die(errno, (char *) 0);
+            fs_Die(errno, (char *) 0);
             return 1;
         }
 
@@ -3207,7 +2939,7 @@ NewCellCmd(struct cmd_syndesc *as, void *arock)
     code = pioctl_utf8(NULL, VIOCNEWCELL2, &blob, 1);
 
     if (code) {
-        Die(errno, as->parms[0].items->data);
+        fs_Die(errno, as->parms[0].items->data);
         return 1;
     }
 
@@ -3254,7 +2986,7 @@ NewAliasCmd(struct cmd_syndesc *as, void *arock)
                    "%s: cell name `%s' in use by an existing cell.\n", pn,
                    aliasName);
        } else {
-           Die(errno, 0);
+           fs_Die(errno, 0);
        }
        return 1;
     }
@@ -3298,7 +3030,7 @@ WhichCellCmd(struct cmd_syndesc *as, void *arock)
             options.field_flags |= CM_IOCTL_QOPTS_FIELD_FID;
             options.fid = fid;
         } else {
-           Die(errno, ti->data);
+           fs_Die(errno, ti->data);
            error = 1;
            continue;
         }
@@ -3308,7 +3040,7 @@ WhichCellCmd(struct cmd_syndesc *as, void *arock)
 
         code = pioctl_utf8(ti->data, VIOC_GETFILETYPE, &blob, 1);
         if (code || blob.out_size != sizeof(filetype)) {
-           Die(errno, ti->data);
+           fs_Die(errno, ti->data);
            error = 1;
            continue;
         }
@@ -3320,13 +3052,13 @@ WhichCellCmd(struct cmd_syndesc *as, void *arock)
            if (errno == ENOENT)
                fprintf(stderr,"%s: no such cell as '%s'\n", pn, ti->data);
            else
-               Die(errno, ti->data);
+               fs_Die(errno, ti->data);
            error = 1;
            continue;
        }
         cell[CELL_MAXNAMELEN - 1] = '\0';
         printf("%s %s lives in cell '%s'\n",
-                filetypestr(filetype),
+                fs_filetypestr(filetype),
                 ti->data, cell);
     }
     return error;
@@ -3346,7 +3078,7 @@ WSCellCmd(struct cmd_syndesc *as, void *arock)
     code = pioctl_utf8(NULL, VIOC_GET_WS_CELL, &blob, 1);
 
     if (code) {
-       Die(errno, NULL);
+       fs_Die(errno, NULL);
         return 1;
     }
     space[AFS_PIOCTL_MAXSIZE - 1] = '\0';
@@ -3416,7 +3148,7 @@ MonitorCmd(struct cmd_syndesc *as, void *arock)
     blob.out = (char *) &hostAddr;
     code = pioctl_utf8(0, VIOC_AFS_MARINER_HOST, &blob, 1);
     if (code || blob.out_size != sizeof(afs_int32)) {
-       Die(errno, 0);
+       fs_Die(errno, 0);
        return 1;
     }
     if (setp) {
@@ -3449,7 +3181,7 @@ SysNameCmd(struct cmd_syndesc *as, void *arock)
     ti = as->parms[0].items;
     if (ti) {
 #ifdef WIN32
-    if ( !IsAdmin() ) {
+    if ( !fs_IsAdmin() ) {
         fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");
         return EACCES;
     }
@@ -3499,7 +3231,7 @@ SysNameCmd(struct cmd_syndesc *as, void *arock)
 
     code = pioctl_utf8(0, VIOC_AFS_SYSNAME, &blob, 1);
     if (code) {
-        Die(errno, 0);
+        fs_Die(errno, 0);
         return 1;
     }
     if (setp) {
@@ -3547,7 +3279,7 @@ static int ExportAfsCmd(struct cmd_syndesc *as, void *arock)
     int exportcall, pwsync = 0, smounts = 0;
 
 #ifdef WIN32
-    if ( !IsAdmin() ) {
+    if ( !fs_IsAdmin() ) {
         fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");
         return EACCES;
     }
@@ -3621,7 +3353,7 @@ static int ExportAfsCmd(struct cmd_syndesc *as, void *arock)
            fprintf(stderr,
                     "Sorry, the %s-exporter type is currently not supported on this AFS client\n", exported_types[type]);
        } else {
-           Die(errno, 0);
+           fs_Die(errno, 0);
        }
         return 1;
     } else {
@@ -3678,7 +3410,7 @@ GetCellCmd(struct cmd_syndesc *as, void *arock)
            if (errno == ENOENT)
                fprintf(stderr,"%s: the cell named '%s' does not exist\n", pn, info.name);
            else
-               Die(errno, info.name);
+               fs_Die(errno, info.name);
            error = 1;
             continue;
        }
@@ -3724,7 +3456,7 @@ static int SetCellCmd(struct cmd_syndesc *as, void *arock)
     args.junk = 0;
 
 #ifdef WIN32
-    if ( !IsAdmin() ) {
+    if ( !fs_IsAdmin() ) {
         fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");
         return EACCES;
     }
@@ -3758,7 +3490,7 @@ static int SetCellCmd(struct cmd_syndesc *as, void *arock)
        blob.out = (caddr_t) 0;
        code = pioctl_utf8(0, VIOC_SETCELLSTATUS, &blob, 1);
        if (code) {
-           Die(errno, info.name);      /* XXX added cell name to Die() call */
+           fs_Die(errno, info.name);      /* XXX added cell name to fs_Die() call */
             error = 1;
        }
     }
@@ -4010,7 +3742,7 @@ SetPrefCmd(struct cmd_syndesc *as, void * arock)
     gblob.out = space;
     gblob.out_size = AFS_PIOCTL_MAXSIZE;
 
-    if ( !IsAdmin() ) {
+    if ( !fs_IsAdmin() ) {
         fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");
         return EACCES;
     }
@@ -4022,7 +3754,7 @@ SetPrefCmd(struct cmd_syndesc *as, void * arock)
         if (debug) fprintf(stderr,"opening file %s\n",ti->data);
         if (!(infd = fopen(ti->data,"r" ))) {
             code = errno;
-            Die(errno,ti->data);
+            fs_Die(errno,ti->data);
         } else {
 #if _MSC_VER < 1400
             while ( fscanf(infd, "%79s%ld", name, &rank) != EOF) {
@@ -4090,7 +3822,7 @@ SetPrefCmd(struct cmd_syndesc *as, void * arock)
     }
 
     if (code)
-        Die(errno,0);
+        fs_Die(errno,0);
 
     return code;
 }
@@ -4211,7 +3943,7 @@ SetPrefCmd(struct cmd_syndesc *as, void *arock)
     }
 
     if (error > 0)
-       Die(error, 0);
+       fs_Die(error, 0);
 
     return error ? 1 : 0;
 }
@@ -4238,7 +3970,7 @@ GetPrefCmd(struct cmd_syndesc *as, void *arock)
     if (ti) {
         if (debug) fprintf(stderr,"opening file %s\n",ti->data);
         if (!(outfd = freopen(ti->data,"w",stdout))) {
-            Die(errno,ti->data);
+            fs_Die(errno,ti->data);
             return errno;
         }
     }
@@ -4264,7 +3996,7 @@ GetPrefCmd(struct cmd_syndesc *as, void *arock)
         code = pioctl_utf8(0, VIOC_GETSPREFS, &blob, 1);
         if (code){
             perror("getserverprefs pioctl");
-            Die (errno,0);
+            fs_Die (errno,0);
         }
         else {
             out = (struct cm_SPrefInfo *) blob.out;
@@ -4385,7 +4117,7 @@ SmbUnicodeCmd(struct cmd_syndesc * asp, void * arock)
         inValue = 2;
     }
 
-    if (inValue != 0 && !IsAdmin()) {
+    if (inValue != 0 && !fs_IsAdmin()) {
         fprintf (stderr, "Permission denied: Requires AFS Client Administrator access.\n");
         return EACCES;
     }
@@ -4397,7 +4129,7 @@ SmbUnicodeCmd(struct cmd_syndesc * asp, void * arock)
 
     code = pioctl_utf8(NULL, VIOC_UNICODECTL, &blob, 1);
     if (code) {
-        Die(errno, NULL);
+        fs_Die(errno, NULL);
         return code;
     }
 
@@ -4448,7 +4180,7 @@ GetFidCmd(struct cmd_syndesc *as, void *arock)
             options.field_flags |= CM_IOCTL_QOPTS_FIELD_FID;
             options.fid = fid;
         } else {
-           Die(errno, ti->data);
+           fs_Die(errno, ti->data);
            error = 1;
            continue;
         }
@@ -4458,7 +4190,7 @@ GetFidCmd(struct cmd_syndesc *as, void *arock)
 
         code = pioctl_utf8(ti->data, VIOC_GETFILETYPE, &blob, 1);
         if (code || blob.out_size != sizeof(filetype)) {
-           Die(errno, ti->data);
+           fs_Die(errno, ti->data);
            error = 1;
            continue;
         }
@@ -4469,7 +4201,7 @@ GetFidCmd(struct cmd_syndesc *as, void *arock)
         if (code == 0)
             cell[CELL_MAXNAMELEN - 1] = '\0';
         printf("%s %s (%u.%u.%u) contained in cell %s\n",
-                filetypestr(filetype),
+                fs_filetypestr(filetype),
                 ti->data, fid.volume, fid.vnode, fid.unique,
                 code ? "unknown-cell" : cell);
     }
@@ -4487,7 +4219,7 @@ UuidCmd(struct cmd_syndesc *asp, void *arock)
 
     if (asp->parms[0].items) {
 #ifdef WIN32
-        if ( !IsAdmin() ) {
+        if ( !fs_IsAdmin() ) {
             fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");
             return EACCES;
         }
@@ -4509,7 +4241,7 @@ UuidCmd(struct cmd_syndesc *asp, void *arock)
 
     code = pioctl_utf8(NULL, VIOC_UUIDCTL, &blob, 1);
     if (code || blob.out_size != sizeof(outValue)) {
-        Die(errno, NULL);
+        fs_Die(errno, NULL);
         return code;
     }
 
@@ -4534,7 +4266,7 @@ TraceCmd(struct cmd_syndesc *asp, void *arock)
     long outValue;
 
 #ifdef WIN32
-    if ( !IsAdmin() ) {
+    if ( !fs_IsAdmin() ) {
         fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");
         return EACCES;
     }
@@ -4568,7 +4300,7 @@ TraceCmd(struct cmd_syndesc *asp, void *arock)
 
     code = pioctl_utf8(NULL, VIOC_TRACECTL, &blob, 1);
     if (code || blob.out_size != sizeof(long)) {
-        Die(errno, NULL);
+        fs_Die(errno, NULL);
         return code;
     }
 
@@ -4600,7 +4332,7 @@ StoreBehindCmd(struct cmd_syndesc *as, void *arock)
     int error = 0;
 
 #ifdef WIN32
-    if ( !IsAdmin() ) {
+    if ( !fs_IsAdmin() ) {
         fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");
         return EACCES;
     }
@@ -4657,14 +4389,14 @@ StoreBehindCmd(struct cmd_syndesc *as, void *arock)
        /* Do this solely to see if the file is there */
        code = pioctl_utf8(ti->data, VIOCWHEREIS, &blob, 1);
        if (code) {
-           Die(errno, ti->data);
+           fs_Die(errno, ti->data);
            error = 1;
            continue;
        }
 
        code = pioctl_utf8(ti->data, VIOC_STOREBEHIND, &blob, 1);
        if (code) {
-           Die(errno, ti->data);
+           fs_Die(errno, ti->data);
            error = 1;
            continue;
        }
@@ -4688,7 +4420,7 @@ StoreBehindCmd(struct cmd_syndesc *as, void *arock)
        tsb.sb_default = allfiles;
        code = pioctl_utf8(0, VIOC_STOREBEHIND, &blob, 1);
        if (code) {
-           Die(errno, ((allfiles == -1) ? 0 : "-allfiles"));
+           fs_Die(errno, ((allfiles == -1) ? 0 : "-allfiles"));
            error = 1;
        }
     }
@@ -4710,7 +4442,7 @@ SetCryptCmd(struct cmd_syndesc *as, void *arock)
     char *tp;
 
 #ifdef WIN32
-    if ( !IsAdmin() ) {
+    if ( !fs_IsAdmin() ) {
         fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");
         return EACCES;
     }
@@ -4733,7 +4465,7 @@ SetCryptCmd(struct cmd_syndesc *as, void *arock)
     blob.out_size = 0;
     code = pioctl_utf8(0, VIOC_SETRXKCRYPT, &blob, 1);
     if (code)
-        Die(code, NULL);
+        fs_Die(code, NULL);
     return 0;
 }
 
@@ -4753,7 +4485,7 @@ GetCryptCmd(struct cmd_syndesc *as, void *arock)
     code = pioctl_utf8(0, VIOC_GETRXKCRYPT, &blob, 1);
 
     if (code || blob.out_size != sizeof(flag))
-        Die(code, NULL);
+        fs_Die(code, NULL);
     else {
         tp = space;
 #if _MSC_VER < 1400
@@ -4785,7 +4517,7 @@ MemDumpCmd(struct cmd_syndesc *asp, void *arock)
     long inValue = 0;
     long outValue;
 
-    if ( !IsAdmin() ) {
+    if ( !fs_IsAdmin() ) {
         fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");
         return EACCES;
     }
@@ -4809,7 +4541,7 @@ MemDumpCmd(struct cmd_syndesc *asp, void *arock)
 
     code = pioctl_utf8(NULL, VIOC_TRACEMEMDUMP, &blob, 1);
     if (code || blob.out_size != sizeof(long)) {
-        Die(errno, NULL);
+        fs_Die(errno, NULL);
         return code;
     }
 
@@ -4830,7 +4562,7 @@ MiniDumpCmd(struct cmd_syndesc *asp, void *arock)
     SC_HANDLE hManager = NULL;
     SC_HANDLE hService = NULL;
 
-    if ( !IsAdmin() ) {
+    if ( !fs_IsAdmin() ) {
         fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");
         return EACCES;
     }
@@ -4871,7 +4603,7 @@ CSCPolicyCmd(struct cmd_syndesc *asp, void *arock)
     HKEY hkCSCPolicy;
     size_t len;
 
-    if ( !IsAdmin() ) {
+    if ( !fs_IsAdmin() ) {
         fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");
         return EACCES;
     }
@@ -4903,7 +4635,7 @@ CSCPolicyCmd(struct cmd_syndesc *asp, void *arock)
             return EACCES;
         }
 
-        if ( !IsAdmin() ) {
+        if ( !fs_IsAdmin() ) {
             fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");
             RegCloseKey(hkCSCPolicy);
             return EACCES;
@@ -5102,7 +4834,7 @@ SetClientAddrsCmd(struct cmd_syndesc *as, void *arock)
 
     code = pioctl_utf8(0, VIOC_SETCPREFS, &blob, 1);   /* network order */
     if (code) {
-       Die(errno, 0);
+       fs_Die(errno, 0);
        error = 1;
     }
 
@@ -5240,7 +4972,7 @@ FlushMountCmd(struct cmd_syndesc *as, void *arock)
            if (errno == EINVAL) {
                fprintf(stderr, "'%s' is not a mount point.\n", ti->data);
            } else {
-               Die(errno, (ti->data ? ti->data : parent_dir));
+               fs_Die(errno, (ti->data ? ti->data : parent_dir));
            }
            error = 1;
        }
@@ -5276,7 +5008,7 @@ RxStatProcCmd(struct cmd_syndesc *as, void *arock)
 
     code = pioctl_utf8(NULL, VIOC_RXSTAT_PROC, &blob, 1);
     if (code != 0) {
-       Die(errno, NULL);
+       fs_Die(errno, NULL);
        return 1;
     }
 
@@ -5310,7 +5042,7 @@ RxStatPeerCmd(struct cmd_syndesc *as, void *arock)
 
     code = pioctl_utf8(NULL, VIOC_RXSTAT_PEER, &blob, 1);
     if (code != 0) {
-       Die(errno, NULL);
+       fs_Die(errno, NULL);
        return 1;
     }
 
@@ -5396,7 +5128,7 @@ TestVolStatCmd(struct cmd_syndesc *as, void *arock)
 
     code = pioctl_utf8(NULL, VIOC_VOLSTAT_TEST, &blob, 1);
     if (code != 0) {
-       Die(errno, NULL);
+       fs_Die(errno, NULL);
        return 1;
     }
 
@@ -5450,7 +5182,7 @@ ChOwnCmd(struct cmd_syndesc *as, void *arock)
             inData.options.field_flags |= CM_IOCTL_QOPTS_FIELD_FID;
             inData.options.fid = fid;
         } else {
-           Die(errno, ti->data);
+           fs_Die(errno, ti->data);
            error = 1;
            continue;
         }
@@ -5468,7 +5200,7 @@ ChOwnCmd(struct cmd_syndesc *as, void *arock)
 
             code = pioctl_utf8(ti->data, VIOC_FILE_CELL_NAME, &blob, 1);
             if (code) {
-                Die(errno, ti->data);
+                fs_Die(errno, ti->data);
                 error = 1;
                 continue;
             }
@@ -5482,7 +5214,7 @@ ChOwnCmd(struct cmd_syndesc *as, void *arock)
             pr_End();
 
             if (code || inData.owner == ANONYMOUSID ) {
-                Die(ECHILD, ti->data);
+                fs_Die(ECHILD, ti->data);
                 error = 1;
                 continue;
             }
@@ -5495,7 +5227,7 @@ ChOwnCmd(struct cmd_syndesc *as, void *arock)
        blob.out_size = 0;
        code = pioctl_utf8(ti->data, VIOC_SETOWNER, &blob, 1);
        if (code) {
-            Die(errno, ti->data);
+            fs_Die(errno, ti->data);
         }
     }
     return error;
@@ -5548,7 +5280,7 @@ ChGrpCmd(struct cmd_syndesc *as, void *arock)
             inData.options.field_flags |= CM_IOCTL_QOPTS_FIELD_FID;
             inData.options.fid = fid;
         } else {
-           Die(errno, ti->data);
+           fs_Die(errno, ti->data);
            error = 1;
            continue;
         }
@@ -5566,7 +5298,7 @@ ChGrpCmd(struct cmd_syndesc *as, void *arock)
 
             code = pioctl_utf8(ti->data, VIOC_FILE_CELL_NAME, &blob, 1);
             if (code) {
-                Die(errno, ti->data);
+                fs_Die(errno, ti->data);
                 error = 1;
                 continue;
             }
@@ -5580,7 +5312,7 @@ ChGrpCmd(struct cmd_syndesc *as, void *arock)
             pr_End();
 
             if (code || inData.group == ANONYMOUSID ) {
-                Die(ECHILD, ti->data);
+                fs_Die(ECHILD, ti->data);
                 error = 1;
                 continue;
             }
@@ -5593,7 +5325,7 @@ ChGrpCmd(struct cmd_syndesc *as, void *arock)
        blob.out_size = 0;
        code = pioctl_utf8(ti->data, VIOC_SETGROUP, &blob, 1);
        if (code) {
-            Die(errno, ti->data);
+            fs_Die(errno, ti->data);
         }
     }
     return error;
@@ -5630,7 +5362,7 @@ ChModCmd(struct cmd_syndesc *as, void *arock)
         while (*unixModeStr >= '0' && *unixModeStr <= '7')
             unixModeBits = (unixModeBits << 3) | (*unixModeStr++ & 07);
         if (*unixModeStr) {
-            Die(EINVAL, "invalid mode");
+            fs_Die(EINVAL, "invalid mode");
             return(1);
         }
         unixModeBits &= ALL_MODES;
@@ -5659,7 +5391,7 @@ ChModCmd(struct cmd_syndesc *as, void *arock)
             inData.options.field_flags |= CM_IOCTL_QOPTS_FIELD_FID;
             inData.options.fid = fid;
         } else {
-           Die(errno, ti->data);
+           fs_Die(errno, ti->data);
            error = 1;
            continue;
         }
@@ -5677,7 +5409,7 @@ ChModCmd(struct cmd_syndesc *as, void *arock)
             blob.out = (char *)&unixModeBits;
             if (pioctl_utf8(ti->data, VIOC_GETUNIXMODE, &blob, 1) != 0)
             {
-                Die(errno, ti->data);
+                fs_Die(errno, ti->data);
                 error = 1;
                 continue;
             }
@@ -5691,7 +5423,7 @@ ChModCmd(struct cmd_syndesc *as, void *arock)
        blob.out_size = 0;
        code = pioctl_utf8(ti->data, VIOC_SETUNIXMODE, &blob, 1);
        if (code) {
-            Die(errno, ti->data);
+            fs_Die(errno, ti->data);
         }
     }
     return error;
@@ -5701,50 +5433,6 @@ ChModCmd(struct cmd_syndesc *as, void *arock)
 #include "AFS_component_version_number.c"
 #endif
 
-static void
-FreeUtf8CmdLine(int argc, char ** argv)
-{
-    int i;
-    for (i=0; i < argc; i++) {
-        if (argv[i])
-            free(argv[i]);
-    }
-    free(argv);
-}
-
-static char **
-MakeUtf8Cmdline(int argc, const wchar_t **wargv)
-{
-    char ** argv;
-    int i;
-
-    argv = calloc(argc, sizeof(argv[0]));
-    if (argv == NULL)
-        return NULL;
-
-    for (i=0; i < argc; i++) {
-        int s;
-
-        s = WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1, NULL, 0, NULL, FALSE);
-        if (s == 0 ||
-            (argv[i] = calloc(s+1, sizeof(char))) == NULL) {
-            break;
-        }
-
-        s = WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1, argv[i], s+1, NULL, FALSE);
-        if (s == 0) {
-            break;
-        }
-    }
-
-    if (i < argc) {
-        FreeUtf8CmdLine(argc, argv);
-        return NULL;
-    }
-
-    return argv;
-}
-
 int wmain(int argc, wchar_t **wargv)
 {
     afs_int32 code;
@@ -5771,7 +5459,9 @@ int wmain(int argc, wchar_t **wargv)
     WSAStartup(0x0101, &WSAjunk);
 #endif /* WIN32 */
 
-    argv = MakeUtf8Cmdline(argc, wargv);
+    fs_SetProcessName(pn);
+
+    argv = fs_MakeUtf8Cmdline(argc, wargv);
 
     /* try to find volume location information */
     osi_Init();
@@ -6078,87 +5768,8 @@ int wmain(int argc, wchar_t **wargv)
     if (rxInitDone)
         rx_Finalize();
 
-    FreeUtf8CmdLine(argc, argv);
+    fs_FreeUtf8CmdLine(argc, argv);
 
     return code;
 }
 
-void
-Die(int code, char *filename)
-{ /*Die*/
-
-    if (code == EINVAL) {
-       if (filename)
-           fprintf(stderr,"%s: Invalid argument; it is possible that %s is not in AFS.\n", pn, filename);
-       else
-            fprintf(stderr,"%s: Invalid argument.\n", pn);
-    }
-    else if (code == ENOENT) {
-       if (filename)
-            fprintf(stderr,"%s: File '%s' doesn't exist\n", pn, filename);
-       else
-            fprintf(stderr,"%s: no such file returned\n", pn);
-    }
-    else if (code == EROFS)
-        fprintf(stderr,"%s: You can not change a backup or readonly volume\n", pn);
-    else if (code == EACCES || code == EPERM) {
-       if (filename)
-            fprintf(stderr,"%s: You don't have the required access rights on '%s'\n", pn, filename);
-       else
-            fprintf(stderr,"%s: You do not have the required rights to do this operation\n", pn);
-    }
-    else if (code == ENODEV) {
-       fprintf(stderr,"%s: AFS service may not have started.\n", pn);
-    }
-    else if (code == ESRCH) {   /* hack */
-       fprintf(stderr,"%s: Cell name not recognized.\n", pn);
-    }
-    else if (code == EPIPE) {   /* hack */
-       fprintf(stderr,"%s: Volume name or ID not recognized.\n", pn);
-    }
-    else if (code == EFBIG) {
-       fprintf(stderr,"%s: Cache size too large.\n", pn);
-    }
-    else if (code == ETIMEDOUT) {
-       if (filename)
-           fprintf(stderr,"%s:'%s': Connection timed out", pn, filename);
-       else
-           fprintf(stderr,"%s: Connection timed out", pn);
-    }
-    else if (code == EBUSY) {
-       if (filename)
-            fprintf(stderr,"%s: All servers are busy on which '%s' resides\n", pn, filename);
-       else
-            fprintf(stderr,"%s: All servers are busy\n", pn);
-    }
-    else if (code == ENXIO) {
-       if (filename)
-            fprintf(stderr,"%s: All volume instances are offline on which '%s' resides\n", pn, filename);
-       else
-            fprintf(stderr,"%s: All volume instances are offline\n", pn);
-    }
-    else if (code == ENOSYS) {
-       if (filename)
-            fprintf(stderr,"%s: All servers are down on which '%s' resides\n", pn, filename);
-       else
-            fprintf(stderr,"%s: All servers are down\n", pn);
-    }
-    else if (code == ECHILD) {  /* hack */
-       if (filename)
-            fprintf(stderr,"%s: Invalid owner specified for '%s'\n", pn, filename);
-       else
-            fprintf(stderr,"%s: Invalid owner specified\n", pn);
-    }
-    else {
-       if (filename)
-            fprintf(stderr,"%s:'%s'", pn, filename);
-       else
-            fprintf(stderr,"%s", pn);
-#ifdef WIN32
-       fprintf(stderr, ": code 0x%x\n", code);
-#else /* not WIN32 */
-       fprintf(stderr,": %s\n", afs_error_message(code));
-#endif /* not WIN32 */
-    }
-} /*Die*/
-
index 66fd4cfbb8e6d8c95f4956d037fe76fcb0c705fa..7fb5d720b90d0c8c2d32296d006b2bcf018f6131 100644 (file)
@@ -12,6 +12,7 @@
 #include <roken.h>
 
 #include <afs/stds.h>
+#include <afs/afs_consts.h>
 
 #include <windows.h>
 #include <stdlib.h>
@@ -23,6 +24,7 @@
 #include <errno.h>
 #include <malloc.h>
 #include <string.h>
+#include <strsafe.h>
 
 #include <osi.h>
 #include <afsd.h>
 #include <fs_utils.h>
 #include <WINNT\afsreg.h>
 
-long fs_ExtractDriveLetter(char *inPathp, char *outPathp)
+long
+fs_ExtractDriveLetter(char *inPathp, char *outPathp)
 {
-       if (inPathp[0] != 0 && inPathp[1] == ':') {
-               /* there is a drive letter */
-                *outPathp++ = *inPathp++;
-                *outPathp++ = *inPathp++;
-                *outPathp++ = 0;
-        }
-       else *outPathp = 0;
+    if (inPathp[0] != 0 && inPathp[1] == ':') {
+        /* there is a drive letter */
+        *outPathp++ = *inPathp++;
+        *outPathp++ = *inPathp++;
+        *outPathp++ = 0;
+    }
+    else
+        *outPathp = 0;
 
-        return 0;
+    return 0;
 }
 
 /* strip the drive letter from a component */
-long fs_StripDriveLetter(char *inPathp, char *outPathp, long outSize)
+long
+fs_StripDriveLetter(char *inPathp, char *outPathp, size_t outSize)
 {
-       char tempBuffer[1000];
-        strcpy(tempBuffer, inPathp);
-        if (tempBuffer[0] != 0 && tempBuffer[1] == ':') {
-               /* drive letter present */
-                strcpy(outPathp, tempBuffer+2);
+    char tempBuffer[1000];
+
+    if( FAILED(StringCbCopy(tempBuffer, sizeof(tempBuffer), inPathp))) {
+        fprintf (stderr, "fs_StripDriveLetter - not enough space on input");
+        exit(1);
+    }
+    if (tempBuffer[0] != 0 && tempBuffer[1] == ':') {
+        /* drive letter present */
+        if( FAILED(StringCbCopy(outPathp, outSize, tempBuffer+2))) {
+            fprintf (stderr, "fs_StripDriveLetter - not enough space on output");
+            exit(1);
         }
-        else {
-               /* no drive letter present */
-               strcpy(outPathp, tempBuffer);
-       }
-        return 0;
+    }
+    else {
+        /* no drive letter present */
+        if( FAILED(StringCbCopy(outPathp, outSize, tempBuffer))) {
+            fprintf (stderr, "fs_StripDriveLetter - not enough space on output");
+            exit(1);
+        }
+    }
+    return 0;
 }
 
 /* take a path with a drive letter, possibly relative, and return a full path
  * without the drive letter.  This is the full path relative to the working
  * dir for that drive letter.  The input and output paths can be the same.
  */
-long fs_GetFullPath(char *pathp, char *outPathp, long outSize)
+long
+fs_GetFullPath(char *pathp, char *outPathp, size_t outSize)
 {
-       char tpath[1000];
-       char origPath[1000];
+    char tpath[1000];
+    char origPath[1000];
     char *firstp;
     long code;
     int pathHasDrive;
     int doSwitch;
     char newPath[3];
 
-       if (pathp[0] != 0 && pathp[1] == ':') {
-               /* there's a drive letter there */
+    if (pathp[0] != 0 && pathp[1] == ':') {
+        /* there's a drive letter there */
         firstp = pathp+2;
         pathHasDrive = 1;
     } else {
         firstp = pathp;
-               pathHasDrive = 0;
-       }
+        pathHasDrive = 0;
+    }
 
     if (*firstp == '\\' || *firstp == '/') {
-               /* already an absolute pathname, just copy it back */
-        strcpy(outPathp, firstp);
+        /* already an absolute pathname, just copy it back */
+        if( FAILED(StringCbCopy(outPathp, outSize, firstp))) {
+            fprintf (stderr, "fs_GetFullPath - not enough space on output");
+            exit(1);
+        }
         return 0;
     }
 
     GetCurrentDirectoryA(sizeof(origPath), origPath);
 
-       doSwitch = 0;
+    doSwitch = 0;
     if (pathHasDrive && (*pathp & ~0x20) != (origPath[0] & ~0x20)) {
-               /* a drive has been specified and it isn't our current drive.
+        /* a drive has been specified and it isn't our current drive.
          * to get path, switch to it first.  Must case-fold drive letters
          * for user convenience.
          */
-               doSwitch = 1;
+        doSwitch = 1;
         newPath[0] = *pathp;
         newPath[1] = ':';
         newPath[2] = 0;
         if (!SetCurrentDirectoryA(newPath)) {
-                       code = GetLastError();
+            code = GetLastError();
             return code;
         }
     }
 
     /* now get the absolute path to the current wdir in this drive */
     GetCurrentDirectoryA(sizeof(tpath), tpath);
-    strcpy(outPathp, tpath+2); /* skip drive letter */
-       /* if there is a non-null name after the drive, append it */
-       if (*firstp != 0) {
-        strcat(outPathp, "\\");
-        strcat(outPathp, firstp);
-       }
+    if( FAILED(StringCbCopy(outPathp, outSize, tpath+2))) {
+        fprintf (stderr, "fs_GetFullPath - not enough space on output");
+        exit(1);
+    }
+    /* if there is a non-null name after the drive, append it */
+    if (*firstp != 0) {
+        if( FAILED(StringCbCat(outPathp, outSize, "\\"))) {
+            fprintf (stderr, "fs_GetFullPath - not enough space on output");
+            exit(1);
+        }
+        if( FAILED(StringCbCat(outPathp, outSize, firstp))) {
+            fprintf (stderr, "fs_GetFullPath - not enough space on output");
+            exit(1);
+        }
+    }
 
-       /* finally, if necessary, switch back to our home drive letter */
+    /* finally, if necessary, switch back to our home drive letter */
     if (doSwitch) {
         SetCurrentDirectoryA(origPath);
     }
@@ -148,29 +176,450 @@ char *cm_mount_root="afs";
 char *cm_slash_mount_root="/afs";
 char *cm_back_slash_mount_root="\\afs";
 
-void fs_utils_InitMountRoot()
+void
+fs_utils_InitMountRoot()
 {
     HKEY parmKey;
     char mountRoot[MAX_PATH+1];
     char *pmount=mountRoot;
     DWORD len=sizeof(mountRoot)-1;
-    printf("int mountroot \n");
+
     if ((RegOpenKeyExA(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY, 0,
                       (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey)!= ERROR_SUCCESS)
         || (RegQueryValueExA(parmKey, "Mountroot", NULL, NULL,(LPBYTE)(mountRoot), &len)!= ERROR_SUCCESS)
          || (len==sizeof(mountRoot)-1)
          )
-        strcpy(mountRoot, "\\afs");
+    {
+        if( FAILED(StringCbCopy(mountRoot, sizeof(mountRoot), "\\afs"))) {
+            fprintf (stderr, "fs_InitMountRoot - not enough space on output");
+            exit(1);
+        }
+    }
     RegCloseKey(parmKey);
     mountRoot[len]=0;       /*safety see ms-help://MS.MSDNQTR.2002OCT.1033/sysinfo/base/regqueryvalueex.htm*/
+
     cm_mount_root=malloc(len+1);
     cm_slash_mount_root=malloc(len+2);
     cm_back_slash_mount_root=malloc(len+2);
     if ((*pmount=='/') || (*pmount='\\'))
         pmount++;
-    strcpy(cm_mount_root,pmount);
-    strcpy(cm_slash_mount_root+1,pmount);
+
+    if( FAILED(StringCbCopy(cm_mount_root, len+1, pmount))) {
+        fprintf (stderr, "fs_InitMountRoot - not enough space on output");
+        exit(1);
+    }
     cm_slash_mount_root[0]='/';
-    strcpy(cm_back_slash_mount_root+1,pmount);
+    if( FAILED(StringCbCopy(cm_slash_mount_root+1, len+1, pmount))) {
+        fprintf (stderr, "fs_InitMountRoot - not enough space on output");
+        exit(1);
+    }
     cm_back_slash_mount_root[0]='\\';
+    if( FAILED(StringCbCopy(cm_back_slash_mount_root+1, len+1, pmount))) {
+        fprintf (stderr, "fs_InitMountRoot - not enough space on output");
+        exit(1);
+    }
+}
+
+/* return a static pointer to a buffer */
+char *
+fs_GetParent(char *apath)
+{
+    static char tspace[1024];
+    char *tp;
+
+    if( FAILED(StringCbCopy(tspace, sizeof(tspace), apath))) {
+        fprintf (stderr, "tspace - not enough space");
+        exit(1);
+    }
+    tp = strrchr(tspace, '\\');
+    if (tp) {
+        if (tp - tspace > 2 &&
+            tspace[1] == ':' &&
+            &tspace[2] == tp)
+           *(tp+1) = 0;        /* lv trailing slash so Parent("k:\foo") is "k:\" not "k:" */
+        else
+            *tp = 0;
+    }
+    else {
+       fs_ExtractDriveLetter(apath, tspace);
+       if( FAILED(StringCbCat(tspace, sizeof(tspace), "."))) {
+           fprintf (stderr, "tspace - not enough space");
+           exit(1);
+       }
+    }
+    return tspace;
+}
+
+/* this function returns TRUE (1) if the file is in AFS, otherwise false (0) */
+int
+fs_InAFS(char *apath)
+{
+    struct ViceIoctl blob;
+    cm_ioctlQueryOptions_t options;
+    cm_fid_t fid;
+    afs_int32 code;
+
+    memset(&options, 0, sizeof(options));
+    options.size = sizeof(options);
+    options.field_flags |= CM_IOCTL_QOPTS_FIELD_LITERAL;
+    options.literal = 1;
+    blob.in_size = options.size;    /* no variable length data */
+    blob.in = &options;
+    blob.out_size = sizeof(cm_fid_t);
+    blob.out = (char *) &fid;
+
+    code = pioctl_utf8(apath, VIOCGETFID, &blob, 1);
+    if (code) {
+       if ((errno == EINVAL) || (errno == ENOENT))
+            return 0;
+    }
+    return 1;
+}
+
+int
+fs_IsFreelanceRoot(char *apath)
+{
+    struct ViceIoctl blob;
+    afs_int32 code;
+    char space[AFS_PIOCTL_MAXSIZE];
+
+    blob.in_size = 0;
+    blob.out_size = AFS_PIOCTL_MAXSIZE;
+    blob.out = space;
+
+    code = pioctl_utf8(apath, VIOC_FILE_CELL_NAME, &blob, 1);
+    if (code == 0) {
+        return !cm_strnicmp_utf8N("Freelance.Local.Root",space, blob.out_size);
+    }
+    return 1;   /* assume it is because it is more restrictive that way */
+}
+
+const char *
+fs_NetbiosName(void)
+{
+    static char buffer[NETBIOSNAMESZ] = "AFS";
+    HKEY  parmKey;
+    DWORD code;
+    DWORD dummyLen;
+    DWORD enabled = 0;
+
+    code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
+                         0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
+    if (code == ERROR_SUCCESS) {
+        dummyLen = sizeof(buffer);
+        code = RegQueryValueEx(parmKey, "NetbiosName", NULL, NULL,
+                              buffer, &dummyLen);
+        RegCloseKey (parmKey);
+    } else {
+       if( FAILED(StringCbCopy(buffer, sizeof(buffer), "AFS"))) {
+           fprintf (stderr, "buffer - not enough space");
+            exit(1);
+       }
+    }
+    return buffer;
+}
+
+#define AFSCLIENT_ADMIN_GROUPNAME "AFS Client Admins"
+
+BOOL
+fs_IsAdmin (void)
+{
+    static BOOL fAdmin = FALSE;
+    static BOOL fTested = FALSE;
+
+    if (!fTested)
+    {
+        /* Obtain the SID for the AFS client admin group.  If the group does
+         * not exist, then assume we have AFS client admin privileges.
+         */
+        PSID psidAdmin = NULL;
+        DWORD dwSize, dwSize2;
+        char pszAdminGroup[ MAX_COMPUTERNAME_LENGTH + sizeof(AFSCLIENT_ADMIN_GROUPNAME) + 2 ];
+        char *pszRefDomain = NULL;
+        SID_NAME_USE snu = SidTypeGroup;
+
+        dwSize = sizeof(pszAdminGroup);
+
+        if (!GetComputerName(pszAdminGroup, &dwSize)) {
+            /* Can't get computer name.  We return false in this case.
+               Retain fAdmin and fTested. This shouldn't happen.*/
+            return FALSE;
+        }
+
+        dwSize = 0;
+        dwSize2 = 0;
+
+       if( FAILED(StringCbCat(pszAdminGroup, MAX_COMPUTERNAME_LENGTH + sizeof(AFSCLIENT_ADMIN_GROUPNAME) + 2,"\\"))) {
+           fprintf (stderr, "pszAdminGroup - not enough space");
+            exit(1);
+       }
+       if( FAILED(StringCbCat(pszAdminGroup, MAX_COMPUTERNAME_LENGTH +
+           sizeof(AFSCLIENT_ADMIN_GROUPNAME) + 2, AFSCLIENT_ADMIN_GROUPNAME))) {
+           fprintf (stderr, "pszAdminGroup - not enough space");
+            exit(1);
+       }
+
+        LookupAccountName(NULL, pszAdminGroup, NULL, &dwSize, NULL, &dwSize2, &snu);
+        /* that should always fail. */
+
+        if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+            /* if we can't find the group, then we allow the operation */
+            fAdmin = TRUE;
+            return TRUE;
+        }
+
+        if (dwSize == 0 || dwSize2 == 0) {
+            /* Paranoia */
+            fAdmin = TRUE;
+            return TRUE;
+        }
+
+        psidAdmin = (PSID)malloc(dwSize); memset(psidAdmin,0,dwSize);
+        assert(psidAdmin);
+        pszRefDomain = (char *)malloc(dwSize2);
+        assert(pszRefDomain);
+
+        if (!LookupAccountName(NULL, pszAdminGroup, psidAdmin, &dwSize, pszRefDomain, &dwSize2, &snu)) {
+            /* We can't lookup the group now even though we looked it up earlier.
+               Could this happen? */
+            fAdmin = TRUE;
+        } else {
+            /* Then open our current ProcessToken */
+            HANDLE hToken;
+
+            if (OpenProcessToken (GetCurrentProcess(), TOKEN_QUERY, &hToken))
+            {
+
+                if (!CheckTokenMembership(hToken, psidAdmin, &fAdmin)) {
+                    /* We'll have to allocate a chunk of memory to store the list of
+                     * groups to which this user belongs; find out how much memory
+                     * we'll need.
+                     */
+                    DWORD dwSize = 0;
+                    PTOKEN_GROUPS pGroups;
+
+                    GetTokenInformation (hToken, TokenGroups, NULL, dwSize, &dwSize);
+
+                    pGroups = (PTOKEN_GROUPS)malloc(dwSize);
+                    assert(pGroups);
+
+                    /* Allocate that buffer, and read in the list of groups. */
+                    if (GetTokenInformation (hToken, TokenGroups, pGroups, dwSize, &dwSize))
+                    {
+                        /* Look through the list of group SIDs and see if any of them
+                         * matches the AFS Client Admin group SID.
+                         */
+                        size_t iGroup = 0;
+                        for (; (!fAdmin) && (iGroup < pGroups->GroupCount); ++iGroup)
+                        {
+                            if (EqualSid (psidAdmin, pGroups->Groups[ iGroup ].Sid)) {
+                                fAdmin = TRUE;
+                            }
+                        }
+                    }
+
+                    if (pGroups)
+                        free(pGroups);
+                }
+
+                /* if do not have permission because we were not explicitly listed
+                 * in the Admin Client Group let's see if we are the SYSTEM account
+                 */
+                if (!fAdmin) {
+                    PTOKEN_USER pTokenUser;
+                    SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY;
+                    PSID pSidLocalSystem = 0;
+                    DWORD gle;
+
+                    GetTokenInformation(hToken, TokenUser, NULL, 0, &dwSize);
+
+                    pTokenUser = (PTOKEN_USER)malloc(dwSize);
+                    assert(pTokenUser);
+
+                    if (!GetTokenInformation(hToken, TokenUser, pTokenUser, dwSize, &dwSize))
+                        gle = GetLastError();
+
+                    if (AllocateAndInitializeSid( &SIDAuth, 1,
+                                                  SECURITY_LOCAL_SYSTEM_RID,
+                                                  0, 0, 0, 0, 0, 0, 0,
+                                                  &pSidLocalSystem))
+                    {
+                        if (EqualSid(pTokenUser->User.Sid, pSidLocalSystem)) {
+                            fAdmin = TRUE;
+                        }
+
+                        FreeSid(pSidLocalSystem);
+                    }
+
+                    if ( pTokenUser )
+                        free(pTokenUser);
+                }
+            }
+        }
+
+        free(psidAdmin);
+        free(pszRefDomain);
+
+        fTested = TRUE;
+    }
+
+    return fAdmin;
+}
+
+void
+fs_FreeUtf8CmdLine(int argc, char ** argv)
+{
+    int i;
+    for (i=0; i < argc; i++) {
+        if (argv[i])
+            free(argv[i]);
+    }
+    free(argv);
+}
+
+char **
+fs_MakeUtf8Cmdline(int argc, const wchar_t **wargv)
+{
+    char ** argv;
+    int i;
+
+    argv = calloc(argc, sizeof(argv[0]));
+    if (argv == NULL)
+        return NULL;
+
+    for (i=0; i < argc; i++) {
+        int s;
+
+        s = WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1, NULL, 0, NULL, FALSE);
+        if (s == 0 ||
+            (argv[i] = calloc(s+1, sizeof(char))) == NULL) {
+            break;
+        }
+
+        s = WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1, argv[i], s+1, NULL, FALSE);
+        if (s == 0) {
+            break;
+        }
+    }
+
+    if (i < argc) {
+        fs_FreeUtf8CmdLine(argc, argv);
+        return NULL;
+    }
+
+    return argv;
+}
+
+static const char *pn = "<cmd>";
+void
+fs_SetProcessName(const char *name)
+{
+    pn = name;
+}
+
+void
+fs_Die(int code, char *filename)
+{
+    if (code == EINVAL) {
+       if (filename)
+           fprintf(stderr,"%s: Invalid argument; it is possible that %s is not in AFS.\n", pn, filename);
+       else
+            fprintf(stderr,"%s: Invalid argument.\n", pn);
+    }
+    else if (code == ENOENT) {
+       if (filename)
+            fprintf(stderr,"%s: File '%s' doesn't exist\n", pn, filename);
+       else
+            fprintf(stderr,"%s: no such file returned\n", pn);
+    }
+    else if (code == EEXIST) {
+       if (filename)
+            fprintf(stderr,"%s: File '%s' already exists.\n", pn, filename);
+       else
+            fprintf(stderr,"%s: the specified file already exists.\n", pn);
+    }
+    else if (code == EROFS)
+        fprintf(stderr,"%s: You can not change a backup or readonly volume\n", pn);
+    else if (code == EACCES || code == EPERM) {
+       if (filename)
+            fprintf(stderr,"%s: You don't have the required access rights on '%s'\n", pn, filename);
+       else
+            fprintf(stderr,"%s: You do not have the required rights to do this operation\n", pn);
+    }
+    else if (code == ENODEV) {
+       fprintf(stderr,"%s: AFS service may not have started.\n", pn);
+    }
+    else if (code == ESRCH) {   /* hack */
+       fprintf(stderr,"%s: Cell name not recognized.\n", pn);
+    }
+    else if (code == EPIPE) {   /* hack */
+       fprintf(stderr,"%s: Volume name or ID not recognized.\n", pn);
+    }
+    else if (code == EFBIG) {
+       fprintf(stderr,"%s: Cache size too large.\n", pn);
+    }
+    else if (code == ETIMEDOUT) {
+       if (filename)
+           fprintf(stderr,"%s:'%s': Connection timed out", pn, filename);
+       else
+           fprintf(stderr,"%s: Connection timed out", pn);
+    }
+    else if (code == EBUSY) {
+       if (filename)
+            fprintf(stderr,"%s: All servers are busy on which '%s' resides\n", pn, filename);
+       else
+            fprintf(stderr,"%s: All servers are busy\n", pn);
+    }
+    else if (code == ENXIO) {
+       if (filename)
+            fprintf(stderr,"%s: All volume instances are offline on which '%s' resides\n", pn, filename);
+       else
+            fprintf(stderr,"%s: All volume instances are offline\n", pn);
+    }
+    else if (code == ENOSYS) {
+       if (filename)
+            fprintf(stderr,"%s: All servers are down on which '%s' resides\n", pn, filename);
+       else
+            fprintf(stderr,"%s: All servers are down\n", pn);
+    }
+    else if (code == ECHILD) {  /* hack */
+       if (filename)
+            fprintf(stderr,"%s: Invalid owner specified for '%s'\n", pn, filename);
+       else
+            fprintf(stderr,"%s: Invalid owner specified\n", pn);
+    }
+    else {
+       if (filename)
+            fprintf(stderr,"%s:'%s'", pn, filename);
+       else
+            fprintf(stderr,"%s", pn);
+
+       fprintf(stderr, ": code 0x%x\n", code);
+    }
+}
+
+/* values match cache manager File Types */
+const char *
+fs_filetypestr(afs_uint32 type)
+{
+    char * s = "Object";
+
+    switch (type) {
+    case 1:
+        s = "File";
+        break;
+    case 2:
+        s = "Directory";
+        break;
+    case 3:
+        s = "Symlink";
+        break;
+    case 4:
+        s = "Mountpoint";
+        break;
+    case 5:
+        s = "DfsLink";
+        break;
+    }
+    return s;
 }
index 283d20e0f406408c00f3ac1ca285ebf68faa2c02..7b37938f4be5ab992c3fc81300c7cebee3b0f0bd 100644 (file)
@@ -35,10 +35,35 @@ extern struct hostent *hostutil_GetHostByName(char *namep);
 
 extern afs_int32 util_GetInt32(char *stringp, afs_int32 *valuep);
 
-extern long fs_StripDriveLetter(char *inPathp, char *outPathp, long outSize);
+extern void fs_utils_InitMountRoot();
+
+extern long fs_StripDriveLetter(char *inPathp, char *outPathp, size_t outSize);
 
 extern long fs_ExtractDriveLetter(char *inPathp, char *outPathp);
 
+extern long fs_GetFullPath(char *pathp, char *outPathp, size_t outSize);
+
+extern char *fs_GetParent(char *apath);
+
+extern int fs_InAFS(char *apath);
+
+extern int fs_IsFreelanceRoot(char *apath);
+
+#define NETBIOSNAMESZ 1024
+extern const char * fs_NetbiosName(void);
+
+extern BOOL fs_IsAdmin (void);
+
+extern char **fs_MakeUtf8Cmdline(int argc, const wchar_t **wargv);
+
+extern void fs_FreeUtf8CmdLine(int argc, char ** argv);
+
+extern void fs_Die(int code, char *filename);
+
+extern const char * fs_filetypestr(afs_uint32 type);
+
+extern void fs_SetProcessName(const char *name);
+
 extern char *cm_mount_root;             /*"afs"*/
 extern char *cm_slash_mount_root;       /*"/afs"*/
 extern char *cm_back_slash_mount_root;  /*"\\afs"*/
index 4c1f56605d4a0750821fb992e445720b3313122a..6b9a69270fb96a2b511fdf62ead6a8d24b6e614b 100644 (file)
@@ -58,7 +58,7 @@ parsemode(char *symbolic, afs_uint32 oldmode)
                 break;
         }
         if (!*symbolic || *symbolic == ',') {
-            Die(EINVAL, "invalid mode");
+            fs_Die(EINVAL, "invalid mode");
             exit(1);
         }
         while (*symbolic) {
@@ -66,7 +66,7 @@ parsemode(char *symbolic, afs_uint32 oldmode)
                 break;
             switch (*symbolic) {
             default:
-                Die(EINVAL, "invalid mode");
+                fs_Die(EINVAL, "invalid mode");
                 exit(1);
             case '+':
             case '-':
index 8353752c4cf0aa5cfe494078c46f197c83359062..ec3ce40b41f1938abba081518de6bcd1fe93f86c 100644 (file)
@@ -19,6 +19,7 @@
 #include <stdlib.h>
 #include <malloc.h>
 #include <string.h>
+#include <strsafe.h>
 #include <stdio.h>
 #include <time.h>
 #include <winsock2.h>
 
 #include "fs_utils.h"
 #include "cmd.h"
+#include "afsd.h"
+#include "cm_ioctl.h"
 
 #define MAXNAME 100
 #define MAXINSIZE 1300    /* pioctl complains if data is larger than this */
 
 static char space[AFS_PIOCTL_MAXSIZE];
-static char tspace[1024];
-
-#ifndef WIN32
-static struct ubik_client *uclient;
-#endif /* not WIN32 */
-
 
 static char pn[] = "symlink";
 static int rxInitDone = 0;
 
-void Die();
-
-#if 0
-foldcmp (a, b)
-    char *a;
-    char *b; {
-    char t, u;
-    while (1) {
-        t = *a++;
-        u = *b++;
-        if (t >= 'A' && t <= 'Z') t += 0x20;
-        if (u >= 'A' && u <= 'Z') u += 0x20;
-        if (t != u) return 1;
-        if (t == 0) return 0;
-    }
-}
-#endif
-
-/* this function returns TRUE (1) if the file is in AFS, otherwise false (0) */
-static int InAFS(char *apath)
-{
-    struct ViceIoctl blob;
-    afs_int32 code;
-
-    blob.in_size = 0;
-    blob.out_size = AFS_PIOCTL_MAXSIZE;
-    blob.out = space;
-
-    code = pioctl_utf8(apath, VIOC_FILE_CELL_NAME, &blob, 1);
-    if (code) {
-       if ((errno == EINVAL) || (errno == ENOENT))
-            return 0;
-    }
-    return 1;
-}
-
 static int
-IsFreelanceRoot(char *apath)
-{
-    struct ViceIoctl blob;
-    afs_int32 code;
-
-    blob.in_size = 0;
-    blob.out_size = AFS_PIOCTL_MAXSIZE;
-    blob.out = space;
-
-    code = pioctl_utf8(apath, VIOC_FILE_CELL_NAME, &blob, 1);
-    if (code == 0)
-        return !strnicmp("Freelance.Local.Root",space,blob.out_size);
-    return 1;   /* assume it is because it is more restrictive that way */
-}
-
-static const char * NetbiosName(void)
-{
-    static char buffer[1024] = "AFS";
-    HKEY  parmKey;
-    DWORD code;
-    DWORD dummyLen;
-    DWORD enabled = 0;
-
-    code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
-                         0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
-    if (code == ERROR_SUCCESS) {
-        dummyLen = sizeof(buffer);
-        code = RegQueryValueEx(parmKey, "NetbiosName", NULL, NULL,
-                              buffer, &dummyLen);
-        RegCloseKey (parmKey);
-    } else {
-       strcpy(buffer, "AFS");
-    }
-    return buffer;
-}
-
-#define AFSCLIENT_ADMIN_GROUPNAME "AFS Client Admins"
-
-static BOOL IsAdmin (void)
-{
-    static BOOL fAdmin = FALSE;
-    static BOOL fTested = FALSE;
-
-    if (!fTested)
-    {
-        /* Obtain the SID for the AFS client admin group.  If the group does
-         * not exist, then assume we have AFS client admin privileges.
-         */
-        PSID psidAdmin = NULL;
-        DWORD dwSize, dwSize2;
-        char pszAdminGroup[ MAX_COMPUTERNAME_LENGTH + sizeof(AFSCLIENT_ADMIN_GROUPNAME) + 2 ];
-        char *pszRefDomain = NULL;
-        SID_NAME_USE snu = SidTypeGroup;
-
-        dwSize = sizeof(pszAdminGroup);
-
-        if (!GetComputerName(pszAdminGroup, &dwSize)) {
-            /* Can't get computer name.  We return false in this case.
-               Retain fAdmin and fTested. This shouldn't happen.*/
-            return FALSE;
-        }
-
-        dwSize = 0;
-        dwSize2 = 0;
-
-        strcat(pszAdminGroup,"\\");
-        strcat(pszAdminGroup, AFSCLIENT_ADMIN_GROUPNAME);
-
-        LookupAccountName(NULL, pszAdminGroup, NULL, &dwSize, NULL, &dwSize2, &snu);
-        /* that should always fail. */
-
-        if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
-            /* if we can't find the group, then we allow the operation */
-            fAdmin = TRUE;
-            return TRUE;
-        }
-
-        if (dwSize == 0 || dwSize2 == 0) {
-            /* Paranoia */
-            fAdmin = TRUE;
-            return TRUE;
-        }
-
-        psidAdmin = (PSID)malloc(dwSize); memset(psidAdmin,0,dwSize);
-        assert(psidAdmin);
-        pszRefDomain = (char *)malloc(dwSize2);
-        assert(pszRefDomain);
-
-        if (!LookupAccountName(NULL, pszAdminGroup, psidAdmin, &dwSize, pszRefDomain, &dwSize2, &snu)) {
-            /* We can't lookup the group now even though we looked it up earlier.
-               Could this happen? */
-            fAdmin = TRUE;
-        } else {
-            /* Then open our current ProcessToken */
-            HANDLE hToken;
-
-            if (OpenProcessToken (GetCurrentProcess(), TOKEN_QUERY, &hToken))
-            {
-
-                if (!CheckTokenMembership(hToken, psidAdmin, &fAdmin)) {
-                    /* We'll have to allocate a chunk of memory to store the list of
-                     * groups to which this user belongs; find out how much memory
-                     * we'll need.
-                     */
-                    DWORD dwSize = 0;
-                    PTOKEN_GROUPS pGroups;
-
-                    GetTokenInformation (hToken, TokenGroups, NULL, dwSize, &dwSize);
-
-                    pGroups = (PTOKEN_GROUPS)malloc(dwSize);
-                    assert(pGroups);
-
-                    /* Allocate that buffer, and read in the list of groups. */
-                    if (GetTokenInformation (hToken, TokenGroups, pGroups, dwSize, &dwSize))
-                    {
-                        /* Look through the list of group SIDs and see if any of them
-                         * matches the AFS Client Admin group SID.
-                         */
-                        size_t iGroup = 0;
-                        for (; (!fAdmin) && (iGroup < pGroups->GroupCount); ++iGroup)
-                        {
-                            if (EqualSid (psidAdmin, pGroups->Groups[ iGroup ].Sid)) {
-                                fAdmin = TRUE;
-                            }
-                        }
-                    }
-
-                    if (pGroups)
-                        free(pGroups);
-                }
-
-                /* if do not have permission because we were not explicitly listed
-                 * in the Admin Client Group let's see if we are the SYSTEM account
-                 */
-                if (!fAdmin) {
-                    PTOKEN_USER pTokenUser;
-                    SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY;
-                    PSID pSidLocalSystem = 0;
-                    DWORD gle;
-
-                    GetTokenInformation(hToken, TokenUser, NULL, 0, &dwSize);
-
-                    pTokenUser = (PTOKEN_USER)malloc(dwSize);
-                    assert(pTokenUser);
-
-                    if (!GetTokenInformation(hToken, TokenUser, pTokenUser, dwSize, &dwSize))
-                        gle = GetLastError();
-
-                    if (AllocateAndInitializeSid( &SIDAuth, 1,
-                                                  SECURITY_LOCAL_SYSTEM_RID,
-                                                  0, 0, 0, 0, 0, 0, 0,
-                                                  &pSidLocalSystem))
-                    {
-                        if (EqualSid(pTokenUser->User.Sid, pSidLocalSystem)) {
-                            fAdmin = TRUE;
-                        }
-
-                        FreeSid(pSidLocalSystem);
-                    }
-
-                    if ( pTokenUser )
-                        free(pTokenUser);
-                }
-            }
-        }
-
-        free(psidAdmin);
-        free(pszRefDomain);
-
-        fTested = TRUE;
-    }
-
-    return fAdmin;
-}
-
-/* return a static pointer to a buffer */
-static char *Parent(char *apath)
-{
-    char *tp;
-    strcpy(tspace, apath);
-    tp = strrchr(tspace, '\\');
-    if (tp) {
-        if (tp - tspace > 2 &&
-            tspace[1] == ':' &&
-            &tspace[2] == tp)
-           *(tp+1) = 0;        /* lv trailing slash so Parent("k:\foo") is "k:\" not "k:" */
-        else
-            *tp = 0;
-    }
-    else {
-       fs_ExtractDriveLetter(apath, tspace);
-       strcat(tspace, ".");
-    }
-    return tspace;
-}
-
-
-static ListLinkCmd(struct cmd_syndesc *as, void *arock)
+ListLinkCmd(struct cmd_syndesc *as, void *arock)
 {
     afs_int32 code;
     struct ViceIoctl blob;
     int error;
     struct cmd_item *ti;
-    char orig_name[1024];              /*Original name, may be modified*/
+    char orig_name[1024];               /* Original name */
     char true_name[1024];              /*``True'' dirname (e.g., symlink target)*/
     char parent_dir[1024];             /*Parent directory of true name*/
-    char *last_component;      /*Last component of true name*/
-#ifndef WIN32
-    struct stat statbuff;              /*Buffer for status info*/
-#endif /* not WIN32 */
-#ifndef WIN32
-    int link_chars_read;               /*Num chars read in readlink()*/
-#endif /* not WIN32 */
-    int        thru_symlink;                   /*Did we get to a mount point via a symlink?*/
+    char *last_component;              /*Last component of true name*/
+    cm_ioctlQueryOptions_t options;
 
     error = 0;
     for(ti=as->parms[0].items; ti; ti=ti->next) {
-       /* once per file */
-       thru_symlink = 0;
-#ifdef WIN32
-       strcpy(orig_name, ti->data);
-#else /* not WIN32 */
-       sprintf(orig_name, "%s%s",
-               (ti->data[0] == '/') ? "" : "./",
-               ti->data);
-#endif /* not WIN32 */
-
-#ifndef WIN32
-       if (lstat(orig_name, &statbuff) < 0) {
-           /* if lstat fails, we should still try the pioctl, since it
-               may work (for example, lstat will fail, but pioctl will
-                   work if the volume of offline (returning ENODEV). */
-           statbuff.st_mode = S_IFDIR; /* lie like pros */
-       }
+        cm_fid_t fid;
+        afs_uint32 filetype;
 
-       /*
-        * The lstat succeeded.  If the given file is a symlink, substitute
-        * the file name with the link name.
-        */
-       if ((statbuff.st_mode & S_IFMT) == S_IFLNK) {
-           thru_symlink = 1;
-           /*
-            * Read name of resolved file.
-            */
-           link_chars_read = readlink(orig_name, true_name, 1024);
-           if (link_chars_read <= 0) {
-               fprintf(stderr,"%s: Can't read target name for '%s' symbolic link!\n",
-                      pn, orig_name);
-               exit(1);
-           }
+       /* once per file */
+        if( FAILED(StringCbCopy(orig_name, sizeof(orig_name), ti->data))) {
+            fprintf (stderr, "ListLinkCmd - input path too long");
+            error = 1;
+            continue;
+        }
 
-           /*
-            * Add a trailing null to what was read, bump the length.
-            */
-           true_name[link_chars_read++] = 0;
+        if( FAILED(StringCbCopy(true_name, sizeof(true_name), ti->data))) {
+            fprintf (stderr, "ListLinkCmd - input path too long");
+            error = 1;
+            continue;
+        }
 
-           /*
-            * If the symlink is an absolute pathname, we're fine.  Otherwise, we
-            * have to create a full pathname using the original name and the
-            * relative symlink name.  Find the rightmost slash in the original
-            * name (we know there is one) and splice in the symlink value.
-            */
-           if (true_name[0] != '\\') {
-               last_component = (char *) strrchr(orig_name, '\\');
-               strcpy(++last_component, true_name);
-               strcpy(true_name, orig_name);
-           }
-       }
-       else
-           strcpy(true_name, orig_name);
-#else  /* WIN32 */
-       strcpy(true_name, orig_name);
-#endif /* WIN32 */
 
        /*
         * Find rightmost slash, if any.
@@ -366,34 +84,50 @@ static ListLinkCmd(struct cmd_syndesc *as, void *arock)
        if (last_component) {
            /*
             * Found it.  Designate everything before it as the parent directory,
-            * everything after it as the final component.
+            * everything after it as the final component.  (explicitly relying
+             * on behavior of strncpy in this case.)
             */
            strncpy(parent_dir, true_name, last_component - true_name + 1);
            parent_dir[last_component - true_name + 1] = 0;
            last_component++;   /*Skip the slash*/
 
-#ifdef WIN32
-           if (!InAFS(parent_dir)) {
-               const char * nbname = NetbiosName();
-               int len = (int)strlen(nbname);
+            /*
+             * The following hack converts \\afs\foobar to \\afs\all\foobar.
+             * However, this hack should no longer be required as the pioctl()
+             * interface handles this conversion for us.
+             */
+           if (!fs_InAFS(parent_dir)) {
+               const char * nbname = fs_NetbiosName();
+               size_t len = strlen(nbname);
 
                if (parent_dir[0] == '\\' && parent_dir[1] == '\\' &&
                    parent_dir[len+2] == '\\' &&
                    parent_dir[len+3] == '\0' &&
                    !strnicmp(nbname,&parent_dir[2],len))
                {
-                   sprintf(parent_dir,"\\\\%s\\all\\", nbname);
-               }
+                   if( FAILED(StringCbPrintf(parent_dir, sizeof(parent_dir), "\\\\%s\\all\\", nbname))) {
+                        fprintf(stderr, "parent_dir cannot be populated");
+                        error = 1;
+                        continue;
+                    }
+               } else {
+                    fprintf(stderr,"'%s' is not in AFS.\n", parent_dir);
+                    error = 1;
+                    continue;
+                }
            }
-#endif
        }
-       else {
+       else
+        {
            /*
             * No slash appears in the given file name.  Set parent_dir to the current
             * directory, and the last component as the given name.
             */
            fs_ExtractDriveLetter(true_name, parent_dir);
-           strcat(parent_dir, ".");
+           if( FAILED(StringCbCat(parent_dir, sizeof(parent_dir), "."))) {
+               fprintf (stderr, "parent_dir - not enough space");
+                exit(1);
+           }
            last_component = true_name;
             fs_StripDriveLetter(true_name, true_name, sizeof(true_name));
        }
@@ -404,70 +138,109 @@ static ListLinkCmd(struct cmd_syndesc *as, void *arock)
            error = 1;
            continue;
        }
+
+        /* Check the object type */
+        memset(&fid, 0, sizeof(fid));
+        memset(&options, 0, sizeof(options));
+        filetype = 0;
+        options.size = sizeof(options);
+        options.field_flags |= CM_IOCTL_QOPTS_FIELD_LITERAL;
+        options.literal = 1;
+       blob.in_size = options.size;    /* no variable length data */
+        blob.in = &options;
+
+        blob.out_size = sizeof(cm_fid_t);
+        blob.out = (char *) &fid;
+        if (0 == pioctl_utf8(orig_name, VIOCGETFID, &blob, 1) &&
+            blob.out_size == sizeof(cm_fid_t)) {
+            options.field_flags |= CM_IOCTL_QOPTS_FIELD_FID;
+            options.fid = fid;
+        } else {
+           fs_Die(errno, ti->data);
+           error = 1;
+           continue;
+        }
+
+        blob.out_size = sizeof(filetype);
+        blob.out = &filetype;
+
+        code = pioctl_utf8(orig_name, VIOC_GETFILETYPE, &blob, 1);
+        if (code || blob.out_size != sizeof(filetype)) {
+           fs_Die(errno, ti->data);
+           error = 1;
+           continue;
+        }
+
+        if (filetype != 3 /* symlink */) {
+            fprintf(stderr,"'%s' is a %s not a Symlink.\n",
+                    orig_name, fs_filetypestr(filetype));
+            error = 1;
+            continue;
+        }
+
        blob.in = last_component;
        blob.in_size = (long)strlen(last_component)+1;
+
+        /* Now determine the symlink target */
        blob.out_size = AFS_PIOCTL_MAXSIZE;
        blob.out = space;
        memset(space, 0, AFS_PIOCTL_MAXSIZE);
 
        code = pioctl_utf8(parent_dir, VIOC_LISTSYMLINK, &blob, 1);
-
        if (code == 0)
-           printf("'%s' is a %ssymlink to '%.*s'\n",
-                  ti->data,
-                  (thru_symlink ? "symbolic link, leading to a " : ""),
+           printf("'%s' is a symlink to '%.*s'\n",
+                  orig_name,
                   blob.out_size,
                    space);
-
        else {
            error = 1;
            if (errno == EINVAL)
                fprintf(stderr,"'%s' is not a symlink.\n",
                       ti->data);
            else {
-               Die(errno, (ti->data ? ti->data : parent_dir));
+               fs_Die(errno, (ti->data ? ti->data : parent_dir));
            }
        }
     }
     return error;
 }
 
-static MakeLinkCmd(struct cmd_syndesc *as, void *arock)
+static int
+MakeLinkCmd(struct cmd_syndesc *as, void *arock)
 {
     afs_int32 code;
     struct ViceIoctl blob;
     char * parent;
     char path[1024] = "";
 
-    strcpy(path, as->parms[0].items->data);
-    parent = Parent(path);
+    if( FAILED(StringCbCopy(path, sizeof(path), as->parms[0].items->data))) {
+        fprintf (stderr, "MakeLinkCmd - input path too long");
+        exit(1);
+    }
+    parent = fs_GetParent(path);
 
-    if (!InAFS(parent)) {
-#ifdef WIN32
-       const char * nbname = NetbiosName();
+    if (!fs_InAFS(parent)) {
+       const char * nbname = fs_NetbiosName();
        int len = (int)strlen(nbname);
 
        if (parent[0] == '\\' && parent[1] == '\\' &&
            (parent[len+2] == '\\' && parent[len+3] == '\0' || parent[len+2] == '\0') &&
            !strnicmp(nbname,&parent[2],len))
        {
-           sprintf(path,"%s%sall%s", parent, parent[len+2]?"":"\\",
-                    &as->parms[0].items->data[strlen(parent)]);
-           parent = Parent(path);
-           if (!InAFS(parent)) {
-               fprintf(stderr,"%s: symlinks must be created within the AFS file system\n", pn);
-               return 1;
-           }
-       } else
-#endif
-       {
-           fprintf(stderr,"%s: symlinks must be created within the AFS file system\n", pn);
-           return 1;
-       }
+           if( FAILED(StringCbPrintf(path, sizeof(path),
+                                      "%s%sall%s", parent, parent[len+2]?"":"\\",
+                                      &as->parms[0].items->data[strlen(parent)]))) {
+                fprintf(stderr, "path cannot be populated\n");
+                exit(1);
+            }
+           parent = fs_GetParent(path);
+       } else {
+            fprintf(stderr,"%s: symlinks must be created within the AFS file system\n", pn);
+            return 1;
+        }
     }
 
-#ifdef WIN32
-    if ( IsFreelanceRoot(parent) && !IsAdmin() ) {
+    if ( fs_IsFreelanceRoot(parent) && !fs_IsAdmin() ) {
        fprintf(stderr,"%s: Only AFS Client Administrators may alter the root.afs volume\n", pn);
        return 1;
     }
@@ -482,11 +255,8 @@ static MakeLinkCmd(struct cmd_syndesc *as, void *arock)
     blob.in = as->parms[1].items->data;
     blob.out = NULL;
     code = pioctl_utf8(path, VIOC_SYMLINK, &blob, 0);
-#else /* not WIN32 */
-    code = symlink(as->parms[1].items->data, path);
-#endif /* not WIN32 */
     if (code) {
-       Die(errno, as->parms[0].items->data);
+       fs_Die(errno, as->parms[0].items->data);
        return 1;
     }
     return 0;
@@ -498,7 +268,8 @@ static MakeLinkCmd(struct cmd_syndesc *as, void *arock)
  *         symlink (or ``.'' if none is provided)
  *      tp: Set to point to the actual name of the symlink to nuke.
  */
-static RemoveLinkCmd(struct cmd_syndesc *as, void *arock)
+static int
+RemoveLinkCmd(struct cmd_syndesc *as, void *arock)
 {
     afs_int32 code=0;
     struct ViceIoctl blob;
@@ -517,9 +288,8 @@ static RemoveLinkCmd(struct cmd_syndesc *as, void *arock)
             tbuffer[code] = 0;
            tp++;   /* skip the slash */
 
-#ifdef WIN32
-           if (!InAFS(tbuffer)) {
-               const char * nbname = NetbiosName();
+           if (!fs_InAFS(tbuffer)) {
+               const char * nbname = fs_NetbiosName();
                int len = (int)strlen(nbname);
 
                if (tbuffer[0] == '\\' && tbuffer[1] == '\\' &&
@@ -527,16 +297,27 @@ static RemoveLinkCmd(struct cmd_syndesc *as, void *arock)
                     tbuffer[len+3] == '\0' &&
                     !strnicmp(nbname,&tbuffer[2],len))
                {
-                   sprintf(tbuffer,"\\\\%s\\all\\", nbname);
+                   if( FAILED(StringCbPrintf(tbuffer, sizeof(tbuffer),
+                                              "\\\\%s\\all\\", nbname))) {
+                        fprintf( stderr, "tbuffer cannot be populated\n");
+                        exit(1);
+                    }
+               } else {
+                    fprintf(stderr,"'%s' is not in AFS.\n", tbuffer);
+                    code = 1;
+                    continue;
                }
            }
-#endif
        }
-       else {
+       else
+        {
            fs_ExtractDriveLetter(ti->data, tbuffer);
-           strcat(tbuffer, ".");
+           if( FAILED(StringCbCat(tbuffer, sizeof(tbuffer), "."))) {
+               fprintf (stderr, "tbuffer - not enough space");
+                exit(1);
+           }
            tp = ti->data;
-            fs_StripDriveLetter(tp, tp, 0);
+            fs_StripDriveLetter(tp, tp, strlen(tp) + 1);
        }
        blob.in = tp;
        blob.in_size = (int)strlen(tp)+1;
@@ -547,12 +328,12 @@ static RemoveLinkCmd(struct cmd_syndesc *as, void *arock)
            if (errno == EINVAL)
                fprintf(stderr,"symlink: '%s' is not a symlink.\n", ti->data);
            else {
-               Die(errno, ti->data);
+               fs_Die(errno, ti->data);
            }
            continue;   /* don't bother trying */
        }
 
-        if ( IsFreelanceRoot(tbuffer) && !IsAdmin() ) {
+        if ( fs_IsFreelanceRoot(tbuffer) && !fs_IsAdmin() ) {
             fprintf(stderr,"symlink: Only AFS Client Administrators may alter the root.afs volume\n");
             code = 1;
             continue;   /* skip */
@@ -563,88 +344,30 @@ static RemoveLinkCmd(struct cmd_syndesc *as, void *arock)
        blob.in_size = (long)strlen(tp)+1;
        code = pioctl_utf8(tbuffer, VIOC_DELSYMLINK, &blob, 0);
        if (code) {
-           Die(errno, ti->data);
+           fs_Die(errno, ti->data);
        }
     }
     return code;
 }
 
-static void
-FreeUtf8CmdLine(int argc, char ** argv)
-{
-    int i;
-    for (i=0; i < argc; i++) {
-        if (argv[i])
-            free(argv[i]);
-    }
-    free(argv);
-}
-
-static char **
-MakeUtf8Cmdline(int argc, const wchar_t **wargv)
-{
-    char ** argv;
-    int i;
-
-    argv = calloc(argc, sizeof(argv[0]));
-    if (argv == NULL)
-        return NULL;
-
-    for (i=0; i < argc; i++) {
-        int s;
-
-        s = WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1, NULL, 0, NULL, FALSE);
-        if (s == 0 ||
-            (argv[i] = calloc(s+1, sizeof(char))) == NULL) {
-            break;
-        }
-
-        s = WideCharToMultiByte(CP_UTF8, 0, wargv[i], -1, argv[i], s+1, NULL, FALSE);
-        if (s == 0) {
-            break;
-        }
-    }
-
-    if (i < argc) {
-        FreeUtf8CmdLine(argc, argv);
-        return NULL;
-    }
-
-    return argv;
-}
-
-static    struct ViceIoctl gblob;
+static struct ViceIoctl gblob;
 static int debug = 0;
 
-int wmain(int argc, wchar_t **wargv)
+int
+wmain(int argc, wchar_t **wargv)
 {
     afs_int32 code;
     struct cmd_syndesc *ts;
     char ** argv;
 
-#ifdef AFS_AIX32_ENV
-    /*
-     * The following signal action for AIX is necessary so that in case of a
-     * crash (i.e. core is generated) we can include the user's data section
-     * in the core dump. Unfortunately, by default, only a partial core is
-     * generated which, in many cases, isn't too useful.
-     */
-    struct sigaction nsa;
-
-    sigemptyset(&nsa.sa_mask);
-    nsa.sa_handler = SIG_DFL;
-    nsa.sa_flags = SA_FULLDUMP;
-    sigaction(SIGSEGV, &nsa, NULL);
-#endif
-
-#ifdef WIN32
     WSADATA WSAjunk;
     WSAStartup(0x0101, &WSAjunk);
-#endif /* WIN32 */
+
+    fs_SetProcessName(pn);
 
     /* try to find volume location information */
 
-    argv = MakeUtf8Cmdline(argc, wargv);
+    argv = fs_MakeUtf8Cmdline(argc, wargv);
 
     osi_Init();
 
@@ -661,63 +384,7 @@ int wmain(int argc, wchar_t **wargv)
 
     code = cmd_Dispatch(argc, argv);
 
-#ifndef WIN32
-    if (rxInitDone) rx_Finalize();
-#endif /* not WIN32 */
-
-    FreeUtf8CmdLine(argc, argv);
+    fs_FreeUtf8CmdLine(argc, argv);
 
     return code;
 }
-
-void Die(code, filename)
-    int   code;
-    char *filename;
-{ /*Die*/
-
-    if (code == EINVAL) {
-       if (filename)
-           fprintf(stderr,"%s: Invalid argument; it is possible that %s is not in AFS.\n", pn, filename);
-       else fprintf(stderr,"%s: Invalid argument.\n", pn);
-    }
-    else if (code == ENOENT) {
-       if (filename) fprintf(stderr,"%s: File '%s' doesn't exist.\n", pn, filename);
-       else fprintf(stderr,"%s: no such file returned.\n", pn);
-    }
-    else if (code == EEXIST) {
-       if (filename) fprintf(stderr,"%s: File '%s' already exists.\n", pn, filename);
-       else fprintf(stderr,"%s: the specified file already exists.\n", pn);
-    }
-    else if (code == EROFS)  fprintf(stderr,"%s: You can not change a backup or readonly volume\n", pn);
-    else if (code == EACCES || code == EPERM) {
-       if (filename) fprintf(stderr,"%s: You don't have the required access rights on '%s'\n", pn, filename);
-       else fprintf(stderr,"%s: You do not have the required rights to do this operation\n", pn);
-    }
-    else if (code == ENODEV) {
-       fprintf(stderr,"%s: AFS service may not have started.\n", pn);
-    }
-    else if (code == ESRCH) {
-       fprintf(stderr,"%s: Cell name not recognized.\n", pn);
-    }
-    else if (code == EPIPE) {
-       fprintf(stderr,"%s: Volume name or ID not recognized.\n", pn);
-    }
-    else if (code == EFBIG) {
-       fprintf(stderr,"%s: Cache size too large.\n", pn);
-    }
-    else if (code == ETIMEDOUT) {
-       if (filename)
-           fprintf(stderr,"%s:'%s': Connection timed out", pn, filename);
-       else
-           fprintf(stderr,"%s: Connection timed out", pn);
-    }
-    else {
-       if (filename) fprintf(stderr,"%s:'%s'", pn, filename);
-       else fprintf(stderr,"%s", pn);
-#ifdef WIN32
-       fprintf(stderr, ": code 0x%x\n", code);
-#else /* not WIN32 */
-       fprintf(stderr,": %s\n", afs_error_message(code));
-#endif /* not WIN32 */
-    }
-} /*Die*/
index 991084e47b7da010a105f42fa301fed6ec1b751e..239f6886ba90a39e3abde086327a2d6924331856 100644 (file)
@@ -49,7 +49,8 @@ EXERES = \
        $(OUT)\afs_config_stub.res
 
 AFSDOBJS = \
-       $(OUT)\fs_utils.obj
+       $(OUT)\fs_utils.obj \
+        $(OUT)\cm_nls.obj
 
 AFSD= ..\afsd
 
@@ -66,7 +67,9 @@ EXELIBS = \
        $(DESTDIR)\lib\libosi.lib \
        $(DESTDIR)\lib\libafsconf.lib \
        $(DESTDIR)\lib\lanahelper.lib \
-       $(DESTDIR)\lib\afs\afsreg.lib
+       $(DESTDIR)\lib\afs\afsreg.lib \
+        $(DESTDIR)\lib\afs\afsutil.lib \
+       $(DESTDIR)\lib\afsroken.lib
 
 ############################################################################
 #
index 3b71e3031784bbfbf122623c27ce5752549c4aef..ff067c923e9b22066ed88843eeb352b7eb9ad65c 100644 (file)
@@ -41,7 +41,8 @@ EXERES = \
        $(OUT)\afscreds_stub.res
 
 AFSDOBJS = \
-       $(OUT)\fs_utils.obj
+       $(OUT)\fs_utils.obj \
+        $(OUT)\cm_nls.obj
 
 CLIENTOBJS = \
        $(OUT)\drivemap.obj \
@@ -67,7 +68,10 @@ EXELIBS = \
        $(DESTDIR)\lib\afsauthent.lib \
        $(DESTDIR)\lib\libafsconf.lib \
        $(DESTDIR)\lib\afs\afsreg.lib \
-       $(DESTDIR)\lib\afskfw.lib
+        $(DESTDIR)\lib\afskfw.lib \
+        $(DESTDIR)\lib\afs\afsutil.lib \
+       $(DESTDIR)\lib\afsroken.lib
+
 
 ############################################################################
 #
index e3a953158cae2804c5c12de6caf85602d16bc1c1..7c14c197d23b5a57b3a86e87cbd7aee776051cdb 100644 (file)
@@ -32,6 +32,7 @@ DLLOBJS =\
        $(OUT)\afs_shl_ext_stub.res \
        $(OUT)\auth_dlg.obj \
        $(OUT)\clear_acl_dlg.obj \
+        $(OUT)\cm_nls.obj \
        $(OUT)\copy_acl_dlg.obj \
        $(OUT)\down_servers_dlg.obj \
        $(OUT)\fs_utils.obj \
@@ -58,7 +59,10 @@ DLLOBJS =\
 AFSD = ..\afsd
 
 $(OUT)\fs_utils.obj: $(AFSD)\fs_utils.c
-       $(C2OBJ) -I$(DESTDIR)\include\rx $**
+       $(C2OBJ) -UUNICODE -U_UNICODE -I$(DESTDIR)\include\rx $**
+
+$(OUT)\cm_nls.obj: $(AFSD)\cm_nls.c
+       $(C2OBJ)  -UUNICODE -U_UNICODE $**
 
 DLLSDKLIBS =\
     mpr.lib