vol-lock-fd-type-20090323
[openafs.git] / src / vol / vol-salvage.c
index 76a5838..91b3d33 100644 (file)
@@ -235,11 +235,18 @@ 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
 
+#ifdef AFS_NT40_ENV
+int canfork = 0;
+#else
+int canfork = 1;
+#endif
+
 #define        MAXPARALLEL     32
 
 int OKToZap;                   /* -o flag */
@@ -262,7 +269,7 @@ char *fileSysPath;          /* The path of the mounted partition currently
 char *fileSysPathName;         /* NT needs this to make name pretty in log. */
 IHandle_t *VGLinkH;            /* Link handle for current volume group. */
 int VGLinkH_cnt;               /* # of references to lnk handle. */
-struct DiskPartition *fileSysPartition;        /* Partition  being salvaged */
+struct DiskPartition64 *fileSysPartition;      /* Partition  being salvaged */
 #ifndef AFS_NT40_ENV
 char *fileSysDeviceName;       /* The block device where the file system
                                 * being salvaged was mounted */
@@ -329,13 +336,13 @@ childJob_t myjob = { SALVAGER_MAGIC, NOT_CHILD, "" };
 void
 ObtainSalvageLock(void)
 {
-    int salvageLock;
+    FD_t salvageLock;
 
 #ifdef AFS_NT40_ENV
     salvageLock =
-       (int)CreateFile(AFSDIR_SERVER_SLVGLOCK_FILEPATH, 0, 0, NULL,
+       (FD_t)CreateFile(AFSDIR_SERVER_SLVGLOCK_FILEPATH, 0, 0, NULL,
                        OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
-    if (salvageLock == (int)INVALID_HANDLE_VALUE) {
+    if (salvageLock == INVALID_FD) {
        fprintf(stderr,
                "salvager:  There appears to be another salvager running!  Aborted.\n");
        Exit(1);
@@ -432,7 +439,7 @@ CheckIfBigFilesFS(char *mountPoint, char *devName)
 #define HDSTR "\\Device\\Harddisk"
 #define HDLEN  (sizeof(HDSTR)-1)       /* Length of "\Device\Harddisk" */
 int
-SameDisk(struct DiskPartition *p1, struct DiskPartition *p2)
+SameDisk(struct DiskPartition64 *p1, struct DiskPartition64 *p2)
 {
 #define RES_LEN 256
     char res[RES_LEN];
@@ -473,10 +480,10 @@ SameDisk(struct DiskPartition *p1, struct DiskPartition *p2)
  * PartsPerDisk are on the same disk.
  */
 void
-SalvageFileSysParallel(struct DiskPartition *partP)
+SalvageFileSysParallel(struct DiskPartition64 *partP)
 {
     struct job {
-       struct DiskPartition *partP;
+       struct DiskPartition64 *partP;
        int pid;                /* Pid for this job */
        int jobnumb;            /* Log file job number */
        struct job *nextjob;    /* Next partition on disk to salvage */
@@ -664,7 +671,7 @@ SalvageFileSysParallel(struct DiskPartition *partP)
 
 
 void
-SalvageFileSys(struct DiskPartition *partP, VolumeId singleVolumeNumber)
+SalvageFileSys(struct DiskPartition64 *partP, VolumeId singleVolumeNumber)
 {
     if (!canfork || debug || Fork() == 0) {
        SalvageFileSys1(partP, singleVolumeNumber);
@@ -696,7 +703,7 @@ get_DevName(char *pbuffer, char *wpath)
 }
 
 void
-SalvageFileSys1(struct DiskPartition *partP, VolumeId singleVolumeNumber)
+SalvageFileSys1(struct DiskPartition64 *partP, VolumeId singleVolumeNumber)
 {
     char *name, *tdir;
     char inodeListPath[256];
@@ -732,7 +739,7 @@ SalvageFileSys1(struct DiskPartition *partP, VolumeId singleVolumeNumber)
        if ((programType != salvageServer) && !VConnectFS()) {
            Abort("Couldn't connect to file server\n");
        }
-       AskOffline(singleVolumeNumber);
+       AskOffline(singleVolumeNumber, partP->name);
     } else {
        if (!Showmode)
            Log("SALVAGING FILE SYSTEM PARTITION %s (device=%s%s)\n",
@@ -783,7 +790,7 @@ SalvageFileSys1(struct DiskPartition *partP, VolumeId singleVolumeNumber)
      * modified to actually do that so that the NT crt can be used there.
      */
     inodeFd =
-       _open_osfhandle((long)nt_open(inodeListPath, O_RDWR, 0), O_RDWR);
+       _open_osfhandle((intptr_t)nt_open(inodeListPath, O_RDWR, 0), O_RDWR);
     nt_unlink(inodeListPath);  /* NT's crt unlink won't if file is open. */
 #else
     inodeFd = afs_open(inodeListPath, O_RDONLY);
@@ -873,6 +880,7 @@ DeleteExtraVolumeHeaderFile(register struct VolumeSummary *vsp)
     vsp->fileName = 0;
 }
 
+int
 CompareInodes(const void *_p1, const void *_p2)
 {
     register const struct ViceInodeInfo *p1 = _p1;
@@ -973,9 +981,9 @@ void
 CountVolumeInodes(register struct ViceInodeInfo *ip, int maxInodes,
                  register struct InodeSummary *summary)
 {
-    int volume = ip->u.vnode.volumeId;
-    int rwvolume = volume;
-    register n, nSpecial;
+    VolumeId volume = ip->u.vnode.volumeId;
+    VolumeId rwvolume = volume;
+    register int n, nSpecial;
     register Unique maxunique;
     n = nSpecial = 0;
     maxunique = 0;
@@ -1000,7 +1008,7 @@ CountVolumeInodes(register struct ViceInodeInfo *ip, int maxInodes,
 }
 
 int
-OnlyOneVolume(struct ViceInodeInfo *inodeinfo, int singleVolumeNumber, void *rock)
+OnlyOneVolume(struct ViceInodeInfo *inodeinfo, afs_uint32 singleVolumeNumber, void *rock)
 {
     if (inodeinfo->u.vnode.vnodeNumber == INODESPECIAL)
        return (inodeinfo->u.special.parentId == singleVolumeNumber);
@@ -1190,14 +1198,15 @@ CompareVolumes(const void *_p1, const void *_p2)
 void
 GetVolumeSummary(VolumeId singleVolumeNumber)
 {
-    DIR *dirp;
+    DIR *dirp = NULL;
     afs_int32 nvols = 0;
     struct VolumeSummary *vsp, vs;
     struct VolumeDiskHeader diskHeader;
     struct dirent *dp;
 
     /* Get headers from volume directory */
-    if (chdir(fileSysPath) == -1 || (dirp = opendir(".")) == NULL)
+    dirp = opendir(fileSysPath);
+    if (dirp  == NULL)
        Abort("Can't read directory %s; not salvaged\n", fileSysPath);
     if (!singleVolumeNumber) {
        while ((dp = readdir(dirp))) {
@@ -1205,7 +1214,9 @@ GetVolumeSummary(VolumeId singleVolumeNumber)
            p = strrchr(dp->d_name, '.');
            if (p != NULL && strcmp(p, VHDREXT) == 0) {
                int fd;
-               if ((fd = afs_open(dp->d_name, O_RDONLY)) != -1
+               char name[64];
+               sprintf(name, "%s/%s", fileSysPath, dp->d_name);
+               if ((fd = afs_open(name, O_RDONLY)) != -1
                    && read(fd, (char *)&diskHeader, sizeof(diskHeader))
                    == sizeof(diskHeader)
                    && diskHeader.stamp.magic == VOLUMEHEADERMAGIC) {
@@ -1239,7 +1250,9 @@ GetVolumeSummary(VolumeId singleVolumeNumber)
        if (p != NULL && strcmp(p, VHDREXT) == 0) {
            int error = 0;
            int fd;
-           if ((fd = afs_open(dp->d_name, O_RDONLY)) == -1
+           char name[64];
+           sprintf(name, "%s/%s", fileSysPath, dp->d_name);
+           if ((fd = afs_open(name, O_RDONLY)) == -1
                || read(fd, &diskHeader, sizeof(diskHeader))
                != sizeof(diskHeader)
                || diskHeader.stamp.magic != VOLUMEHEADERMAGIC) {
@@ -1258,17 +1271,32 @@ GetVolumeSummary(VolumeId singleVolumeNumber)
                DiskToVolumeHeader(&vsp->header, &diskHeader);
                if (singleVolumeNumber && vsp->header.id == singleVolumeNumber
                    && vsp->header.parent != singleVolumeNumber) {
-                   Log("%u is a read-only volume; not salvaged\n",
-                       singleVolumeNumber);
-                   Exit(1);
+                   if (programType == salvageServer) {
+#ifdef SALVSYNC_BUILD_CLIENT
+                       Log("fileserver requested salvage of clone %u; scheduling salvage of volume group %u...\n",
+                           vsp->header.id, vsp->header.parent);
+                       if (SALVSYNC_LinkVolume(vsp->header.parent,
+                                               vsp->header.id,
+                                               fileSysPartition->name,
+                                               NULL) != SYNC_OK) {
+                           Log("schedule request failed\n");
+                       }
+#endif
+                       Exit(SALSRV_EXIT_VOLGROUP_LINK);
+                   } else {
+                       Log("%u is a read-only volume; not salvaged\n",
+                           singleVolumeNumber);
+                       Exit(1);
+                   }
                }
                if (!singleVolumeNumber
                    || (vsp->header.id == singleVolumeNumber
                        || vsp->header.parent == singleVolumeNumber)) {
                    (void)afs_snprintf(nameShouldBe, sizeof nameShouldBe,
-                                      VFORMAT, vsp->header.id);
-                   if (singleVolumeNumber)
-                       AskOffline(vsp->header.id);
+                                      VFORMAT, afs_cast_uint32(vsp->header.id));
+                   if (singleVolumeNumber 
+                       && vsp->header.id != singleVolumeNumber)
+                       AskOffline(vsp->header.id, fileSysPartition->name);
                    if (strcmp(nameShouldBe, dp->d_name)) {
                        if (!Showmode)
                            Log("Volume header file %s is incorrectly named; %sdeleted (it will be recreated later, if necessary)\n", dp->d_name, (Testing ? "it would have been " : ""));
@@ -1407,7 +1435,7 @@ DoSalvageVolumeGroup(register struct InodeSummary *isp, int nVols)
     int check;
     Inode ino;
     int dec_VGLinkH = 0;
-    int VGLinkH_p1;
+    int VGLinkH_p1 =0;
     FdHandle_t *fdP = NULL;
 
     VGLinkH_cnt = 0;
@@ -1612,7 +1640,7 @@ QuickCheck(register struct InodeSummary *isp, int nVols)
            && volHeader.stamp.magic == VOLUMEINFOMAGIC
            && volHeader.dontSalvage == DONT_SALVAGE
            && volHeader.needsSalvaged == 0 && volHeader.destroyMe == 0) {
-           if (volHeader.inUse == 1) {
+           if (volHeader.inUse != 0) {
                volHeader.inUse = 0;
                volHeader.inService = 1;
                if (!Testing) {
@@ -1714,23 +1742,26 @@ SalvageVolumeHeaderFile(register struct InodeSummary *isp,
     }
 
     if (isp->volSummary == NULL) {
-       char name[64];
-       (void)afs_snprintf(name, sizeof name, VFORMAT, isp->volumeId);
+       char path[64];
+       char headerName[64];
+       (void)afs_snprintf(headerName, sizeof headerName, VFORMAT, afs_cast_uint32(isp->volumeId));
+       (void)afs_snprintf(path, sizeof path, "%s/%s", fileSysPath, headerName);
        if (check) {
            Log("No header file for volume %u\n", isp->volumeId);
            return -1;
        }
        if (!Showmode)
-           Log("No header file for volume %u; %screating %s/%s\n",
+           Log("No header file for volume %u; %screating %s\n",
                isp->volumeId, (Testing ? "it would have been " : ""),
-               fileSysPathName, name);
-       headerFd = afs_open(name, O_RDWR | O_CREAT | O_TRUNC, 0644);
+               path);
+       headerFd = afs_open(path, O_RDWR | O_CREAT | O_TRUNC, 0644);
        assert(headerFd != -1);
        isp->volSummary = (struct VolumeSummary *)
            malloc(sizeof(struct VolumeSummary));
-       isp->volSummary->fileName = ToString(name);
+       isp->volSummary->fileName = ToString(headerName);
     } else {
-       char name[64];
+       char path[64];
+       char headerName[64];
        /* hack: these two fields are obsolete... */
        isp->volSummary->header.volumeAcl = 0;
        isp->volSummary->header.volumeMountTable = 0;
@@ -1740,18 +1771,19 @@ SalvageVolumeHeaderFile(register struct InodeSummary *isp,
             sizeof(struct VolumeHeader))) {
            /* We often remove the name before calling us, so we make a fake one up */
            if (isp->volSummary->fileName) {
-               strcpy(name, isp->volSummary->fileName);
+               strcpy(headerName, isp->volSummary->fileName);
            } else {
-               (void)afs_snprintf(name, sizeof name, VFORMAT, isp->volumeId);
-               isp->volSummary->fileName = ToString(name);
+               (void)afs_snprintf(headerName, sizeof headerName, VFORMAT, afs_cast_uint32(isp->volumeId));
+               isp->volSummary->fileName = ToString(headerName);
            }
+           (void)afs_snprintf(path, sizeof path, "%s/%s", fileSysPath, headerName);
 
-           Log("Header file %s is damaged or no longer valid%s\n", name,
+           Log("Header file %s is damaged or no longer valid%s\n", path,
                (check ? "" : "; repairing"));
            if (check)
                return -1;
 
-           headerFd = afs_open(name, O_RDWR | O_TRUNC, 0644);
+           headerFd = afs_open(path, O_RDWR | O_TRUNC, 0644);
            assert(headerFd != -1);
        }
     }
@@ -2294,10 +2326,12 @@ CopyAndSalvage(register struct DirSummary *dir)
     struct VnodeClassInfo *vcp = &VnodeClassInfo[vLarge];
     Inode oldinode, newinode;
     DirHandle newdir;
+    FdHandle_t *fdP;
     afs_int32 code;
     afs_sfsize_t lcode;
     afs_int32 parentUnique = 1;
     struct VnodeEssence *vnodeEssence;
+    afs_fsize_t length;
 
     if (Testing)
        return;
@@ -2352,12 +2386,14 @@ CopyAndSalvage(register struct DirSummary *dir)
     }
     vnode.cloned = 0;
     VNDISK_SET_INO(&vnode, newinode);
-    VNDISK_SET_LEN(&vnode, Length(&newdir));
+    length = Length(&newdir);
+    VNDISK_SET_LEN(&vnode, length);
     lcode =
        IH_IWRITE(vnodeInfo[vLarge].handle,
                  vnodeIndexOffset(vcp, dir->vnodeNumber), (char *)&vnode,
                  sizeof(vnode));
     assert(lcode == sizeof(vnode));
+#if 0
 #ifdef AFS_NT40_ENV
     nt_sync(fileSysDevice);
 #else
@@ -2365,12 +2401,19 @@ CopyAndSalvage(register struct DirSummary *dir)
                                 * an open FD on the file itself to fsync.
                                 */
 #endif
+#else
+    vnodeInfo[vLarge].handle->ih_synced = 1;
+#endif
+    /* make sure old directory file is really closed */
+    fdP = IH_OPEN(dir->dirHandle.dirh_handle);
+    FDH_REALLYCLOSE(fdP);
+    
     code = IH_DEC(dir->ds_linkH, oldinode, dir->rwVid);
     assert(code == 0);
     dir->dirHandle = newdir;
 }
 
-void
+int
 JudgeEntry(struct DirSummary *dir, char *name, VnodeId vnodeNumber,
           Unique unique)
 {
@@ -2388,7 +2431,7 @@ JudgeEntry(struct DirSummary *dir, char *name, VnodeId vnodeNumber,
            CopyOnWrite(dir);
            assert(Delete(&dir->dirHandle, name) == 0);
        }
-       return;
+       return 0;
     }
 #ifdef AFS_AIX_ENV
 #ifndef AFS_NAMEI_ENV
@@ -2402,7 +2445,7 @@ JudgeEntry(struct DirSummary *dir, char *name, VnodeId vnodeNumber,
            CopyOnWrite(dir);
            assert(Delete(&dir->dirHandle, name) == 0);
        }
-       return;
+       return 0;
     }
 #endif
 #endif
@@ -2420,7 +2463,7 @@ JudgeEntry(struct DirSummary *dir, char *name, VnodeId vnodeNumber,
                CopyOnWrite(dir);
                assert(Delete(&dir->dirHandle, name) == 0);
            }
-           return;
+           return 0;
        }
     }
 
@@ -2435,7 +2478,7 @@ JudgeEntry(struct DirSummary *dir, char *name, VnodeId vnodeNumber,
             * entry. Otherwise, it will get created in the next 
             * salvage and deleted again here. So Just skip it.
             */
-           return;
+           return 0;
        }
 
        todelete = ((!vnodeEssence->unique || dirOrphaned) ? 1 : 0);
@@ -2453,7 +2496,7 @@ JudgeEntry(struct DirSummary *dir, char *name, VnodeId vnodeNumber,
                assert(Create(&dir->dirHandle, name, &fid) == 0);
        }
        if (todelete)
-           return;             /* no need to continue */
+           return 0;           /* no need to continue */
     }
 
     if (strcmp(name, ".") == 0) {
@@ -2510,31 +2553,51 @@ JudgeEntry(struct DirSummary *dir, char *name, VnodeId vnodeNumber,
        }
        vnodeEssence->claimed = 0;      /* Not claimed: Orphaned */
        vnodeEssence->todelete = 1;     /* Will later delete vnode and decr inode */
-       return;
+       return 0;
     } else {
        if (ShowSuid && (vnodeEssence->modeBits & 06000))
            Log("FOUND suid/sgid file: %s/%s (%u.%u %05o) author %u (vnode %u dir %u)\n", dir->name ? dir->name : "??", name, vnodeEssence->owner, vnodeEssence->group, vnodeEssence->modeBits, vnodeEssence->author, vnodeNumber, dir->vnodeNumber);
-       if (ShowMounts && (vnodeEssence->type == vSymlink)
+       if (/* ShowMounts && */ (vnodeEssence->type == vSymlink)
            && !(vnodeEssence->modeBits & 0111)) {
            int code, size;
-           char buf[1024];
+           char buf[1025];
            IHandle_t *ihP;
            FdHandle_t *fdP;
 
            IH_INIT(ihP, fileSysDevice, dir->dirHandle.dirh_handle->ih_vid,
                    vnodeEssence->InodeNumber);
            fdP = IH_OPEN(ihP);
-           assert(fdP != NULL);
+           if (fdP == NULL) {
+               Log("ERROR %s could not open mount point vnode %u\n", dir->vname, vnodeNumber);
+               IH_RELEASE(ihP);
+               return 0;
+           }
            size = FDH_SIZE(fdP);
-           assert(size != -1);
-           memset(buf, 0, 1024);
+           if (size < 0) {
+               Log("ERROR %s mount point has invalid size %d, vnode %u\n", dir->vname, size, vnodeNumber);
+               FDH_REALLYCLOSE(fdP);
+               IH_RELEASE(ihP);
+               return 0;
+           }
+       
            if (size > 1024)
                size = 1024;
            code = FDH_READ(fdP, buf, size);
-           assert(code == size);
-           Log("In volume %u (%s) found mountpoint %s/%s to '%s'\n",
-               dir->dirHandle.dirh_handle->ih_vid, dir->vname,
-               dir->name ? dir->name : "??", name, buf);
+           if (code == size) {
+               buf[size] = '\0';
+               if ( (*buf != '#' && *buf != '%') || buf[strlen(buf)-1] != '.' ) {
+                   Log("Volume %u (%s) mount point %s/%s to '%s' invalid, %s to symbolic link\n",
+                       dir->dirHandle.dirh_handle->ih_vid, dir->vname, dir->name ? dir->name : "??", name, buf,
+                       Testing ? "would convert" : "converted");
+                   vnodeEssence->modeBits |= 0111;
+                   vnodeEssence->changed = 1;
+               } else if (ShowMounts) Log("In volume %u (%s) found mountpoint %s/%s to '%s'\n",
+                   dir->dirHandle.dirh_handle->ih_vid, dir->vname,
+                   dir->name ? dir->name : "??", name, buf);
+           } else {
+               Log("Volume %s cound not read mount point vnode %u size %d code %d\n",
+                   dir->vname, vnodeNumber, size, code);
+           }
            FDH_REALLYCLOSE(fdP);
            IH_RELEASE(ihP);
        }
@@ -2581,13 +2644,14 @@ JudgeEntry(struct DirSummary *dir, char *name, VnodeId vnodeNumber,
                    CopyOnWrite(dir);
                    assert(Delete(&dir->dirHandle, name) == 0);
                }
-               return;
+               return 0;
            }
        }
        /* This directory claims the vnode */
        vnodeEssence->claimed = 1;
     }
     vnodeEssence->count--;
+    return 0;
 }
 
 void
@@ -2828,6 +2892,11 @@ SalvageVolume(register struct InodeSummary *rwIsp, IHandle_t * alinkH)
        SalvageDir(volHeader.name, vid, dirVnodeInfo, alinkH, i, &rootdir,
                   &rootdirfound);
     }
+#ifdef AFS_NT40_ENV
+    nt_sync(fileSysDevice);
+#else
+    sync();                            /* This used to be done lower level, for every dir */
+#endif
     if (Showmode) {
        IH_RELEASE(h);
        return 0;
@@ -3005,6 +3074,8 @@ SalvageVolume(register struct InodeSummary *rwIsp, IHandle_t * alinkH)
                    if (!Showmode) {
                        Log("Vnode %u: link count incorrect (was %d, %s %d)\n", vnodeNumber, oldCount, (Testing ? "would have changed to" : "now"), vnode.linkCount);
                    }
+               } else {
+                   vnode.modeBits = vnp->modeBits;
                }
 
                vnode.dataVersion++;
@@ -3128,12 +3199,12 @@ MaybeZapVolume(register struct InodeSummary *isp, char *message, int deleteMe,
 
 
 void
-AskOffline(VolumeId volumeId)
+AskOffline(VolumeId volumeId, char * partition)
 {
     afs_int32 code, i;
 
     for (i = 0; i < 3; i++) {
-       code = FSYNC_VolOp(volumeId, NULL, FSYNC_VOL_OFF, FSYNC_SALVAGE, NULL);
+       code = FSYNC_VolOp(volumeId, partition, FSYNC_VOL_OFF, FSYNC_SALVAGE, NULL);
 
        if (code == SYNC_OK) {
            break;
@@ -3229,7 +3300,7 @@ PrintInodeList(void)
     register struct ViceInodeInfo *ip;
     struct ViceInodeInfo *buf;
     struct afs_stat status;
-    register nInodes;
+    register int nInodes;
 
     assert(afs_fstat(inodeFd, &status) == 0);
     buf = (struct ViceInodeInfo *)malloc(status.st_size);
@@ -3278,16 +3349,38 @@ Fork(void)
 #else
     f = fork();
     assert(f >= 0);
+#ifdef AFS_DEMAND_ATTACH_FS
+    if ((f == 0) && (programType == salvageServer)) {
+       /* we are a salvageserver child */
+#ifdef FSSYNC_BUILD_CLIENT
+       VChildProcReconnectFS_r();
+#endif
+#ifdef SALVSYNC_BUILD_CLIENT
+       VReconnectSALV_r();
 #endif
+    }
+#endif /* AFS_DEMAND_ATTACH_FS */
+#endif /* !AFS_NT40_ENV */
     return f;
 }
 
 void
-Exit(code)
-     int code;
+Exit(int code)
 {
     if (ShowLog)
        showlog();
+
+#ifdef AFS_DEMAND_ATTACH_FS
+    if (programType == salvageServer) {
+#ifdef SALVSYNC_BUILD_CLIENT
+       VDisconnectSALV();
+#endif
+#ifdef FSSYNC_BUILD_CLIENT
+       VDisconnectFS();
+#endif
+    }
+#endif /* AFS_DEMAND_ATTACH_FS */
+
 #ifdef AFS_NT40_ENV
     if (main_thread != pthread_self())
        pthread_exit((void *)code);
@@ -3319,7 +3412,7 @@ TimeStamp(time_t clock, int precision)
     static char timestamp[20];
     lt = localtime(&clock);
     if (precision)
-       (void)strftime(timestamp, 20, "%m/%d/%Y %T", lt);
+       (void)strftime(timestamp, 20, "%m/%d/%Y %H:%M:%S", lt);
     else
        (void)strftime(timestamp, 20, "%m/%d/%Y %H:%M", lt);
     return timestamp;
@@ -3418,11 +3511,11 @@ Log(const char *format, ...)
        syslog(LOG_INFO, "%s", tmp);
     } else
 #endif
-    {
-       gettimeofday(&now, 0);
-       fprintf(logFile, "%s %s", TimeStamp(now.tv_sec, 1), tmp);
-       fflush(logFile);
-    }
+       if (logFile) {
+           gettimeofday(&now, 0);
+           fprintf(logFile, "%s %s", TimeStamp(now.tv_sec, 1), tmp);
+           fflush(logFile);
+       }
 }
 
 void
@@ -3439,12 +3532,12 @@ Abort(const char *format, ...)
        syslog(LOG_INFO, "%s", tmp);
     } else
 #endif
-    {
-       fprintf(logFile, "%s", tmp);
-       fflush(logFile);
-       if (ShowLog)
-           showlog();
-    }
+       if (logFile) {
+           fprintf(logFile, "%s", tmp);
+           fflush(logFile);
+           if (ShowLog)
+               showlog();
+       }
 
     if (debug)
        abort();
@@ -3459,16 +3552,18 @@ ToString(char *s)
     assert(p != NULL);
     strcpy(p, s);
     return p;
-
 }
 
 /* Remove the FORCESALVAGE file */
 void
 RemoveTheForce(char *path)
 {
+    char target[1024];
+    struct afs_stat force; /* so we can use afs_stat to find it */
+    strcpy(target,path);
+    strcat(target,"/FORCESALVAGE");
     if (!Testing && ForceSalvage) {
-       if (chdir(path) == 0)
-           unlink("FORCESALVAGE");
+        if (afs_stat(target,&force) == 0)  unlink(target);
     }
 }
 
@@ -3480,10 +3575,11 @@ int
 UseTheForceLuke(char *path)
 {
     struct afs_stat force;
+    char target[1024];
+    strcpy(target,path);
+    strcat(target,"/FORCESALVAGE");
 
-    assert(chdir(path) != -1);
-
-    return (afs_stat("FORCESALVAGE", &force) == 0);
+    return (afs_stat(target, &force) == 0);
 }
 #else
 /*