hfs-366.50.19.tar.gz macos-10124 macos-10125 v366.50.19
authorApple <opensource@apple.com>
Wed, 29 Mar 2017 20:15:56 +0000 (20:15 +0000)
committerApple <opensource@apple.com>
Wed, 29 Mar 2017 20:15:56 +0000 (20:15 +0000)
29 files changed:
CopyHFSMeta/SparseBundle.c
CopyHFSMeta/main.c
core/hfs.h
core/hfs_catalog.c
core/hfs_chash.c
core/hfs_cnode.c
core/hfs_cnode.h
core/hfs_cprotect.c
core/hfs_endian.c
core/hfs_iokit.cpp
core/hfs_readwrite.c
core/hfs_vfsops.c
core/hfs_vfsutils.c
core/hfs_vnops.c
fs/Info.plist
fsck_hfs/dfalib/BlockCache.c
fsck_hfs/dfalib/CatalogCheck.c
fsck_hfs/dfalib/SDevice.c
fsck_hfs/dfalib/SRebuildBTree.c
fsck_hfs/dfalib/SRepair.c
fsck_hfs/dfalib/SVerify2.c
fsck_hfs/dfalib/fsck_journal.c
fsck_hfs/dfalib/hfs_endian.c
hfs.xcodeproj/project.pbxproj
tests/cases/test-hard-links.m
tests/cases/test-raw-dev-unaligned.c [new file with mode: 0644]
tests/cases/test-throttled-io.c
tests/hfs-tests.entitlements
tests/hfs-tests.mm

