windows-cm_ioctl_query_opts-20080115
[openafs.git] / src / WINNT / afsd / fs.c
index 960d0b9..22438f3 100644 (file)
@@ -50,17 +50,17 @@ static char tspace[1024];
 
 static struct ubik_client *uclient;
 
-static int GetClientAddrsCmd(struct cmd_syndesc *asp, char *arock);
-static int SetClientAddrsCmd(struct cmd_syndesc *asp, char *arock);
-static int FlushMountCmd(struct cmd_syndesc *asp, char *arock);
-static int RxStatProcCmd(struct cmd_syndesc *asp, char *arock);
-static int RxStatPeerCmd(struct cmd_syndesc *asp, char *arock);
+static int GetClientAddrsCmd(struct cmd_syndesc *asp, void *arock);
+static int SetClientAddrsCmd(struct cmd_syndesc *asp, void *arock);
+static int FlushMountCmd(struct cmd_syndesc *asp, void *arock);
+static int RxStatProcCmd(struct cmd_syndesc *asp, void *arock);
+static int RxStatPeerCmd(struct cmd_syndesc *asp, void *arock);
 
 extern struct cmd_syndesc *cmd_CreateSyntax();
 
-static int MemDumpCmd(struct cmd_syndesc *asp, char *arock);
-static int CSCPolicyCmd(struct cmd_syndesc *asp, char *arock);
-static int MiniDumpCmd(struct cmd_syndesc *asp, char *arock);
+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;
@@ -873,7 +873,7 @@ static BOOL IsAdmin (void)
 }
 
 static int
-SetACLCmd(struct cmd_syndesc *as, char *arock)
+SetACLCmd(struct cmd_syndesc *as, void *arock)
 {
     afs_int32 code;
     struct ViceIoctl blob;
@@ -1003,7 +1003,7 @@ SetACLCmd(struct cmd_syndesc *as, char *arock)
 }
 
 static int 
-CopyACLCmd(struct cmd_syndesc *as, char *arock)
+CopyACLCmd(struct cmd_syndesc *as, void *arock)
 {
     afs_int32 code;
     struct ViceIoctl blob;
@@ -1099,7 +1099,7 @@ GetCell(char *fname, char *cellname)
     blob.out = cellname;
 
     code = pioctl(fname, VIOC_FILE_CELL_NAME, &blob, 1);
-    return code ? errno : 0;
+    return code;
 }
 
 /* Check if a username is valid: If it contains only digits (or a
@@ -1179,7 +1179,7 @@ CleanAcl(struct Acl *aa, char *fname)
 
 /* clean up an acl to not have bogus entries */
 static int 
-CleanACLCmd(struct cmd_syndesc *as, char *arock)
+CleanACLCmd(struct cmd_syndesc *as, void *arock)
 {
     afs_int32 code;
     struct Acl *ta = 0;
@@ -1266,7 +1266,7 @@ CleanACLCmd(struct cmd_syndesc *as, char *arock)
 }
 
 static int 
-ListACLCmd(struct cmd_syndesc *as, char *arock) 
+ListACLCmd(struct cmd_syndesc *as, void *arock) 
 {
     afs_int32 code;
     struct Acl *ta = 0;
@@ -1332,7 +1332,7 @@ ListACLCmd(struct cmd_syndesc *as, char *arock)
 }
 
 static int
-FlushAllCmd(struct cmd_syndesc *as, char *arock)
+FlushAllCmd(struct cmd_syndesc *as, void *arock)
 {
     afs_int32 code;
     struct ViceIoctl blob;
@@ -1347,7 +1347,7 @@ FlushAllCmd(struct cmd_syndesc *as, char *arock)
 }
 
 static int
-FlushVolumeCmd(struct cmd_syndesc *as, char *arock)
+FlushVolumeCmd(struct cmd_syndesc *as, void *arock)
 {
     afs_int32 code;
     struct ViceIoctl blob;
@@ -1369,16 +1369,28 @@ FlushVolumeCmd(struct cmd_syndesc *as, char *arock)
 }
 
 static int 
