largefile-do-offsets-correctly-when-64bit-but-not-largefile-20030313
[openafs.git] / src / volser / dumpstuff.c
index 71ebfa3..85da7bc 100644 (file)
@@ -25,6 +25,13 @@ RCSID("$Header$");
 #include <netinet/in.h>
 #include <unistd.h>
 #endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
 #include <sys/stat.h>
 #include <afs/assert.h>
 #include <rx/xdr.h>
@@ -75,13 +82,14 @@ static int DumpPartial(register struct iod *iodp, register Volume *vp,
 static int DumpVnodeIndex(register struct iod *iodp, Volume *vp,
                          VnodeClass class, afs_int32 fromtime, int forcedump);
 static int DumpVnode(register struct iod *iodp, struct VnodeDiskObject *v,
-                    int vnodeNumber, int dumpEverything);
+                    int volid, int vnodeNumber, int dumpEverything);
 static int ReadDumpHeader(register struct iod *iodp, struct DumpHeader *hp);
 static int ReadVnodes(register struct iod *iodp, Volume *vp,
                      int incremental, afs_int32 *Lbuf, afs_int32 s1,
                      afs_int32 *Sbuf, afs_int32 s2, afs_int32 delo);
-static bit32 volser_WriteFile(int vn, struct iod *iodp, FdHandle_t *handleP,
-                             Error *status);
+static afs_offs_t volser_WriteFile(int vn, struct iod *iodp,
+                                  FdHandle_t *handleP,
+                                  int tag, Error *status);
 
 
 static void iod_Init(register struct iod *iodp, register struct rx_call *call)
