volinfo: accept vice partition id for -part option
[openafs.git] / src / vol / vol-info.c
index f381290..33f3812 100644 (file)
@@ -93,6 +93,18 @@ void PrintVnode(afs_foff_t offset, VnodeDiskObject * vnode, VnodeId vnodeNumber,
                Inode ino, Volume * vp);
 void HandleVnodes(Volume * vp, VnodeClass class);
 
+/**
+ * Format time as a timestamp string
+ *
+ * @param[in] date  time value to format
+ *
+ * @return timestamp string in the form YYYY/MM/DD.hh:mm:ss
+ *
+ * @note A static array of 8 strings are stored by this
+ *       function. The array slots are overwritten, so the
+ *       caller must not reference the returned string after
+ *       seven additional calls to this function.
+ */
 char *
 date(time_t date)
 {
@@ -108,6 +120,38 @@ date(time_t date)
     return results[next];
 }
 
+#ifdef AFS_NT40_ENV
+/**
+ * Format file time as a timestamp string
+ *
+ * @param[in] ft  file time
+ *
+ * @return timestamp string in the form YYYY/MM/DD.hh:mm:ss
+ *
+ * @note A static array of 8 strings are stored by this
+ *       function. The array slots are overwritten, so the
+ *       caller must not reference the returned string after
+ *       seven additional calls to this function.
+ */
+char *
+NT_date(FILETIME * ft)
+{
+    static char result[8][64];
+    static int next = 0;
+    SYSTEMTIME st;
+    FILETIME lft;
+
+    if (!FileTimeToLocalFileTime(ft, &lft)
+       || !FileTimeToSystemTime(&lft, &st)) {
+       fprintf(stderr, "%s: Time conversion failed.\n", progname);
+       exit(1);
+    }
+    sprintf(result[next = ((next + 1) & 7)], "%4d/%02d/%02d.%2d:%2d:%2d",
+           st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
+    return result[next];
+}
+#endif
+
 /**
  * Print the volume size table heading line, if needed.
  *
@@ -189,6 +233,19 @@ PrintServerTotals(void)
           serverTotals.vnodesize, serverTotals.size_k, diff_k);
 }
 
+/**
+ * Read a volume header file
+ *
+ * @param[in] ih        ihandle of the header file
+ * @param[in] to        destination
+ * @param[in] size      expected header size
+ * @param[in] magic     expected header magic number
+ * @param[in] version   expected header version number
+ *
+ * @return error code
+ *   @retval 0 success
+ *   @retval -1 failed to read file
+ */
 int
 ReadHdr1(IHandle_t * ih, char *to, int size, u_int magic, u_int version)
 {
@@ -235,7 +292,15 @@ ReadHdr1(IHandle_t * ih, char *to, int size, u_int magic, u_int version)
     return 0;
 }
 
-
+/**
+ * Simplified attach volume
+ *
+ * param[in] dp       vice disk partition object
+ * param[in] volname  volume header file name
+ * param[in] header   volume header object
+ *
+ * @return volume object or null on error
+ */
 Volume *
 AttachVolume(struct DiskPartition64 * dp, char *volname,
             struct VolumeHeader * header)
@@ -283,14 +348,62 @@ AttachVolume(struct DiskPartition64 * dp, char *volname,
     return vp;
 }
 
+/**
+ * Convert the partition device number into a partition name.
+ *
+ * @param[in]   partId      partition number, 0 to 254
+ * @param[out]  partName    buffer to hold partition name (e.g. /vicepa)
+ * @param[in]   partNameSize    size of partName buffer
+ *
+ * @return status
+ *   @retval 0 success
+ *   @retval -1 error, partId is out of range
+ *   @retval -2 error, partition name exceeds partNameSize
+ */
+static int
+GetPartitionName(afs_uint32 partId, char *partName, afs_size_t partNameSize)
+{
+    const int OLD_NUM_DEVICES = 26;    /* a..z */
+
+    if (partId < OLD_NUM_DEVICES) {
+       if (partNameSize < 8) {
+           return -2;
+       }
+       strlcpy(partName, "/vicep", partNameSize);
+       partName[6] = partId + 'a';
+       partName[7] = '\0';
+       return 0;
+    }
+    if (partId < VOLMAXPARTS) {
+       if (partNameSize < 9) {
+           return -2;
+       }
+       strlcpy(partName, "/vicep", partNameSize);
+       partId -= OLD_NUM_DEVICES;
+       partName[6] = 'a' + (partId / OLD_NUM_DEVICES);
+       partName[7] = 'a' + (partId % OLD_NUM_DEVICES);
+       partName[8] = '\0';
+       return 0;
+    }
+    return -1;
+}
 
+/**
+ * Process command line options and start scanning
+ *
+ * @param[in] as     command syntax object
+ * @param[in] arock  opaque object; not used
+ *
+ * @return error code
+ */
 static int
 handleit(struct cmd_syndesc *as, void *arock)
 {
     struct cmd_item *ti;
     int err = 0;
     afs_uint32 volumeId = 0;
-    char *partName = 0;
+    char *partNameOrId = 0;
+    char partName[64] = "";
     struct DiskPartition64 *partP = NULL;
 
 
@@ -318,7 +431,7 @@ handleit(struct cmd_syndesc *as, void *arock)
        InodeTimes = 1;
     }
     if ((ti = as->parms[5].items)) {   /* -part */
-       partName = ti->data;
+       partNameOrId = ti->data;
     }
     if ((ti = as->parms[6].items)) {   /* -volumeid */
        volumeId = strtoul(ti->data, NULL, 10);
@@ -357,6 +470,22 @@ handleit(struct cmd_syndesc *as, void *arock)
        DumpVnodes = 1;         /* implied */
     }
 
+    /* Allow user to specify partition by name or id. */
+    if (partNameOrId) {
+       afs_uint32 partId = volutil_GetPartitionID(partNameOrId);
+       if (partId == -1) {
+           fprintf(stderr, "%s: Could not parse '%s' as a partition name.\n",
+                   progname, partNameOrId);
+           return 1;
+       }
+       if (GetPartitionName(partId, partName, sizeof(partName))) {
+           fprintf(stderr,
+                   "%s: Could not format '%s' as a partition name.\n",
+                   progname, partNameOrId);
+           return 1;
+       }
+    }
+
     DInit(10);
 
     err = VAttachPartitions();
@@ -365,7 +494,7 @@ handleit(struct cmd_syndesc *as, void *arock)
                progname, err);
     }
 