-FlushCmd(struct cmd_syndesc *as, char *arock) 
+FlushCmd(struct cmd_syndesc *as, void *arock) 
 {
     afs_int32 code;
     struct ViceIoctl blob;
     struct cmd_item *ti;
-
     int error = 0;
+    int literal = 0;
+    cm_ioctlQueryOptions_t options;
 
+    if (as->parms[1].items)
+        literal = 1;
+    
     for(ti=as->parms[0].items; ti; ti=ti->next) {
-       blob.in_size = blob.out_size = 0;
+        /* once per file */
+        memset(&options, 0, sizeof(options));
+        options.size = sizeof(options);
+        options.field_flags |= CM_IOCTL_QOPTS_FIELD_LITERAL;
+        options.literal = literal;
+       blob.in_size = options.size;    /* no variable length data */
+        blob.in = &options;
+
+       blob.out_size = 0;
        code = pioctl(ti->data, VIOCFLUSH, &blob, 0);
        if (code) {
            if (errno == EMFILE) {
@@ -1397,7 +1409,7 @@ FlushCmd(struct cmd_syndesc *as, char *arock)
 
 /* all this command does is repackage its args and call SetVolCmd */
 static int
-SetQuotaCmd(struct cmd_syndesc *as, char *arock) {
+SetQuotaCmd(struct cmd_syndesc *as, void *arock) {
     struct cmd_syndesc ts;
 
     /* copy useful stuff from our command slot; we may later have to reorder */
@@ -1406,7 +1418,7 @@ SetQuotaCmd(struct cmd_syndesc *as, char *arock) {
 }
 
 static int
-SetVolCmd(struct cmd_syndesc *as, char *arock) {
+SetVolCmd(struct cmd_syndesc *as, void *arock) {
     afs_int32 code;
     struct ViceIoctl blob;
     struct cmd_item *ti;
@@ -1470,52 +1482,89 @@ SetVolCmd(struct cmd_syndesc *as, char *arock) {
     return error;
 }
 
-#ifndef WIN32
-/* 
- * Why is VenusFid declared in the kernel-only section of afs.h, 
- * if it's the exported interface of the (UNIX) cache manager?
- */
-struct VenusFid {
-    afs_int32 Cell;
-    AFSFid Fid;
-};
-#endif /* WIN32 */
+/* 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, char *arock)
+ExamineCmd(struct cmd_syndesc *as, void *arock)
 {
     afs_int32 code;
     struct ViceIoctl blob;
     struct cmd_item *ti;
     struct VolumeStatus *status;
     char *name, *offmsg, *motd;
-    long   online_state;
     int error = 0;
-    
+    int literal = 0;
+    cm_ioctlQueryOptions_t options;
+
+    if (as->parms[1].items)
+        literal = 1;
+
     SetDotDefault(&as->parms[0].items);
     for(ti=as->parms[0].items; ti; ti=ti->next) {
         cm_fid_t fid;
+        afs_uint32 filetype;
        afs_uint32 owner[2];
        char cell[MAXCELLCHARS];
 
-       code = GetCell(ti->data, cell);
-       if (code) {
-           Die(errno, ti->data);
-           error = 1;
-           continue;
-       }
-
-       /* once per file */
-       blob.in_size = 0;
+        /* once per file */
+        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 = literal;
+       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(ti->data, VIOCGETFID, &blob, 1)) {
-            printf("File %s (%u.%u.%u) contained in cell %s\n",
-                    ti->data, fid.volume, fid.vnode, fid.unique,
-                    cell);
+            options.field_flags |= CM_IOCTL_QOPTS_FIELD_FID;
+            options.fid = fid;
+        } else {
+           Die(errno, ti->data);
+           error = 1;
+           continue;
         }
 
+        blob.out_size = sizeof(filetype);
+        blob.out = &filetype;
+
+        code = pioctl(ti->data, VIOC_GETFILETYPE, &blob, 1);
+
+        blob.out_size = MAXCELLCHARS;
+        blob.out = cell;
+
+        code = pioctl(ti->data, VIOC_FILE_CELL_NAME, &blob, 1);
+        printf("%s %s (%u.%u.%u) contained in cell %s\n",
+                filetypestr(filetype),
+                ti->data, fid.volume, fid.vnode, fid.unique,
+                code ? "unknown-cell" : cell);
+
        blob.out_size = 2 * sizeof(afs_uint32);
         blob.out = (char *) &owner;
        if (0 == pioctl(ti->data, VIOCGETOWNER, &blob, 1)) {
@@ -1540,22 +1589,25 @@ ExamineCmd(struct cmd_syndesc *as, char *arock)
         } else {
             Die(errno, ti->data);
         }
-        online_state = pioctl(ti->data, VIOC_PATH_AVAILABILITY, &blob, 1);
-        switch (online_state) {
+
+        errno = 0;
+        code = pioctl(ti->data, VIOC_PATH_AVAILABILITY, &blob, 1);
+        switch (errno) {
         case 0:
             printf("Volume is online\n");
             break;
-        case CM_ERROR_ALLOFFLINE:
-            printf("Volume offline\n");
+        case ENXIO:
+            printf("Volume is offline\n");
             break;
-        case CM_ERROR_ALLDOWN:
+        case ENOSYS:
             printf("All Volume servers are down\n");
             break;
-        case CM_ERROR_ALLBUSY:
+        case EBUSY:
             printf("All volume servers are busy\n");
             break;
         default:
-            Die(online_state, ti->data);
+            printf("Unknown volume state\n");
+            Die(errno, ti->data);
         }
         printf("\n");
     }
@@ -1563,7 +1615,7 @@ ExamineCmd(struct cmd_syndesc *as, char *arock)
 }
 
 static int
-ListQuotaCmd(struct cmd_syndesc *as, char *arock) 
+ListQuotaCmd(struct cmd_syndesc *as, void *arock) 
 {
     afs_int32 code;
     struct ViceIoctl blob;
@@ -1595,7 +1647,7 @@ ListQuotaCmd(struct cmd_syndesc *as, char *arock)
 }
 
 static int
-WhereIsCmd(struct cmd_syndesc *as, char *arock)
+WhereIsCmd(struct cmd_syndesc *as, void *arock)
 {
     afs_int32 code;
     struct ViceIoctl blob;
@@ -1604,12 +1656,44 @@ WhereIsCmd(struct cmd_syndesc *as, char *arock)
     afs_int32 *hosts;
     char *tp;
     int error = 0;
+    int literal = 0;
+    cm_ioctlQueryOptions_t options;
+
+    if (as->parms[1].items)
+        literal = 1;
     
     SetDotDefault(&as->parms[0].items);
     for(ti=as->parms[0].items; ti; ti=ti->next) {
-       /* once per file */
-       blob.out_size = MAXSIZE;
-       blob.in_size = 0;
+        cm_fid_t fid;
+        afs_uint32 filetype;
+
+        /* once per file */
+        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 = literal;
+       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(ti->data, VIOCGETFID, &blob, 1)) {
+            options.field_flags |= CM_IOCTL_QOPTS_FIELD_FID;
+            options.fid = fid;
+        } else {
+           Die(errno, ti->data);
+           error = 1;
+           continue;
+        }
+
+        blob.out_size = sizeof(filetype);
+        blob.out = &filetype;
+
+        code = pioctl(ti->data, VIOC_GETFILETYPE, &blob, 1);
+
+        blob.out_size = MAXSIZE;
        blob.out = space;
        memset(space, 0, sizeof(space));
        code = pioctl(ti->data, VIOCWHEREIS, &blob, 1);
@@ -1619,7 +1703,9 @@ WhereIsCmd(struct cmd_syndesc *as, char *arock)
            continue;
        }
        hosts = (afs_int32 *) space;
-       printf("File %s is on host%s ", ti->data, 
+       printf("%s %s is on host%s ", 
+                filetypestr(filetype),
+                ti->data,
                 (hosts[0] && !hosts[1]) ? "": "s");
        for(j=0; j<MAXHOSTS; j++) {
            if (hosts[j] == 0) 
@@ -1634,7 +1720,7 @@ WhereIsCmd(struct cmd_syndesc *as, char *arock)
 
 
 static int
-DiskFreeCmd(struct cmd_syndesc *as, char *arock)
+DiskFreeCmd(struct cmd_syndesc *as, void *arock)
 {
     afs_int32 code;
     struct ViceIoctl blob;
@@ -1665,7 +1751,7 @@ DiskFreeCmd(struct cmd_syndesc *as, char *arock)
 }
 
 static int
-QuotaCmd(struct cmd_syndesc *as, char *arock)
+QuotaCmd(struct cmd_syndesc *as, void *arock)
 {
     afs_int32 code;
     struct ViceIoctl blob;
@@ -1697,7 +1783,7 @@ QuotaCmd(struct cmd_syndesc *as, char *arock)
 }
 
 static int
-ListMountCmd(struct cmd_syndesc *as, char *arock)
+ListMountCmd(struct cmd_syndesc *as, void *arock)
 {
     afs_int32 code;
     struct ViceIoctl blob;
@@ -1849,7 +1935,7 @@ ListMountCmd(struct cmd_syndesc *as, char *arock)
 }
 
 static int
-MakeMountCmd(struct cmd_syndesc *as, char *arock)
+MakeMountCmd(struct cmd_syndesc *as, void *arock)
 {
     afs_int32 code;
     char *cellName, *volName, *tmpName;
@@ -1930,8 +2016,11 @@ MakeMountCmd(struct cmd_syndesc *as, char *arock)
                cellName = localCellName;
        }
     } else {
-       if (!cellName)
-           GetCell(parent,space);
+       if (!cellName) {
+           code = GetCell(parent,space);
+            if (code)
+                return 1;
+        }
     }
 
     code = GetCellName(cellName?cellName:space, &info);
@@ -1991,7 +2080,7 @@ MakeMountCmd(struct cmd_syndesc *as, char *arock)
  *      tp: Set to point to the actual name of the mount point to nuke.
  */
 static int
-RemoveMountCmd(struct cmd_syndesc *as, char *arock) {
+RemoveMountCmd(struct cmd_syndesc *as, void *arock) {
     afs_int32 code=0;
     struct ViceIoctl blob;
     struct cmd_item *ti;
@@ -2067,7 +2156,7 @@ RemoveMountCmd(struct cmd_syndesc *as, char *arock) {
 */
 
 static int
-CheckServersCmd(struct cmd_syndesc *as, char *arock)
+CheckServersCmd(struct cmd_syndesc *as, void *arock)
 {
     afs_int32 code;
     struct ViceIoctl blob;
@@ -2173,7 +2262,7 @@ CheckServersCmd(struct cmd_syndesc *as, char *arock)
 }
 
 static int
-MessagesCmd(struct cmd_syndesc *as, char *arock)
+MessagesCmd(struct cmd_syndesc *as, void *arock)
 {
     afs_int32 code=0;
     struct ViceIoctl blob;
@@ -2216,7 +2305,7 @@ MessagesCmd(struct cmd_syndesc *as, char *arock)
 }
 
 static int
-CheckVolumesCmd(struct cmd_syndesc *as, char *arock)
+CheckVolumesCmd(struct cmd_syndesc *as, void *arock)
 {
     afs_int32 code;
     struct ViceIoctl blob;
@@ -2234,7 +2323,7 @@ CheckVolumesCmd(struct cmd_syndesc *as, char *arock)
 }
 
 static int
-SetCacheSizeCmd(struct cmd_syndesc *as, char *arock)
+SetCacheSizeCmd(struct cmd_syndesc *as, void *arock)
 {
     afs_int32 code;
     struct ViceIoctl blob;
@@ -2278,7 +2367,7 @@ SetCacheSizeCmd(struct cmd_syndesc *as, char *arock)
 }
 
 static int
-GetCacheParmsCmd(struct cmd_syndesc *as, char *arock)
+GetCacheParmsCmd(struct cmd_syndesc *as, void *arock)
 {
     afs_int32 code;
     struct ViceIoctl blob;
@@ -2303,7 +2392,7 @@ GetCacheParmsCmd(struct cmd_syndesc *as, char *arock)
 }
 
 static int
-ListCellsCmd(struct cmd_syndesc *as, char *arock)
+ListCellsCmd(struct cmd_syndesc *as, void *arock)
 {
     afs_int32 code;
     afs_int32 i, j, *lp, magic, size;
@@ -2363,7 +2452,7 @@ ListCellsCmd(struct cmd_syndesc *as, char *arock)
 
 #ifndef WIN32
 static int
-ListAliasesCmd(struct cmd_syndesc *as, char *arock)
+ListAliasesCmd(struct cmd_syndesc *as, void *arock)
 {
     afs_int32 code, i;
     char *tp, *aliasName, *realName;
@@ -2393,7 +2482,7 @@ ListAliasesCmd(struct cmd_syndesc *as, char *arock)
 }
 
 static int
-CallBackRxConnCmd(struct cmd_syndesc *as, char *arock)
+CallBackRxConnCmd(struct cmd_syndesc *as, void *arock)
 {
     afs_int32 code;
     struct ViceIoctl blob;
@@ -2433,7 +2522,7 @@ CallBackRxConnCmd(struct cmd_syndesc *as, char *arock)
 #endif /* WIN32 */
 
 static int
-NewCellCmd(struct cmd_syndesc *as, char *arock)
+NewCellCmd(struct cmd_syndesc *as, void *arock)
 {
 #ifndef WIN32
     afs_int32 code, linkedstate=0, size=0, *lp;
@@ -2530,7 +2619,7 @@ NewCellCmd(struct cmd_syndesc *as, char *arock)
 
 #ifndef WIN32
 static int
-NewAliasCmd(struct cmd_syndesc *as, char *arock)
+NewAliasCmd(struct cmd_syndesc *as, void *arock)
 {
     afs_int32 code;
     struct ViceIoctl blob;
@@ -2566,16 +2655,54 @@ NewAliasCmd(struct cmd_syndesc *as, char *arock)
 #endif /* WIN32 */
 
 static int
-WhichCellCmd(struct cmd_syndesc *as, char *arock)
+WhichCellCmd(struct cmd_syndesc *as, void *arock)
 {
     afs_int32 code;
     struct cmd_item *ti;
+    struct ViceIoctl blob;
     int error = 0;
-    char cell[MAXCELLCHARS]="";
+    int literal = 0;
+    cm_ioctlQueryOptions_t options;
+
+    if (as->parms[1].items)
+        literal = 1;
     
     SetDotDefault(&as->parms[0].items);
     for(ti=as->parms[0].items; ti; ti=ti->next) {
-        code = GetCell(ti->data, cell);
+        cm_fid_t fid;
+        afs_uint32 filetype;
+       char cell[MAXCELLCHARS];
+
+        /* once per file */
+        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 = literal;
+       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(ti->data, VIOCGETFID, &blob, 1)) {
+            options.field_flags |= CM_IOCTL_QOPTS_FIELD_FID;
+            options.fid = fid;
+        } else {
+           Die(errno, ti->data);
+           error = 1;
+           continue;
+        }
+
+        blob.out_size = sizeof(filetype);
+        blob.out = &filetype;
+
+        code = pioctl(ti->data, VIOC_GETFILETYPE, &blob, 1);
+
+        blob.out_size = MAXCELLCHARS;
+        blob.out = cell;
+
+        code = pioctl(ti->data, VIOC_FILE_CELL_NAME, &blob, 1);
        if (code) {
            if (errno == ENOENT)
                fprintf(stderr,"%s: no such cell as '%s'\n", pn, ti->data);
@@ -2584,13 +2711,15 @@ WhichCellCmd(struct cmd_syndesc *as, char *arock)
            error = 1;
            continue;
        }
-        printf("File %s lives in cell '%s'\n", ti->data, cell);
+        printf("%s %s lives in cell '%s'\n",
+                filetypestr(filetype),
+                ti->data, cell);
     }
     return error;
 }
 
 static int
-WSCellCmd(struct cmd_syndesc *as, char *arock)
+WSCellCmd(struct cmd_syndesc *as, void *arock)
 {
     afs_int32 code;
     struct ViceIoctl blob;
@@ -2613,15 +2742,16 @@ WSCellCmd(struct cmd_syndesc *as, char *arock)
 
 /*
 static int
-PrimaryCellCmd(struct cmd_syndesc *as, char *arock)
+PrimaryCellCmd(struct cmd_syndesc *as, void *arock)
 {
     fprintf(stderr,"This command is obsolete, as is the concept of a primary token.\n");
     return 0;
 }
 */
 
+#ifndef AFS_NT40_ENV
 static int
-MonitorCmd(struct cmd_syndesc *as, char *arock)
+MonitorCmd(struct cmd_syndesc *as, void *arock)
 {
     afs_int32 code;
     struct ViceIoctl blob;
@@ -2679,9 +2809,10 @@ MonitorCmd(struct cmd_syndesc *as, char *arock)
     }
     return 0;
 }
+#endif /* AFS_NT40_ENV */
 
 static int
-SysNameCmd(struct cmd_syndesc *as, char *arock)
+SysNameCmd(struct cmd_syndesc *as, void *arock)
 {
     afs_int32 code;
     struct ViceIoctl blob;
@@ -2750,8 +2881,9 @@ SysNameCmd(struct cmd_syndesc *as, char *arock)
     return 0;
 }
 
+#ifndef AFS_NT40_ENV
 static char *exported_types[] = {"null", "nfs", ""};
-static int ExportAfsCmd(struct cmd_syndesc *as, char *arock)
+static int ExportAfsCmd(struct cmd_syndesc *as, void *arock)
 {
     afs_int32 code;
     struct ViceIoctl blob;
@@ -2851,10 +2983,10 @@ static int ExportAfsCmd(struct cmd_syndesc *as, char *arock)
     }
     return 0;
 }
-
+#endif
 
 static int
-GetCellCmd(struct cmd_syndesc *as, char *arock)
+GetCellCmd(struct cmd_syndesc *as, void *arock)
 {
     afs_int32 code;
     struct ViceIoctl blob;
@@ -2903,7 +3035,7 @@ GetCellCmd(struct cmd_syndesc *as, char *arock)
     return error;
 }
 
-static int SetCellCmd(struct cmd_syndesc *as, char *arock)
+static int SetCellCmd(struct cmd_syndesc *as, void *arock)
 {
     afs_int32 code;
     struct ViceIoctl blob;
@@ -3001,7 +3133,7 @@ VLDBInit(int noAuthFlag, struct afsconf_cell *info)
 {
     afs_int32 code;
 
-    code = ugen_ClientInit(noAuthFlag, AFSDIR_CLIENT_ETC_DIRPATH, 
+    code = ugen_ClientInit(noAuthFlag, (char *)AFSDIR_CLIENT_ETC_DIRPATH, 
                           info->name, 0, &uclient, 
                            NULL, pn, rxkad_clear,
                            VLDB_MAXSERVERS, AFSCONF_VLDBSERVICE, 50,
@@ -3190,7 +3322,7 @@ static BOOL IsWindowsNT (void)
 
 #ifdef WIN32
 static int
-SetPrefCmd(struct cmd_syndesc *as, char * arock)
+SetPrefCmd(struct cmd_syndesc *as, void * arock)
 {
     FILE *infd;
     afs_int32 code;
@@ -3280,7 +3412,7 @@ SetPrefCmd(struct cmd_syndesc *as, char * arock)
 }
 #else
 static int
-SetPrefCmd(struct cmd_syndesc *as, char *arock)
+SetPrefCmd(struct cmd_syndesc *as, void *arock)
 {
     FILE *infd;
     afs_int32 code;
@@ -3386,7 +3518,7 @@ SetPrefCmd(struct cmd_syndesc *as, char *arock)
 
 #ifdef WIN32
 static int 
-GetPrefCmd(struct cmd_syndesc *as, char *arock)
+GetPrefCmd(struct cmd_syndesc *as, void *arock)
 {
     afs_int32 code;
     struct cmd_item *ti;
@@ -3457,7 +3589,7 @@ GetPrefCmd(struct cmd_syndesc *as, char *arock)
 }
 #else
 static int
-GetPrefCmd(struct cmd_syndesc *as, char *arock)
+GetPrefCmd(struct cmd_syndesc *as, void *arock)
 {
     afs_int32 code;
     struct cmd_item *ti;
@@ -3528,7 +3660,7 @@ GetPrefCmd(struct cmd_syndesc *as, char *arock)
 #endif /* WIN32 */
 
 static int
-UuidCmd(struct cmd_syndesc *asp, char *arock)
+UuidCmd(struct cmd_syndesc *asp, void *arock)
 {
     long code;
     long inValue;
@@ -3536,19 +3668,18 @@ UuidCmd(struct cmd_syndesc *asp, char *arock)
     struct ViceIoctl blob;
     char * uuidstring = NULL;
 
+    if (asp->parms[0].items) {
 #ifdef WIN32
-    if ( !IsAdmin() ) {
-        fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");
-        return EACCES;
-    }
+        if ( !IsAdmin() ) {
+            fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");
+            return EACCES;
+        }
 #else
-    if (geteuid()) {
-        fprintf (stderr, "Permission denied: requires root access.\n");
-        return EACCES;
-    }
+        if (geteuid()) {
+            fprintf (stderr, "Permission denied: requires root access.\n");
+            return EACCES;
+        }
 #endif
-
-    if (asp->parms[0].items) {
         inValue = 1;            /* generate new UUID */
     } else {
         inValue = 0;            /* just show the current UUID */
@@ -3578,7 +3709,7 @@ UuidCmd(struct cmd_syndesc *asp, char *arock)
 }
 
 static int
-TraceCmd(struct cmd_syndesc *asp, char *arock)
+TraceCmd(struct cmd_syndesc *asp, void *arock)
 {
     long code;
     struct ViceIoctl blob;
@@ -3640,7 +3771,7 @@ static void sbusage(void)
 
 /* fs sb -kbytes 9999 -files *.o -default 64 */
 static int
-StoreBehindCmd(struct cmd_syndesc *as, char *arock)
+StoreBehindCmd(struct cmd_syndesc *as, void *arock)
 {
     afs_int32 code = 0;
     struct ViceIoctl blob;
@@ -3747,7 +3878,7 @@ StoreBehindCmd(struct cmd_syndesc *as, char *arock)
 }
 
 static afs_int32 
-SetCryptCmd(struct cmd_syndesc *as, char *arock)
+SetCryptCmd(struct cmd_syndesc *as, void *arock)
 {
     afs_int32 code = 0, flag;
     struct ViceIoctl blob;
@@ -3780,7 +3911,7 @@ SetCryptCmd(struct cmd_syndesc *as, char *arock)
 }
 
 static afs_int32 
-GetCryptCmd(struct cmd_syndesc *as, char *arock)
+GetCryptCmd(struct cmd_syndesc *as, void *arock)
 {
     afs_int32 code = 0, flag;
     struct ViceIoctl blob;
@@ -3808,7 +3939,7 @@ GetCryptCmd(struct cmd_syndesc *as, char *arock)
 }
 
 static int
-MemDumpCmd(struct cmd_syndesc *asp, char *arock)
+MemDumpCmd(struct cmd_syndesc *asp, void *arock)
 {
     long code;
     struct ViceIoctl blob;
@@ -3853,7 +3984,7 @@ MemDumpCmd(struct cmd_syndesc *asp, char *arock)
 }
 
 static int
-MiniDumpCmd(struct cmd_syndesc *asp, char *arock)
+MiniDumpCmd(struct cmd_syndesc *asp, void *arock)
 {
     BOOL success = 0;
     SERVICE_STATUS status;
@@ -3894,7 +4025,7 @@ MiniDumpCmd(struct cmd_syndesc *asp, char *arock)
 }
 
 static int
-CSCPolicyCmd(struct cmd_syndesc *asp, char *arock)
+CSCPolicyCmd(struct cmd_syndesc *asp, void *arock)
 {
     struct cmd_item *ti;
     char *share = NULL;
@@ -4008,7 +4139,7 @@ CSCPolicyCmd(struct cmd_syndesc *asp, char *arock)
 #ifndef WIN32
 /* get clients interface addresses */
 static int
-GetClientAddrsCmd(struct cmd_syndesc *as, char *arock)
+GetClientAddrsCmd(struct cmd_syndesc *as, void *arock)
 {
     afs_int32 code;
     struct cmd_item *ti;
@@ -4054,7 +4185,7 @@ GetClientAddrsCmd(struct cmd_syndesc *as, char *arock)
 }
 
 static int
-SetClientAddrsCmd(struct cmd_syndesc *as, char *arock)
+SetClientAddrsCmd(struct cmd_syndesc *as, void *arock)
 {
     afs_int32 code, addr;
     struct cmd_item *ti;
@@ -4128,7 +4259,7 @@ SetClientAddrsCmd(struct cmd_syndesc *as, char *arock)
 }
 
 static int
-FlushMountCmd(struct cmd_syndesc *as, char *arock)
+FlushMountCmd(struct cmd_syndesc *as, void *arock)
 {
     afs_int32 code;
     struct ViceIoctl blob;
@@ -4245,7 +4376,7 @@ FlushMountCmd(struct cmd_syndesc *as, char *arock)
 #endif /* WIN32 */
 
 static int
-RxStatProcCmd(struct cmd_syndesc *as, char *arock)
+RxStatProcCmd(struct cmd_syndesc *as, void *arock)
 {
     afs_int32 code;
     afs_int32 flags = 0;
@@ -4279,7 +4410,7 @@ RxStatProcCmd(struct cmd_syndesc *as, char *arock)
 }
 
 static int
-RxStatPeerCmd(struct cmd_syndesc *as, char *arock)
+RxStatPeerCmd(struct cmd_syndesc *as, void *arock)
 {
     afs_int32 code;
     afs_int32 flags = 0;
@@ -4312,6 +4443,86 @@ RxStatPeerCmd(struct cmd_syndesc *as, char *arock)
     return 0;
 }
 
+static int
+TestVolStatCmd(struct cmd_syndesc *as, void *arock)
+{
+    afs_int32 code;
+    struct VolStatTest test;
+    struct ViceIoctl blob;
+    char * tp;
+    afs_uint32 n;
+
+    memset(&test, 0, sizeof(test));
+
+    if (as->parms[0].items) {  /* -network */
+        tp = as->parms[0].items->data;
+        if (strcmp(tp, "up") == 0)
+            test.flags |= VOLSTAT_TEST_NETWORK_UP;
+        else if (strcmp(tp, "down") == 0)
+            test.flags |= VOLSTAT_TEST_NETWORK_DOWN;
+        else {
+            fprintf (stderr, "%s: %s must be \"up\" or \"down\".\n", pn, tp);
+            return EINVAL;
+        }
+    }
+    if (as->parms[1].items) {  /* check */
+        test.flags |= VOLSTAT_TEST_CHECK_VOLUME;
+    }
+    if (as->parms[2].items) {  /* cell */
+        tp = as->parms[2].items->data;
+        n = atoi(tp);
+        if (n != 0)
+            test.fid.cell = n;
+        else {
+            strncpy(test.cellname, tp, sizeof(test.cellname));
+            test.cellname[sizeof(test.cellname)-1] = '\0';
+        }
+    }
+    if (as->parms[3].items) {  /* volume */
+        tp = as->parms[3].items->data;
+        n = atoi(tp);
+        if (n != 0)
+            test.fid.volume = n;
+        else {
+            strncpy(test.volname, tp, sizeof(test.volname));
+            test.volname[sizeof(test.volname)-1] = '\0';
+        }
+    }
+    if (as->parms[4].items) {   /* state */
+        tp = as->parms[4].items->data;
+        if (strcmp(tp, "online") == 0)
+            test.state = vl_online;
+        else if (strcmp(tp, "busy") == 0)
+            test.state = vl_busy;
+        else if (strcmp(tp, "offline") == 0)
+            test.state = vl_offline;
+        else if (strcmp(tp, "down") == 0)
+            test.state = vl_alldown;
+        else {
+            fprintf (stderr, "%s: %s must be \"online\", \"busy\", \"offline\" or \"down\".\n", pn, tp);
+            return EINVAL;
+        }
+    }
+
+    if ((test.fid.cell || test.cellname[0]) && !(test.fid.volume || test.volname[0]) ||
+         !(test.fid.cell || test.cellname[0]) && (test.fid.volume || test.volname[0])) {
+        fprintf (stderr, "%s: both a cell and a volume must be specified.\n", pn, tp);
+        return EINVAL;
+    }
+
+    blob.in = (char *)&test;
+    blob.in_size = sizeof(test);
+    blob.out_size = 0;
+
+    code = pioctl(NULL, VIOC_VOLSTAT_TEST, &blob, 1);
+    if (code != 0) {
+       Die(errno, NULL);
+       return 1;
+    }
+
+    return 0;
+}
+
 #ifndef WIN32
 #include "AFS_component_version_number.c"
 #endif
@@ -4345,32 +4556,32 @@ main(int argc, char **argv)
     osi_Init();
 
 #ifndef WIN32
-    ts = cmd_CreateSyntax("getclientaddrs", GetClientAddrsCmd, 0,
+    ts = cmd_CreateSyntax("getclientaddrs", GetClientAddrsCmd, NULL,
                          "get client network interface addresses");
     cmd_CreateAlias(ts, "gc");
 
-    ts = cmd_CreateSyntax("setclientaddrs", SetClientAddrsCmd, 0,
+    ts = cmd_CreateSyntax("setclientaddrs", SetClientAddrsCmd, NULL,
                          "set client network interface addresses");
     cmd_AddParm(ts, "-address", CMD_LIST, CMD_OPTIONAL | CMD_EXPANDS,
                 "client network interfaces");
     cmd_CreateAlias(ts, "sc");
 #endif /* WIN32 */
 
-    ts = cmd_CreateSyntax("setserverprefs", SetPrefCmd, 0, "set server ranks");
+    ts = cmd_CreateSyntax("setserverprefs", SetPrefCmd, NULL, "set server ranks");
     cmd_AddParm(ts, "-servers", CMD_LIST, CMD_OPTIONAL|CMD_EXPANDS, "fileserver names and ranks");
     cmd_AddParm(ts, "-vlservers", CMD_LIST, CMD_OPTIONAL|CMD_EXPANDS, "VL server names and ranks");
     cmd_AddParm(ts, "-file", CMD_SINGLE, CMD_OPTIONAL, "input from named file");
     cmd_AddParm(ts, "-stdin", CMD_FLAG, CMD_OPTIONAL, "input from stdin");
     cmd_CreateAlias(ts, "sp");
 
-    ts = cmd_CreateSyntax("getserverprefs", GetPrefCmd, 0, "get server ranks");
+    ts = cmd_CreateSyntax("getserverprefs", GetPrefCmd, NULL, "get server ranks");
     cmd_AddParm(ts, "-file", CMD_SINGLE, CMD_OPTIONAL, "output to named file");
     cmd_AddParm(ts, "-numeric", CMD_FLAG, CMD_OPTIONAL, "addresses only");
     cmd_AddParm(ts, "-vlservers", CMD_FLAG, CMD_OPTIONAL, "VL servers");
     /* cmd_AddParm(ts, "-cell", CMD_FLAG, CMD_OPTIONAL, "cellname"); */
     cmd_CreateAlias(ts, "gp");
 
-    ts = cmd_CreateSyntax("setacl", SetACLCmd, 0, "set access control list");
+    ts = cmd_CreateSyntax("setacl", SetACLCmd, NULL, "set access control list");
     cmd_AddParm(ts, "-dir", CMD_LIST, 0, "directory");
     cmd_AddParm(ts, "-acl", CMD_LIST, 0, "access list entries");
     cmd_AddParm(ts, "-clear", CMD_FLAG, CMD_OPTIONAL, "clear access list");
@@ -4380,17 +4591,17 @@ main(int argc, char **argv)
     cmd_AddParm(ts, "-if", CMD_FLAG, CMD_OPTIONAL, "initial file acl (DFS only)");
     cmd_CreateAlias(ts, "sa");
     
-    ts = cmd_CreateSyntax("listacl", ListACLCmd, 0, "list access control list");
+    ts = cmd_CreateSyntax("listacl", ListACLCmd, NULL, "list access control list");
     cmd_AddParm(ts, "-path", CMD_LIST, CMD_OPTIONAL, "dir/file path");
     parm_listacl_id = ts->nParms;
     cmd_AddParm(ts, "-id", CMD_FLAG, CMD_OPTIONAL, "initial directory acl");
     cmd_AddParm(ts, "-if", CMD_FLAG, CMD_OPTIONAL, "initial file acl");
     cmd_CreateAlias(ts, "la");
     
-    ts = cmd_CreateSyntax("cleanacl", CleanACLCmd, 0, "clean up access control list");
+    ts = cmd_CreateSyntax("cleanacl", CleanACLCmd, NULL, "clean up access control list");
     cmd_AddParm(ts, "-path", CMD_LIST, CMD_OPTIONAL, "dir/file path");
     
-    ts = cmd_CreateSyntax("copyacl", CopyACLCmd, 0, "copy access control list");
+    ts = cmd_CreateSyntax("copyacl", CopyACLCmd, NULL, "copy access control list");
     cmd_AddParm(ts, "-fromdir", CMD_SINGLE, 0, "source directory (or DFS file)");
     cmd_AddParm(ts, "-todir", CMD_LIST, 0, "destination directory (or DFS file)");
     cmd_AddParm(ts, "-clear", CMD_FLAG, CMD_OPTIONAL, "first clear dest access list");
@@ -4400,16 +4611,17 @@ main(int argc, char **argv)
     
     cmd_CreateAlias(ts, "ca");
 
-    ts = cmd_CreateSyntax("flush", FlushCmd, 0, "flush file from cache");
+    ts = cmd_CreateSyntax("flush", FlushCmd, NULL, "flush file from cache");
     cmd_AddParm(ts, "-path", CMD_LIST, CMD_OPTIONAL, "dir/file path");
+    cmd_AddParm(ts, "-literal", CMD_FLAG, CMD_OPTIONAL, "literal evaluation of mountpoints and symlinks");
     
 #ifndef WIN32
-    ts = cmd_CreateSyntax("flushmount", FlushMountCmd, 0,
+    ts = cmd_CreateSyntax("flushmount", FlushMountCmd, NULL,
                            "flush mount symlink from cache");
     cmd_AddParm(ts, "-path", CMD_LIST, CMD_OPTIONAL, "dir/file path");
 #endif
 
-    ts = cmd_CreateSyntax("setvol", SetVolCmd, 0, "set volume status");
+    ts = cmd_CreateSyntax("setvol", SetVolCmd, NULL, "set volume status");
     cmd_AddParm(ts, "-path", CMD_LIST, CMD_OPTIONAL, "dir/file path");
     cmd_AddParm(ts, "-max", CMD_SINGLE, CMD_OPTIONAL, "disk space quota in 1K units");
 #ifdef notdef
@@ -4419,29 +4631,30 @@ main(int argc, char **argv)
     cmd_AddParm(ts, "-offlinemsg", CMD_SINGLE, CMD_OPTIONAL, "offline message");
     cmd_CreateAlias(ts, "sv");
     
-    ts = cmd_CreateSyntax("messages", MessagesCmd, 0, "control Cache Manager messages");
+    ts = cmd_CreateSyntax("messages", MessagesCmd, NULL, "control Cache Manager messages");
     cmd_AddParm(ts, "-show", CMD_SINGLE, CMD_OPTIONAL, "[user|console|all|none]");
 
-    ts = cmd_CreateSyntax("examine", ExamineCmd, 0, "display file/volume status");
+    ts = cmd_CreateSyntax("examine", ExamineCmd, NULL, "display file/volume status");
     cmd_AddParm(ts, "-path", CMD_LIST, CMD_OPTIONAL, "dir/file path");
+    cmd_AddParm(ts, "-literal", CMD_FLAG, CMD_OPTIONAL, "literal evaluation of mountpoints and symlinks");
     cmd_CreateAlias(ts, "lv");
     cmd_CreateAlias(ts, "listvol");
     
-    ts = cmd_CreateSyntax("listquota", ListQuotaCmd, 0, "list volume quota");
+    ts = cmd_CreateSyntax("listquota", ListQuotaCmd, NULL, "list volume quota");
     cmd_AddParm(ts, "-path", CMD_LIST, CMD_OPTIONAL, "dir/file path");
     cmd_CreateAlias(ts, "lq");
     
-    ts = cmd_CreateSyntax("diskfree", DiskFreeCmd, 0, "show server disk space usage");
+    ts = cmd_CreateSyntax("diskfree", DiskFreeCmd, NULL, "show server disk space usage");
     cmd_AddParm(ts, "-path", CMD_LIST, CMD_OPTIONAL, "dir/file path");
     cmd_CreateAlias(ts, "df");
     
-    ts = cmd_CreateSyntax("quota", QuotaCmd, 0, "show volume quota usage");
+    ts = cmd_CreateSyntax("quota", QuotaCmd, NULL, "show volume quota usage");
     cmd_AddParm(ts, "-path", CMD_LIST, CMD_OPTIONAL, "dir/file path");
     
-    ts = cmd_CreateSyntax("lsmount", ListMountCmd, 0, "list mount point");    
+    ts = cmd_CreateSyntax("lsmount", ListMountCmd, NULL, "list mount point");    
     cmd_AddParm(ts, "-dir", CMD_LIST, 0, "directory");
     
-    ts = cmd_CreateSyntax("mkmount", MakeMountCmd, 0, "make mount point");
+    ts = cmd_CreateSyntax("mkmount", MakeMountCmd, NULL, "make mount point");
     cmd_AddParm(ts, "-dir", CMD_SINGLE, 0, "directory");
     cmd_AddParm(ts, "-vol", CMD_SINGLE, 0, "volume name");
     cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cell name");
@@ -4456,31 +4669,31 @@ main(int argc, char **argv)
     */
 
     
-    ts = cmd_CreateSyntax("rmmount", RemoveMountCmd, 0, "remove mount point");
+    ts = cmd_CreateSyntax("rmmount", RemoveMountCmd, NULL, "remove mount point");
     cmd_AddParm(ts, "-dir", CMD_LIST, 0, "directory");
     
-    ts = cmd_CreateSyntax("checkservers", CheckServersCmd, 0, "check local cell's servers");
+    ts = cmd_CreateSyntax("checkservers", CheckServersCmd, NULL, "check local cell's servers");
     cmd_AddParm(ts, "-cell", CMD_SINGLE, CMD_OPTIONAL, "cell to check");
     cmd_AddParm(ts, "-all", CMD_FLAG, CMD_OPTIONAL, "check all cells");
     cmd_AddParm(ts, "-fast", CMD_FLAG, CMD_OPTIONAL, "just list, don't check");
     cmd_AddParm(ts,"-interval",CMD_SINGLE,CMD_OPTIONAL,"seconds between probes");
     
-    ts = cmd_CreateSyntax("checkvolumes", CheckVolumesCmd,0, "check volumeID/name mappings");
+    ts = cmd_CreateSyntax("checkvolumes", CheckVolumesCmd, NULL, "check volumeID/name mappings");
     cmd_CreateAlias(ts, "checkbackups");
 
     
-    ts = cmd_CreateSyntax("setcachesize", SetCacheSizeCmd, 0, "set cache size");
+    ts = cmd_CreateSyntax("setcachesize", SetCacheSizeCmd, NULL, "set cache size");
     cmd_AddParm(ts, "-blocks", CMD_SINGLE, CMD_OPTIONAL, "size in 1K byte blocks (0 => reset)");
     cmd_CreateAlias(ts, "cachesize");
 
     cmd_AddParm(ts, "-reset", CMD_FLAG, CMD_OPTIONAL, "reset size back to boot value");
     
-    ts = cmd_CreateSyntax("getcacheparms", GetCacheParmsCmd, 0, "get cache usage info");
+    ts = cmd_CreateSyntax("getcacheparms", GetCacheParmsCmd, NULL, "get cache usage info");
 
-    ts = cmd_CreateSyntax("listcells", ListCellsCmd, 0, "list configured cells");
+    ts = cmd_CreateSyntax("listcells", ListCellsCmd, NULL, "list configured cells");
     cmd_AddParm(ts, "-numeric", CMD_FLAG, CMD_OPTIONAL, "addresses only");
     
-    ts = cmd_CreateSyntax("setquota", SetQuotaCmd, 0, "set volume quota");
+    ts = cmd_CreateSyntax("setquota", SetQuotaCmd, NULL, "set volume quota");
     cmd_AddParm(ts, "-path", CMD_SINGLE, CMD_OPTIONAL, "dir/file path");
     cmd_AddParm(ts, "-max", CMD_SINGLE, 0, "max quota in kbytes");
 #ifdef notdef
@@ -4488,7 +4701,7 @@ main(int argc, char **argv)
 #endif
     cmd_CreateAlias(ts, "sq");
 
-    ts = cmd_CreateSyntax("newcell", NewCellCmd, 0, "configure new cell");
+    ts = cmd_CreateSyntax("newcell", NewCellCmd, NULL, "configure new cell");
 #ifndef WIN32
     cmd_AddParm(ts, "-name", CMD_SINGLE, 0, "cell name");
     cmd_AddParm(ts, "-servers", CMD_LIST, CMD_REQUIRED, "primary servers");
@@ -4505,104 +4718,115 @@ main(int argc, char **argv)
     cmd_AddParm(ts, "-vlport", CMD_SINGLE, CMD_OPTIONAL, "cell's vldb server port");
 #endif
 
-    ts = cmd_CreateSyntax("newalias", NewAliasCmd, 0,
+    ts = cmd_CreateSyntax("newalias", NewAliasCmd, NULL,
                          "configure new cell alias");
     cmd_AddParm(ts, "-alias", CMD_SINGLE, 0, "alias name");
     cmd_AddParm(ts, "-name", CMD_SINGLE, 0, "real name of cell");
 #endif
 
-    ts = cmd_CreateSyntax("whichcell", WhichCellCmd, 0, "list file's cell");
+    ts = cmd_CreateSyntax("whichcell", WhichCellCmd, NULL, "list file's cell");
     cmd_AddParm(ts, "-path", CMD_LIST, CMD_OPTIONAL, "dir/file path");
+    cmd_AddParm(ts, "-literal", CMD_FLAG, CMD_OPTIONAL, "literal evaluation of mountpoints and symlinks");
 
-    ts = cmd_CreateSyntax("whereis", WhereIsCmd, 0, "list file's location");
+    ts = cmd_CreateSyntax("whereis", WhereIsCmd, NULL, "list file's location");
     cmd_AddParm(ts, "-path", CMD_LIST, CMD_OPTIONAL, "dir/file path");
+    cmd_AddParm(ts, "-literal", CMD_FLAG, CMD_OPTIONAL, "literal evaluation of mountpoints and symlinks");
 
-    ts = cmd_CreateSyntax("wscell", WSCellCmd, 0, "list workstation's cell");
+    ts = cmd_CreateSyntax("wscell", WSCellCmd, NULL, "list workstation's cell");
     
     /*
      ts = cmd_CreateSyntax("primarycell", PrimaryCellCmd, 0, "obsolete (listed primary cell)");
      */
     
-    ts = cmd_CreateSyntax("monitor", MonitorCmd, 0, "set cache monitor host address");
+#ifndef AFS_NT40_ENV
+    ts = cmd_CreateSyntax("monitor", MonitorCmd, NULL, "set cache monitor host address");
     cmd_AddParm(ts, "-server", CMD_SINGLE, CMD_OPTIONAL, "host name or 'off'");
     cmd_CreateAlias(ts, "mariner");
-    
-   
-    ts = cmd_CreateSyntax("getcellstatus", GetCellCmd, 0, "get cell status");
+#endif
+
+    ts = cmd_CreateSyntax("getcellstatus", GetCellCmd, NULL, "get cell status");
     cmd_AddParm(ts, "-cell", CMD_LIST, 0, "cell name");
     
-    ts = cmd_CreateSyntax("setcell", SetCellCmd, 0, "set cell status");
+    ts = cmd_CreateSyntax("setcell", SetCellCmd, NULL, "set cell status");
     cmd_AddParm(ts, "-cell", CMD_LIST, 0, "cell name");
     cmd_AddParm(ts, "-suid", CMD_FLAG, CMD_OPTIONAL, "allow setuid programs");
     cmd_AddParm(ts, "-nosuid", CMD_FLAG, CMD_OPTIONAL, "disallow setuid programs");
 
-    ts = cmd_CreateSyntax("flushall", FlushAllCmd, 0, "flush all data");
+    ts = cmd_CreateSyntax("flushall", FlushAllCmd, NULL, "flush all data");
 
-    ts = cmd_CreateSyntax("flushvolume", FlushVolumeCmd, 0, "flush all data in volume");
+    ts = cmd_CreateSyntax("flushvolume", FlushVolumeCmd, NULL, "flush all data in volume");
     cmd_AddParm(ts, "-path", CMD_LIST, CMD_OPTIONAL, "dir/file path");
 
-    ts = cmd_CreateSyntax("sysname", SysNameCmd, 0, "get/set sysname (i.e. @sys) value");
+    ts = cmd_CreateSyntax("sysname", SysNameCmd, NULL, "get/set sysname (i.e. @sys) value");
     cmd_AddParm(ts, "-newsys", CMD_LIST, CMD_OPTIONAL, "new sysname");
 
-    ts = cmd_CreateSyntax("exportafs", ExportAfsCmd, 0, "enable/disable translators to AFS");
+#ifndef AFS_NT40_ENV
+    ts = cmd_CreateSyntax("exportafs", ExportAfsCmd, NULL, "enable/disable translators to AFS");
     cmd_AddParm(ts, "-type", CMD_SINGLE, 0, "exporter name");
     cmd_AddParm(ts, "-start", CMD_SINGLE, CMD_OPTIONAL, "start/stop translator ('on' or 'off')");
     cmd_AddParm(ts, "-convert", CMD_SINGLE, CMD_OPTIONAL, "convert from afs to unix mode ('on or 'off')");
     cmd_AddParm(ts, "-uidcheck", CMD_SINGLE, CMD_OPTIONAL, "run on strict 'uid check' mode ('on' or 'off')");
     cmd_AddParm(ts, "-submounts", CMD_SINGLE, CMD_OPTIONAL, "allow nfs mounts to subdirs of /afs/.. ('on' or 'off')");
+#endif
 
-
-    ts = cmd_CreateSyntax("storebehind", StoreBehindCmd, 0, 
+    ts = cmd_CreateSyntax("storebehind", StoreBehindCmd, NULL, 
                          "store to server after file close");
     cmd_AddParm(ts, "-kbytes", CMD_SINGLE, CMD_OPTIONAL, "asynchrony for specified names");
     cmd_AddParm(ts, "-files", CMD_LIST, CMD_OPTIONAL, "specific pathnames");
     cmd_AddParm(ts, "-allfiles", CMD_SINGLE, CMD_OPTIONAL, "new default (KB)");
     cmd_CreateAlias(ts, "sb");
 
-    ts = cmd_CreateSyntax("setcrypt", SetCryptCmd, 0, "set cache manager encryption flag");
+    ts = cmd_CreateSyntax("setcrypt", SetCryptCmd, NULL, "set cache manager encryption flag");
     cmd_AddParm(ts, "-crypt", CMD_SINGLE, 0, "on or off");
 
-    ts = cmd_CreateSyntax("getcrypt", GetCryptCmd, 0, "get cache manager encryption flag");
+    ts = cmd_CreateSyntax("getcrypt", GetCryptCmd, NULL, "get cache manager encryption flag");
 
-    ts = cmd_CreateSyntax("rxstatproc", RxStatProcCmd, 0,
+    ts = cmd_CreateSyntax("rxstatproc", RxStatProcCmd, NULL,
                          "Manage per process RX statistics");
     cmd_AddParm(ts, "-enable", CMD_FLAG, CMD_OPTIONAL, "Enable RX stats");
     cmd_AddParm(ts, "-disable", CMD_FLAG, CMD_OPTIONAL, "Disable RX stats");
     cmd_AddParm(ts, "-clear", CMD_FLAG, CMD_OPTIONAL, "Clear RX stats");
 
-    ts = cmd_CreateSyntax("rxstatpeer", RxStatPeerCmd, 0,
+    ts = cmd_CreateSyntax("rxstatpeer", RxStatPeerCmd, NULL,
                          "Manage per peer RX statistics");
     cmd_AddParm(ts, "-enable", CMD_FLAG, CMD_OPTIONAL, "Enable RX stats");
     cmd_AddParm(ts, "-disable", CMD_FLAG, CMD_OPTIONAL, "Disable RX stats");
     cmd_AddParm(ts, "-clear", CMD_FLAG, CMD_OPTIONAL, "Clear RX stats");
 
 #ifndef WIN32
-    ts = cmd_CreateSyntax("setcbaddr", CallBackRxConnCmd, 0, "configure callback connection address");
+    ts = cmd_CreateSyntax("setcbaddr", CallBackRxConnCmd, NULL, "configure callback connection address");
     cmd_AddParm(ts, "-addr", CMD_SINGLE, CMD_OPTIONAL, "host name or address");
 #endif
 
-    ts = cmd_CreateSyntax("trace", TraceCmd, 0, "enable or disable CM tracing");
+    ts = cmd_CreateSyntax("trace", TraceCmd, NULL, "enable or disable CM tracing");
     cmd_AddParm(ts, "-on", CMD_FLAG, CMD_OPTIONAL, "enable tracing");
     cmd_AddParm(ts, "-off", CMD_FLAG, CMD_OPTIONAL, "disable tracing");
     cmd_AddParm(ts, "-reset", CMD_FLAG, CMD_OPTIONAL, "reset log contents");
     cmd_AddParm(ts, "-dump", CMD_FLAG, CMD_OPTIONAL, "dump log contents");
     cmd_CreateAlias(ts, "tr");
 
-    ts = cmd_CreateSyntax("uuid", UuidCmd, 0, "manage the UUID for the cache manager");
+    ts = cmd_CreateSyntax("uuid", UuidCmd, NULL, "manage the UUID for the cache manager");
     cmd_AddParm(ts, "-generate", CMD_FLAG, CMD_OPTIONAL, "generate a new UUID");
 
-    ts = cmd_CreateSyntax("memdump", MemDumpCmd, 0, "dump memory allocs in debug builds");
+    ts = cmd_CreateSyntax("memdump", MemDumpCmd, NULL, "dump memory allocs in debug builds");
     cmd_AddParm(ts, "-begin", CMD_FLAG, CMD_OPTIONAL, "set a memory checkpoint");
     cmd_AddParm(ts, "-end", CMD_FLAG, CMD_OPTIONAL, "dump memory allocs");
     
-    ts = cmd_CreateSyntax("cscpolicy", CSCPolicyCmd, 0, "change client side caching policy for AFS shares");
+    ts = cmd_CreateSyntax("cscpolicy", CSCPolicyCmd, NULL, "change client side caching policy for AFS shares");
     cmd_AddParm(ts, "-share", CMD_SINGLE, CMD_OPTIONAL, "AFS share");
     cmd_AddParm(ts, "-manual", CMD_FLAG, CMD_OPTIONAL, "manual caching of documents");
     cmd_AddParm(ts, "-programs", CMD_FLAG, CMD_OPTIONAL, "automatic caching of programs and documents");
     cmd_AddParm(ts, "-documents", CMD_FLAG, CMD_OPTIONAL, "automatic caching of documents");
     cmd_AddParm(ts, "-disable", CMD_FLAG, CMD_OPTIONAL, "disable caching");
 
-    ts = cmd_CreateSyntax("minidump", MiniDumpCmd, 0, "Generate MiniDump of current service state");
+    ts = cmd_CreateSyntax("minidump", MiniDumpCmd, NULL, "Generate MiniDump of current service state");
+
+    ts = cmd_CreateSyntax("test_volstat", TestVolStatCmd, NULL, (char *)CMD_HIDDEN);
+    cmd_AddParm(ts, "-network", CMD_SINGLE, CMD_OPTIONAL, "set network state up or down");
+    cmd_AddParm(ts, "-check",   CMD_FLAG,   CMD_OPTIONAL, "check state of offline volumes");
+    cmd_AddParm(ts, "-cell",    CMD_SINGLE, CMD_OPTIONAL, "cell name or number");
+    cmd_AddParm(ts, "-volume",  CMD_SINGLE, CMD_OPTIONAL, "volume name or number");
+    cmd_AddParm(ts, "-state",   CMD_SINGLE, CMD_OPTIONAL, "new volume state: online, busy, offline, down");
 
     code = cmd_Dispatch(argc, argv);