index 455903eebec2fbf7b7c2e7003a393de4145f0e59..2d966c46744d6997bfd54c677592ad7ab72fa9b0 100644 (file)
@@ -73,19 +73,23 @@ doSparseRead(struct IOWrapper *context, off_t offset, void *buffer, off_t len)
 {
        struct SparseBundleContext *ctx = context->context;
        off_t blockSize = ctx->bandSize;
-       size_t nread = 0;
+       ssize_t nread = 0;
        ssize_t retval = -1;
 
        while (nread < len) {
                off_t bandNum = (offset + nread) / blockSize;   // Which band file to use
                off_t bandOffset = (offset + nread) % blockSize;        // how far to go into the file
-               size_t amount = MIN(len - nread, blockSize - bandOffset);       // How many bytes to write in this band file
-               struct stat sbuf;
+               ssize_t amount = MIN(len - nread, blockSize - bandOffset);      // How many bytes to write in this band file
                char *bandName;
-               ssize_t n;;
+               ssize_t n;
                int fd;
 
-               asprintf(&bandName, "%s/bands/%x", ctx->pathname, bandNum);
+               asprintf(&bandName, "%s/bands/%llx", ctx->pathname, bandNum);
+               if (!bandName) {
+                       warn("Cannot allocate memory for path '%s/bands/%llx'", ctx->pathname, bandNum);
+                       retval = -1;
+                       goto done;
+               }
                fd = open(bandName, O_RDONLY);
                if (fd == -1) {
                        if (errno == ENOENT) {
@@ -100,15 +104,19 @@ doSparseRead(struct IOWrapper *context, off_t offset, void *buffer, off_t len)
                        free(bandName);
                        goto done;
                }
+
                n = pread(fd, (char*)buffer + nread, amount, bandOffset);
                if (n == -1) {
-                       warn("Cannot write to band file %s/band/%x for offset %llu for amount %zu", ctx->pathname, bandNum, offset+nread, amount);
+                       warn("Cannot read from band file %s for offset %llu for amount %zu", bandName, offset+nread, amount);
                        close(fd);
+                       free(bandName);
                        goto done;
                }
                if (n < amount) {       // hit EOF, pad out with zeroes
                        memset(buffer + nread + amount, 0, amount - n);
                }
+               free(bandName);
+               close(fd);
                nread += n;
        }
        retval = nread;
@@ -121,29 +129,38 @@ done:
  * Write a chunk of data to a bundle.
  */
 static ssize_t
-doSparseWrite(IOWrapper_t *context, off_t offset, void *buffer, size_t len)
+doSparseWrite(IOWrapper_t *context, off_t offset, void *buffer, off_t len)
 {
        struct SparseBundleContext *ctx = context->context;
        off_t blockSize = ctx->bandSize;
-       size_t written = 0;
+       ssize_t written = 0;
        ssize_t retval = -1;
 
        while (written < len) {
                off_t bandNum = (offset + written) / blockSize; // Which band file to use
                off_t bandOffset = (offset + written) % blockSize;      // how far to go into the file
                size_t amount = MIN(len - written, blockSize - bandOffset);     // How many bytes to write in this band file
-               char *bandName;
                ssize_t nwritten;
                int fd;
 
                if (ctx->cfd == -1 || ctx->cBandNum != bandNum) {
+                       char *bandName = NULL;
+
                        if (ctx->cfd != -1) {
                                close(ctx->cfd);
+                               ctx->cfd = -1;
                        }
-                       asprintf(&bandName, "%s/bands/%x", ctx->pathname, bandNum);
+                       asprintf(&bandName, "%s/bands/%llx", ctx->pathname, bandNum);
+                       if (!bandName) {
+                               warnx("Cannot allocate memory for band %s/bands/%llx", ctx->pathname, bandNum);
+                               retval = -1;
+                               goto done;
+                       }
+
                        fd = open(bandName, O_WRONLY | O_CREAT, 0666);
                        if (fd == -1) {
                                warn("Cannot open band file %s for offset %llu", bandName, offset + written);
+                               free(bandName);
                                retval = -1;
                                goto done;
                        }
@@ -165,7 +182,7 @@ doSparseWrite(IOWrapper_t *context, off_t offset, void *buffer, size_t len)
                }
                nwritten = pwrite(fd, (char*)buffer + written, amount, bandOffset);
                if (nwritten == -1) {
-                       warn("Cannot write to band file %s/band/%x for offset %llu for amount %zu", ctx->pathname, bandNum, offset+written, amount);
+                       warn("Cannot write to band file %s/band/%llx for offset %llu for amount %zu", ctx->pathname, bandNum, offset+written, amount);
                        close(fd);
                        ctx->cfd = -1;
                        retval = -1;
@@ -188,7 +205,7 @@ done:
 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;
+       const ssize_t bufSize = 1024 * 1024;
        uint8_t *buffer = NULL;
        ssize_t retval = 0;
        off_t total = 0;
@@ -204,7 +221,7 @@ WriteExtentToSparse(struct IOWrapper * context, DeviceInfo_t *devp, off_t start,
        while (total < len) {
                ssize_t nread;
                ssize_t nwritten;
-               size_t amt = MIN(bufSize, len - total);
+               ssize_t amt = MIN(bufSize, len - total);
                nread = UnalignedRead(devp, buffer, amt, start + total);
                if (nread == -1) {
                        warn("Cannot read from device at offset %lld", start + total);
@@ -251,7 +268,7 @@ GetSizesFromPlist(const char *path, size_t *bandSize, off_t *devSize)
        long long tmpLL;
 
 
-       inFileURL = CFURLCreateFromFileSystemRepresentation(NULL, path, strlen(path), FALSE);
+       inFileURL = CFURLCreateFromFileSystemRepresentation(NULL, (const UInt8 *)path, strlen(path), FALSE);
        if (inFileURL == NULL) {
                if (debug) warn("Cannot create url from pathname %s", path);
                goto done;
@@ -398,10 +415,10 @@ struct IOWrapper *
 InitSparseBundle(const char *path, DeviceInfo_t *devp)
 {
        struct SparseBundleContext ctx = { 0 };
-       struct SparseBundleContext *retctx = NULL;
-       IOWrapper_t *retval = NULL;
+       IOWrapper_t *wrapper = NULL;
        struct stat sb;
-       char tmpname[strlen(path) + sizeof("Info.plist") + 2];  // '/' + NUL
+       char *tmpname = NULL;
+       int tmplen;
 
        if (strstr(path, ".sparsebundle") == NULL) {
                asprintf(&ctx.pathname, "%s.sparsebundle", path);
@@ -409,6 +426,10 @@ InitSparseBundle(const char *path, DeviceInfo_t *devp)
                ctx.pathname = strdup(path);
        }
 
+       if (ctx.pathname == NULL) {
+               return NULL;
+       }
+
        if (lstat(ctx.pathname, &sb) == -1) {
                if (errno != ENOENT) {
                        warn("cannot check sparse bundle %s", ctx.pathname);
@@ -422,7 +443,14 @@ InitSparseBundle(const char *path, DeviceInfo_t *devp)
                warnx("sparse bundle object %s is not a directory", ctx.pathname);
                goto done;
        }
-       sprintf(tmpname, "%s/Info.plist", ctx.pathname);
+       /* NB! All names we create inside the bundle directory are shorter
+        * then "Info.plist", we re-use the buffer allocated here for
+        * multiple file names. */
+       tmplen = asprintf(&tmpname, "%s/Info.plist", ctx.pathname);
+       if (tmpname == NULL) {
+               goto done;
+       }
+
        if (stat(tmpname, &sb) != -1) {
                size_t bandSize = 0;
                off_t devSize = 0;
@@ -445,46 +473,64 @@ InitSparseBundle(const char *path, DeviceInfo_t *devp)
                        goto done;
                }
                ctx.bandSize = kBandSize;
-               fprintf(fp, bundlePrototype, kBandSize, devp->size);
-               fclose(fp);
-               sprintf(tmpname, "%s/Info.bckup", ctx.pathname);
-               fp = fopen(tmpname, "w");
-               if (fp) {
-                       fprintf(fp, bundlePrototype, kBandSize, devp->size);
-                       fclose(fp);
+               if (fprintf(fp, bundlePrototype, kBandSize, devp->size) < 0) {
+                       warn("failed to set bundle information in %s", tmpname);
+                       fclose(fp); /* eat error return */
+                       goto done;
+               }
+               if (fclose(fp) != 0) {
+                       warn("failed to update bundle information in %s", tmpname);
+                       goto done;
                }
-               sprintf(tmpname, "%s/bands", ctx.pathname);
-               if (mkdir(tmpname, 0777) == -1) {
+               snprintf(tmpname, tmplen + 1, "%s/Info.bckup", ctx.pathname);
+               if ((int)strlen(tmpname) == tmplen) { /* Only update backup if we get the full path */
+                       /* Failure to create a backup is not fatal */
+                       fp = fopen(tmpname, "w");
+                       if (fp) {
+                               if ((fprintf(fp, bundlePrototype, kBandSize, devp->size) < 0) ||
+                                       (fclose(fp) < 0)) {
+                                       unlink(tmpname);
+                               }
+                       }
+               } else {
+                       warn("Cannot create backup bundle information file in %s", tmpname);
+               }
+               if ((snprintf(tmpname, tmplen + 1, "%s/bands", ctx.pathname) > tmplen) ||
+                       (mkdir(tmpname, 0777) == -1)) {
                        warn("cannot create bands directory in sparse bundle %s", ctx.pathname);
                        goto done;
                }
-               sprintf(tmpname, "%s/token", ctx.pathname);
-               close(open(tmpname, O_CREAT | O_TRUNC, 0666));
-       }
-
-       retval = malloc(sizeof(*retval));
-       if (retval == NULL) {
-               free(retval);
-               retval = NULL;
-               goto done;
+               if (snprintf(tmpname, tmplen + 1, "%s/token", ctx.pathname) <= tmplen) {
+                       close(open(tmpname, O_CREAT | O_TRUNC, 0666));
+               }
        }
-       retctx = malloc(sizeof(*retctx));
-       if (retctx) {
-               *retctx = ctx;
-               retctx->cfd = -1;
 
+       wrapper = malloc(sizeof(*wrapper));
+       if (wrapper) {
+               struct SparseBundleContext *wrapped_ctx;
+
+               wrapped_ctx = malloc(sizeof(*wrapped_ctx));
+               if (wrapped_ctx) {
+                       *wrapped_ctx = ctx;
+                       wrapped_ctx->cfd = -1;
+
+                       wrapper->writer = &WriteExtentToSparse;
+                       wrapper->reader = &doSparseRead;
+                       wrapper->getprog = &GetProgress;
+                       wrapper->setprog = &SetProgress;
+                       wrapper->cleanup = &doCleanup;
+                       wrapper->context = wrapped_ctx;
+               } else {
+                       free(wrapper);
+                       wrapper = NULL;
+               }
        }
-       retval->writer = &WriteExtentToSparse;
-       retval->reader = &doSparseRead;
-       retval->getprog = &GetProgress;
-       retval->setprog = &SetProgress;
-       retval->cleanup = &doCleanup;
-
-       retval->context = retctx;
 done:
-       if (retval == NULL) {
+       if (wrapper == NULL) {
                if (ctx.pathname)
                        free(ctx.pathname);
        }
-       return retval;
+
+       free(tmpname);
+       return wrapper;
 }
index d562d7f44737abcf51a6fd02bc954ebfe626ce93..0954cf8b45bc81a882fbac0c4736226e05bc7e89 100644 (file)
@@ -58,7 +58,7 @@ usage(const char *progname)
        errx(kBadExit, "usage: %s [-vdpS] [-g gatherFile] [-C] [-r <bytes>] <src device> <destination>", progname);
 }
 
-
+int
 main(int ac, char **av)
 {
        char *src = NULL;
@@ -66,7 +66,6 @@ main(int ac, char **av)
        DeviceInfo_t *devp = NULL;
        VolumeDescriptor_t *vdp = NULL;
        VolumeObjects_t *vop = NULL;
-       IOWrapper_t *wrapper = NULL;
        int ch;
        off_t restart = 0;
        int printEstimate = 0;
@@ -148,10 +147,12 @@ main(int ac, char **av)
         * If we're given a destination, initialize it.
         */
        if (dst) {
-               wrapper = InitSparseBundle(dst, devp);
-       }
+               IOWrapper_t *wrapper = InitSparseBundle(dst, devp);
+
+               if (wrapper == NULL) {
+                       err(kBadExit, "cannot initialize destination container %s", dst);
+               }
 
-       if (wrapper) {
                // See if we're picking up from a previous copy
                if (restart == 0) {
                        restart = wrapper->getprog(wrapper);
index d91f47956606a82483c6cd2fc3248244cd56b791..f726cd31e1220ae448ed097921c7d6be200aece6 100644 (file)
@@ -61,6 +61,7 @@
 #include <kern/locks.h>
 #include <vm/vm_kern.h>
 #include <sys/sysctl.h>
+#include <uuid/uuid.h>
 
 #include "../hfs_encodings/hfs_encodings.h"
 
@@ -95,7 +96,6 @@ struct cprotect;
 // multiple separate transactions)
 #define HFS_BIGFILE_SIZE (400LL * 1024LL * 1024LL)
 
-
 enum { kMDBSize = 512 };                               /* Size of I/O transfer to read entire MDB */
 
 enum { kMasterDirectoryBlock = 2 };                    /* MDB offset on disk in 512-byte blocks */
@@ -399,6 +399,9 @@ typedef struct hfsmount {
 
 #endif
 
+       /* the full UUID of the volume, not the one stored in finderinfo */
+       uuid_t           hfs_full_uuid;
+
        /* Per mount cnode hash variables: */
        lck_mtx_t      hfs_chash_mutex; /* protects access to cnode hash table */
        u_long         hfs_cnodehash;   /* size of cnode hash table - 1 */
@@ -430,21 +433,6 @@ typedef struct hfsmount {
        };
        // These lists are not sorted like a range list usually is
        struct rl_head hfs_reserved_ranges[2];
-
-       // cnode zone
-       struct cnode_zone {
-               int elem_size;
-               int chunk_size;
-               int alloc_count;
-               int gcd;
-               int y;
-               struct chunk_hdr **heap;
-               int heap_max_count, heap_count;
-               lck_mtx_t alloc_mtx;
-               bool allocating : 1;
-               bool waiting : 1;
-               struct chunk_hdr *spare;
-       } z;
 } hfsmount_t;
 
 /*
@@ -822,6 +810,9 @@ int hfs_truncatefs(struct hfsmount *hfsmp, u_int64_t newsize, vfs_context_t cont
 /*****************************************************************************
        Functions from hfs_vfsops.c
 ******************************************************************************/
+
+extern void hfs_getvoluuid(struct hfsmount *hfsmp, uuid_t result);
+
 /* used as a callback by the journaling code */
 extern void hfs_sync_metadata(void *arg);
 
@@ -993,6 +984,30 @@ int unicode_to_hfs(ExtendedVCB *vcb, ByteCount srcLen, u_int16_t* srcStr, Str31
 void *hfs_malloc(size_t size);
 void hfs_free(void *ptr, size_t size);
 void *hfs_mallocz(size_t size);
+
+typedef enum {
+       HFS_CNODE_ZONE,
+       HFS_FILEFORK_ZONE,
+       HFS_DIRHINT_ZONE,
+       HFS_NUM_ZONES
+} hfs_zone_kind_t;
+
+typedef struct hfs_zone_entry {
+       hfs_zone_kind_t hze_kind;
+       size_t                  hze_elem_size;
+       const char *    hze_name;
+       boolean_t               hze_noencrypt;
+} hfs_zone_entry_t;
+
+typedef struct hfs_zone {
+       zone_t hz_zone;
+       size_t hz_elem_size;
+} hfs_zone_t;
+
+void hfs_init_zones(void);
+void *hfs_zalloc(hfs_zone_kind_t type);
+void hfs_zfree(void *ptr, hfs_zone_kind_t type);
+
 void hfs_sysctl_register(void);
 void hfs_sysctl_unregister(void);
 
index a70d32e603dbd922ed558c320a567eb806df1018..8a2009baef9a1d51827625b2a807d5199c6fb094 100644 (file)
@@ -3038,7 +3038,6 @@ exit:
 }
 
 #define SMALL_DIRENTRY_SIZE  (int)(sizeof(struct dirent) - (MAXNAMLEN + 1) + 8)
-#define MAX_LINKINFO_ENTRIES 3000
 
 /*
  * Callback to pack directory entries.
@@ -3518,12 +3517,13 @@ cat_getdirentries(struct hfsmount *hfsmp, u_int32_t entrycnt, directoryhint_t *d
        }
        fcb = hfsmp->hfs_catalog_cp->c_datafork;
 
+       #define MAX_LINKINFO_ENTRIES 275
        /*
-        * Get a buffer for link info array, btree iterator and a direntry. 
-        * 
-        * We impose an cap of 3000 link entries when trying to compute
-        * the total number of hardlink entries that we'll allow in the  
-        * linkinfo array
+        * Get a buffer for link info array, btree iterator and a direntry.
+        *
+        * We impose an cap of 275 link entries when trying to compute
+        * the total number of hardlink entries that we'll allow in the
+        * linkinfo array, as this has been shown to noticeably impact performance.
         *
         * Note that in the case where there are very few hardlinks,
         * this does not restrict or prevent us from vending out as many entries
@@ -3532,8 +3532,11 @@ cat_getdirentries(struct hfsmount *hfsmp, u_int32_t entrycnt, directoryhint_t *d
         * this MALLOC'd array. It also limits itself to maxlinks of hardlinks.
         */
 
-       /* Now compute the maximum link array size */
-       maxlinks = MIN (entrycnt, MAX_LINKINFO_ENTRIES);
+       // This value cannot underflow: both entrycnt and the rhs are unsigned 32-bit
+       // ints, so the worst-case MIN of them is 0.
+       maxlinks = MIN (entrycnt, (u_int32_t)(uio_resid(uio) / SMALL_DIRENTRY_SIZE));
+       // Prevent overflow.
+       maxlinks = MIN (maxlinks, MAX_LINKINFO_ENTRIES);
        bufsize = MAXPATHLEN + (maxlinks * sizeof(linkinfo_t)) + sizeof(*iterator);     
        
        if (extended) {
index 5796f78c4d38842f13d8ad63a435cbb72824218b..5fe0bc34a84065c5a7dfe7591ba76d17957c3b5b 100644 (file)
@@ -81,13 +81,8 @@ lck_grp_t * chash_lck_grp;
 lck_grp_attr_t * chash_lck_grp_attr;
 lck_attr_t * chash_lck_attr;
 
-static cnode_t *hfs_cnode_alloc(hfsmount_t *hfsmp, bool *unlocked);
-
 #define CNODEHASH(hfsmp, inum) (&hfsmp->hfs_cnodehashtbl[(inum) & hfsmp->hfs_cnodehash])
 
-static void hfs_cnode_zone_init(hfsmount_t *hfsmp);
-static void hfs_cnode_zone_free(hfsmount_t *hfsmp);
-
 /*
  * Initialize cnode hash table.
  */
@@ -125,8 +120,6 @@ hfs_chashinit_finish(struct hfsmount *hfsmp)
        lck_mtx_init(&hfsmp->hfs_chash_mutex, chash_lck_grp, chash_lck_attr);
 
        hfsmp->hfs_cnodehashtbl = hashinit(desiredvnodes / 4, M_TEMP, &hfsmp->hfs_cnodehash);
-
-       hfs_cnode_zone_init(hfsmp);
 }
 
 void
@@ -135,8 +128,6 @@ hfs_delete_chash(struct hfsmount *hfsmp)
        lck_mtx_destroy(&hfsmp->hfs_chash_mutex, chash_lck_grp);
 
        FREE(hfsmp->hfs_cnodehashtbl, M_TEMP);
-
-       hfs_cnode_zone_free(hfsmp);
 }
 
 
@@ -347,7 +338,7 @@ loop_with_lock:
                         * this cnode and add it to the hash
                         * just dump our allocation
                         */
-                       hfs_cnode_free(hfsmp, ncp);
+                       hfs_zfree(ncp, HFS_CNODE_ZONE);
                        ncp = NULL;
                }
 
@@ -401,12 +392,17 @@ loop_with_lock:
                panic("%s - should never get here when skiplock is set \n", __FUNCTION__);
 
        if (ncp == NULL) {
-               bool unlocked;
-
-               ncp = hfs_cnode_alloc(hfsmp, &unlocked);
-
-               if (unlocked)
-                       goto loop_with_lock;
+               hfs_chash_unlock(hfsmp);
+               
+               ncp = hfs_zalloc(HFS_CNODE_ZONE);
+               
+               /*
+                * since we dropped the chash lock,
+                * we need to go back and re-verify
+                * that this node hasn't come into
+                * existence...
+                */
+               goto loop;
        }
        hfs_chash_lock_convert(hfsmp);
 
@@ -580,469 +576,3 @@ hfs_chash_set_childlinkbit(struct hfsmount *hfsmp, cnid_t cnid)
 
        return retval;
 }
-
-// -- Cnode Memory Allocation --
-
-/*
- * We allocate chunks but to minimise fragmentation, we store the
- * chunks in a heap ordered such that the chunk with the least number
- * of free elements is at the top.  At the end of each chunk we store
- * a pointer to a header somewhere within the chunk.  When all
- * elements in a chunk are in use, the pointer is NULL.  Given that
- * chunks will always be aligned to a page, we can compute the element
- * index in the chunk using this equation:
- *
- *             y * (uintptr_t)el % PAGE_SIZE / gcd % (PAGE_SIZE / gcd)
- *
- * where gcd is the greatest common divisor of elem_size and
- * PAGE_SIZE, (which we calculate using the Euclidean algorithm) and y
- * also falls out of the Euclidean algorithm -- see
- * hfs_cnode_zone_init below.  The proof for this is left as an
- * exercise for the reader.  Hint: start with the equation:
- *
- *      elem_ndx * elem_size = PAGE_SIZE * elem_pg + elem_addr % PAGE_SIZE
- *
- * Now realise that can be made to look like a Diophantine equation
- * (ax + by = c) which is solvable using the Extended Euclidean
- * algorithm and from there you will arrive at the equation above.
- */
-
-enum {
-       CHUNK_HDR_MAGIC         = 0x6b6e6863,                   // chnk
-       CNODE_MAGIC                     = 0x65646f6e63736668,   // hfscnode
-       ELEMENT_ALIGNMENT       = 8,
-
-       /*
-        * We store the pointer to the header for a chunk 8 bytes in from
-        * the end of the chunk.
-        */
-       CHUNK_TAIL_LEN          = 8,
-};
-
-typedef struct chunk_hdr
-{
-       void *next_free;
-       uint32_t magic;                                         // = CHUNK_HDR_MAGIC
-       uint16_t free_count;
-       uint16_t heap_ndx;
-       struct chunk_hdr **phdr;
-} chunk_hdr_t;
-
-static void hfs_cnode_zone_init(hfsmount_t *hfsmp)
-{
-       struct cnode_zone *z = &hfsmp->z;
-       
-       int elem_size = sizeof(cnode_t);
-
-       elem_size = roundup(elem_size, ELEMENT_ALIGNMENT);
-
-       z->elem_size = elem_size;
-
-       // Figure out chunk_size
-       int npages, chunk_size, waste;
-       
-       for (npages = 1;; ++npages) {
-               chunk_size = npages * page_size;
-               waste = (chunk_size - CHUNK_TAIL_LEN) % elem_size;
-
-               // If waste is less than 1%, that's good enough
-               if (waste < chunk_size / 100)
-                       break;
-       }
-
-       z->chunk_size = chunk_size;
-       z->alloc_count = (chunk_size - CHUNK_TAIL_LEN) / elem_size;
-
-       // Compute the GCD of elem_size and page_size using Euclidean algorithm
-       int t = 1, last_t = 0, r = z->elem_size, last_r = PAGE_SIZE;
-
-       while (r != 0) {
-               int q = last_r / r;
-               int next_r = last_r - q * r;
-               last_r = r;
-               r = next_r;
-               int next_t = last_t - q * t;
-               last_t = t;
-               t = next_t;
-       }
-
-       z->gcd = last_r;
-       z->y = last_t;
-
-       z->heap_max_count = 128 / sizeof(void *);
-       z->heap = hfs_malloc(z->heap_max_count * sizeof(void *));
-
-#if DEBUG
-       printf("hfs: cnode size %d, chunk size %d, # per chunk %d, waste %d\n",
-                  elem_size, chunk_size, z->alloc_count, waste);
-#endif
-}
-
-static void hfs_cnode_zone_free(hfsmount_t *hfsmp)
-{
-       // Check that all heap chunks are completely free
-       struct cnode_zone *z = &hfsmp->z;
-
-       for (int i = 0; i < z->heap_count; ++i) {
-#if DEBUG
-               hfs_assert(z->heap[i]->free_count == z->alloc_count);
-#else
-               if (z->heap[i]->free_count != z->alloc_count) {
-                       printf("hfs: cnodes leaked!\n");
-                       continue;
-               }
-#endif
-               void *chunk = (void *)((uintptr_t)z->heap[i]->phdr
-                                                          - (z->chunk_size - CHUNK_TAIL_LEN));
-               hfs_free(chunk, z->chunk_size);
-       }
-
-       hfs_free(z->heap, z->heap_max_count * sizeof(void *));
-}
-
-static void *zel(struct cnode_zone *z, void *chunk, int i)
-{
-       return chunk + i * z->elem_size;
-}
-
-static chunk_hdr_t **zphdr(struct cnode_zone *z, void *chunk)
-{
-       return chunk + z->chunk_size - CHUNK_TAIL_LEN;
-}
-
-#if 0
-static void hfs_check_heap(hfsmount_t *hfsmp, void *just_removed)
-{
-       struct cnode_zone *z = &hfsmp->z;
-       
-       for (int i = 0; i < z->heap_count; ++i) {
-               hfs_assert(z->heap[i]->magic == CHUNK_HDR_MAGIC);
-               hfs_assert(z->heap[i]->free_count > 0
-                          && z->heap[i]->free_count <= z->alloc_count);
-               hfs_assert(z->heap[i]->heap_ndx == i);
-               void *max_el = z->heap[i]->phdr;
-               void *min_el = (void *)((uintptr_t)z->heap[i]->phdr
-                                                               + CHUNK_TAIL_LEN - z->chunk_size);
-               int count = 1;
-               hfs_assert(z->heap[i] != just_removed);
-               void *el = z->heap[i]->next_free;
-               size_t bitmap_size = (z->alloc_count + 7) / 8;
-               uint8_t bitmap[bitmap_size];
-               bzero(bitmap, bitmap_size);
-               int ndx = (int)((void *)z->heap[i] - min_el) / z->elem_size;
-               bitmap[ndx / 8] |= 0x80 >> ndx % 8;
-               while (el) {
-                       hfs_assert(el != just_removed);
-                       hfs_assert(el >= min_el
-                                  && el < max_el && (el - min_el) % z->elem_size == 0);
-                       int n = (int)(el - min_el) / z->elem_size;
-                       hfs_assert(!(bitmap[n / 8] & (0x80 >> n % 8)));
-                       bitmap[n / 8] |= 0x80 >> n % 8;
-                       el = *(void **)el;
-                       ++count;
-               }
-               hfs_assert(count == z->heap[i]->free_count);
-               if (i)
-                       hfs_assert(z->heap[(i + 1) / 2 - 1]->free_count <= z->heap[i]->free_count);
-       }
-}
-#else
-#define hfs_check_heap(a, b)   (void)0
-#endif
-
-static void hfs_cnode_set_magic(cnode_t *cp, uint64_t v)
-{
-#if HFS_MALLOC_DEBUG
-       cp->magic = v;
-#endif
-}
-
-static cnode_t *hfs_cnode_alloc(hfsmount_t *hfsmp, bool *unlocked)
-{
-       hfs_check_heap(hfsmp, NULL);
-
-       *unlocked = false;
-
-       struct cnode_zone *z = &hfsmp->z;
-       void *el;
-
-       while (!z->heap_count) {
-               if (z->spare) {
-                       /*
-                        * We have a spare chunk we can use so initialise it, add
-                        * it to the heap and return one element from it.
-                        */
-                       chunk_hdr_t *chunk_hdr = z->spare;
-                       z->spare = NULL;
-                       void *last = NULL;
-                       for (int i = z->alloc_count - 2; i > 0; --i) {
-                               void *p = zel(z, chunk_hdr, i);
-                               *(void **)p = last;
-                               hfs_cnode_set_magic(p, 0);
-                               last = p;
-                       }
-                       hfs_cnode_set_magic((void *)chunk_hdr, 0);
-                       chunk_hdr->phdr = zphdr(z, chunk_hdr);
-                       chunk_hdr->next_free = last;
-                       chunk_hdr->free_count = z->alloc_count - 1;
-                       chunk_hdr->heap_ndx = 0;
-                       // Set the tail to the index of the chunk_hdr
-                       *zphdr(z, chunk_hdr) = chunk_hdr;
-                       z->heap[0] = chunk_hdr;
-                       z->heap_count = 1;
-                       el = zel(z, chunk_hdr, z->alloc_count - 1);
-                       hfs_cnode_set_magic(el, 0);
-                       goto exit;
-               }
-
-               *unlocked = true;
-
-               if (z->allocating) {
-                       z->waiting = true;
-                       msleep(z, &hfsmp->hfs_chash_mutex, PINOD | PSPIN,
-                                  "hfs_cnode_alloc", NULL);
-               } else {
-                       z->allocating = true;
-                       lck_mtx_unlock(&hfsmp->hfs_chash_mutex);
-                       chunk_hdr_t *chunk_hdr = hfs_malloc(z->chunk_size);
-                       chunk_hdr->magic = CHUNK_HDR_MAGIC;
-                       hfs_assert(!((uintptr_t)chunk_hdr & PAGE_MASK));
-                       lck_mtx_lock_spin(&hfsmp->hfs_chash_mutex);
-                       z->allocating = false;
-                       if (z->waiting) {
-                               wakeup(z);
-                               z->waiting = false;
-                       }
-                       hfs_assert(!z->spare);
-                       z->spare = chunk_hdr;
-               }
-       }
-
-       chunk_hdr_t *chunk_hdr = z->heap[0];
-       if (chunk_hdr->next_free) {
-               /*
-                * Not the last element in this chunk, so just pull an element
-                * off and return it.  This chunk should remain at the top of
-                * the heap.
-                */
-               el = chunk_hdr->next_free;
-               chunk_hdr->next_free = *(void **)chunk_hdr->next_free;
-               --chunk_hdr->free_count;
-               
-               goto exit;
-       }
-
-       /*
-        * This is the last element in the chunk so we need to fix up the
-        * heap.
-        */
-       el = chunk_hdr;
-
-       *chunk_hdr->phdr = NULL;
-       chunk_hdr->magic = ~CHUNK_HDR_MAGIC;
-
-       if (!--z->heap_count)
-               goto exit;
-
-       chunk_hdr_t *v = z->heap[z->heap_count];
-
-       // Fix heap downwards; offset by one to make easier
-       int k = 1;
-       chunk_hdr_t **a = &z->heap[0] - 1;
-       int N = z->heap_count;
-       
-       for (;;) {
-               // Look at the next level down
-               int j = k * 2;
-               if (j > N)
-                       break;
-               // Pick the smaller of the two that we're looking at
-               if (j < N && a[j]->free_count > a[j+1]->free_count)
-                       ++j;
-               if (v->free_count <= a[j]->free_count)
-                       break;
-               // Shift element at j to k
-               a[k] = a[j];
-               a[k]->heap_ndx = k - 1;
-               
-               // Descend
-               k = j;
-       }
-       
-       a[k] = v;
-       a[k]->heap_ndx = k - 1;
-       
-exit:
-       
-       hfs_check_heap(hfsmp, el);
-
-#if HFS_MALLOC_DEBUG
-       if (((cnode_t *)el)->magic == CNODE_MAGIC) {
-#if __x86_64__
-               asm("int $3\n");
-#elif __arm64__
-               asm("svc 0\n");
-#else
-               asm("trap\n");
-#endif
-       }
-#endif // HFS_MALLOC_DEBUG
-
-       hfs_cnode_set_magic(el, CNODE_MAGIC);
-
-       return el;
-}
-
-void hfs_cnode_free(hfsmount_t *hfsmp, cnode_t *cp)
-{
-       void *el = cp;
-       void *old_heap = NULL;
-       size_t old_heap_size = 0;
-       struct cnode_zone *z = &hfsmp->z;
-
-       int ndx_in_chunk = (z->y * (uintptr_t)el % PAGE_SIZE
-                                               / z->gcd % (PAGE_SIZE / z->gcd));
-
-       void *free_chunk = NULL, *chunk = el - ndx_in_chunk * z->elem_size;
-
-       lck_mtx_lock_spin(&hfsmp->hfs_chash_mutex);
-
-#if HFS_MALLOC_DEBUG
-       hfs_assert(cp->magic == CNODE_MAGIC);
-       cp->magic = ~CNODE_MAGIC;
-#endif
-
-loop:
-       
-       hfs_check_heap(hfsmp, NULL);
-
-       chunk_hdr_t *hdr = *zphdr(z, chunk);
-
-       int k, orig_k;
-
-       if (hdr) {
-               /*
-                * This chunk already has some free elements in it so we chain this
-                * element on and then fix up the heap.
-                */
-               hfs_assert(hdr->magic == CHUNK_HDR_MAGIC);
-
-               *(void **)el = hdr->next_free;
-               hdr->next_free = el;
-               hfs_assert(hdr->next_free != hdr);
-               
-               chunk_hdr_t *v;
-               orig_k = k = hdr->heap_ndx + 1;
-               
-               chunk_hdr_t **a = &z->heap[0] - 1;
-               
-               if (++hdr->free_count == z->alloc_count) {
-                       // Chunk is totally free
-
-                       // Always keep at least one chunk on the heap
-                       if (z->heap_count == 1)
-                               goto exit;
-
-                       // Remove the chunk
-                       free_chunk = chunk;
-                       --z->heap_count;
-                       v = z->heap[z->heap_count];
-                       
-                       if (k > 1 && a[k / 2]->free_count > v->free_count) {
-                               do {
-                                       a[k] = a[k / 2];
-                                       a[k]->heap_ndx = k - 1;
-                                       k = k / 2;
-                               } while (k > 1 && a[k / 2]->free_count > v->free_count);
-                               a[k] = v;
-                               a[k]->heap_ndx = k - 1;
-                               goto exit;
-                       }
-               } else
-                       v = hdr;
-
-               // Fix up the heap
-               int N = z->heap_count;
-
-               for (;;) {
-                       // Look at the next level down
-                       int j = k * 2;
-                       if (j > N)
-                               break;
-                       // Pick the smaller of the two that we're looking at
-                       if (j < N && a[j]->free_count > a[j+1]->free_count)
-                               ++j;
-                       if (v->free_count <= a[j]->free_count)
-                               break;
-                       // Shift element at j to k
-                       a[k] = a[j];
-                       a[k]->heap_ndx = k - 1;
-                       
-                       // Descend
-                       k = j;
-               }
-               
-               a[k] = v;
-               a[k]->heap_ndx = k - 1;
-       } else {
-               // This element is the first that's free in this chunk
-
-               if (z->heap_count == z->heap_max_count) {
-                       // We need to resize the heap
-                       int new_max_count = z->heap_max_count * 2;
-                       lck_mtx_unlock(&hfsmp->hfs_chash_mutex);
-                       if (old_heap)
-                               hfs_free(old_heap, old_heap_size);
-                       struct chunk_hdr **new_heap = hfs_malloc(new_max_count * sizeof(void *));
-                       lck_mtx_lock_spin(&hfsmp->hfs_chash_mutex);
-                       // Check to see if someone beat us to it
-                       if (new_max_count > z->heap_max_count) {
-                               memcpy(new_heap, z->heap, z->heap_count * sizeof(void *));
-                               old_heap_size = z->heap_max_count * sizeof(void *);
-                               z->heap_max_count = new_max_count;
-                               old_heap = z->heap;
-                               z->heap = new_heap;
-                       } else {
-                               old_heap = new_heap;
-                               old_heap_size = new_max_count * sizeof(void *);
-                       }
-                       // Lock was dropped so we have to go around again
-                       goto loop;
-               }
-
-               hdr = (chunk_hdr_t *)el;
-               *zphdr(z, chunk) = hdr;
-               hdr->free_count = 1;
-               hdr->next_free = NULL;
-               hdr->heap_ndx = 0;
-               hdr->phdr = zphdr(z, chunk);
-               hdr->magic = CHUNK_HDR_MAGIC;
-
-               // Fix heap upwards; offset by one to make easier
-               chunk_hdr_t **a = &z->heap[0] - 1;
-
-               if (z->heap_count++) {
-                       k = z->heap_count;
-                       chunk_hdr_t *v = z->heap[0];
-                       while (k > 3 && a[k / 2]->free_count > v->free_count) {
-                               a[k] = a[k / 2];
-                               a[k]->heap_ndx = k - 1;
-                               k = k / 2;
-                       }
-                       a[k] = v;
-                       a[k]->heap_ndx = k - 1;
-               }
-
-               z->heap[0] = hdr;
-       }
-
-exit:
-
-       hfs_check_heap(hfsmp, NULL);
-       lck_mtx_unlock(&hfsmp->hfs_chash_mutex);
-
-       if (old_heap)
-               hfs_free(old_heap, old_heap_size);
-       if (free_chunk)
-               hfs_free(free_chunk, z->chunk_size);
-}
index 84520fb9d5357a8bb2981cf5c9a7c0eaf323e0f8..12b126cd45809363bc02862bde7b7437873b2a70 100644 (file)
@@ -806,7 +806,7 @@ hfs_vnop_reclaim(struct vnop_reclaim_args *ap)
                        hfs_free(fp->ff_symlinkptr, fp->ff_size);
                }
                rl_remove_all(&fp->ff_invalidranges);
-               hfs_free(fp, sizeof(struct filefork));
+               hfs_zfree(fp, HFS_FILEFORK_ZONE);
        }
 
        /* 
@@ -938,8 +938,12 @@ hfs_getnewvnode(
        issystemfile = (descp->cd_flags & CD_ISMETA) && (vtype == VREG);
        wantrsrc = flags & GNV_WANTRSRC;
 
-       /* Sanity check the vtype and mode */
-       if (vtype == VBAD) {
+       /* Sanity checks: */
+       if (vtype == VBAD ||
+               (vtype != VDIR && forkp &&
+                       (attrp->ca_blocks < forkp->cf_blocks ||
+                        howmany((uint64_t)forkp->cf_size, hfsmp->blockSize) > forkp->cf_blocks ||
+                        (vtype == VLNK && (uint64_t)forkp->cf_size > MAXPATHLEN)))) {
                /* Mark the FS as corrupt and bail out */
                hfs_mark_inconsistent(hfsmp, HFS_INCONSISTENCY_DETECTED);
                retval = EINVAL;
@@ -1215,12 +1219,10 @@ hfs_getnewvnode(
                        panic("hfs_getnewvnode: orphaned vnode (data)");
                cvpp = &cp->c_vp;
        } else {
-               if (forkp && attrp->ca_blocks < forkp->cf_blocks)
-                       panic("hfs_getnewvnode: bad ca_blocks (too small)");
                /*
                 * Allocate and initialize a file fork...
                 */
-               fp = hfs_malloc(sizeof(struct filefork));
+               fp = hfs_zalloc(HFS_FILEFORK_ZONE);
                fp->ff_cp = cp;
                if (forkp)
                        bcopy(forkp, &fp->ff_data, sizeof(struct cat_fork));
@@ -1381,7 +1383,7 @@ hfs_getnewvnode(
                        else
                                cp->c_rsrcfork = NULL;
 
-                       hfs_free(fp, sizeof(struct filefork));
+                       hfs_zfree(fp, HFS_FILEFORK_ZONE);
                }
                /*
                 * If this is a newly created cnode or a vnode reclaim
@@ -1524,7 +1526,7 @@ hfs_reclaim_cnode(hfsmount_t *hfsmp, struct cnode *cp)
        (void)hfsmp;    // Prevent compiler warning
 #endif
 
-       hfs_cnode_free(hfsmp, cp);
+       hfs_zfree(cp, HFS_CNODE_ZONE);
 }
 
 
index e6a83aa46a3878ebce9eef4134c33411f0e58211..dd426b8a7d4ae5dd7b0b891f1311f14dcaa88efa 100644 (file)
@@ -468,8 +468,6 @@ extern int hfs_valid_cnode(struct hfsmount *hfsmp, struct vnode *dvp, struct com
 
 extern int hfs_chash_set_childlinkbit(struct hfsmount *hfsmp, cnid_t cnid);
 
-void hfs_cnode_free(struct hfsmount *hfsmp, cnode_t *cp);
-
 /*
  * HFS cnode lock functions.
  *
index bc1b2c3bab718a70d492fc05feeb1bc94308650f..3fa485b27e8e8d4405c2eff8d27798ac5243588f 100644 (file)
@@ -38,6 +38,7 @@
 #include <sys/kauth.h>
 #include <sys/sysctl.h>
 #include <sys/ubc.h>
+#include <uuid/uuid.h>
 
 #include "hfs.h"
 #include "hfs_cnode.h"
@@ -2499,19 +2500,37 @@ cpnew_fail:
        return error;
 }
 
+
 /* Initialize the aks_cred_t structure passed to AKS */
 static void cp_init_access(aks_cred_t access, struct cnode *cp)
 {
        vfs_context_t context = vfs_context_current();
        kauth_cred_t cred = vfs_context_ucred(context);
        proc_t proc = vfs_context_proc(context);
+       struct hfsmount *hfsmp;
+       struct vnode *vp;
+       uuid_t hfs_uuid;
 
        bzero(access, sizeof(*access));
 
+       vp = CTOV(cp, 0);
+       if (vp == NULL) {
+               /* is it a rsrc */
+               vp = CTOV(cp,1);
+               if (vp == NULL) {
+                       //leave the struct bzeroed. 
+                       return;
+               }
+       }
+
+       hfsmp = VTOHFS(vp);
+       hfs_getvoluuid(hfsmp, hfs_uuid);
+
        /* Note: HFS uses 32-bit fileID, even though inode is a 64-bit value */
        access->inode = cp->c_fileid;
        access->pid = proc_pid(proc);
        access->uid = kauth_cred_getuid(cred);
+       uuid_copy (access->volume_uuid, hfs_uuid);      
 
        if (cp->c_cpentry)
                access->key_revision = cp->c_cpentry->cp_key_revision;
index 22b716fef769b4ff0c5ff3b843fc06a4a823bef8..bdc9c7a0fb5b361fddfd7356bffa49373f088963 100644 (file)
@@ -204,7 +204,8 @@ hfs_swap_BTNode (
                            (allow_empty_node == false) && (srcOffs[i] == 0)) ||
                                (srcOffs[i] < sizeof(BTNodeDescriptor) && srcOffs[i] != 0) || 
                                (srcOffs[i] > (src->blockSize - 2 * (srcDesc->numRecords + 1)))) {
-               printf("hfs_swap_BTNode: record #%d invalid offset (0x%04X)\n", srcDesc->numRecords-i-1, srcOffs[i]);
+               printf("hfs_swap_BTNode: offset #%d invalid (0x%04X) (blockSize 0x%x numRecords %d)\n",
+                                          i, srcOffs[i], src->blockSize, srcDesc->numRecords);
                error = fsBTInvalidHeaderErr;
                goto fail;
             }
@@ -215,7 +216,7 @@ hfs_swap_BTNode (
              */
             if ((i != 0) && (srcOffs[i] >= srcOffs[i-1])) {
                printf("hfs_swap_BTNode: offsets %d and %d out of order (0x%04X, 0x%04X)\n",
-                   srcDesc->numRecords-i-1, srcDesc->numRecords-i, srcOffs[i], srcOffs[i-1]);
+                   i, i-1, srcOffs[i], srcOffs[i-1]);
                error = fsBTInvalidHeaderErr;
                goto fail;
             }
@@ -359,7 +360,8 @@ hfs_swap_BTNode (
                            ((allow_empty_node == false) && (srcOffs[i] == 0)) ||
                                (srcOffs[i] < sizeof(BTNodeDescriptor) && srcOffs[i] != 0) || 
                                (srcOffs[i] > (src->blockSize - 2 * (srcDesc->numRecords + 1)))) {
-               panic("hfs_UNswap_BTNode: record #%d invalid offset (0x%04X)\n", srcDesc->numRecords-i-1, srcOffs[i]);
+               panic("hfs_UNswap_BTNode: offset #%d invalid (0x%04X) (blockSize 0x%x numRecords %d)\n",
+                                         i, srcOffs[i], src->blockSize, srcDesc->numRecords);
                error = fsBTInvalidHeaderErr;
                goto fail;
             }
@@ -370,7 +372,7 @@ hfs_swap_BTNode (
              */
             if ((i < srcDesc->numRecords) && (srcOffs[i+1] >= srcOffs[i])) {
                panic("hfs_UNswap_BTNode: offsets %d and %d out of order (0x%04X, 0x%04X)\n",
-                   srcDesc->numRecords-i-2, srcDesc->numRecords-i-1, srcOffs[i+1], srcOffs[i]);
+                   i+1, i, srcOffs[i+1], srcOffs[i]);
                error = fsBTInvalidHeaderErr;
                goto fail;
             }
index ac9a43df100d0be08a1d14301dfe21c92b5c53b5..5908364c1c778d8667679cc1a8ce9de59d791452 100644 (file)
@@ -118,6 +118,8 @@ bool com_apple_filesystems_hfs::start(IOService *provider)
                return false;
        }
 
+       hfs_init_zones();
+       
        hfs_sysctl_register();
 
        return true;
index f3a0827940638fa22ac772ed065ef023ed5c1d28..879fe0a0c6bf161b19bd9bf1000f90c12364f114 100644 (file)
@@ -49,6 +49,7 @@
 #include <sys/fsctl.h>
 #include <sys/ubc.h>
 #include <sys/fsevents.h>
+#include <uuid/uuid.h>
 
 #include <libkern/OSDebug.h>
 
@@ -2530,6 +2531,8 @@ fail_change_next_allocation:
                }
                hfs_lock_mount (hfsmp);
                bcopy(ap->a_data, &hfsmp->vcbFndrInfo, sizeof(hfsmp->vcbFndrInfo));
+               /* Null out the cached UUID, to be safe */
+               uuid_clear (hfsmp->hfs_full_uuid);
                hfs_unlock_mount (hfsmp);
                (void) hfs_flushvolumeheader(hfsmp, HFS_FVH_WAIT);
                break;
index 7144459d25f87bcee772a3d2fa4fb672e4c2a05b..10e5f533aa154aa1434378fe81c14e74ec87d29c 100644 (file)
@@ -479,6 +479,10 @@ hfs_mount(struct mount *mp, vnode_t devvp, user_addr_t data, vfs_context_t conte
                }
 
        } else /* not an update request */ {
+               if (devvp == NULL) {
+                       retval = EINVAL;
+                       goto out;
+               }
                /* Set the mount flag to indicate that we support volfs  */
                vfs_setflags(mp, (u_int64_t)((unsigned int)MNT_DOVOLFS));
 
@@ -4190,22 +4194,31 @@ err_exit:
  * Creates a UUID from a unique "name" in the HFS UUID Name space.
  * See version 3 UUID.
  */
-static void
-hfs_getvoluuid(struct hfsmount *hfsmp, uuid_t result)
+void
+hfs_getvoluuid(struct hfsmount *hfsmp, uuid_t result_uuid)
 {
-       MD5_CTX  md5c;
-       uint8_t  rawUUID[8];
 
-       ((uint32_t *)rawUUID)[0] = hfsmp->vcbFndrInfo[6];
-       ((uint32_t *)rawUUID)[1] = hfsmp->vcbFndrInfo[7];
+       if (uuid_is_null(hfsmp->hfs_full_uuid)) {
+               uuid_t result;
 
-       MD5Init( &md5c );
-       MD5Update( &md5c, HFS_UUID_NAMESPACE_ID, sizeof( uuid_t ) );
-       MD5Update( &md5c, rawUUID, sizeof (rawUUID) );
-       MD5Final( result, &md5c );
+               MD5_CTX  md5c;
+               uint8_t  rawUUID[8];
+
+               ((uint32_t *)rawUUID)[0] = hfsmp->vcbFndrInfo[6];
+               ((uint32_t *)rawUUID)[1] = hfsmp->vcbFndrInfo[7];
+
+               MD5Init( &md5c );
+               MD5Update( &md5c, HFS_UUID_NAMESPACE_ID, sizeof( uuid_t ) );
+               MD5Update( &md5c, rawUUID, sizeof (rawUUID) );
+               MD5Final( result, &md5c );
+
+               result[6] = 0x30 | ( result[6] & 0x0F );
+               result[8] = 0x80 | ( result[8] & 0x3F );
+       
+               uuid_copy(hfsmp->hfs_full_uuid, result);
+       }
+       uuid_copy (result_uuid, hfsmp->hfs_full_uuid);
 
-       result[6] = 0x30 | ( result[6] & 0x0F );
-       result[8] = 0x80 | ( result[8] & 0x3F );
 }
 
 /*
index 0e73c58e7756c15a0049119310b145bbe527a619..e841c412b19898a25ffa98192ee94e420d43d9d5 100644 (file)
@@ -57,6 +57,7 @@
 /* for parsing boot-args */
 #include <pexpert/pexpert.h>
 #include <kern/kalloc.h>
+#include <kern/zalloc.h>
 
 #include "hfs_iokit.h"
 #include "hfs.h"
@@ -815,7 +816,14 @@ OSErr hfs_MountHFSPlusVolume(struct hfsmount *hfsmp, HFSPlusVolumeHeader *vhp,
        /* reset retval == 0. we don't care about errors in volname conversion */
        retval = 0;
 
-       
+       /* 
+        * pull in the volume UUID while we are still single-threaded.
+        * This brings the volume UUID into the cached one dangling off of the HFSMP
+        * Otherwise it would have to be computed on first access.
+        */
+       uuid_t throwaway;
+       hfs_getvoluuid (hfsmp, throwaway); 
+
        /* 
         * We now always initiate a full bitmap scan even if the volume is read-only because this is 
         * our only shot to do I/Os of dramaticallly different sizes than what the buffer cache ordinarily
@@ -2323,7 +2331,7 @@ hfs_getdirhint(struct cnode *dcp, int index, int detach)
                need_init = true;
                if (dcp->c_dirhintcnt < HFS_MAXDIRHINTS) { /* we don't need recycling */
                        /* Create a default directory hint */
-                       hint = hfs_malloc(sizeof(directoryhint_t));
+                       hint = hfs_zalloc(HFS_DIRHINT_ZONE);
                        ++dcp->c_dirhintcnt;
                        need_remove = false;
                } else {                                /* recycle the last (i.e., the oldest) hint */
@@ -2387,7 +2395,7 @@ hfs_reldirhint(struct cnode *dcp, directoryhint_t * relhint)
                relhint->dh_desc.cd_flags &= ~CD_HASBUF;
                vfs_removename((const char *)name);
        }
-       hfs_free(relhint, sizeof(*relhint));
+       hfs_zfree(relhint, HFS_DIRHINT_ZONE);
 }
 
 /*
@@ -2418,7 +2426,7 @@ hfs_reldirhints(struct cnode *dcp, int stale_hints_only)
                }
                prev = TAILQ_PREV(hint, hfs_hinthead, dh_link); /* must save this pointer before calling FREE_ZONE on this node */
                TAILQ_REMOVE(&dcp->c_hintlist, hint, dh_link);
-               hfs_free(hint, sizeof(*hint));
+               hfs_zfree(hint, HFS_DIRHINT_ZONE);
                --dcp->c_dirhintcnt;
        }
 }
@@ -4251,7 +4259,6 @@ bool hfs_dump_allocations(void)
 HFS_SYSCTL(QUAD, _vfs_generic_hfs, OID_AUTO, allocated,
                   CTLFLAG_RD | CTLFLAG_LOCKED, &hfs_allocated, "Memory allocated")
 
-// Any allocation >= PAGE_SIZE will be page aligned
 void *hfs_malloc(size_t size)
 {
 #if HFS_MALLOC_DEBUG
@@ -4260,11 +4267,7 @@ void *hfs_malloc(size_t size)
        struct alloc_debug_header *hdr;
 
        void *ptr;
-
-       if (size >= PAGE_SIZE)
-               ptr = IOMallocAligned(size + sizeof(*hdr), PAGE_SIZE);
-       else
-               ptr = kalloc(size + sizeof(*hdr));
+       ptr = kalloc(size + sizeof(*hdr));
 
        hdr = ptr + size;
 
@@ -4281,10 +4284,7 @@ void *hfs_malloc(size_t size)
                hdr->chain.le_prev = NULL;
 #else
        void *ptr;
-       if (size >= PAGE_SIZE)
-               ptr = IOMallocAligned(size, PAGE_SIZE);
-       else
-               ptr = kalloc(size);
+       ptr = kalloc(size);
 #endif
 
        OSAddAtomic64(size, &hfs_allocated);
@@ -4313,15 +4313,9 @@ void hfs_free(void *ptr, size_t size)
                lck_mtx_unlock(hfs_alloc_mtx);
        }
 
-       if (size >= PAGE_SIZE)
-               IOFreeAligned(ptr, size + sizeof(*hdr));
-       else
-               kfree(ptr, size + sizeof(*hdr));
+       kfree(ptr, size + sizeof(*hdr));
 #else
-       if (size >= PAGE_SIZE)
-               IOFreeAligned(ptr, size);
-       else
-               kfree(ptr, size);
+       kfree(ptr, size);
 #endif
 }
 
@@ -4332,6 +4326,41 @@ void *hfs_mallocz(size_t size)
        return ptr;
 }
 
+// -- Zone allocator-related structures and routines --
+
+hfs_zone_entry_t hfs_zone_entries[HFS_NUM_ZONES] = {
+       { HFS_CNODE_ZONE, sizeof(struct cnode), "HFS node", true },
+       { HFS_FILEFORK_ZONE, sizeof(struct filefork), "HFS fork", true },
+       { HFS_DIRHINT_ZONE, sizeof(struct directoryhint), "HFS dirhint", true }
+};
+
+hfs_zone_t hfs_zones[HFS_NUM_ZONES];
+
+void hfs_init_zones(void) {
+       for (int i = 0; i < HFS_NUM_ZONES; i++) {
+               hfs_zones[i].hz_zone = zinit(hfs_zone_entries[i].hze_elem_size, 1024 * 1024, PAGE_SIZE, hfs_zone_entries[i].hze_name);
+               hfs_zones[i].hz_elem_size = hfs_zone_entries[i].hze_elem_size;
+               
+               zone_change(hfs_zones[i].hz_zone, Z_CALLERACCT, false);
+               if (hfs_zone_entries[i].hze_noencrypt)
+                       zone_change(hfs_zones[i].hz_zone, Z_NOENCRYPT, true);
+       }
+}
+
+void *hfs_zalloc(hfs_zone_kind_t zone)
+{
+       OSAddAtomic64(hfs_zones[zone].hz_elem_size, &hfs_allocated);
+       
+       return zalloc(hfs_zones[zone].hz_zone);
+}
+
+void hfs_zfree(void *ptr, hfs_zone_kind_t zone)
+{
+       OSAddAtomic64(-(int64_t)hfs_zones[zone].hz_elem_size, &hfs_allocated);
+       
+       zfree(hfs_zones[zone].hz_zone, ptr);
+}
+
 struct hfs_sysctl_chain *sysctl_list;
 
 void hfs_sysctl_register(void)
index 2eae260c8e08f807a7647384fb40406c22b4655c..316a657d88bb2793b19e7935a43bafad4c72bd91 100644 (file)
@@ -1334,7 +1334,15 @@ hfs_vnop_setattr(struct vnop_setattr_args *ap)
         * NOTE: HFS COMPRESSION depends on the data_size being set *before* the bsd flags are updated
         */
        VATTR_SET_SUPPORTED(vap, va_data_size);
-       if (VATTR_IS_ACTIVE(vap, va_data_size) && !vnode_islnk(vp)) {
+       if (VATTR_IS_ACTIVE(vap, va_data_size)) {
+               if (!vnode_isreg(vp)) {
+                       if (vnode_isdir(vp)) {
+                               return EISDIR;
+                       }
+                       //otherwise return EINVAL
+                       return EINVAL;
+               }
+
 #if HFS_COMPRESSION
                /* keep the compressed state locked until we're done truncating the file */
                decmpfs_cnode *dp = VTOCMP(vp);
@@ -3874,7 +3882,8 @@ hfs_removefile(struct vnode *dvp, struct vnode *vp, struct componentname *cnp,
                         * The resource fork vnode & filefork did not exist.
                         * Create a temporary one for use in this function only. 
                         */
-                       temp_rsrc_fork = hfs_mallocz(sizeof(struct filefork));
+                       temp_rsrc_fork = hfs_zalloc(HFS_FILEFORK_ZONE);
+                       bzero(temp_rsrc_fork, sizeof(struct filefork));
                        temp_rsrc_fork->ff_cp = cp;
                        rl_init(&temp_rsrc_fork->ff_invalidranges);
                }       
@@ -3886,7 +3895,7 @@ hfs_removefile(struct vnode *dvp, struct vnode *vp, struct componentname *cnp,
                        error = cat_lookup (hfsmp, &desc, 1, 0, (struct cat_desc*) NULL, 
                                        (struct cat_attr*) NULL, &temp_rsrc_fork->ff_data, NULL);
                        if (error) {
-                               hfs_free(temp_rsrc_fork, sizeof(struct filefork));
+                               hfs_zfree(temp_rsrc_fork, HFS_FILEFORK_ZONE);
                                hfs_systemfile_unlock (hfsmp, lockflags);
                                goto out;
                        }
@@ -3895,7 +3904,7 @@ hfs_removefile(struct vnode *dvp, struct vnode *vp, struct componentname *cnp,
                if (!skip_reserve) {
                        if ((error = cat_preflight(hfsmp, CAT_DELETE, NULL, 0))) {
                                if (temp_rsrc_fork) {
-                                       hfs_free(temp_rsrc_fork, sizeof(struct filefork));
+                                       hfs_zfree(temp_rsrc_fork, HFS_FILEFORK_ZONE);
                                }
                                hfs_systemfile_unlock(hfsmp, lockflags);
                                goto out;
@@ -3924,7 +3933,7 @@ hfs_removefile(struct vnode *dvp, struct vnode *vp, struct componentname *cnp,
 
                if (error) {
                        if (temp_rsrc_fork) {
-                               hfs_free(temp_rsrc_fork, sizeof(struct filefork));
+                               hfs_zfree(temp_rsrc_fork, HFS_FILEFORK_ZONE);
                        }
                        goto out;
                }
@@ -3997,7 +4006,7 @@ hfs_removefile(struct vnode *dvp, struct vnode *vp, struct componentname *cnp,
 
                /* Get rid of the temporary rsrc fork */
                if (temp_rsrc_fork) {
-                       hfs_free(temp_rsrc_fork, sizeof(struct filefork));
+                       hfs_zfree(temp_rsrc_fork, HFS_FILEFORK_ZONE);
                }
 
                cp->c_flag |= C_NOEXISTS;
@@ -5179,7 +5188,10 @@ hfs_vnop_symlink(struct vnop_symlink_args *ap)
                return (EINVAL);
 
        hfsmp = VTOHFS(dvp);
+       
        len = strlen(ap->a_target);
+       if (len > MAXPATHLEN)
+               return (ENAMETOOLONG);
 
        /* Check for free space */
        if (((u_int64_t)hfs_freeblks(hfsmp, 0) * (u_int64_t)hfsmp->blockSize) < len) {
index 18bcc3081e39ca8731b8bc653a14b3cc7877fa3e..c8a77b15be570d44e26b5450bb27995195d6c48a 100644 (file)
                        <string>-n</string>
                        <key>FSVerificationExecutable</key>
                        <string>fsck_hfs</string>
+                       <key>FSfileObjectsAreCasePreserving</key>
+                       <true/>
+                       <key>FSfileObjectsAreCaseSensitive</key>
+                       <false/>
+                       <key>FSvolumeNameIsCasePreserving</key>
+                       <true/>
                </dict>
                <key>HFS+</key>
                <dict>
                        <string>-fn</string>
                        <key>FSVerificationExecutable</key>
                        <string>fsck_hfs</string>
+                       <key>FSfileObjectsAreCasePreserving</key>
+                       <true/>
+                       <key>FSfileObjectsAreCaseSensitive</key>
+                       <false/>
+                       <key>FSvolumeNameIsCasePreserving</key>
+                       <true/>
                </dict>
                <key>Journaled HFS+</key>
                <dict>
                        <string>-l</string>
                        <key>FSCoreStorageEncryptionName</key>
                        <string>Mac OS Extended (Journaled, Encrypted)</string>
+                       <key>FSfileObjectsAreCasePreserving</key>
+                       <true/>
+                       <key>FSfileObjectsAreCaseSensitive</key>
+                       <false/>
+                       <key>FSvolumeNameIsCasePreserving</key>
+                       <true/>
                </dict>
                <key>Case-sensitive HFS+</key>
                <dict>
                        <string>-fn</string>
                        <key>FSVerificationExecutable</key>
                        <string>fsck_hfs</string>
+                       <key>FSfileObjectsAreCasePreserving</key>
+                       <true/>
+                       <key>FSfileObjectsAreCaseSensitive</key>
+                       <true/>
+                       <key>FSvolumeNameIsCasePreserving</key>
+                       <true/>
                </dict>
                <key>Case-sensitive Journaled HFS+</key>
                <dict>
                        <string>-l</string>
                        <key>FSCoreStorageEncryptionName</key>
                        <string>Mac OS Extended (Case-sensitive, Journaled, Encrypted)</string>
+                       <key>FSfileObjectsAreCasePreserving</key>
+                       <true/>
+                       <key>FSfileObjectsAreCaseSensitive</key>
+                       <true/>
+                       <key>FSvolumeNameIsCasePreserving</key>
+                       <true/>
                </dict>
        </dict>
 </dict>
index cb58f89dba890e9bd1ad2c9ef677b3bb82afacdc..132139ed23fb0b538b017be04e53fc0a78edb15a 100644 (file)
@@ -285,7 +285,9 @@ ReadFragmentedBlock (SFCB *file, UInt32 blockNum, BlockDescriptor *block)
                if (result) goto ErrorExit;
                
                if (bufs[i]->Length != fragSize) {
-                       plog("ReadFragmentedBlock: cache failure (Length != fragSize)\n");
+            if (debug) {
+                plog("ReadFragmentedBlock: cache failure (Length != fragSize)\n");
+            }
                        result = -1;
                        goto ErrorExit;
                }
@@ -337,7 +339,9 @@ WriteFragmentedBlock( SFCB *file, BlockDescriptor *block, int age, uint32_t writ
        bufEnd = buffer + file->fcbBlockSize;
 
        if (bufs == NULL) {
-               plog("WriteFragmentedBlock: NULL bufs list!\n");
+        if (debug) {
+            plog("WriteFragmentedBlock: NULL bufs list!\n");
+        }
                return (-1);
        }
        
@@ -384,7 +388,9 @@ ReleaseFragmentedBlock (SFCB *file, BlockDescriptor *block, int age)
        bufs  = (Buf_t **) block->blockHeader;
 
        if (bufs == NULL) {
-               plog("ReleaseFragmentedBlock: NULL buf list!\n");
+        if (debug) {
+            plog("ReleaseFragmentedBlock: NULL buf list!\n");
+        }
                return (-1);
        }
 
index ae0c983469d8035a37e7167bdd57c9c2a431f678..beb332f6d67c3db522366987ab35182b66cbdebe 100644 (file)
@@ -1035,7 +1035,8 @@ CheckFile(const HFSPlusCatalogKey * key, const HFSPlusCatalogFile * file)
                                        uint8_t *dataBuffer = malloc(file->dataFork.totalBlocks * gScavGlobals->calculatedVCB->vcbBlockSize + 1);
                                        
                                        if (dataBuffer == NULL) {
-                                               plog("Unable to allocate %llu bytes for reading symlink", file->dataFork.logicalSize);
+                        if (debug)
+                            plog("Unable to allocate %llu bytes for reading symlink", file->dataFork.logicalSize);
                                        } else {
                                                char *curPtr = (char*)dataBuffer;
                                                size_t nread = 0;
index d1c7d1f7ae46a84fa8948baec20d7d9a777e4069..c8225a6876fcab00c9b1b32f2c0ed02ea956ed12 100644 (file)
@@ -47,12 +47,12 @@ OSErr GetDeviceSize(int driveRefNum, UInt64 *numBlocks, UInt32 *blockSize)
        int devBlockSize = 0;
 
        if (ioctl(driveRefNum, DKIOCGETBLOCKCOUNT, &devBlockCount) < 0) {
-               plog("ioctl(DKIOCGETBLOCKCOUNT) for fd %d: %s\n", driveRefNum, strerror(errno));
+               if (debug) plog("ioctl(DKIOCGETBLOCKCOUNT) for fd %d: %s\n", driveRefNum, strerror(errno));
                return (-1);
        }
        
        if (ioctl(driveRefNum, DKIOCGETBLOCKSIZE, &devBlockSize) < 0) {
-               plog("ioctl(DKIOCGETBLOCKSIZE) for fd %d: %s\n", driveRefNum, strerror(errno));
+               if (debug) plog("ioctl(DKIOCGETBLOCKSIZE) for fd %d: %s\n", driveRefNum, strerror(errno));
                return (-1);
        }
 
@@ -193,7 +193,7 @@ OSErr DeviceRead(int device, int drive, void* buffer, SInt64 offset, UInt32 reqB
 
        seek_off = lseek(device, offset, SEEK_SET);
        if (seek_off == -1) {
-               plog("# DeviceRead: lseek(%qd) failed with %d\n", offset, errno);
+               if (debug) plog("# DeviceRead: lseek(%qd) failed with %d\n", offset, errno);
                return (errno);
        }
 
@@ -201,7 +201,7 @@ OSErr DeviceRead(int device, int drive, void* buffer, SInt64 offset, UInt32 reqB
        if (nbytes == -1)
                return (errno);
        if (nbytes == 0) {
-               plog("CANNOT READ: BLK %ld\n", (long)offset/512);
+               if (debug) plog("CANNOT READ: BLK %ld\n", (long)offset/512);
                return (5);
        }
 
@@ -245,7 +245,7 @@ OSErr DeviceWrite(int device, int drive, void* buffer, SInt64 offset, UInt32 req
 
        seek_off = lseek(device, offset, SEEK_SET);
        if (seek_off == -1) {
-               plog("# DeviceRead: lseek(%qd) failed with %d\n", offset, errno);
+               if (debug) plog("# DeviceRead: lseek(%qd) failed with %d\n", offset, errno);
                return (errno);
        }
 
@@ -254,7 +254,7 @@ OSErr DeviceWrite(int device, int drive, void* buffer, SInt64 offset, UInt32 req
                return (errno);
        }
        if (nbytes == 0) {
-               plog("CANNOT WRITE: BLK %ld\n", (long)offset/512);
+               if (debug) plog("CANNOT WRITE: BLK %ld\n", (long)offset/512);
                return (5);
        }
 
index 79ef408da072b9ed987f4157e9d06d4dfef29c23..99511684cb670c4ef836fa68196f633f82826a32 100755 (executable)
        
        Written by:     Jerry Cottingham
 
-       Copyright:      © 1986, 1990, 1992-2002 by Apple Computer, Inc., all rights reserved.
+       Copyright:       1986, 1990, 1992-2002 by Apple Computer, Inc., all rights reserved.
 
 */
 
 #define SHOW_ELAPSED_TIMES  0
-#define DEBUG_REBUILD  1
+#define DEBUG_REBUILD  0
 
 extern void MyIndirectLog(const char *);
 
index 4a80776ea1c44c3a6dc53fba665b7918a3b8ff83..f1d32cd7365b283866347bacf58881124496d282 100644 (file)
@@ -2899,7 +2899,7 @@ static OSErr FixBadExtent(SGlobPtr GPtr, RepairOrderPtr p)
                /* Lookup record in catalog BTree */
                err = GetCatalogRecord(GPtr, fileID, isHFSPlus, &catKey, &catRecord, &recordSize);
                if (err) {
-                       plog("%s: Could not get catalog record for fileID %u\n", __FUNCTION__, fileID);
+                       if (debug) plog("%s: Could not get catalog record for fileID %u\n", __FUNCTION__, fileID);
                        goto out;
                }
 
@@ -2935,7 +2935,7 @@ static OSErr FixBadExtent(SGlobPtr GPtr, RepairOrderPtr p)
                err = ReplaceBTreeRecord(GPtr->calculatedCatalogFCB, &catKey, kNoHint, 
                                                                &catRecord, recordSize, &hint);
                if (err) {
-                       plog("%s: Could not replace catalog record for fileID %u\n", __FUNCTION__, fileID);
+                       if (debug) plog("%s: Could not replace catalog record for fileID %u\n", __FUNCTION__, fileID);
                        goto out;
                }
                didRepair = true;
@@ -2952,7 +2952,8 @@ static OSErr FixBadExtent(SGlobPtr GPtr, RepairOrderPtr p)
                err = SearchBTreeRecord (GPtr->calculatedExtentsFCB, &extentKey, kNoHint, 
                                                                 &extentKey, &extentRecord, &recordSize, &hint);
                if (err) {
-                       plog("%s: Could not get overflow extents record for fileID %u, fork %u, start block %u\n", __FUNCTION__, fileID, forkType, extentStartBlock);
+                       if (debug) plog("%s: Could not get overflow extents record for fileID %u, fork %u, start block %u\n", __FUNCTION__, fileID, forkType,
+                            extentStartBlock);
                        goto out;
                }
 
@@ -2973,7 +2974,8 @@ static OSErr FixBadExtent(SGlobPtr GPtr, RepairOrderPtr p)
                err = ReplaceBTreeRecord(GPtr->calculatedExtentsFCB, &extentKey, hint,
                                                                &extentRecord, recordSize, &hint);
                if (err) {
-                       plog("%s: Could not replace overflow extents record for fileID %u, fork %u, start block %u\n", __FUNCTION__, fileID, forkType, extentStartBlock);
+                       if (debug) plog("%s: Could not replace overflow extents record for fileID %u, fork %u, start block %u\n", __FUNCTION__, fileID,
+                            forkType, extentStartBlock);
                        goto out;
                }
                didRepair = true;
@@ -3599,7 +3601,7 @@ static OSErr GetCatalogRecord(SGlobPtr GPtr, UInt32 fileID, Boolean isHFSPlus, C
        BuildCatalogKey(fileID, NULL, isHFSPlus, &catThreadKey);
        err = SearchBTreeRecord(GPtr->calculatedCatalogFCB, &catThreadKey, kNoHint, catKey, catRecord, recordSize, &hint);
        if (err) {
-               plog ("%s: No matching catalog thread record found\n", __FUNCTION__);
+               if (debug) plog ("%s: No matching catalog thread record found\n", __FUNCTION__);
                goto out;
        }
 
@@ -3625,7 +3627,7 @@ static OSErr GetCatalogRecord(SGlobPtr GPtr, UInt32 fileID, Boolean isHFSPlus, C
        BuildCatalogKey(catRecord->hfsPlusThread.parentID, &catalogName, isHFSPlus, catKey); 
        err = SearchBTreeRecord(GPtr->calculatedCatalogFCB, catKey, kNoHint, catKey, catRecord, recordSize, &hint);
        if (err) {
-               plog ("%s: No matching catalog record found\n", __FUNCTION__);
+               if (debug) plog ("%s: No matching catalog record found\n", __FUNCTION__);
                if (cur_debug_level & d_dump_record)
                {
                        plog ("Searching for key:\n");
index 4280b9cbca0eaba789406796e28eef16175c9d5c..1249cf76d1951c8a5e0112f66d2d24672fdd87a0 100644 (file)
@@ -27,7 +27,7 @@
 
        Version:        xxx put version here xxx
 
-       Copyright:      © 1997-1999 by Apple Computer, Inc., all rights reserved.
+       Copyright:       1997-1999 by Apple Computer, Inc., all rights reserved.
 */
 
 #include <sys/ioctl.h>
@@ -1307,8 +1307,9 @@ static int BTKeyChk( SGlobPtr GPtr, NodeDescPtr nodeP, BTreeControlBlock *btcb )
                                        } 
                                        else
                                        {
-                                               RcdError( GPtr, E_KeyOrd );
-                                               plog("Records %d and %d (0-based); offsets 0x%04X and 0x%04X\n", index-1, index, (long)prevkeyP - (long)nodeP, (long)keyPtr - (long)nodeP);
+                        RcdError( GPtr, E_KeyOrd );
+                        if (fsckGetVerbosity(GPtr->context) > 0)
+                            plog("Records %d and %d (0-based); offsets 0x%04X and 0x%04X\n", index-1, index, (long)prevkeyP - (long)nodeP, (long)keyPtr - (long)nodeP);
                                                result = E_KeyOrd;
                                        }
                                }
index 6c5b0e41cda7854984579186d575cb00f65fa2ba..d14410671809b0aeae1ef8229c8b40547de07ec0 100644 (file)
@@ -506,8 +506,11 @@ journal_open(int jfd,
                                 * XXX
                                 * I am not sure about this; this behaviour is not in TN1150 at all,
                                 * but I _think_ this is what the kernel is doing.
-                                */
-                               plog("Journal sequence number is 0, is going into the end okay?\n");
+                 */
+#if DEBUG_JOURNAL
+                if (debug)
+                    plog("Journal sequence number is 0, is going into the end okay?\n");
+#endif
                        }
                        into_the_weeds = 1;
 #if DEBUG_JOURNAL
index 74c66e636c53e46b606f78fca56bbb154ccfb81e..8fdd66d86b7e54b1ade4234b986302e446677453 100755 (executable)
@@ -202,13 +202,13 @@ hfs_swap_BTNode (
 
 #ifdef ENDIAN_DEBUG
     if (direction == kSwapBTNodeBigToHost) {
-        plog ("BE -> Native Swap\n");
+        if (debug) plog ("BE -> Native Swap\n");
     } else if (direction == kSwapBTNodeHostToBig) {
-        plog ("Native -> BE Swap\n");
+        if (debug) plog ("Native -> BE Swap\n");
     } else if (direction == kSwapBTNodeHeaderRecordOnly) {
-        plog ("Not swapping descriptors\n");
+        if (debug) plog ("Not swapping descriptors\n");
     } else {
-        plog ("hfs_swap_BTNode: This is impossible");
+        if (debug) plog ("hfs_swap_BTNode: This is impossible");
         exit(99);
     }
 #endif
@@ -272,7 +272,8 @@ hfs_swap_BTNode (
              * This is why we allow the record offset to be zero.
              */
             if ((srcOffs[i] & 1) || (srcOffs[i] < sizeof(BTNodeDescriptor) && srcOffs[i] != 0) || (srcOffs[i] >= src->blockSize)) {
-               if (debug) plog("hfs_swap_BTNode: record #%d invalid offset (0x%04X)\n", srcDesc->numRecords-i-1, srcOffs[i]);
+               if (debug) plog("hfs_swap_BTNode: offset #%d invalid  (0x%04X) (blockSize 0x%x numRecords %d)\n",
+                                i, srcOffs[i], src->blockSize, srcDesc->numRecords);
                                WriteError(fcb->fcbVolume->vcbGPtr, E_BadNode, fcb->fcbFileID, src->blockNum);
                error = E_BadNode;
                goto fail;
@@ -284,7 +285,7 @@ hfs_swap_BTNode (
              */
             if ((i != 0) && (srcOffs[i] >= srcOffs[i-1])) {
                if (debug) plog("hfs_swap_BTNode: offsets %d and %d out of order (0x%04X, 0x%04X)\n",
-                   srcDesc->numRecords-i-1, srcDesc->numRecords-i, srcOffs[i], srcOffs[i-1]);
+                   i, i-1, srcOffs[i], srcOffs[i-1]);
                                WriteError(fcb->fcbVolume->vcbGPtr, E_BadNode, fcb->fcbFileID, src->blockNum);
                error = E_BadNode;
                goto fail;
@@ -395,7 +396,8 @@ hfs_swap_BTNode (
              * This is why we allow the record offset to be zero.
              */
             if ((srcOffs[i] & 1) || (srcOffs[i] < sizeof(BTNodeDescriptor) && srcOffs[i] != 0) || (srcOffs[i] >= src->blockSize)) {
-               if (debug) plog("hfs_UNswap_BTNode: record #%d invalid offset (0x%04X)\n", srcDesc->numRecords-i-1, srcOffs[i]);
+               if (debug) plog("hfs_UNswap_BTNode: offset #%d invalid  (0x%04X) (blockSize 0x%x numRecords %d)\n",
+                                i, srcOffs[i], src->blockSize, srcDesc->numRecords);
                                WriteError(fcb->fcbVolume->vcbGPtr, E_BadNode, fcb->fcbFileID, src->blockNum);
                error = E_BadNode;
                goto fail;
@@ -407,7 +409,7 @@ hfs_swap_BTNode (
              */
             if ((i < srcDesc->numRecords) && (srcOffs[i+1] >= srcOffs[i])) {
                if (debug) plog("hfs_UNswap_BTNode: offsets %d and %d out of order (0x%04X, 0x%04X)\n",
-                   srcDesc->numRecords-i-2, srcDesc->numRecords-i-1, srcOffs[i+1], srcOffs[i]);
+                   i+1, i, srcOffs[i+1], srcOffs[i]);
                                WriteError(fcb->fcbVolume->vcbGPtr, E_BadNode, fcb->fcbFileID, src->blockNum);
                error = E_BadNode;
                goto fail;
@@ -860,7 +862,7 @@ hfs_swap_HFSPlusBTInternalNode (
                srcRec->recordType = SWAP_BE32(srcRec->recordType);
        }
     } else {
-               plog("hfs_swap_HFSPlusBTInternalNode: fileID %u is not a system B-tree\n", fileID);
+               if (debug) plog("hfs_swap_HFSPlusBTInternalNode: fileID %u is not a system B-tree\n", fileID);
         exit(99);
     }
 
@@ -1111,7 +1113,7 @@ hfs_swap_HFSBTInternalNode (
         }
         
     } else {
-       plog("hfs_swap_HFSBTInternalNode: fileID %u is not a system B-tree\n", fileID);
+       if (debug) plog("hfs_swap_HFSBTInternalNode: fileID %u is not a system B-tree\n", fileID);
        exit(99);
     }
 
index 71a9ec7628fe67ada91ba54f128266de09c1ecc8..ef8da41d2f2c87b7e09475650edb9093b96a9a93 100644 (file)
                0703A0541CD826160035BCFD /* test-defrag.c in Sources */ = {isa = PBXBuildFile; fileRef = 0703A0531CD826160035BCFD /* test-defrag.c */; };
                07C2BF891CB43F5E00D8327D /* test-renamex.c in Sources */ = {isa = PBXBuildFile; fileRef = 07C2BF881CB43F5E00D8327D /* test-renamex.c */; };
                2A386A3B1C22209C007FEDAC /* test-list-ids.c in Sources */ = {isa = PBXBuildFile; fileRef = 2A386A3A1C221E67007FEDAC /* test-list-ids.c */; };
+               2A84DBD41D9E15F2007964B8 /* test-raw-dev-unaligned.c in Sources */ = {isa = PBXBuildFile; fileRef = 2A84DBD31D9E1179007964B8 /* test-raw-dev-unaligned.c */; };
                2A9399951BDFEB5200FB075B /* test-access.c in Sources */ = {isa = PBXBuildFile; fileRef = 2A9399941BDFEA6E00FB075B /* test-access.c */; };
                2A9399981BDFF7E500FB075B /* test-chflags.c in Sources */ = {isa = PBXBuildFile; fileRef = 2A9399961BDFEF3900FB075B /* test-chflags.c */; };
                2A93999D1BE0146E00FB075B /* test-class-roll.c in Sources */ = {isa = PBXBuildFile; fileRef = 2A93999B1BE0146000FB075B /* test-class-roll.c */; };
                0703A0531CD826160035BCFD /* test-defrag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "test-defrag.c"; sourceTree = "<group>"; };
                07C2BF881CB43F5E00D8327D /* test-renamex.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "test-renamex.c"; sourceTree = "<group>"; };
                2A386A3A1C221E67007FEDAC /* test-list-ids.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "test-list-ids.c"; sourceTree = "<group>"; };
+               2A84DBD31D9E1179007964B8 /* test-raw-dev-unaligned.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "test-raw-dev-unaligned.c"; sourceTree = "<group>"; };
                2A9399941BDFEA6E00FB075B /* test-access.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "test-access.c"; sourceTree = "<group>"; };
                2A9399961BDFEF3900FB075B /* test-chflags.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "test-chflags.c"; sourceTree = "<group>"; };
                2A93999B1BE0146000FB075B /* test-class-roll.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "test-class-roll.c"; sourceTree = "<group>"; };
                FB55AE551B7CD89600701D03 /* cases */ = {
                        isa = PBXGroup;
                        children = (
+                               2A84DBD31D9E1179007964B8 /* test-raw-dev-unaligned.c */,
                                07C2BF881CB43F5E00D8327D /* test-renamex.c */,
                                2A386A3A1C221E67007FEDAC /* test-list-ids.c */,
                                2A9399D41BE2C14800FB075B /* test-unicode-file-names.c */,
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
+                               2A84DBD41D9E15F2007964B8 /* test-raw-dev-unaligned.c in Sources */,
                                2A386A3B1C22209C007FEDAC /* test-list-ids.c in Sources */,
                                2ABDCEA71BF3DAA100CFC70C /* test-journal-toggle.c in Sources */,
                                FBE1B1D41BD6E41D00CEB443 /* test-move-data-extents.c in Sources */,
index d38c669b223ef4639f28135af0ca16b5eda32755..57025617417cc47b14214a20e9dc72f754f90f58 100644 (file)
@@ -167,7 +167,7 @@ static void run(void)
                        ssize_t res;
                        do {
                                res = fsgetpath(path, sizeof(path), &sfs.f_fsid, (uint64_t)sb.st_ino);
-                       } while (res != -1 || errno == EAGAIN);
+                       } while (res != -1);
                        assert_with_errno(errno == ENOENT);
                });
 
diff --git a/tests/cases/test-raw-dev-unaligned.c b/tests/cases/test-raw-dev-unaligned.c
new file mode 100644 (file)
index 0000000..8e5bfd7
--- /dev/null
@@ -0,0 +1,93 @@
+#include <sys/fcntl.h>
+#include <unistd.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/param.h>
+#include <sys/mount.h>
+
+#include "hfs-tests.h"
+#include "test-utils.h"
+#include "disk-image.h"
+
+TEST(raw_dev_unaligned, .run_as_root = 1);
+
+int run_raw_dev_unaligned(__unused test_ctx_t *ctx)
+{
+       struct statfs sfs;
+       
+       assert(statfs("/tmp", &sfs) == 0);
+       if (strcmp(sfs.f_fstypename, "hfs")) {
+               printf("raw_dev_aligned needs hfs as root file system - skipping.\n");
+               return 0;
+       }
+       
+       int fd = open("/tmp/raw-dev-unaligned", O_CREAT | O_RDWR | O_TRUNC, 0666);
+
+       assert_with_errno(fd >= 0);
+
+       assert_no_err(ftruncate(fd, 4096));
+
+       assert_no_err(fcntl(fd, F_FULLFSYNC));
+
+       struct log2phys l2p = {};
+
+       assert_no_err(fcntl(fd, F_LOG2PHYS_EXT, &l2p));
+
+       assert(!strncmp(sfs.f_mntfromname, "/dev/disk", 9));
+
+       char *rdev;
+       asprintf(&rdev, "/dev/rdisk%s", sfs.f_mntfromname + 9);
+
+       int raw_fd;
+       assert_with_errno((raw_fd = open(rdev, O_RDWR)) >= 0);
+
+       void *buf = malloc(16384);
+
+       off_t offset = l2p.l2p_devoffset;
+
+       // Make p non-aligned
+       char *p = (char *)((((uintptr_t)buf + 64) & ~63) + 8);
+
+       unsigned bs = 4096;
+       if (bs < sfs.f_bsize)
+               bs = sfs.f_bsize;
+
+       check_io(pread(raw_fd, p, bs, offset), bs);
+
+       // Make a change
+       check_io(pwrite(fd, &fd, 4, 0), 4);
+
+       assert_no_err(fcntl(fd, F_FULLFSYNC));
+
+       char *state = malloc(bs);
+
+       /*
+        * Make sure it changed on the raw device so we know we've got the
+        * correct location.  We can't actually check the contents because
+        * it's encrypted on iOS.
+        */
+       check_io(pread(raw_fd, state, bs, offset), bs);
+
+       assert(memcmp(state, p, bs));
+
+       assert_no_err(close(fd));
+
+       for (int i = 0; i < 3000; ++i) {
+               for (unsigned i = 0; i < bs; ++i)
+                       state[i] ^= 0xff;
+               memcpy(p, state, bs);
+               check_io(pwrite(raw_fd, p, bs, offset), bs);
+               check_io(pread(raw_fd, p, bs, offset), bs);
+               assert(!memcmp(p, state, bs));
+       }
+
+       // cleanup
+       assert_no_err(close(raw_fd));
+       assert_no_err(unlink("/tmp/raw-dev-unaligned"));
+       free(buf);
+       free(state);
+
+       return 0;
+}
index 803c0b721d074ec0ea5dd3d96999b12bb5f05077..2d38181896dc4b0e3be9542b945c7a84e1623c5b 100644 (file)
 
 TEST(throttled_io)
 
-static disk_image_t *di;
-static char *file1, *file2, *file3;
+static disk_image_t *gDI;
+static char *gFile1, *gFile2, *gFile3;
 
-static pid_t pid;
-static void *buf;
-static const size_t buf_size = 64 * 1024 * 1024;
+static pid_t gPID = 0;
+static void *gBuf;
+static const size_t gBuf_size = 64 * 1024 * 1024;
 
-static int run_test1(void)
+static void start_background_io(void)
 {
        char *of;
-       asprintf(&of, "of=%s", file1);
+       asprintf(&of, "of=%s", gFile1);
        
+       assert_no_err(posix_spawn(&gPID, "/bin/dd", NULL, NULL,
+                                                         (char *[]){ "/bin/dd", "if=/dev/random",
+                                                                 of, NULL },
+                                                         NULL));
+}
+
+static void end_background_io(void)
+{
+       if ( gPID != 0 )
+       {
+               kill(gPID, SIGKILL);
+               int stat;
+               wait(&stat);
+               gPID = 0;
+       }
+}
+
+static int run_test1(void)
+{
+
        // Kick off another process to ensure we get throttled
-       assert_no_err(posix_spawn(&pid, "/bin/dd", NULL, NULL, 
-                                                         (char *[]){ "/bin/dd", "if=/dev/random", 
-                                                                         of, NULL },
-                       NULL));
+       start_background_io();
 
        assert_no_err(setiopolicy_np(IOPOL_TYPE_DISK, IOPOL_SCOPE_PROCESS, 
                                                                 IOPOL_THROTTLE));
 
        int fd, fd2;
        assert_with_errno((fd = open("/dev/random", O_RDONLY)) >= 0);
-       assert_with_errno((fd2 = open(file2, 
+       assert_with_errno((fd2 = open(gFile2, 
                                                                  O_RDWR | O_CREAT | O_TRUNC, 0666)) >= 0);
 
        assert_no_err(fcntl(fd2, F_SINGLE_WRITER, 1));
        assert_no_err(fcntl(fd2, F_NOCACHE, 1));
 
-       buf = valloc(buf_size);
+       gBuf = valloc(gBuf_size);
        CC_SHA1_CTX ctx;
        CC_SHA1_Init(&ctx);
 
-       ssize_t res = check_io(read(fd, buf, buf_size), buf_size);
+       ssize_t res = check_io(read(fd, gBuf, gBuf_size), gBuf_size);
 
-       CC_SHA1_Update(&ctx, buf, (CC_LONG)res);
+       CC_SHA1_Update(&ctx, gBuf, (CC_LONG)res);
 
-       res = check_io(write(fd2, buf, res), res);
+       res = check_io(write(fd2, gBuf, res), res);
 
-       bzero(buf, buf_size);
+       bzero(gBuf, gBuf_size);
 
        CC_SHA1_CTX ctx2;
        CC_SHA1_Init(&ctx2);
 
        lseek(fd2, 0, SEEK_SET);
 
-       res = check_io(read(fd2, buf, buf_size), buf_size);
+       res = check_io(read(fd2, gBuf, gBuf_size), gBuf_size);
 
-       CC_SHA1_Update(&ctx2, buf, (CC_LONG)res);
+       CC_SHA1_Update(&ctx2, gBuf, (CC_LONG)res);
 
        uint8_t digest1[CC_SHA1_DIGEST_LENGTH], digest2[CC_SHA1_DIGEST_LENGTH];
        CC_SHA1_Final(digest1, &ctx);
@@ -76,6 +93,11 @@ static int run_test1(void)
 
        assert(!memcmp(digest1, digest2, CC_SHA1_DIGEST_LENGTH));
 
+       assert_no_err (close(fd));
+       assert_no_err (close(fd2));
+       
+       end_background_io();
+
        return 0;
 }
 
@@ -84,10 +106,10 @@ static volatile bool done;
 
 static void test2_thread(void)
 {
-       int fd = open(file3, O_RDONLY);
+       int fd = open(gFile3, O_RDONLY);
        assert(fd >= 0);
 
-       void *b = buf + buf_size / 2;
+       void *b = gBuf + gBuf_size / 2;
        uLong seq = crc32(0, Z_NULL, 0);
        uint32_t offset = 0;
 
@@ -95,7 +117,7 @@ static void test2_thread(void)
                ssize_t res;
 
                do {
-                       res = check_io(pread(fd, b, buf_size / 2, offset), -1);
+                       res = check_io(pread(fd, b, gBuf_size / 2, offset), -1);
                } while (res == 0 && !done);
 
                assert (res % 4 == 0);
@@ -111,11 +133,16 @@ static void test2_thread(void)
                        continue;
                OSMemoryBarrier();
        } while (!done);
+       
+       assert_no_err (close(fd));
+       
 }
 
 static int run_test2(void)
 {
-       int fd = open(file3, O_RDWR | O_CREAT | O_TRUNC, 0666);
+       start_background_io();
+       
+       int fd = open(gFile3, O_RDWR | O_CREAT | O_TRUNC, 0666);
        assert(fd >= 0);
 
        assert_no_err(fcntl(fd, F_SINGLE_WRITER, 1));
@@ -126,13 +153,13 @@ static int run_test2(void)
        uLong seq = crc32(0, Z_NULL, 0);
 
        for (int i = 0; i < 4; ++i) {
-               uLong *p = buf;
-               for (unsigned i = 0; i < buf_size / 2 / sizeof(uLong); ++i) {
+               uLong *p = gBuf;
+               for (unsigned i = 0; i < gBuf_size / 2 / sizeof(uLong); ++i) {
                        seq = crc32(Z_NULL, (void *)&seq, 4);
                        p[i] = seq;
                }
 
-               ssize_t res = check_io(write(fd, buf, buf_size / 2), buf_size / 2);
+               ssize_t res = check_io(write(fd, gBuf, gBuf_size / 2), gBuf_size / 2);
 
                written += res;
        }
@@ -143,45 +170,47 @@ static int run_test2(void)
 
        pthread_join(thread, NULL);
 
+       assert_no_err (close(fd));
+       
+       end_background_io();
+
        return 0;
 }
 
 static bool clean_up(void)
 {
-       kill(pid, SIGKILL);
-       int stat;
-       wait(&stat);
+       end_background_io();
 
-       unlink(file1);
-       unlink(file2);
-       unlink(file3);
+       unlink(gFile1);
+       unlink(gFile2);
+       unlink(gFile3);
+       
+       free(gFile1);
+       free(gFile2);
+       free(gFile3);
        
        return true;
 }
 
 int run_throttled_io(__unused test_ctx_t *ctx)
 {
+       gDI = disk_image_get();
+       
+       asprintf(&gFile1, "%s/throttled_io.1", gDI->mount_point);
+       asprintf(&gFile2, "%s/throttled_io.2", gDI->mount_point);
+       asprintf(&gFile3, "%s/throttled_io.3", gDI->mount_point);
+       
        test_cleanup(^ bool {
                return clean_up();
        });
        
-       di = disk_image_get();
-       asprintf(&file1, "%s/throttled_io.1", di->mount_point);
-       asprintf(&file2, "%s/throttled_io.2", di->mount_point);
-       asprintf(&file3, "%s/throttled_io.3", di->mount_point);
-
        int res = run_test1();
        if (res)
-               goto out;
-
+               return res;
+       
        res = run_test2();
        if (res)
-               goto out;
-
-out:
-       free(file1);
-       free(file2);
-       free(file3);
+               return res;
        
        return res;
 }
index 9b864ae7381c2672eee8d2dc67569977cd221d55..994efb83d30d6e78f2792dd8c6e01b65bc41ff37 100644 (file)
@@ -2,6 +2,10 @@
 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 <plist version="1.0">
 <dict>
+       <key>com.apple.rootless.internal-installer-equivalent</key>
+       <true/>
+       <key>com.apple.private.security.disk-device-access</key>
+       <true/>
        <key>com.apple.keystore.device</key>
        <true/>
        <key>com.apple.managedconfiguration.mdmd-access</key>
index 054d1f6c4a6280e810769e8006009578166a186a..7ece91acff8fd821436a04d1f6aa02231d30a639 100644 (file)
@@ -217,7 +217,7 @@ int main(int argc, char *argv[])
                                        else {
                                                test_t *test = it->second;
                                                
-                                               int ret = systemx(progname, "--test", test->name, "--no-spawn", "run", NULL);
+                                               ret = systemx(progname, "--test", test->name, "--no-spawn", "run", NULL);
                                                
                                                if (ret)
                                                        std::cout << "[FAIL] " << test->name << std::endl;