-    if (partName) {
+    if (partName[0]) {
        partP = VGetPartition(partName, 0);
        if (!partP) {
            fprintf(stderr,
@@ -400,6 +529,11 @@ handleit(struct cmd_syndesc *as, void *arock)
     return 0;
 }
 
+/**
+ * Determine if the current directory is a vice partition
+ *
+ * @return disk partition object
+ */
 #ifdef AFS_NT40_ENV
 #include <direct.h>
 struct DiskPartition64 *
@@ -450,6 +584,11 @@ FindCurrentPartition(void)
 }
 #endif
 
+/**
+ * Scan and handle all the partitions detected on this server
+ *
+ * @return none
+ */
 void
 HandleAllPart(void)
 {
@@ -469,7 +608,13 @@ HandleAllPart(void)
     }
 }
 
-
+/**
+ * Scan the partition and handle volumes
+ *
+ * @param[in] partP  disk partition to scan
+ *
+ * @return none
+ */
 void
 HandlePart(struct DiskPartition64 *partP)
 {
@@ -607,6 +752,17 @@ HandleHeaderFiles(struct DiskPartition64 *dp, FD_t header_fd,
     }
 }
 
+/**
+ * Attach and scan the volume and handle the header and vnodes
+ *
+ * Print the volume header and vnode information, depending on the
+ * current modes.
+ *
+ * @param[in] dp    vice partition object for this volume
+ * @param[in] name  volume header file name
+ *
+ * @return none
+ */
 void
 HandleVolume(struct DiskPartition64 *dp, char *name)
 {
@@ -673,6 +829,9 @@ HandleVolume(struct DiskPartition64 *dp, char *name)
     free(vp);
 }
 
+/**
+ * volinfo program entry
+ */
 int
 main(int argc, char **argv)
 {
@@ -690,7 +849,7 @@ main(int argc, char **argv)
     cmd_AddParm(ts, "-itime", CMD_FLAG, CMD_OPTIONAL,
                "Dump special inode's mod times");
     cmd_AddParm(ts, "-part", CMD_LIST, CMD_OPTIONAL,
-               "AFS partition name (default current partition)");
+               "AFS partition name or id (default current partition)");
     cmd_AddParm(ts, "-volumeid", CMD_LIST, CMD_OPTIONAL, "Volume id");
     cmd_AddParm(ts, "-header", CMD_FLAG, CMD_OPTIONAL,
                "Dump volume's header info");
@@ -711,6 +870,13 @@ main(int argc, char **argv)
 
 #define typestring(type) (type == RWVOL? "read/write": type == ROVOL? "readonly": type == BACKVOL? "backup": "unknown")
 
+/**
+ * Print the volume header information
+ *
+ * @param[in]  volume object
+ *
+ * @return none
+ */
 void
 PrintHeader(Volume * vp)
 {
@@ -749,29 +915,19 @@ PrintHeader(Volume * vp)
     printf("volUpdateCounter = %u\n", V_volUpCounter(vp));
 }
 
-/* GetFileInfo
- * OS independent file info. Die on failure.
+/**
+ * Get the size and times of a file
+ *
+ * @param[in]  fd     file descriptor of file to stat
+ * @param[out] size   size of the file
+ * @param[out] ctime  ctime of file as a formatted string
+ * @param[out] mtime  mtime of file as a formatted string
+ * @param[out] atime  atime of file as a formatted string
+ *
+ * @return error code
+ *   @retval 0 success
+ *   @retval -1 failed to retrieve file information
  */
-#ifdef AFS_NT40_ENV
-char *
-NT_date(FILETIME * ft)
-{
-    static char result[8][64];
-    static int next = 0;
-    SYSTEMTIME st;
-    FILETIME lft;
-
-    if (!FileTimeToLocalFileTime(ft, &lft)
-       || !FileTimeToSystemTime(&lft, &st)) {
-       fprintf(stderr, "%s: Time conversion failed.\n", progname);
-       exit(1);
-    }
-    sprintf(result[next = ((next + 1) & 7)], "%4d/%02d/%02d.%2d:%2d:%2d",
-           st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
-    return result[next];
-}
-#endif
-
 static int
 GetFileInfo(FD_t fd, afs_sfsize_t * size, char **ctime, char **mtime,
            char **atime)
@@ -812,7 +968,7 @@ GetFileInfo(FD_t fd, afs_sfsize_t * size, char **ctime, char **mtime,
  * @param[in] vnode  vnode object
  * @param[in] inode  inode of the source file
  *
- * @returns none
+ * @return none
  */
 static void
 SaveInode(Volume * vp, struct VnodeDiskObject *vnode, Inode ino)
@@ -884,6 +1040,14 @@ SaveInode(Volume * vp, struct VnodeDiskObject *vnode, Inode ino)
           PrintInode(NULL, ino), nfile, (unsigned long)total);
 }
 
+/**
+ * Scan a volume index and handle each vnode
+ *
+ * @param[in] vp      volume object
+ * @param[in] class   which index to scan
+ *
+ * @return none
+ */
 void
 HandleVnodes(Volume * vp, VnodeClass class)
 {
@@ -977,6 +1141,17 @@ HandleVnodes(Volume * vp, VnodeClass class)
     }
 }
 
+/**
+ * Print vnode information
+ *
+ * @param[in] offset       index offset of this vnode
+ * @param[in] vnode        vnode object to be printed
+ * @param[in] vnodeNumber  vnode number
+ * @param[in] ino          fileserver inode number
+ * @param[in] vp           parent volume of the vnode
+ *
+ * @return none
+ */
 void
 PrintVnode(afs_foff_t offset, VnodeDiskObject * vnode, VnodeId vnodeNumber,
           Inode ino, Volume * vp)