vol: Use FDH_SIZE more consistently
[openafs.git] / src / vol / vol-salvage.c
index 4d3afb5..f10e7b1 100644 (file)
@@ -119,13 +119,9 @@ Vnodes with 0 inode pointers in RW volumes are now deleted.
 #endif
 #endif
 #else /* AFS_VFSINCL_ENV */
-#ifdef AFS_OSF_ENV
-#include <ufs/inode.h>
-#else /* AFS_OSF_ENV */
 #if !defined(AFS_LINUX20_ENV) && !defined(AFS_XBSD_ENV) && !defined(AFS_DARWIN_ENV)
 #include <sys/inode.h>
 #endif
-#endif
 #endif /* AFS_VFSINCL_ENV */
 #endif /* AFS_SGI_ENV */
 #ifdef AFS_AIX_ENV
@@ -190,10 +186,9 @@ Vnodes with 0 inode pointers in RW volumes are now deleted.
 #include <pthread.h>
 #endif
 
-#ifdef AFS_OSF_ENV
-extern void *calloc();
-#endif
-static char *TimeStamp(time_t clock, int precision);
+#define SALV_BUFFER_SIZE 1024
+
+static char *TimeStamp(char *buffer, size_t size, time_t clock, int precision);
 
 
 int debug;                     /* -d flag */
@@ -205,16 +200,12 @@ int Parallel = 4;         /* -para X flag */
 int PartsPerDisk = 8;          /* Salvage up to 8 partitions on same disk sequentially */
 int forceR = 0;                        /* -b flag */
 int ShowLog = 0;               /* -showlog flag */
+char *ShowLogFilename = NULL;    /* log file name for -showlog */
 int ShowSuid = 0;              /* -showsuid flag */
 int ShowMounts = 0;            /* -showmounts flag */
 int orphans = ORPH_IGNORE;     /* -orphans option */
 int Showmode = 0;
-
-
-#ifndef AFS_NT40_ENV
-int useSyslog = 0;             /* -syslog flag */
-int useSyslogFacility = LOG_DAEMON;    /* -syslogfacility option */
-#endif
+int ClientMode = 0;            /* running as salvager server client */
 
 #ifdef AFS_NT40_ENV
 int canfork = 0;
@@ -228,8 +219,6 @@ int OKToZap;                        /* -o flag */
 int ForceSalvage;              /* If salvage should occur despite the DONT_SALVAGE flag
                                 * in the volume header */
 
-FILE *logFile = 0;     /* one of {/usr/afs/logs,/vice/file}/SalvageLog */
-
 #define ROOTINODE      2       /* Root inode of a 4.2 Unix file system
                                 * partition */
 /**
@@ -281,6 +270,8 @@ char *tmpdir = NULL;
 
 
 /* Forward declarations */
+static void QuietExit(int) AFS_NORETURN;
+static void SalvageShowLog(void);
 static int IsVnodeOrphaned(struct SalvInfo *salvinfo, VnodeId vnode);
 static int AskVolumeSummary(struct SalvInfo *salvinfo,
                             VolumeId singleVolumeNumber);
@@ -481,12 +472,10 @@ SalvageFileSysParallel(struct DiskPartition64 *partP)
     struct job *thisjob = 0;
     static int numjobs = 0;
     static int jobcount = 0;
-    char buf[1024];
     int wstatus;
     struct job *oldjob;
     int startjob;
     FILE *passLog;
-    char logFileName[256];
     int i, j, pid;
 
     if (partP) {
@@ -607,26 +596,26 @@ SalvageFileSysParallel(struct DiskPartition64 *partP)
                numjobs++;
            } else {
                int fd;
+               char *filename;
+               struct logOptions logopts;
+
+               memset(&logopts, 0, sizeof(logopts));
+               logopts.lopt_dest = logDest_file;
 
-               ShowLog = 0;
                for (fd = 0; fd < 16; fd++)
                    close(fd);
                open(OS_DIRSEP, 0);
                dup2(0, 1);
                dup2(0, 2);
-#ifndef AFS_NT40_ENV
-               if (useSyslog) {
-                   openlog("salvager", LOG_PID, useSyslogFacility);
-               } else
-#endif
-               {
-                   snprintf(logFileName, sizeof logFileName, "%s.%d",
+
+               ShowLog = 0; /* Child processes do not display. */
+               if (asprintf(&filename, "%s.%d",
                             AFSDIR_SERVER_SLVGLOG_FILEPATH,
-                            jobs[startjob]->jobnumb);
-                   logFile = afs_fopen(logFileName, "w");
+                            jobs[startjob]->jobnumb) >= 0) {
+                   logopts.lopt_filename = filename;
+                   OpenLog(&logopts);
+                   free(filename);
                }
-               if (!logFile)
-                   logFile = stdout;
 
                SalvageFileSys1(jobs[startjob]->partP, 0);
                Exit(0);
@@ -635,24 +624,37 @@ SalvageFileSysParallel(struct DiskPartition64 *partP)
        }
     }                          /* while ( thisjob || (!partP && numjobs > 0) ) */
 
