]> git.saurik.com Git - apple/hfs.git/blobdiff - CopyHFSMeta/SparseBundle.c
hfs-366.30.3.tar.gz
[apple/hfs.git] / CopyHFSMeta / SparseBundle.c
index e342d470bcb45df8a6f4bed6fcc0cd3f5ff28423..455903eebec2fbf7b7c2e7003a393de4145f0e59 100644 (file)
@@ -5,11 +5,13 @@
 #include <fcntl.h>
 #include <err.h>
 #include <errno.h>
+#include <unistd.h>
 #include <sys/stat.h>
 #include <sys/fcntl.h>
 #include <removefile.h>
 
 #include <CoreFoundation/CoreFoundation.h>
+#include <System/sys/fsctl.h> 
 
 #include "hfsmeta.h"
 #include "Sparse.h"
  * no encryption.
  */
 
-#define MIN(a, b) \
+#ifndef MIN
+# define MIN(a, b) \
        ({ __typeof(a) __a = (a); __typeof(b) __b = (b); \
                __a < __b ? __a : __b; })
+#endif
 
 /*
  * Context for the sparse bundle routines.  The path name,
@@ -59,6 +63,7 @@ static const char *bundlePrototype =
 "</dict>\n"
        "</plist>\n";
 
+
 /*
  * Read from a sparse bundle.  If the band file doesn't exist, or is shorter than
  * what we need to get from it, we pad out with 0's.
@@ -132,19 +137,29 @@ doSparseWrite(IOWrapper_t *context, off_t offset, void *buffer, size_t len)
                int fd;
 
                if (ctx->cfd == -1 || ctx->cBandNum != bandNum) {
-                               if (ctx->cfd != -1)
-                                       close(ctx->cfd);
-                               asprintf(&bandName, "%s/bands/%x", ctx->pathname, bandNum);
-                               fd = open(bandName, O_WRONLY | O_CREAT, 0666);
-                               if (fd == -1) {
-                                       warn("Cannot open band file %s for offset %llu", bandName, offset + written);
-                                       retval = -1;
-                                       goto done;
-                               }
-                               free(bandName);
-                               bandName = NULL;
-                               ctx->cfd = fd;
-                               ctx->cBandNum = bandNum;
+                       if (ctx->cfd != -1) {
+                               close(ctx->cfd);
+                       }
+                       asprintf(&bandName, "%s/bands/%x", ctx->pathname, bandNum);
+                       fd = open(bandName, O_WRONLY | O_CREAT, 0666);
+                       if (fd == -1) {
+                               warn("Cannot open band file %s for offset %llu", bandName, offset + written);
+                               retval = -1;
+                               goto done;
+                       }
+                       /*
+                        * When we create a new band file, we sync the volume
+                        * it's on, so that we can ensure that the band file is present
+                        * on disk.  (Otherwise, with a crash, we can end up with the
+                        * data not where we expected.)  In this case, however, we probably
+                        * don't need to wait for it -- just start the sync.
+                        */
+                       fsync_volume_np(fd, 0);
+                       fcntl(fd, F_NOCACHE, 1);
+                       free(bandName);
+                       bandName = NULL;
+                       ctx->cfd = fd;
+                       ctx->cBandNum = bandNum;
                } else {
                        fd = ctx->cfd;
                }
@@ -156,7 +171,8 @@ doSparseWrite(IOWrapper_t *context, off_t offset, void *buffer, size_t len)
                        retval = -1;
                        goto done;
                }
-               (void)fcntl(fd, F_FULLFSYNC, 0);
+               // Sync the data out.
+               fsync(fd);
                written += nwritten;
        }
        retval = written;
@@ -173,30 +189,44 @@ static ssize_t
 WriteExtentToSparse(struct IOWrapper * context, DeviceInfo_t *devp, off_t start, off_t len, void (^bp)(off_t))
 {
        const size_t bufSize = 1024 * 1024;
-       uint8_t buffer[bufSize];
+       uint8_t *buffer = NULL;
+       ssize_t retval = 0;
        off_t total = 0;
 
        if (debug) printf("Writing extent <%lld, %lld>\n", start, len);
+       buffer = malloc(bufSize);
+       if (buffer == NULL) {
+               warn("%s(%s):  Could not allocate %zu bytes for buffer", __FILE__, __FUNCTION__, bufSize);
+               retval = -1;
+               goto done;
+       }
+
        while (total < len) {
                ssize_t nread;
                ssize_t nwritten;
                size_t amt = MIN(bufSize, len - total);
-               nread = pread(devp->fd, buffer, amt, start + total);
+               nread = UnalignedRead(devp, buffer, amt, start + total);
                if (nread == -1) {
                        warn("Cannot read from device at offset %lld", start + total);
-                       return -1;
+                       retval = -1;
+                       break;
                }
                if (nread < amt) {
                        warnx("Short read from source device -- got %zd, expected %zd", nread, amt);
                }
                nwritten = doSparseWrite(context, start + total, buffer, nread);
-               if (nwritten == -1)
-                       return -1;
+               if (nwritten == -1) {
+                       retval = -1;
+                       break;
+               }
                bp(nread);
                total += nread;
        }
        if (debug) printf("\twrote %lld\n", total);
-       return 0;
+done:
+       if (buffer)
+               free(buffer);
+       return retval;
 }
 
 static const CFStringRef kBandSizeKey = CFSTR("band-size");