@@ -205,7 +213,7 @@ static int ReadVolumeHeader(register struct iod *iodp, VolumeDiskData *vol)
 {
     register tag;
     afs_uint32 trash;
-    bzero(vol, sizeof(*vol));
+    memset(vol, 0, sizeof(*vol));
     while ((tag = iod_getc(iodp)) > D_MAX && tag != EOF) {
        switch (tag) {
            case 'i':
@@ -413,23 +421,35 @@ static int DumpByteString(register struct iod *iodp, char tag,
     return 0;
 }
     
-static int DumpFile(struct iod *iodp, char tag, int vnode, FdHandle_t *handleP)
+static int DumpFile(struct iod *iodp, int vnode, FdHandle_t *handleP)
 {
     int   code = 0, lcode = 0, error = 0;
     afs_int32 pad = 0, offset;
-    int   n, nbytes, howMany;
+    afs_size_t   n, nbytes, howMany, howBig;
     byte  *p;
+#ifdef AFS_LARGEFILE_ENV
+    struct stat64 status;
+#else
     struct stat status;
-    int size;
+#endif
+    afs_size_t size;
 #ifdef AFS_AIX_ENV
 #include <sys/statfs.h>
     struct statfs tstatfs;
 #endif
 
 #ifdef AFS_NT40_ENV
-    howMany = 4096; /* Page size */
+    howBig = _filelength(handleP->fd_fd);
+    howMany = 4096;
+
 #else
+#ifdef AFS_LARGEFILE_ENV
+    fstat64(handleP->fd_fd, &status);
+#else /* !AFS_LARGEFILE_ENV */
     fstat(handleP->fd_fd, &status);
+#endif /* !AFS_LARGEFILE_ENV */
+    howBig = status.st_size;
+
 #ifdef AFS_AIX_ENV
     /* Unfortunately in AIX valuable fields such as st_blksize are 
      * gone from the stat structure.
@@ -438,11 +458,24 @@ static int DumpFile(struct iod *iodp, char tag, int vnode, FdHandle_t *handleP)
     howMany = tstatfs.f_bsize;
 #else
     howMany = status.st_blksize;
-#endif
+#endif /* AFS_AIX_ENV */
 #endif /* AFS_NT40_ENV */
 
+
     size = FDH_SIZE(handleP);
-    code = DumpInt32(iodp, tag, size);
+#ifdef AFS_LARGEFILE_ENV
+    {
+       afs_uint32      hi,lo;
+       SplitInt64(size, hi, lo);
+       if (hi == 0L) {
+           code = DumpInt32(iodp, 'f', lo);
+       } else {
+           code = DumpDouble(iodp, 'h', hi, lo);
+       }
+    }
+#else /* !AFS_LARGEFILE_ENV */
+    code = DumpInt32(iodp, 'f', size);
+#endif /* !AFS_LARGEFILE_ENV */
     if (code) {
        return VOLSERDUMPERROR;
     }
@@ -488,9 +521,9 @@ static int DumpFile(struct iod *iodp, char tag, int vnode, FdHandle_t *handleP)
           /* Pad the rest of the buffer with zeros. Remember offset we started 
            * padding. Keep total tally of padding.
            */
-          bzero(p+n, howMany-n);
+          memset(p+n, 0, howMany-n);
           if (!pad)
-             offset = (status.st_size - nbytes) + n;
+             offset = (howBig - nbytes) + n;
           pad += (howMany-n);
           
           /* Now seek over the data we could not get. An error here means we
@@ -631,7 +664,6 @@ static int DumpVnodeIndex(register struct iod *iodp, Volume *vp,
     char buf[SIZEOF_LARGEDISKVNODE];
     struct VnodeDiskObject *vnode = (struct VnodeDiskObject *) buf;
     StreamHandle_t *file;
-    IHandle_t *handle;
     FdHandle_t *fdP;
     int size;
     int flag;
@@ -645,8 +677,8 @@ static int DumpVnodeIndex(register struct iod *iodp, Volume *vp,
     assert(size != -1);
     nVnodes = (size / vcp->diskSize) - 1;
     if (nVnodes > 0) {
-       assert((nVnodes+1)*vcp->diskSize == size)
-       assert(STREAM_SEEK(file, vcp->diskSize, 0) == 0)
+       assert((nVnodes+1)*vcp->diskSize == size);
+       assert(STREAM_SEEK(file, vcp->diskSize, 0) == 0);
     }
     else nVnodes = 0;
     for (vnodeIndex = 0; nVnodes && STREAM_READ(vnode, vcp->diskSize, 1, file) == 1 && !code;
@@ -655,7 +687,7 @@ static int DumpVnodeIndex(register struct iod *iodp, Volume *vp,
        /* Note:  the >= test is very important since some old volumes may not have
           a serverModifyTime.  For an epoch dump, this results in 0>=0 test, which
           does dump the file! */
-       if (!code) code = DumpVnode(iodp, vnode, bitNumberToVnodeNumber(vnodeIndex, class), flag);
+       if (!code) code = DumpVnode(iodp, vnode, V_id(vp), bitNumberToVnodeNumber(vnodeIndex, class), flag);
        if (!flag) IOMGR_Poll(); /* if we dont' xfr data, but scan instead, could lose conn */
     }
     STREAM_CLOSE(file);
@@ -682,7 +714,7 @@ static int DumpDumpHeader(register struct iod *iodp, register Volume *vp,
 }
 
 static int DumpVnode(register struct iod *iodp, struct VnodeDiskObject *v,
-                    int vnodeNumber, int dumpEverything)
+                    int volid, int vnodeNumber, int dumpEverything)
 {
     int code = 0;
     IHandle_t *ihP;
@@ -711,12 +743,12 @@ static int DumpVnode(register struct iod *iodp, struct VnodeDiskObject *v,
        IH_INIT(ihP, iodp->device, iodp->parentId, VNDISK_GET_INO(v));
        fdP = IH_OPEN(ihP);
        if (fdP == NULL) {
-           Log("1 Volser: DumpVnode: dump: Unable to open inode %d for vnode %d; not dumped, error %d\n",
-               VNDISK_GET_INO(v), vnodeNumber, errno);
+           Log("1 Volser: DumpVnode: dump: Unable to open inode %d for vnode %d (volume %d); not dumped, error %d\n",
+               VNDISK_GET_INO(v), vnodeNumber, volid, errno);
            IH_RELEASE(ihP);
            return VOLSERREAD_DUMPERROR;
        }
-       code = DumpFile(iodp, 'f', vnodeNumber, fdP);
+       code = DumpFile(iodp, vnodeNumber, fdP);
        FDH_CLOSE(fdP);
        IH_RELEASE(ihP);
     }
@@ -737,7 +769,7 @@ int ProcessIndex(Volume *vp, VnodeClass class, afs_int32 **Bufp, int *sizep,
     char buf[SIZEOF_LARGEDISKVNODE], zero[SIZEOF_LARGEDISKVNODE];
     register struct VnodeDiskObject *vnode = (struct VnodeDiskObject *) buf;
     
-    bzero(zero, sizeof(zero)); /* zero out our proto-vnode */
+    memset(zero, 0, sizeof(zero));     /* zero out our proto-vnode */
     fdP = IH_OPEN(vp->vnodeIndex[class].handle);
     if (fdP == NULL)
        return -1;
@@ -754,9 +786,19 @@ int ProcessIndex(Volume *vp, VnodeClass class, afs_int32 **Bufp, int *sizep,
                    if (vnode->type != vNull && VNDISK_GET_INO(vnode)) {
                        cnt1++;
                        if (DoLogging) {
+#ifdef AFS_LARGEFILE_ENV
+                          afs_offs_t fileLen;
+                          VNDISK_GET_LEN(fileLen, vnode);
+                          Log("RestoreVolume %d Cleanup: Removing old vnode=%d inode=%d size=(0X%x,0X%x)\n", 
+                              V_id(vp), bitNumberToVnodeNumber(i,class),
+                              VNDISK_GET_INO(vnode),
+                              (unsigned) (fileLen >> 32),
+                              (unsigned) (fileLen & 0xffffffff));
+#else /* !AFS_LARGEFILE_ENV */
                           Log("RestoreVolume %d Cleanup: Removing old vnode=%d inode=%d size=%d\n", 
                               V_id(vp), bitNumberToVnodeNumber(i,class),
                               VNDISK_GET_INO(vnode), vnode->length);
+#endif /* !AFS_LARGEFILE_ENV */
                        }
                        IH_DEC(V_linkHandle(vp), VNDISK_GET_INO(vnode),
                             V_parentId(vp));
@@ -776,13 +818,13 @@ int ProcessIndex(Volume *vp, VnodeClass class, afs_int32 **Bufp, int *sizep,
        OS_SYNC(afile->str_fd);
     } else {
        size = OS_SIZE(fdP->fd_fd);
-       assert(size != -1)
+       assert(size != -1);
        nVnodes = (size <= vcp->diskSize ? 0 :
                   size-vcp->diskSize) >> vcp->logSize;
        if (nVnodes > 0) {
            Buf = (afs_int32 *) malloc(nVnodes * sizeof(afs_int32));
            if (Buf == NULL) return 1;
-           bzero((char *)Buf, nVnodes * sizeof(afs_int32));
+           memset((char *)Buf, 0, nVnodes * sizeof(afs_int32));
            STREAM_SEEK(afile, offset = vcp->diskSize, 0);
            while (1) {
                code = STREAM_READ(vnode, vcp->diskSize, 1, afile);
@@ -916,7 +958,7 @@ static int ReadVnodes(register struct iod *iodp, Volume *vp,
     V_pref(vp, nearInode);
     while (tag == D_VNODE) {
         int haveStuff = 0;
-       bzero(buf, sizeof (buf));
+       memset(buf, 0, sizeof (buf));
        if (!ReadInt32(iodp, (afs_uint32 *)&vnodeNumber))
            break;
 
@@ -966,9 +1008,13 @@ static int ReadVnodes(register struct iod *iodp, Volume *vp,
                                   VAclDiskSize(vnode));
                    acl_NtohACL(VVnodeDiskACL(vnode));
                    break;
+#ifdef AFS_LARGEFILE_ENV
+               case 'h':
+#endif
                case 'f': {
                    Inode ino;
                    Error error;
+                   afs_offs_t fileLen;
 
                    ino = IH_CREATE(V_linkHandle(vp),
                                    V_device(vp),
@@ -989,8 +1035,10 @@ static int ReadVnodes(register struct iod *iodp, Volume *vp,
                        IH_RELEASE(tmpH);
                        return VOLSERREAD_DUMPERROR;
                    }
-                   vnode->length = volser_WriteFile(vnodeNumber, iodp, fdP,
-                                                    &error);
+                   
+                   fileLen = volser_WriteFile(vnodeNumber, iodp, fdP,
+                                                    tag, &error);
+                   VNDISK_SET_LEN(vnode, fileLen);
                    FDH_REALLYCLOSE(fdP);
                    IH_RELEASE(tmpH);
                    if (error) {
@@ -1058,22 +1106,41 @@ static int ReadVnodes(register struct iod *iodp, Volume *vp,
  * needing to read an ungetc'd character, since the ReadInt32 will have read
  * it instead.
  */
-static bit32 volser_WriteFile(int vn, struct iod *iodp, FdHandle_t *handleP,
-                             Error *status)
+static afs_offs_t volser_WriteFile(int vn, struct iod *iodp, FdHandle_t *handleP,
+                             int tag, Error *status)
 {
     afs_int32 code;
-    afs_uint32 filesize;
-    bit32 written=0;
+    afs_offs_t filesize;
+    afs_offs_t written=0;
     register afs_uint32 size = 8192;
-    register afs_uint32 nbytes;
+    register afs_offs_t nbytes;
     unsigned char *p;
 
 
     *status = 0;
+#ifdef AFS_64BIT_ENV
+    {
+       afs_uint32 filesize_high = 0L, filesize_low = 0L;
+#ifdef AFS_LARGEFILE_ENV
+       if (tag == 'h') {
+           if (!ReadInt32(iodp, &filesize_high) ) {
+               *status = 1;
+               return(0);
+           }
+       }
+#endif
+       if (!ReadInt32(iodp, &filesize_low)) {
+           *status = 1;
+           return(0);
+       }
+       FillInt64(filesize, filesize_high, filesize_low);
+    }
+#else /* !AFS_64BIT_ENV */
     if (!ReadInt32(iodp, &filesize)) {
         *status = 1;
        return(0);
     }
+#endif /* !AFS_64BIT_ENV */
     p = (unsigned char *) malloc(size);
     if (p == NULL) {
         *status = 2;
@@ -1084,7 +1151,14 @@ static bit32 volser_WriteFile(int vn, struct iod *iodp, FdHandle_t *handleP,
            size = nbytes;
        
        if ((code = iod_Read(iodp, p, size)) != size) {
+#ifdef AFS_64BIT_ENV
+           Log("1 Volser: WriteFile: Error reading dump file %d size=(0X%x,0X%x) nbytes=%d (%d of %d); restore aborted\n", vn,
+               (unsigned) (filesize >> 32),
+               (unsigned) (filesize & 0xffffffff),
+               nbytes, code, size);
+#else /* !AFS_LARGEFILE_ENV */
            Log("1 Volser: WriteFile: Error reading dump file %d size=%d nbytes=%d (%d of %d); restore aborted\n", vn, filesize, nbytes, code, size);
+#endif /* !AFS_LARGEFILE_ENV */
            *status = 3;
            break;
        }