-    /* If waited for all jobs to complete, now collect log files and return */
-#ifndef AFS_NT40_ENV
-    if (!useSyslog)            /* if syslogging - no need to collect */
-#endif
+    /*
+     * If waited for all jobs to complete, now collect log files and return.
+     * No files can be collected when logging to the system log (syslog).
+     */
+    if (GetLogDest() == logDest_file) {
        if (!partP) {
-           for (i = 0; i < jobcount; i++) {
-               snprintf(logFileName, sizeof logFileName, "%s.%d",
-                        AFSDIR_SERVER_SLVGLOG_FILEPATH, i);
-               if ((passLog = afs_fopen(logFileName, "r"))) {
-                   while (fgets(buf, sizeof(buf), passLog)) {
-                       fputs(buf, logFile);
+           char *buf = calloc(1, SALV_BUFFER_SIZE);
+           char *logFileName;
+
+           if (buf == NULL) {
+               Log("out of memory");
+           } else {
+               for (i = 0; i < jobcount; i++) {
+                   if (asprintf(&logFileName, "%s.%d",
+                                AFSDIR_SERVER_SLVGLOG_FILEPATH, i) < 0) {
+                       Log("out of memory");
+                       break;
+                   }
+                   if ((passLog = afs_fopen(logFileName, "r"))) {
+                       while (fgets(buf, SALV_BUFFER_SIZE, passLog)) {
+                           WriteLogBuffer(buf, strlen(buf));
+                       }
+                       fclose(passLog);
                    }
-                   fclose(passLog);
+                   (void)unlink(logFileName);
+                   free(logFileName);
                }
-               (void)unlink(logFileName);
+               free(buf);
            }
-           fflush(logFile);
        }
+    }
     return;
 }
 
@@ -663,8 +665,7 @@ SalvageFileSys(struct DiskPartition64 *partP, VolumeId singleVolumeNumber)
     if (!canfork || debug || Fork() == 0) {
        SalvageFileSys1(partP, singleVolumeNumber);
        if (canfork && !debug) {
-           ShowLog = 0;
-           Exit(0);
+           QuietExit(0);
        }
     } else
        Wait("SalvageFileSys");
@@ -693,7 +694,7 @@ void
 SalvageFileSys1(struct DiskPartition64 *partP, VolumeId singleVolumeNumber)
 {
     char *name, *tdir;
-    char inodeListPath[256];
+    char *inodeListPath = NULL;
     FD_t inodeFile = INVALID_FD;
     static char tmpDevName[100];
     static char wpath[100];
@@ -803,10 +804,16 @@ SalvageFileSys1(struct DiskPartition64 *partP, VolumeId singleVolumeNumber)
     tdir = (tmpdir ? tmpdir : salvinfo->fileSysPath);
 #ifdef AFS_NT40_ENV
     (void)_putenv("TMP=");     /* If "TMP" is set, then that overrides tdir. */
-    (void)strncpy(inodeListPath, _tempnam(tdir, "salvage.inodes."), 255);
+    inodeListPath = strdup(_tempnam(tdir, "salvage.inodes."));
+    if (inodeListPath == NULL) {
+       Abort("Error allocating memory for inodeListPath\n");
+    }
 #else
-    snprintf(inodeListPath, 255, "%s" OS_DIRSEP "salvage.inodes.%s.%d", tdir, name,
+    code = asprintf(&inodeListPath, "%s" OS_DIRSEP "salvage.inodes.%s.%d", tdir, name,
             getpid());
+    if (code == -1) {
+       Abort("Error allocating memory for inodeListPath\n");
+    }
 #endif
 
     inodeFile = OS_OPEN(inodeListPath, O_RDWR|O_TRUNC|O_CREAT, 0666);
@@ -835,11 +842,16 @@ SalvageFileSys1(struct DiskPartition64 *partP, VolumeId singleVolumeNumber)
 
     if (GetInodeSummary(salvinfo, inodeFile, singleVolumeNumber) < 0) {
        OS_CLOSE(inodeFile);
+       free(inodeListPath);
        return;
     }
     salvinfo->inodeFd = inodeFile;
     if (salvinfo->inodeFd == INVALID_FD)
        Abort("Temporary file %s is missing...\n", inodeListPath);
+
+    free(inodeListPath);
+    inodeListPath = NULL;
+
     OS_SEEK(salvinfo->inodeFd, 0L, SEEK_SET);
     if (ListInodeOption) {
        PrintInodeList(salvinfo);
@@ -971,7 +983,7 @@ SalvageFileSys1(struct DiskPartition64 *partP, VolumeId singleVolumeNumber)
 void
 DeleteExtraVolumeHeaderFile(struct SalvInfo *salvinfo, struct VolumeSummary *vsp)
 {
-    char path[64];
+    char path[VMAXPATHLEN + 10];
     char filename[VMAXPATHLEN];
 
     if (vsp->deleted) {
@@ -1304,8 +1316,7 @@ GetInodeSummary(struct SalvInfo *salvinfo, FD_t inodeFile, VolumeId singleVolume
            goto error;
        }
        if (canfork && !debug) {
-           ShowLog = 0;
-           Exit(0);
+           QuietExit(0);
        }
     } else {
        if (Wait("Inode summary") == -1) {
@@ -1801,10 +1812,11 @@ GetVolumeSummary(struct SalvInfo *salvinfo, VolumeId singleVolumeNumber)
     return 0;
 }
 
-/* Find the link table. This should be associated with the RW volume or, if
- * a RO only site, then the RO volume. For now, be cautious and hunt carefully.
+#ifdef AFS_NAMEI_ENV
+/* Find the link table. This should be associated with the RW volume, even
+ * if there is only an RO volume at this site.
  */
-Inode
+static Inode
 FindLinkHandle(struct InodeSummary *isp, int nVols,
               struct ViceInodeInfo *allInodes)
 {
@@ -1814,13 +1826,65 @@ FindLinkHandle(struct InodeSummary *isp, int nVols,
     for (i = 0; i < nVols; i++) {
        ip = allInodes + isp[i].index;
        for (j = 0; j < isp[i].nSpecialInodes; j++) {
-           if (ip[j].u.special.type == VI_LINKTABLE)
+           if (ip[j].u.special.volumeId == isp->RWvolumeId &&
+               ip[j].u.special.parentId == isp->RWvolumeId &&
+               ip[j].u.special.type == VI_LINKTABLE) {
                return ip[j].inodeNumber;
+           }
        }
     }
     return (Inode) - 1;
 }
 
+static int
+CheckDupLinktable(struct SalvInfo *salvinfo, struct InodeSummary *isp, struct ViceInodeInfo *ip)
+{
+    afs_ino_str_t stmp;
+    if (ip->u.vnode.vnodeNumber != INODESPECIAL) {
+       /* not a linktable; process as a normal file */
+       return 0;
+    }
+    if (ip->u.special.type != VI_LINKTABLE) {
+       /* not a linktable; process as a normal file */
+       return 0;
+    }
+
+    /* make sure nothing inc/decs it */
+    ip->linkCount = 0;
+
+    if (ip->u.special.volumeId == ip->u.special.parentId) {
+       /* This is a little weird, but shouldn't break anything, and there is
+        * no known way that this can happen; just do nothing, in case deleting
+        * it would screw something up. */
+       Log("Inode %s appears to be a valid linktable for id (%u), but it's not\n",
+           PrintInode(stmp, ip->inodeNumber), ip->u.special.parentId);
+       Log("the linktable for our volume group (%u). This is unusual, since\n",
+           isp->RWvolumeId);
+       Log("there should only be one linktable per volume group. I'm leaving\n");
+       Log("it alone, just to be safe.\n");
+       return -1;
+    }
+
+    Log("Linktable %s appears to be invalid (parentid/volumeid mismatch: %u != %u)\n",
+        PrintInode(stmp, ip->inodeNumber), ip->u.special.parentId, ip->u.special.volumeId);
+    if (Testing) {
+       Log("Would have deleted linktable inode %s\n", PrintInode(stmp, ip->inodeNumber));
+    } else {
+       IHandle_t *tmpH;
+       namei_t ufs_name;
+
+       Log("Deleting linktable inode %s\n", PrintInode(stmp, ip->inodeNumber));
+       IH_INIT(tmpH, salvinfo->fileSysDevice, isp->RWvolumeId, ip->inodeNumber);
+       namei_HandleToName(&ufs_name, tmpH);
+       if (unlink(ufs_name.n_path) < 0) {
+           Log("Error %d unlinking path %s\n", errno, ufs_name.n_path);
+       }
+    }
+
+    return -1;
+}
+#endif
+
 int
 CreateLinkTable(struct SalvInfo *salvinfo, struct InodeSummary *isp, Inode ino)
 {
@@ -1985,7 +2049,7 @@ DoSalvageVolumeGroup(struct SalvInfo *salvinfo, struct InodeSummary *isp, int nV
                for (i = 0; i < nVols; i++) {
                    ip = allInodes + isp[i].index;
                    for (j = isp[i].nSpecialInodes; j < isp[i].nInodes; j++) {
-                       namei_SetLinkCount(fdP, ip[j].inodeNumber, 1, 1);
+                       namei_SetLinkCount(fdP, ip[j].inodeNumber, 1, 0);
                        ip[j].linkCount = 1;
                    }
                }
@@ -2006,15 +2070,33 @@ DoSalvageVolumeGroup(struct SalvInfo *salvinfo, struct InodeSummary *isp, int nV
        int rw = (i == 0);
        struct InodeSummary *lisp = &isp[i];
 #ifdef AFS_NAMEI_ENV
-       /* If only the RO is present on this partition, the link table
-        * shows up as a RW volume special file. Need to make sure the
-        * salvager doesn't try to salvage the non-existent RW.
-        */
-       if (rw && nVols > 1 && isp[i].nSpecialInodes == 1) {
-           /* If this only special inode is the link table, continue */
-           if (inodes->u.special.type == VI_LINKTABLE) {
-               haveRWvolume = 0;
-               continue;
+       if (rw && (nVols > 1 || isp[i].nSpecialInodes == isp[i].nInodes)) {
+           /* If nVols > 1, we have more than one vol in this volgroup, so
+            * the RW inodes we detected may just be for the linktable, and
+            * there is no actual RW volume.
+            *
+            * Additionally, if we only have linktable inodes (no other
+            * special inodes, no data inodes), there is also no actual RW
+            * volume to salvage; this is just cruft left behind by something
+            * else. In that case nVols will only be 1, though, so also
+            * perform this linktables-only check if we don't have any
+            * non-special inodes. */
+           int inode_i;
+           int all_linktables = 1;
+           for (inode_i = 0; inode_i < isp[i].nSpecialInodes; inode_i++) {
+               if (inodes[inode_i].u.special.type != VI_LINKTABLE) {
+                   all_linktables = 0;
+                   break;
+               }
+           }
+           if (all_linktables) {
+               /* All we have are linktable special inodes, so skip salvaging
+                * the RW; there was never an RW volume here. If we don't do
+                * this, we risk creating a new "phantom" RW that the VLDB
+                * doesn't know about, which is confusing and can cause
+                * problems. */
+                haveRWvolume = 0;
+                continue;
            }
        }
 #endif
@@ -2056,6 +2138,9 @@ DoSalvageVolumeGroup(struct SalvInfo *salvinfo, struct InodeSummary *isp, int nV
                dec_VGLinkH = ip->linkCount - salvinfo->VGLinkH_cnt;
                VGLinkH_p1 = ip->u.param[0];
                continue;       /* Deal with this last. */
+           } else if (CheckDupLinktable(salvinfo, isp, ip)) {
+               /* Don't touch this inode; CheckDupLinktable has handled it */
+               continue;
            }
 #endif
            if (ip->linkCount != 0 && TraceBadLinkCounts) {
@@ -2118,8 +2203,7 @@ DoSalvageVolumeGroup(struct SalvInfo *salvinfo, struct InodeSummary *isp, int nV
     IH_RELEASE(salvinfo->VGLinkH);
 
     if (canfork && !debug) {
-       ShowLog = 0;
-       Exit(0);
+       QuietExit(0);
     }
 }
 
@@ -2356,7 +2440,7 @@ SalvageVolumeHeaderFile(struct SalvInfo *salvinfo, struct InodeSummary *isp,
     }
 
     if (isp->volSummary == NULL) {
-       char path[64];
+       char path[VMAXPATHLEN];
        char headerName[64];
        snprintf(headerName, sizeof headerName, VFORMAT,
                 afs_printable_VolumeId_lu(isp->volumeId));
@@ -2374,7 +2458,7 @@ SalvageVolumeHeaderFile(struct SalvInfo *salvinfo, struct InodeSummary *isp,
 
        writefunc = VCreateVolumeDiskHeader;
     } else {
-       char path[64];
+       char path[VMAXPATHLEN];
        char headerName[64];
        /* hack: these two fields are obsolete... */
        isp->volSummary->header.volumeAcl = 0;
@@ -2562,16 +2646,17 @@ SalvageHeader(struct SalvInfo *salvinfo, struct afs_inode_info *sp,
     if (sp->inodeType == VI_VOLINFO) {
        salvinfo->VolInfo = header.volumeInfo;
        if (check) {
-           char update[25];
+           char update[64];
+           char buffer[64];
 
            if (salvinfo->VolInfo.updateDate) {
-               strcpy(update, TimeStamp(salvinfo->VolInfo.updateDate, 0));
+               strcpy(update, TimeStamp(buffer, sizeof(buffer), salvinfo->VolInfo.updateDate, 0));
                if (!Showmode)
                    Log("%s (%" AFS_VOLID_FMT ") %supdated %s\n", salvinfo->VolInfo.name,
                        afs_printable_VolumeId_lu(salvinfo->VolInfo.id),
                        (Testing ? "it would have been " : ""), update);
            } else {
-               strcpy(update, TimeStamp(salvinfo->VolInfo.creationDate, 0));
+               strcpy(update, TimeStamp(buffer, sizeof(buffer), salvinfo->VolInfo.creationDate, 0));
                if (!Showmode)
                    Log("%s (%" AFS_VOLID_FMT ") not updated (created %s)\n",
                        salvinfo->VolInfo.name, afs_printable_VolumeId_lu(salvinfo->VolInfo.id), update);
@@ -2630,7 +2715,7 @@ SalvageIndex(struct SalvInfo *salvinfo, Inode ino, VnodeClass class, int RW,
     file = FDH_FDOPEN(fdP, "r+");
     opr_Assert(file != NULL);
     vcp = &VnodeClassInfo[class];
-    size = OS_SIZE(fdP->fd_fd);
+    size = FDH_SIZE(fdP);
     opr_Assert(size != -1);
     nVnodes = (size / vcp->diskSize) - 1;
     if (nVnodes > 0) {
@@ -3302,7 +3387,7 @@ DistilVnodeEssence(struct SalvInfo *salvinfo, VolumeId rwVId,
     opr_Assert(fdP != NULL);
     file = FDH_FDOPEN(fdP, "r+");
     opr_Assert(file != NULL);
-    size = OS_SIZE(fdP->fd_fd);
+    size = FDH_SIZE(fdP);
     opr_Assert(size != -1);
     vip->nVnodes = (size / vcp->diskSize) - 1;
     if (vip->nVnodes > 0) {
@@ -3967,8 +4052,15 @@ SalvageVolume(struct SalvInfo *salvinfo, struct InodeSummary *rwIsp, IHandle_t *
             * link count was not incremented in JudgeEntry().
             */
            if (class == vLarge) {      /* directory vnode */
-               pv = vnodeIdToBitNumber(vep->parent);
-               if (salvinfo->vnodeInfo[vLarge].vnodes[pv].unique != 0) {
+               struct VnodeEssence *parent_vep;
+
+               parent_vep = CheckVnodeNumber(salvinfo, vep->parent);
+
+               if (!parent_vep)
+                   Log("Vnode %d has invalid or out-of-range parent vnode %d;" \
+                       " ignore parent count adjustment\n",
+                       ThisVnode, vep->parent);
+               else if (parent_vep->unique != 0) {
                    if (vep->parent == 1 && newrootdir) {
                        /* this vnode's parent was the volume root, and
                         * we just created the volume root. So, the parent
@@ -3979,7 +4071,7 @@ SalvageVolume(struct SalvInfo *salvinfo, struct InodeSummary *rwIsp, IHandle_t *
                         /* noop */
 
                    } else {
-                       salvinfo->vnodeInfo[vLarge].vnodes[pv].count++;
+                       parent_vep->count++;
                    }
                }
            }
@@ -4224,7 +4316,12 @@ SalvageVolume(struct SalvInfo *salvinfo, struct InodeSummary *rwIsp, IHandle_t *
     volHeader.inUse = 0;       /* clear flag indicating inUse@last crash */
     volHeader.needsSalvaged = 0;       /* clear 'damaged' flag */
     volHeader.inService = 1;   /* allow service again */
-    volHeader.needsCallback = (salvinfo->VolumeChanged != 0);
+    if (salvinfo->VolumeChanged) {
+       volHeader.needsCallback = 1;
+       volHeader.updateDate = time(NULL);
+    } else {
+       volHeader.needsCallback = 0;
+    }
     volHeader.dontSalvage = DONT_SALVAGE;
     salvinfo->VolumeChanged = 0;
     if (!Testing) {
@@ -4288,7 +4385,7 @@ MaybeZapVolume(struct SalvInfo *salvinfo, struct InodeSummary *isp,
            }
            if (!Testing) {
                afs_int32 code;
-               char path[64];
+               char path[VMAXPATHLEN + 10];
                char filename[VMAXPATHLEN];
                VolumeExternalName_r(isp->volumeId, filename, sizeof(filename));
                sprintf(path, "%s" OS_DIRSEP "%s", salvinfo->fileSysPath, filename);
@@ -4689,12 +4786,9 @@ Fork(void)
     return f;
 }
 
-void
-Exit(int code)
+static void
+QuietExit(int code)
 {
-    if (ShowLog)
-       showlog();
-
 #ifdef AFS_DEMAND_ATTACH_FS
     if (programType == salvageServer) {
        /* release all volume locks before closing down our SYNC channels.
@@ -4728,6 +4822,14 @@ Exit(int code)
 #endif
 }
 
+void
+Exit(int code)
+{
+    SalvageShowLog();
+    QuietExit(code);
+}
+
+
 int
 Wait(char *prog)
 {
@@ -4743,143 +4845,84 @@ Wait(char *prog)
 }
 
 static char *
-TimeStamp(time_t clock, int precision)
+TimeStamp(char *buffer, size_t size, time_t clock, int precision)
 {
     struct tm *lt;
-    static char timestamp[20];
+    size_t nbytes;
+
     lt = localtime(&clock);
     if (precision)
-       (void)strftime(timestamp, 20, "%m/%d/%Y %H:%M:%S", lt);
+       nbytes = strftime(buffer, size, "%m/%d/%Y %H:%M:%S", lt);
     else
-       (void)strftime(timestamp, 20, "%m/%d/%Y %H:%M", lt);
-    return timestamp;
+       nbytes = strftime(buffer, size, "%m/%d/%Y %H:%M", lt);
+    if (nbytes == 0)
+       memset(buffer, 0, size);
+    return buffer;
 }
 
-void
-CheckLogFile(char * log_path)
-{
-    char oldSlvgLog[AFSDIR_PATH_MAX];
-
-#ifndef AFS_NT40_ENV
-    if (useSyslog) {
-       ShowLog = 0;
-       return;
-    }
-#endif
-
-    strcpy(oldSlvgLog, log_path);
-    strcat(oldSlvgLog, ".old");
-    if (!logFile) {
-       rk_rename(log_path, oldSlvgLog);
-       logFile = afs_fopen(log_path, "a");
-
-       if (!logFile) {         /* still nothing, use stdout */
-           logFile = stdout;
-           ShowLog = 0;
-       }
-#ifndef AFS_NAMEI_ENV
-       AFS_DEBUG_IOPS_LOG(logFile);
-#endif
-    }
-}
-
-#ifndef AFS_NT40_ENV
-void
-TimeStampLogFile(char * log_path)
-{
-    char stampSlvgLog[AFSDIR_PATH_MAX];
-    struct tm *lt;
-    time_t now;
-
-    now = time(0);
-    lt = localtime(&now);
-    snprintf(stampSlvgLog, sizeof stampSlvgLog,
-            "%s.%04d-%02d-%02d.%02d:%02d:%02d", log_path,
-            lt->tm_year + 1900, lt->tm_mon + 1, lt->tm_mday, lt->tm_hour,
-            lt->tm_min, lt->tm_sec);
-
-    /* try to link the logfile to a timestamped filename */
-    /* if it fails, oh well, nothing we can do */
-    link(log_path, stampSlvgLog);
-}
-#endif
-
-void
-showlog(void)
+static void
+SalvageShowLog(void)
 {
     char line[256];
+    char *filename;
+    FILE *logFile;
 
-#ifndef AFS_NT40_ENV
-    if (useSyslog) {
-       printf("Can't show log since using syslog.\n");
-       fflush(stdout);
-       return;
+    if (ShowLog == 0 || ClientMode) {
+       return; /* nothing to do */
     }
-#endif
-
-    if (logFile) {
-       rewind(logFile);
-       fclose(logFile);
-    }
-
-    logFile = afs_fopen(AFSDIR_SERVER_SLVGLOG_FILEPATH, "r");
+    filename = strdup(GetLogFilename());
+    opr_Assert(filename != NULL);
+    CloseLog();
 
+    logFile = afs_fopen(filename, "r");
     if (!logFile)
-       printf("Can't read %s, exiting\n", AFSDIR_SERVER_SLVGLOG_FILEPATH);
+       printf("Can't read %s, exiting\n", ShowLogFilename);
     else {
-       rewind(logFile);
        while (fgets(line, sizeof(line), logFile))
            printf("%s", line);
        fflush(stdout);
     }
+    free(filename);
+}
+
+static void
+vLog(const char *format, va_list args)
+{
+    if (!ClientMode) {
+       vFSLog(format, args);
+    } else {
+       struct timeval now;
+       char buffer[64];
+
+       gettimeofday(&now, NULL);
+       fprintf(stderr, "%s ", TimeStamp(buffer, sizeof(buffer), now.tv_sec, 1));
+       vfprintf(stderr, format, args);
+       fflush(stderr);
+    }
 }
 
 void
 Log(const char *format, ...)
 {
-    struct timeval now;
-    char tmp[1024];
     va_list args;
 
     va_start(args, format);
-    vsnprintf(tmp, sizeof tmp, format, args);
+    vLog(format, args);
     va_end(args);
-#ifndef AFS_NT40_ENV
-    if (useSyslog) {
-       syslog(LOG_INFO, "%s", tmp);
-    } else
-#endif
-       if (logFile) {
-           gettimeofday(&now, NULL);
-           fprintf(logFile, "%s %s", TimeStamp(now.tv_sec, 1), tmp);
-           fflush(logFile);
-       }
 }
 
 void
 Abort(const char *format, ...)
 {
     va_list args;
-    char tmp[1024];
 
     va_start(args, format);
-    vsnprintf(tmp, sizeof tmp, format, args);
+    vLog(format, args);
     va_end(args);
-#ifndef AFS_NT40_ENV
-    if (useSyslog) {
-       syslog(LOG_INFO, "%s", tmp);
-    } else
-#endif
-       if (logFile) {
-           fprintf(logFile, "%s", tmp);
-           fflush(logFile);
-           if (ShowLog)
-               showlog();
-       }
-
+    SalvageShowLog();
     if (debug)
        abort();
-    Exit(1);
+    QuietExit(1);
 }
 
 char *
@@ -4964,7 +5007,7 @@ int
 nt_SetupPartitionSalvage(void *datap, int len)
 {
     childJob_t *jobp = (childJob_t *) datap;
-    char logname[AFSDIR_PATH_MAX];
+    char *logname;
 
     if (len != sizeof(childJob_t))
        return -1;
@@ -4973,11 +5016,11 @@ nt_SetupPartitionSalvage(void *datap, int len)
     myjob = *jobp;
 
     /* Open logFile */
-    (void)sprintf(logname, "%s.%d", AFSDIR_SERVER_SLVGLOG_FILEPATH,
-                 myjob.cj_number);
-    logFile = afs_fopen(logname, "w");
-    if (!logFile)
-       logFile = stdout;
+    if (asprintf(&logname, "%s.%d", AFSDIR_SERVER_SLVGLOG_FILEPATH,
+                myjob.cj_number) < 0)
+       return -1;
+    OpenLog(logname);
+    free(logname);
 
     return 0;
 }