]> git.saurik.com Git - apple/hfs.git/commitdiff
hfs-556.41.1.tar.gz macos-1101 v556.41.1
authorApple <opensource@apple.com>
Thu, 19 Nov 2020 01:07:08 +0000 (01:07 +0000)
committerApple <opensource@apple.com>
Thu, 19 Nov 2020 01:07:08 +0000 (01:07 +0000)
72 files changed:
CopyHFSMeta/DeviceWrapper.c
CopyHFSMeta/Gather.c
CopyHFSMeta/ScanExtents.c
CopyHFSMeta/SparseBundle.c
CopyHFSMeta/dump.c
core/.open_source_exclude [deleted file]
core/BTreeMiscOps.c
core/FileExtentMapping.c
core/VolumeAllocation.c
core/hfs.h
core/hfs_catalog.c
core/hfs_cnode.c
core/hfs_cnode.h
core/hfs_cprotect.c
core/hfs_fsctl.h
core/hfs_iokit.cpp
core/hfs_journal.c
core/hfs_readwrite.c
core/hfs_vfsops.c
core/hfs_vfsutils.c
core/hfs_vnops.c
core/hfs_xattr.c
fsck_hfs/cache.c
fsck_hfs/dfalib/BTreeAllocate.c
fsck_hfs/dfalib/HardLinkCheck.c
fsck_hfs/dfalib/SBTree.c
fsck_hfs/dfalib/SDevice.c
fsck_hfs/dfalib/SExtents.c
fsck_hfs/dfalib/SRebuildBTree.c
fsck_hfs/dfalib/SRepair.c
fsck_hfs/dfalib/SStubs.c
fsck_hfs/dfalib/SUtils.c
fsck_hfs/dfalib/SVerify1.c
fsck_hfs/dfalib/VolumeBitmapCheck.c
fsck_hfs/dfalib/dirhardlink.c
fsck_hfs/dfalib/fsck_journal.c
fsck_hfs/dfalib/hfs_endian.c
fsck_hfs/fsck_hfs.c
fsck_hfs/utilities.c
hfs.xcodeproj/project.pbxproj
hfs_util/hfsutil_jnl.c
hfs_util/hfsutil_main.c
livefiles_cs_plugin/lf_cs.h [new file with mode: 0644]
livefiles_cs_plugin/lf_cs_checksum.c [new file with mode: 0644]
livefiles_cs_plugin/lf_cs_checksum.h [new file with mode: 0644]
livefiles_cs_plugin/lf_cs_disk_format.h [new file with mode: 0644]
livefiles_cs_plugin/lf_cs_logging.c [new file with mode: 0644]
livefiles_cs_plugin/lf_cs_logging.h [new file with mode: 0644]
livefiles_cs_plugin/lf_cs_vfsops.c [new file with mode: 0644]
livefiles_cs_plugin/livefiles_cs_tester.c [new file with mode: 0644]
livefiles_cs_plugin/livefiles_cs_tester.entitlements [new file with mode: 0644]
livefiles_hfs_plugin/lf_hfs.h
livefiles_hfs_plugin/lf_hfs_catalog.c
livefiles_hfs_plugin/lf_hfs_chash.c
livefiles_hfs_plugin/lf_hfs_cnode.c
livefiles_hfs_plugin/lf_hfs_fsops_handler.c
livefiles_hfs_plugin/lf_hfs_journal.c
livefiles_hfs_plugin/lf_hfs_link.c
livefiles_hfs_plugin/lf_hfs_vfsops.c
livefiles_hfs_plugin/lf_hfs_vnode.c
livefiles_hfs_plugin/lf_hfs_xattr.c
mount_hfs/mount_hfs.c
newfs_hfs/makehfs.c
newfs_hfs/newfs_hfs.c
tests/cases/test-external-jnl.c
tests/cases/test-key-roll.c
tests/cases/test-lf-cs-plugin.c [new file with mode: 0644]
tests/disk-image.m
tests/gen-custom-dmg.sh [new file with mode: 0755]
tests/gen-test-plist.sh
tests/generate-compressed-image.c [new file with mode: 0644]
tests/hfs-tests.entitlements

index 74dd4b606fe05d1945d6f19b2789bd9f6bfb9b9a..a05814323a576d5649d2a4481046300853a0bb2d 100644 (file)
@@ -140,6 +140,10 @@ InitDeviceWrapper(const char *path, DeviceInfo_t *devp)
        }
 
        ctx.pathname = strdup(rawname);
+       if (ctx.pathname == NULL) {
+               warn("Cannot strdup the pathname");
+               goto done;
+       }
        retctx = malloc(sizeof(ctx));
        if (retctx == NULL) {
                warn("Cannot allocate space for device context");
index 27c4c7a89f5e7de4eebf7b7e0289830c2bebdd57..30e155970ff4d62ec5789b85006b89e1b38eb15e 100644 (file)
@@ -5,6 +5,8 @@
 #include <err.h>
 #include <errno.h>
 #include <zlib.h>
+#include <limits.h>
+#include <assert.h>
 
 #include "hfsmeta.h"
 #include "Data.h"
@@ -51,7 +53,7 @@ WriteExtent(gzFile outf, DeviceInfo_t *devp, off_t start, off_t len)
                if (nread != amt) {
                        warnx("Tried to read %zu bytes, only read %zd", amt, nread);
                }
-               nwritten = gzwrite(outf, (char*)buffer, amt);
+               nwritten = gzwrite(outf, (char*)buffer, (unsigned)amt);
                if (nwritten == -1) {
                        warn("tried to gzwrite %zu bytes", amt);
                        return -1;
@@ -73,6 +75,7 @@ WriteGatheredData(const char *pathname, VolumeObjects_t *vop)
        HFSDataObject *objs = NULL, *op;
        ExtentList_t *ep;
        int i;
+       size_t len;
 
        hdr.version = S32(kHFSInfoHeaderVersion);
        hdr.deviceBlockSize = S32((uint32_t)vop->devp->blockSize);
@@ -111,7 +114,9 @@ WriteGatheredData(const char *pathname, VolumeObjects_t *vop)
        }
 
        gzwrite(outf, &hdr, sizeof(hdr));
-       gzwrite(outf, objs, sizeof(HFSDataObject) * vop->count);
+       len = sizeof(HFSDataObject) * vop->count;
+       assert(len < UINT_MAX);
+       gzwrite(outf, objs, (unsigned)len);
 
        int count = 0;
        for (ep = vop->list;
index 470a699dbadabd5e1d2567e6d2ff550394ad5f52..25e5a5597fe014fcc7e2e4ba91292cd0e2f4bd3b 100644 (file)
@@ -194,7 +194,6 @@ ScanExtents(VolumeObjects_t *vop, int useAltHdr)
        off_t vBlockSize;
        size_t nodeSize;
        size_t bufferSize;
-       int blocksPerNode;
        void *nodePtr = NULL;
        unsigned int nodeNum = 0;
 
@@ -227,10 +226,8 @@ ScanExtents(VolumeObjects_t *vop, int useAltHdr)
         * does mean it is less efficient than it should be.
         */
        if (nodeSize < vBlockSize) {
-               blocksPerNode = 1;      // 1 block will hold multiple nodes
                bufferSize = vBlockSize;
        } else {
-               blocksPerNode = nodeSize / vBlockSize;
                bufferSize = nodeSize;
        }
 
index 2d966c46744d6997bfd54c677592ad7ab72fa9b0..8c7c2daba361fb9e72ff3f5ad76ff19f7f966173 100644 (file)
@@ -176,7 +176,8 @@ doSparseWrite(IOWrapper_t *context, off_t offset, void *buffer, off_t len)
                        free(bandName);
                        bandName = NULL;
                        ctx->cfd = fd;
-                       ctx->cBandNum = bandNum;
+                       assert(bandNum < INT_MAX);
+                       ctx->cBandNum = (int)bandNum;
                } else {
                        fd = ctx->cfd;
                }
index 67067e445ec835c60d9385032ac26d8aa9449394..5e096076e19a91ca63cf0403f143639b075d4e8d 100644 (file)
@@ -53,7 +53,7 @@ DumpData(const void *data, size_t len)
                        if (*tmp)
                                allzeroes = 0;
                }
-               for (i = gap; i >= 0; i--) {
+               for (i = (int)gap; i >= 0; i--) {
                        printf("  ");
                        if (i % 2 == 1)
                                printf(" ");
diff --git a/core/.open_source_exclude b/core/.open_source_exclude
deleted file mode 100644 (file)
index 0c36529..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-hfs_key_roll.c
-hfs_key_roll.h
index a8682ef0c4b5e51be3a2929ad9e2d6bf2b4cc726..4f89b785192ae38f276fd850bef7c01c42757463 100644 (file)
@@ -527,7 +527,7 @@ OSStatus    CheckInsertParams               (FCB                                            *filePtr,
        BTreeControlBlockPtr    btreePtr;
        
        if (filePtr == nil)                                                                     return  paramErr;
-
+       if (recordLen == 0)                                                                     return  paramErr;
        btreePtr = (BTreeControlBlockPtr) filePtr->fcbBTCBPtr;
        if (btreePtr == nil)                                                            return  fsBTInvalidFileErr;
        if (iterator == nil)                                                            return  paramErr;
index 1ea93f983924e828e598cc4a4b7fa10273230207..a4e177bd21d18f38db4f183af9fe2672e8379365 100644 (file)
@@ -221,7 +221,7 @@ static OSErr FindExtentRecord(
        struct BTreeIterator *btIterator = NULL;
        FSBufferDescriptor      btRecord;
        OSErr                           err;
-       u_int16_t                       btRecordSize;
+       u_int16_t                       btRecordSize = 0;
        
        err = noErr;
        if (foundHint)
@@ -348,7 +348,7 @@ static OSErr CreateExtentRecord(
 {
        struct BTreeIterator *btIterator = NULL;
        FSBufferDescriptor      btRecord;
-       u_int16_t  btRecordSize;
+       u_int16_t  btRecordSize = 0;
        int  lockflags;
        OSErr  err;
        
@@ -1025,7 +1025,7 @@ OSErr ExtendFileC (
        int                                     allowFlushTxns;
        u_int32_t                       actualStartBlock;
        u_int32_t                       actualNumBlocks;
-       u_int32_t                       numExtentsPerRecord;
+       u_int32_t                       numExtentsPerRecord = 0;
        int64_t                         maximumBytes;
        int64_t                         availbytes;
        int64_t                         peof;
index f26811cd783c18cdb5f0acb80c0299ac5573cef2..fabe691934659515c61f1a1040ec42f57eb887d2 100644 (file)
@@ -160,7 +160,9 @@ Optimization Routines
 #include <sys/types.h>
 #include <sys/buf.h>
 
-#if !HFS_ALLOC_TEST
+#if HFS_ALLOC_TEST
+#define KERNEL_DEBUG_CONSTANT(x, a, b, c, d, e) do {} while (0)
+#else // !HFS_ALLOC_TEST
 
 #include "hfs_macos_defs.h"
 #include <sys/systm.h>
index 786199c03cf8a1866475c6e2a83ffbbeea0679a6..c450aea388615d391946145492aa3d5bf3fdce6e 100644 (file)
@@ -1002,7 +1002,6 @@ 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 {
index d48a1066bf34cca29d44ffea7df0ced3236d5970..1f6765a8539c607076e6edca0984127b12e88828 100644 (file)
@@ -444,7 +444,7 @@ cat_convertkey(
 {
        int std_hfs = HFSTOVCB(hfsmp)->vcbSigWord == kHFSSigWord;
        HFSPlusCatalogKey * pluskey = NULL;
-       u_int32_t encoding;
+       u_int32_t encoding = 0;
        cnid_t cnid = 0;
        int err = 0;
 
@@ -3507,7 +3507,7 @@ cat_getdirentries(struct hfsmount *hfsmp, u_int32_t entrycnt, directoryhint_t *d
        void * buffer;
        int bufsize;
        int maxlinks;
-       int result;
+       int result = 0;
        int index;
        int have_key;
        int extended;
index 12b126cd45809363bc02862bde7b7437873b2a70..ee37f2f4db88df68ce7458a6583a80705e23fcec 100644 (file)
@@ -64,6 +64,8 @@ static int hfs_isordered(struct cnode *, struct cnode *);
 
 extern int hfs_removefile_callback(struct buf *bp, void *hfsmp);
 
+uint32_t _hfs_max_origins = MAX_CACHED_ORIGINS_DEFAULT;
+uint32_t _hfs_max_file_origins = MAX_CACHED_FILE_ORIGINS_DEFAULT;
 
 __inline__ int hfs_checkdeleted (struct cnode *cp) {
        return ((cp->c_flag & (C_DELETED | C_NOEXISTS)) ? ENOENT : 0);  
index 088c4459eaa49d0556ac10cf81f07562a0302787..19ba70dc9ad219327869f1f745b6c3c4eca9f168 100644 (file)
@@ -131,8 +131,13 @@ struct linkorigin {
 };
 typedef struct linkorigin linkorigin_t;
 
-#define MAX_CACHED_ORIGINS  10
-#define MAX_CACHED_FILE_ORIGINS 8
+extern uint32_t _hfs_max_origins;
+extern uint32_t _hfs_max_file_origins;
+
+#define MAX_CACHED_ORIGINS_DEFAULT 10
+#define MAX_CACHED_ORIGINS (_hfs_max_origins)
+#define MAX_CACHED_FILE_ORIGINS_DEFAULT 8
+#define MAX_CACHED_FILE_ORIGINS (_hfs_max_file_origins)
 
 /*
  * The cnode is used to represent each active (or recently active)
index 3fa485b27e8e8d4405c2eff8d27798ac5243588f..937595b69659fd5482a87eebcc536fd98d643074 100644 (file)
@@ -74,6 +74,11 @@ void cpkp_init(cp_key_pair_t *cpkp, uint16_t max_pers_key_len,
 {
        cpkp->cpkp_max_pers_key_len = max_pers_key_len;
        cpkp->cpkp_pers_key_len = 0;
+
+       cpx_t embedded_cpx = cpkp_cpx(cpkp);
+       /* XNU requires us to allocate the AES context separately */
+       cpx_alloc_ctx (embedded_cpx);
+
        cpx_init(cpkp_cpx(cpkp), max_cached_key_len);
 
        // Default to using offsets
@@ -449,7 +454,7 @@ int cp_setup_newentry (struct hfsmount *hfsmp, struct cnode *dcp,
  */
 int cpx_gentempkeys(cpx_t *pcpx, __unused struct hfsmount *hfsmp)
 {
-       cpx_t cpx = cpx_alloc(CP_MAX_KEYSIZE);
+       cpx_t cpx = cpx_alloc(CP_MAX_KEYSIZE, true);
 
        cpx_set_key_len(cpx, CP_MAX_KEYSIZE);
        read_random(cpx_key(cpx), CP_MAX_KEYSIZE);
@@ -661,7 +666,7 @@ cp_vnode_setclass(struct vnode *vp, cp_key_class_t newclass)
                                goto out;
                        }
 
-                       cp_key_pair_t *cpkp;
+                       cp_key_pair_t *cpkp = NULL;
                        cprotect_t new_entry = cp_entry_alloc(NULL, 0, CP_MAX_KEYSIZE, &cpkp);
 
                        if (!new_entry) {
@@ -1570,7 +1575,7 @@ cp_entry_alloc(cprotect_t old, uint16_t pers_key_len,
        size += 4;      // Extra for magic2
 #endif
 
-       cp_entry = hfs_malloc(size);
+       cp_entry = hfs_mallocz(size);
 
        if (old) {
                memcpy(cp_entry, old, offsetof(struct cprotect, cp_keys));
@@ -1579,8 +1584,6 @@ cp_entry_alloc(cprotect_t old, uint16_t pers_key_len,
                // We don't copy the key roll context
                cp_entry->cp_key_roll_ctx = NULL;
 #endif
-       } else {
-               bzero(cp_entry, offsetof(struct cprotect, cp_keys));
        }
 
 #if DEBUG
@@ -1617,6 +1620,13 @@ cp_entry_dealloc(__unused hfsmount_t *hfsmp, struct cprotect *entry)
 
        size_t entry_size = (sizeof(struct cprotect) - sizeof(cp_key_pair_t)
                                                 + cpkp_sizex(&entry->cp_keys));
+       
+       /* 
+        * We are freeing the HFS cprotect, which contains the memory for 'cpx'
+        * Don't forget to release the CPX AES context 
+        */
+       cpx_t embedded_cpx = cpkp_cpx(&entry->cp_keys);
+       cpx_free_ctx (embedded_cpx);
 
 #if DEBUG
        hfs_assert(entry->cp_magic1 == cp_magic1);
@@ -1665,7 +1675,7 @@ static int cp_read_xattr_v4(__unused hfsmount_t *hfsmp, struct cp_xattr_v4 *xatt
        }
 
        /* set up entry with information from xattr */
-       cp_key_pair_t *cpkp;
+       cp_key_pair_t *cpkp = NULL;
        cprotect_t entry;
        
        if (ISSET(options, CP_GET_XATTR_BASIC_INFO)) {
@@ -1753,7 +1763,7 @@ int cp_read_xattr_v5(hfsmount_t *hfsmp, struct cp_xattr_v5 *xattr,
        }
 #endif
 
-       cp_key_pair_t *cpkp;
+       cp_key_pair_t *cpkp = NULL;
        cprotect_t entry;
        
        /* 
index 0b89b25c7c87f649906b5fa476a7a92e0e837fe0..ea397d586832af95c56e5ec1977a0df390719fa4 100644 (file)
@@ -373,6 +373,9 @@ enum {
 
 #define HFSIOC_FORCE_ENABLE_DEFRAG _IOWR('h', 49, u_int32_t)
 
+/* NOTE: fsctl selector 'h' 50 is defined in XNU  */
+
+
 /* These fsctls are ported from apfs. */
 #ifndef APFSIOC_SET_NEAR_LOW_DISK
 #define APFSIOC_SET_NEAR_LOW_DISK _IOW('J', 17, u_int32_t)
index 5908364c1c778d8667679cc1a8ce9de59d791452..eb2d703e1f60ee15c75e2b0d0b560356b2f42876 100644 (file)
@@ -37,6 +37,7 @@
 #include "hfs_iokit.h"
 #include "hfs.h"
 #include "hfs_dbg.h"
+#include "hfs_cnode.h"
 
 #ifndef panic_on_assert
 bool panic_on_assert;
@@ -122,6 +123,18 @@ bool com_apple_filesystems_hfs::start(IOService *provider)
        
        hfs_sysctl_register();
 
+       uint32_t num_cpus;
+       size_t sz = sizeof(num_cpus);
+
+       if (sysctlbyname("hw.physicalcpu", &num_cpus,  &sz, NULL, 0) == 0) {
+               if ((2 * num_cpus) > MAX_CACHED_ORIGINS_DEFAULT) {
+                       _hfs_max_origins = 2 * num_cpus;
+                       _hfs_max_file_origins = 2 * num_cpus;
+               } else if ((2 * num_cpus) > MAX_CACHED_FILE_ORIGINS_DEFAULT) {
+                       _hfs_max_file_origins = 2 * num_cpus;
+               }
+       }
+
        return true;
 }
 
index f1e6ee60883e09d3ab7aba265a7227bf47207033..6900da50d4dfba0ddb73dc4bc0325d52a3a9f2f7 100644 (file)
@@ -2916,6 +2916,14 @@ journal_modify_block_end(journal *jnl, struct buf *bp, void (*func)(buf_t bp, vo
                 * corresponding write to the btree.
                 */
                task_update_logical_writes(current_task(), (2 * bsize), TASK_WRITE_METADATA, vp);
+               /*
+                * Update the physical writes counter for metadata writes.
+                * We use (2 * bsize) to account for the write to the on-disk journal
+                * followed by write to actual location later.
+                */
+               task_update_physical_writes(current_task(), TASK_PHYSICAL_WRITE_METADATA,
+                                                                       (2 * bsize),
+                                                                       TASK_BALANCE_CREDIT);
 
                if (func) {
                        void (*old_func)(buf_t, void *)=NULL, *old_arg=NULL;
@@ -3881,11 +3889,11 @@ end_transaction(transaction *tr, int force_it, errno_t (*callback)(void*), void
 
        lock_oldstart(jnl);
        /*
-        * Because old_start is locked above, we can cast away the volatile qualifier before passing it to memcpy.
+        * Because old_start is locked above, we can cast away the volatile qualifier before passing it to memmove.
         * slide everyone else down and put our latest guy in the last
         * entry in the old_start array
         */
-       memcpy(__CAST_AWAY_QUALIFIER(&jnl->old_start[0], volatile, void *), __CAST_AWAY_QUALIFIER(&jnl->old_start[1], volatile, void *), sizeof(jnl->old_start)-sizeof(jnl->old_start[0]));
+       memmove(__CAST_AWAY_QUALIFIER(&jnl->old_start[0], volatile, void *), __CAST_AWAY_QUALIFIER(&jnl->old_start[1], volatile, void *), sizeof(jnl->old_start)-sizeof(jnl->old_start[0]));
        jnl->old_start[sizeof(jnl->old_start)/sizeof(jnl->old_start[0]) - 1] = tr->journal_start | 0x8000000000000000LL;
 
        unlock_oldstart(jnl);
index 99092aa45ab98743115fa470961363d40ec617ea..d7a070e2101a44e50d11c463b22b9b86756a155b 100644 (file)
@@ -354,7 +354,7 @@ hfs_vnop_write(struct vnop_write_args *ap)
        off_t filebytes;
        off_t offset;
        ssize_t resid;
-       int eflags;
+       int eflags = 0;
        int ioflag = ap->a_ioflag;
        int retval = 0;
        int lockflags;
@@ -1556,10 +1556,14 @@ hfs_vnop_ioctl( struct vnop_ioctl_args /* {
        {
                struct vnode *file_vp;
                cnid_t  cnid;
-               int  outlen;
-               char *bufptr;
                int error;
                int flags = 0;
+               char *bufptr;
+#ifdef VN_GETPATH_NEW
+               size_t outlen;
+#else  // VN_GETPATH_NEW
+               int outlen;
+#endif // VN_GETPATH_NEW
 
                /* Caller must be owner of file system. */
                vfsp = vfs_statfs(HFSTOVFS(hfsmp));
@@ -1579,14 +1583,15 @@ hfs_vnop_ioctl( struct vnop_ioctl_args /* {
 
                /* We need to call hfs_vfs_vget to leverage the code that will
                 * fix the origin list for us if needed, as opposed to calling
-                * hfs_vget, since we will need the parent for build_path call.
+                * hfs_vget, since we will need the parent for vn_getpath_ext call.
                 */
 
                if ((error = hfs_vfs_vget(HFSTOVFS(hfsmp), cnid, &file_vp, context))) {
                        return (error);
                }
 
-               error = build_path(file_vp, bufptr, sizeof(pathname_t), &outlen, flags, context);
+               outlen = sizeof(pathname_t);
+               error = vn_getpath_ext(file_vp, NULLVP,  bufptr, &outlen, flags);
                vnode_put(file_vp);
 
                return (error);
@@ -5364,7 +5369,7 @@ hfs_relocate(struct  vnode *vp, u_int32_t  blockHint, kauth_cred_t cred,
        u_int32_t  growsize;
        u_int32_t  nextallocsave;
        daddr64_t  sector_a,  sector_b;
-       int eflags;
+       int eflags = 0;
        off_t  newbytes;
        int  retval;
        int lockflags = 0;
index 6ceab5416aebcdf3700e9162d1596465b52c34b4..2859ac2d1c112d18c54d40794c0b597d3268e053 100644 (file)
@@ -140,7 +140,7 @@ extern struct vnodeopv_desc hfs_std_vnodeop_opv_desc;
 static int hfs_flushMDB(struct hfsmount *hfsmp, int waitfor, int altflush);
 #endif
 
-/* not static so we can re-use in hfs_readwrite.c for build_path calls */
+/* not static so we can re-use in hfs_readwrite.c for vn_getpath_ext calls */
 int hfs_vfs_vget(struct mount *mp, ino64_t ino, struct vnode **vpp, vfs_context_t context);
 
 static int hfs_changefs(struct mount *mp, struct hfs_mount_args *args);
@@ -1218,6 +1218,16 @@ hfs_mountfs(struct vnode *devvp, struct mount *mp, struct hfs_mount_args *args,
                goto error_exit;
        }
 
+       if (phys_blksize < log_blksize) {
+               /*
+                * In the off chance that the phys_blksize is SMALLER than the logical
+                * then don't let that happen.  Pretend that the PHYSICALBLOCKSIZE
+                * ioctl was not supported.
+                */
+               phys_blksize = log_blksize;
+       }
+
+
        /* Switch to 512 byte sectors (temporarily) */
        if (log_blksize > 512) {
                u_int32_t size512 = 512;
@@ -1288,6 +1298,7 @@ hfs_mountfs(struct vnode *devvp, struct mount *mp, struct hfs_mount_args *args,
                        goto error_exit;
                }
        }
+
        /*
         * At this point:
         *   minblksize is the minimum physical block size
@@ -1296,6 +1307,7 @@ hfs_mountfs(struct vnode *devvp, struct mount *mp, struct hfs_mount_args *args,
         */
 
        mdb_offset = (daddr64_t)HFS_PRI_SECTOR(log_blksize);
+
        if ((retval = (int)buf_meta_bread(devvp, 
                                HFS_PHYSBLK_ROUNDDOWN(mdb_offset, (phys_blksize/log_blksize)), 
                                phys_blksize, cred, &bp))) {
@@ -3220,7 +3232,7 @@ hfs_sysctl(int *name, u_int namelen, user_addr_t oldp, size_t *oldlenp,
 
 /* 
  * hfs_vfs_vget is not static since it is used in hfs_readwrite.c to support
- * the build_path ioctl.  We use it to leverage the code below that updates
+ * the vn_getpath_ext.  We use it to leverage the code below that updates
  * the origin list cache if necessary
  */
 
@@ -4258,17 +4270,36 @@ hfs_vfs_getattr(struct mount *mp, struct vfs_attr *fsap, __unused vfs_context_t
        }
 #endif
 
+       /*
+        * Some of these attributes can be expensive to query if we're
+        * backed by a disk image; hfs_freeblks() has to ask the backing
+        * store, and this might involve a trip to a network file server.
+        * Only ask for them if the caller really wants them.  Preserve old
+        * behavior for file systems not backed by a disk image.
+        */
+#if HFS_SPARSE_DEV
+       const int diskimage = (hfsmp->hfs_backingvp != NULL);
+#else
+       const int diskimage = 0;
+#endif
+
        VFSATTR_RETURN(fsap, f_objcount, (u_int64_t)hfsmp->vcbFilCnt + (u_int64_t)hfsmp->vcbDirCnt);
        VFSATTR_RETURN(fsap, f_filecount, (u_int64_t)hfsmp->vcbFilCnt);
        VFSATTR_RETURN(fsap, f_dircount, (u_int64_t)hfsmp->vcbDirCnt);
        VFSATTR_RETURN(fsap, f_maxobjcount, (u_int64_t)0xFFFFFFFF);
        VFSATTR_RETURN(fsap, f_iosize, (size_t)cluster_max_io_size(mp, 0));
        VFSATTR_RETURN(fsap, f_blocks, (u_int64_t)hfsmp->totalBlocks);
-       VFSATTR_RETURN(fsap, f_bfree, (u_int64_t)hfs_freeblks(hfsmp, 0));
-       VFSATTR_RETURN(fsap, f_bavail, (u_int64_t)hfs_freeblks(hfsmp, 1));
+       if (VFSATTR_WANTED(fsap, f_bfree) || !diskimage) {
+               VFSATTR_RETURN(fsap, f_bfree, (u_int64_t)hfs_freeblks(hfsmp, 0));
+       }
+       if (VFSATTR_WANTED(fsap, f_bavail) || !diskimage) {
+               VFSATTR_RETURN(fsap, f_bavail, (u_int64_t)hfs_freeblks(hfsmp, 1));
+       }
        VFSATTR_RETURN(fsap, f_bsize, (u_int32_t)vcb->blockSize);
        /* XXX needs clarification */
-       VFSATTR_RETURN(fsap, f_bused, hfsmp->totalBlocks - hfs_freeblks(hfsmp, 1));
+       if (VFSATTR_WANTED(fsap, f_bused) || !diskimage) {
+               VFSATTR_RETURN(fsap, f_bused, hfsmp->totalBlocks - hfs_freeblks(hfsmp, 1));
+       }
        VFSATTR_RETURN(fsap, f_files, (u_int64_t)HFS_MAX_FILES);
        VFSATTR_RETURN(fsap, f_ffree, (u_int64_t)hfs_free_cnids(hfsmp));
 
index fa2d856e8b4a3175489286b071ec4af3612eb863..6aeac8d6005178a4df649aa99979f202641e72ce 100644 (file)
@@ -4403,21 +4403,17 @@ void *hfs_mallocz(size_t size)
 // -- 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_CNODE_ZONE, sizeof(struct cnode), "HFS node" },
+       { HFS_FILEFORK_ZONE, sizeof(struct filefork), "HFS fork" },
+       { HFS_DIRHINT_ZONE, sizeof(struct directoryhint), "HFS dirhint" }
 };
 
 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);
+               hfs_zones[i].hz_zone = zone_create(hfs_zone_entries[i].hze_name,
+                   hfs_zone_entries[i].hze_elem_size, ZC_NOENCRYPT);
        }
 }
 
index db88785d9128ce76fabf55737313f8229504c280..237f071a12bfe95356231708597dd7eb088c463c 100644 (file)
@@ -4672,16 +4672,6 @@ relock:
        tdcp = VTOC(tdvp);
        tcp = tvp ? VTOC(tvp) : NULL;
 
-
-       /*
-        * If caller requested an exclusive rename (VFS_RENAME_EXCL) and 'tcp' exists
-        * then we must fail the operation. 
-        */
-       if (tcp && rename_exclusive) {
-               error = EEXIST;
-               goto out;
-       }
-
        //
        // if the item is tracked but doesn't have a document_id, assign one and generate an fsevent for it
        //
@@ -5102,9 +5092,24 @@ relock:
                        struct FndrExtendedDirInfo *tfip = (struct FndrExtendedDirInfo *)((char *)&tcp->c_attr.ca_finderinfo + 16);
                        
                        if (ffip->document_id && tfip->document_id) {
-                               // both documents are tracked.  only save a tombstone from tcp and do nothing else.
-                               doc_tombstone_save(tdvp, tvp, tcnp, hfs_get_document_id(tcp),
-                                                                  tcp->c_fileid);
+                               // Both documents are tracked.  `tvp` is deleted and `fvp` is
+                               // renamed on top of it.  Send FSE_DOCID_CHANGED for both inodes,
+                               // clear tombstone of `old_doc_vp` and save tombstone of `fvp`.
+                               add_fsevent(FSE_DOCID_CHANGED, vfs_context_current(),
+                                               FSE_ARG_DEV, hfsmp->hfs_raw_dev,
+                                               FSE_ARG_INO, (ino64_t)tcp->c_fileid,           // src inode #
+                                               FSE_ARG_INO, (ino64_t)0ULL,                    // dst inode #
+                                               FSE_ARG_INT32, (uint32_t)tfip->document_id,
+                                               FSE_ARG_DONE);
+                               add_fsevent(FSE_DOCID_CHANGED, vfs_context_current(),
+                                               FSE_ARG_DEV, hfsmp->hfs_raw_dev,
+                                               FSE_ARG_INO, (ino64_t)fcp->c_fileid,           // src inode #
+                                               FSE_ARG_INO, (ino64_t)tcp->c_fileid,           // dst inode #
+                                               FSE_ARG_INT32, (uint32_t)ffip->document_id,
+                                               FSE_ARG_DONE);
+                               doc_tombstone_clear(doc_tombstone_get(), &old_doc_vp);
+                               doc_tombstone_save(tdvp, fvp, tcnp, hfs_get_document_id(fcp),
+                                                                  fcp->c_fileid);
                        } else {
                                struct  doc_tombstone *ut;
                                ut = doc_tombstone_get();
@@ -5148,9 +5153,16 @@ relock:
                /*
                 * When fvp matches tvp they could be case variants
                 * or matching hard links.
+                * If the caller requested an exclusive rename (VFS_RENAME_EXCL),
+                * we allow rename when the target already exists when the following
+                * conditions are met:
+                * 1. the volume is case insensitive
+                * 2. source and target directories are the same
+                * 3. source and target files are the same
+                * 4. name only differs in case
                 */
                if (fvp == tvp) {
-                       if (!(fcp->c_flag & C_HARDLINK)) {
+                       if (!rename_exclusive && !(fcp->c_flag & C_HARDLINK)) {
                                /* 
                                 * If they're not hardlinks, then fvp == tvp must mean we 
                                 * are using case-insensitive HFS because case-sensitive would
@@ -5193,8 +5205,12 @@ relock:
                                 * op was dir1/fred -> dir1/bob
                                 * That would fail/do nothing.
                                 */
+
                                goto skip_rm;  /* case-variant hardlink in the same dir */
-                       } else {
+                       } else if (rename_exclusive) {
+                               error = EEXIST;
+                               goto out;
+                       } else  {
                                goto out;  /* matching hardlink, nothing to do */
                        }
                }
@@ -6353,12 +6369,17 @@ hfs_update(struct vnode *vp, int options)
 
        if (__builtin_expect(kdebug_enable & KDEBUG_TRACE, 0)) {
                long dbg_parms[NUMPARMS];
-               int  dbg_namelen;
+               int err;
+#ifdef VN_GETPATH_NEW
+               size_t dbg_namelen;
+#else  // VN_GETPATH_NEW
+               int dbg_namelen;
+#endif // VN_GETPATH_NEW
 
                dbg_namelen = NUMPARMS * sizeof(long);
-               vn_getpath(vp, (char *)dbg_parms, &dbg_namelen);
+               err = vn_getpath_ext(vp, NULLVP,  (char *)dbg_parms, &dbg_namelen, 0);
 
-               if (dbg_namelen < (int)sizeof(dbg_parms))
+               if (!err && (dbg_namelen < (int)sizeof(dbg_parms)))
                        memset((char *)dbg_parms + dbg_namelen, 0, sizeof(dbg_parms) - dbg_namelen);
 
                kdebug_lookup_gen_events(dbg_parms, dbg_namelen, (void *)vp, TRUE);
index 0d3dcd357bf86bf0c698e542df8f4d831a795626..311b901610d3bb56e4d93a4afeb4abd3d8c2c7bc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2017 Apple Inc. All rights reserved.
+ * Copyright (c) 2004-2020 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
@@ -1080,6 +1080,12 @@ int hfs_setxattr_internal (struct cnode *cp, const void *data_ptr, size_t attrsi
        
        /* If it won't fit inline then use extent-based attributes. */
        if (attrsize > hfsmp->hfs_max_inline_attrsize) {
+#if (TARGET_OS_OSX && TARGET_CPU_ARM64)
+               printf("hfs_setxattr: non-inline attributes are not supported\n");
+               //NOTE: ENOTSUP will fool XNU into thinking we need AppleDouble files...
+               result = EPERM;
+               goto exit;
+#else
                int blkcnt;
                int extentblks;
                u_int32_t *keystartblk;
@@ -1180,6 +1186,7 @@ int hfs_setxattr_internal (struct cnode *cp, const void *data_ptr, size_t attrsi
                        extentblks = count_extent_blocks(blkcnt, recp->overflowExtents.extents);
                        blkcnt -= extentblks;
                }
+#endif //(TARGET_OS_OSX && TARGET_CPU_ARM64)
        } else { /* Inline data */ 
                if (exists) {
                        result = remove_attribute_records(hfsmp, iterator);
@@ -2429,7 +2436,7 @@ read_attr_data(struct hfsmount *hfsmp, uio_t uio, size_t datasize, HFSPlusExtent
 /*
  * Write an extent based attribute.
  */
-static int
+__unused static int
 write_attr_data(struct hfsmount *hfsmp, uio_t uio, size_t datasize, HFSPlusExtentDescriptor *extents)
 {
        vnode_t evp = hfsmp->hfs_attrdata_vp;
@@ -2479,7 +2486,7 @@ write_attr_data(struct hfsmount *hfsmp, uio_t uio, size_t datasize, HFSPlusExten
 /*
  * Allocate blocks for an extent based attribute.
  */
-static int
+__unused static int
 alloc_attr_blks(struct hfsmount *hfsmp, size_t attrsize, size_t extentbufsize, HFSPlusExtentDescriptor *extents, int *blocks)
 {
        int blkcnt;
index a5ce2b6aafd4c6bde10dbe44cee8b3b53d18e020..26c8a4a97fb361a11bec9f22702f126ce44357b8 100644 (file)
@@ -179,7 +179,7 @@ void CalculateCacheSizes(uint64_t cacheSize, uint32_t *calcBlockSize, uint32_t *
        }
 
        *calcBlockSize = blockSize;
-       *calcTotalBlocks = cacheSize / blockSize;
+       *calcTotalBlocks = (uint32_t)(cacheSize / blockSize);
        
 out:
        return;
index f85a014961221acb0179701428ca2d9853ceb45f..f096887a4008cca91f53a319f3c7cf1441d8f5e7 100644 (file)
@@ -315,7 +315,7 @@ OSStatus    ExtendBTree     (BTreeControlBlockPtr   btreePtr,
        
        //////////////////// Calc New Total Number Of Nodes /////////////////////////
        
-       newTotalNodes = filePtr->fcbLogicalSize / nodeSize;             //¥¥ hack!
+       newTotalNodes = (UInt32)(filePtr->fcbLogicalSize / nodeSize);           //¥¥ hack!
        //¥¥ do we wish to perform any verification of newTotalNodes at this point?
 
        btreePtr->totalNodes = newTotalNodes;           //¥¥ do we need to update freeNodes here too?
@@ -534,7 +534,7 @@ UInt32              CalcMapBits     (BTreeControlBlockPtr    btreePtr)
 {
        UInt32          mapBits;
        
-       mapBits         = M_HeaderMapRecordSize (btreePtr->nodeSize) << 3;
+       mapBits         = (UInt32)(M_HeaderMapRecordSize (btreePtr->nodeSize) << 3);
        
        while (mapBits < btreePtr->totalNodes)
                mapBits += M_MapRecordSize (btreePtr->nodeSize) << 3;
index bc1787dc0e3f68f0c190b3f6f578927358f32c15..91dde7ba4e2835042acd7beee9c21204c70e7847 100755 (executable)
@@ -802,8 +802,18 @@ RepairHardLinkChains(SGlobPtr gp, Boolean isdir)
                        flags = rec.hfsPlusFolder.flags;
                        li = hash_search(inodeID, slots, slotsUsed, linkInfo);
                } else {
+            long ref_num;
+
                        inodeID = rec.hfsPlusFile.fileID;
-                       link_ref_num = atol((char*)&filename[prefixlen]);
+            ref_num = atol((char*)&filename[prefixlen]);
+            if (ref_num < 0 || ref_num > UINT32_MAX) {
+                result = EINVAL;
+                if (fsckGetVerbosity(gp->context) >= kDebugLog) {
+                    plog ("\tLink reference num=%ld is invalid for inode=%u result=%d\n", ref_num, inodeID, result);
+                }
+                break;
+            }
+                       link_ref_num = (UInt32)ref_num;
                        flags = rec.hfsPlusFile.flags;
                        li = hash_search(link_ref_num, slots, slotsUsed, linkInfo);
                }
index 517cddcfb24da6acd0c615295dd6651205f32af3..e2e83feb1776010a37b93bde4d59e07373e835de 100644 (file)
@@ -357,7 +357,7 @@ SetEndOfForkProc ( SFCB *filePtr, FSSize minEOF, FSSize maxEOF )
        if ( filePtr->fcbFileID == kHFSRepairCatalogFileID)
                flags |= kEFNoExtOvflwMask;
        
-       result = ExtendFileC ( vcb, filePtr, (bytesToAdd+511)>>9, flags, &actualSectorsAdded );
+       result = ExtendFileC ( vcb, filePtr, (UInt32)((bytesToAdd+511)>>9), flags, &actualSectorsAdded );
        ReturnIfError(result);
 
        filePtr->fcbLogicalSize = filePtr->fcbPhysicalSize;     // new B-tree looks at fcbEOF
@@ -388,7 +388,7 @@ SetEndOfForkProc ( SFCB *filePtr, FSSize minEOF, FSSize maxEOF )
                        
                        //      Zero newly allocated portion of HFS+ private file.
                        if ( result == noErr )
-                               result = ZeroFileBlocks( vcb, filePtr, fileSize - actualSectorsAdded, actualSectorsAdded );
+                               result = ZeroFileBlocks( vcb, filePtr, (UInt32)(fileSize - actualSectorsAdded), actualSectorsAdded );
                }
        }
        else if ( vcb->vcbSignature == kHFSSigWord )
@@ -399,7 +399,7 @@ SetEndOfForkProc ( SFCB *filePtr, FSSize minEOF, FSSize maxEOF )
                        MarkVCBDirty( vcb );
                        result = FlushAlternateVolumeControlBlock( vcb, false );
                        if ( result == noErr )
-                               result = ZeroFileBlocks( vcb, filePtr, fileSize - actualSectorsAdded, actualSectorsAdded );
+                               result = ZeroFileBlocks( vcb, filePtr, (UInt32)(fileSize - actualSectorsAdded), actualSectorsAdded );
                }
                else if ( filePtr->fcbFileID == kHFSCatalogFileID || filePtr->fcbFileID == kHFSRepairCatalogFileID )
                {
@@ -407,7 +407,7 @@ SetEndOfForkProc ( SFCB *filePtr, FSSize minEOF, FSSize maxEOF )
                        MarkVCBDirty( vcb );
                        result = FlushAlternateVolumeControlBlock( vcb, false );
                        if ( result == noErr )
-                               result = ZeroFileBlocks( vcb, filePtr, fileSize - actualSectorsAdded, actualSectorsAdded );
+                               result = ZeroFileBlocks( vcb, filePtr, (UInt32)(fileSize - actualSectorsAdded), actualSectorsAdded );
                }
        }
        
index c8225a6876fcab00c9b1b32f2c0ed02ea956ed12..67dab52e065a87eb30f15ca295d470519071dba9 100644 (file)
@@ -205,7 +205,7 @@ OSErr DeviceRead(int device, int drive, void* buffer, SInt64 offset, UInt32 reqB
                return (5);
        }
 
-       *actBytes = nbytes;
+       *actBytes = (UInt32)nbytes;
        return (0);
 
 #else
@@ -258,7 +258,7 @@ OSErr DeviceWrite(int device, int drive, void* buffer, SInt64 offset, UInt32 req
                return (5);
        }
 
-       *actBytes = nbytes;
+       *actBytes = (UInt32)nbytes;
        return (0);
 #else
        OSErr err;
index 129790590c1d9cc1b08ec7c22aa15d431a6b6cfd..cc06d34a63aad2f3588568392c34627c8d83d351 100644 (file)
@@ -495,7 +495,7 @@ OSErr MapFileBlockC (
        if (temp > numberOfBytes)
                *availableBytes = numberOfBytes;                // more there than they asked for, so pin the output
        else
-               *availableBytes = temp;
+               *availableBytes = (UInt32)temp;
        
 //     LogEndTime(kTraceMapFileBlock, noErr);
 
@@ -787,7 +787,7 @@ OSErr ExtendFileC (
        //
        //      Determine the physical EOF in allocation blocks
        //
-       eofBlocks = fcb->fcbPhysicalSize / vcb->vcbBlockSize;
+       eofBlocks = (UInt32)(fcb->fcbPhysicalSize / vcb->vcbBlockSize);
 
        //
        //      Make sure the request won't make the file too big (>=2GB).
@@ -1346,7 +1346,7 @@ static OSErr SearchExtentFile(
        UInt32                          filePositionBlock;
        Boolean                         noMoreExtents = true;
        
-       filePositionBlock = sectorOffset / (vcb->vcbBlockSize >> kSectorShift);
+       filePositionBlock = (UInt32)(sectorOffset / (vcb->vcbBlockSize >> kSectorShift));
        
        //      Search the resident FCB first.
        err = GetFCBExtentRecord(vcb, fcb, foundExtentData);
@@ -1603,7 +1603,7 @@ static OSErr MapFileBlockFromFCB(
        UInt32  index;
        UInt32  offsetBlocks;
        
-       offsetBlocks = sectorOffset / (vcb->vcbBlockSize >> kSectorShift);
+       offsetBlocks = (UInt32)(sectorOffset / (vcb->vcbBlockSize >> kSectorShift));
        
        if (vcb->vcbSignature == kHFSSigWord) {
                const HFSExtentDescriptor *extent;
index 99511684cb670c4ef836fa68196f633f82826a32..c92ad81531132735cf33d3c6b72610216bfbeffb 100755 (executable)
@@ -474,7 +474,7 @@ ExitThisRoutine:
        SFCB *                                  myFCBPtr, * oldFCBPtr;
        UInt32                                  myBytesUsed = 0;
        UInt32                                  myMapNodeCount;
-       UInt64                                  myNumBlocks;
+       UInt32                                  myNumBlocks;
        FSSize                                  myNewEOF;
        BTHeaderRec                             myHeaderRec;
        
@@ -532,7 +532,7 @@ ExitThisRoutine:
        myErr = BlockFindAll( myBTreeCBPtr->fcbPtr, myNumBlocks);
        ReturnIfError( myErr );
        myBTreeCBPtr->fcbPtr->fcbPhysicalSize = myNewEOF;
-       myErr = ZeroFileBlocks( myVCBPtr, myBTreeCBPtr->fcbPtr, 0, myNewEOF >> kSectorShift );
+       myErr = ZeroFileBlocks( myVCBPtr, myBTreeCBPtr->fcbPtr, 0, (UInt32)(myNewEOF >> kSectorShift) );
        ReturnIfError( myErr );
 
        /* now set real values in our BTree Control Block */
@@ -544,7 +544,7 @@ ExitThisRoutine:
        else if (FileID == kHFSExtentsFileID)
                myFCBPtr->fcbClumpSize = myVCBPtr->vcbExtentsFile->fcbClumpSize;
        
-       myBTreeCBPtr->totalNodes = ( myFCBPtr->fcbPhysicalSize / myBTreeCBPtr->nodeSize );
+       myBTreeCBPtr->totalNodes = (UInt32)( myFCBPtr->fcbPhysicalSize / myBTreeCBPtr->nodeSize );
        myBTreeCBPtr->freeNodes = myBTreeCBPtr->totalNodes;
 
        // Initialize our new BTree (write out header node and an empty leaf node)
index f1d32cd7365b283866347bacf58881124496d282..65cc03ac8acadc8fcbab56989de6ee0c37615a3e 100644 (file)
@@ -877,7 +877,7 @@ OSErr FixBadLinkChainFirst(SGlobPtr GPtr, RepairOrderPtr p)
                (void)snprintf((char*)&attrRec->attrData[0],
                        sizeof(attrdata) - offsetof(HFSPlusAttrData, attrData),
                        "%lu", (unsigned long)(p->correct));
-               attrRec->attrSize = 1 + strlen((char*)&attrRec->attrData[0]);
+               attrRec->attrSize = (u_int32_t)(1 + strlen((char*)&attrRec->attrData[0]));
                bt_data.bufferAddress = attrRec;
                recsize = sizeof(HFSPlusAttrData) - 2 + attrRec->attrSize + ((attrRec->attrSize & 1) ? 1 : 0);
                bt_data.itemSize = recsize;
@@ -941,7 +941,7 @@ OSErr FixHardLinkBadDate(SGlobPtr GPtr, RepairOrderPtr p)
                if (rec.recordType != kHFSPlusFileRecord) {
                        retval = IntError(GPtr, R_IntErr);
                } else {
-                       rec.hfsPlusFile.createDate = p->correct;
+                       rec.hfsPlusFile.createDate = (u_int32_t)p->correct;
                        retval = ReplaceBTreeRecord(GPtr->calculatedCatalogFCB, &key, kNoHint, &rec, recsize, &hint);
                }
        }
@@ -1298,7 +1298,7 @@ OSErr UpdFolderCount( SGlobPtr GPtr, RepairOrderPtr p)
        }
 #endif
 
-       record.hfsPlusFolder.folderCount = p->correct;
+       record.hfsPlusFolder.folderCount = (u_int32_t)p->correct;
        result = ReplaceBTreeRecord( GPtr->calculatedCatalogFCB, &foundKey, hint,
                &record, recSize, &hint);
        if (result) {
@@ -2879,7 +2879,7 @@ static OSErr FixBadExtent(SGlobPtr GPtr, RepairOrderPtr p)
        Boolean didRepair;
 
        fileID = p->parid;
-       badExtentIndex = p->correct;
+       badExtentIndex = (UInt32)p->correct;
        extentStartBlock = p->hint;
        forkType = p->forkType;
 
@@ -4036,7 +4036,7 @@ Output:           <0 if *a < *b
 
 int cmpLongs ( const void *a, const void *b )
 {
-       return( *(long*)a - *(long*)b );
+       return (int)( *(long*)a - *(long*)b );
 }
 
 /* Function: FixOverlappingExtents
@@ -5142,7 +5142,7 @@ OSErr GetSystemFileName(UInt32 fileID, char *filename, unsigned int *filenamelen
                                break;
                };
                filename[len] = '\0';
-               *filenamelen = strlen (filename);
+               *filenamelen = (unsigned int)strlen (filename);
        }
        return err;
 }
@@ -5284,7 +5284,7 @@ OSErr GetFileNamePathByID(SGlobPtr GPtr, UInt32 fileID, char *fullPath, unsigned
                }
 
                /* Do not NULL terminate the string */
-               curPtr->namelen = namelen;
+               curPtr->namelen = (unsigned int)namelen;
                curPtr->name = malloc(namelen);
                if (!curPtr->name) {
                        err = memFullErr;
@@ -5581,7 +5581,7 @@ FixMissingDirectory( SGlob *GPtr, UInt32 theObjID, UInt32 theParID )
        // no way to find the original name and this should make it unique within our
        // lost+found directory.
        sprintf( myString, "%ld", (long)theObjID );
-       nameLen = strlen( myString );
+       nameLen = (int)strlen( myString );
 
     if ( isHFSPlus )
     {
@@ -5927,7 +5927,7 @@ UInt32 CreateDirByName(SGlob *GPtr , const u_char *dirName, const UInt32 parentI
        
        isHFSPlus = VolumeObjectIsHFSPlus( );
        fcbPtr = GPtr->calculatedCatalogFCB;
-       nameLen = strlen( (char *)dirName );
+       nameLen = (int)strlen( (char *)dirName );
 
     if ( isHFSPlus )
     {
index 23b4ea7d0c627901af169dd1f5b60de36a83145a..0223f5e42884803ccdaba9232219fb6ee7472ef4 100644 (file)
@@ -51,7 +51,8 @@ UInt32 GetTimeUTC(void)
 
        (void) gettimeofday(&time, &zone);
 
-       return time.tv_sec + MAC_GMT_FACTOR;
+    // Value will be bigger than UIN32_MAX in 2040
+       return (UInt32)(time.tv_sec + MAC_GMT_FACTOR);
 }
 
 /*
index 9c6605963fee5856c244e1f73c6cec32a672544c..961545345c4e51d4d3eaa4ceec7238795ea0e75a 100644 (file)
@@ -1642,7 +1642,7 @@ DumpData(const void *data, size_t len, char *label)
                        if (*tmp)
                                allzeroes = 0;
                }
-               for (i = gap; i >= 0; i--) {
+               for (i = (int)gap; i >= 0; i--) {
                        fprintf(stderr, "  ");
                        if (i % 2 == 1)
                                fprintf(stderr, " ");
@@ -2308,17 +2308,17 @@ OSErr   FlushVolumeControlBlock( SVCB *vcb )
                fcb = vcb->vcbExtentsFile;
                CopyMemory( fcb->fcbExtents32, volumeHeader->extentsFile.extents, sizeof(HFSPlusExtentRecord) );
                volumeHeader->extentsFile.logicalSize = fcb->fcbLogicalSize;
-               volumeHeader->extentsFile.totalBlocks = fcb->fcbPhysicalSize / vcb->vcbBlockSize;
+               volumeHeader->extentsFile.totalBlocks = (u_int32_t)(fcb->fcbPhysicalSize / vcb->vcbBlockSize);
        
                fcb = vcb->vcbCatalogFile;
                CopyMemory( fcb->fcbExtents32, volumeHeader->catalogFile.extents, sizeof(HFSPlusExtentRecord) );
                volumeHeader->catalogFile.logicalSize = fcb->fcbLogicalSize;
-               volumeHeader->catalogFile.totalBlocks = fcb->fcbPhysicalSize / vcb->vcbBlockSize;
+               volumeHeader->catalogFile.totalBlocks = (u_int32_t)(fcb->fcbPhysicalSize / vcb->vcbBlockSize);
 
                fcb = vcb->vcbAllocationFile;
                CopyMemory( fcb->fcbExtents32, volumeHeader->allocationFile.extents, sizeof(HFSPlusExtentRecord) );
                volumeHeader->allocationFile.logicalSize = fcb->fcbLogicalSize;
-               volumeHeader->allocationFile.totalBlocks = fcb->fcbPhysicalSize / vcb->vcbBlockSize;
+               volumeHeader->allocationFile.totalBlocks = (u_int32_t)(fcb->fcbPhysicalSize / vcb->vcbBlockSize);
                
                if (vcb->vcbAttributesFile != NULL)     //      Only update fields if an attributes file existed and was open
                {
@@ -2326,7 +2326,7 @@ OSErr     FlushVolumeControlBlock( SVCB *vcb )
                        CopyMemory( fcb->fcbExtents32, volumeHeader->attributesFile.extents, sizeof(HFSPlusExtentRecord) );
                        volumeHeader->attributesFile.logicalSize = fcb->fcbLogicalSize;
                        volumeHeader->attributesFile.clumpSize = fcb->fcbClumpSize;
-                       volumeHeader->attributesFile.totalBlocks = fcb->fcbPhysicalSize / vcb->vcbBlockSize;
+                       volumeHeader->attributesFile.totalBlocks = (u_int32_t)(fcb->fcbPhysicalSize / vcb->vcbBlockSize);
                }
        }
        else
index 7ccbafdf90ccb7188fc75bae1d78fda77257490e..cb81689367f1b99eb81312decaf98d54e2176559 100644 (file)
@@ -259,7 +259,7 @@ GetJournalInfoBlock(SGlobPtr GPtr, JournalInfoBlock *jibp, UInt32 *bsizep)
                        if (jibp)
                                memcpy(jibp, block, sizeof(JournalInfoBlock));
                        if (bsizep)
-                               *bsizep = blockSize;
+                               *bsizep = (UInt32)blockSize;
                        result = 0;
                } else {
                        if (debug) {
@@ -602,6 +602,7 @@ OSErr IVChk( SGlobPtr GPtr )
        OSErr                                           err;
        HFSMasterDirectoryBlock *       myMDBPtr;
        HFSPlusVolumeHeader *           myVHBPtr;
+       UInt64                                  numBlk;
        UInt32                                  numABlks;
        UInt32                                  minABlkSz;
        UInt32                                  maxNumberOfAllocationBlocks;
@@ -721,7 +722,7 @@ OSErr IVChk( SGlobPtr GPtr )
                
                // catch the case where the volume allocation block count is greater than 
                // maximum number of device allocation blocks. - bug 2916021
-               numABlks = myVOPtr->totalDeviceSectors / ( myVHBPtr->blockSize / Blk_Size );
+               numABlks = (UInt32)(myVOPtr->totalDeviceSectors / ( myVHBPtr->blockSize / Blk_Size ));
                if ( myVHBPtr->totalBlocks > numABlks ) {
                        RcdError( GPtr, E_NABlks );
                        err = E_NABlks;                                 
@@ -753,16 +754,17 @@ OSErr IVChk( SGlobPtr GPtr )
 
        //  verify volume allocation info
        //      Note: i is the number of sectors per allocation block
-       numABlks = totalSectors;
+       numBlk = totalSectors;
        minABlkSz = Blk_Size;                                                   //      init minimum ablock size
        //      loop while #ablocks won't fit
-       for( i = 2; numABlks > maxNumberOfAllocationBlocks; i++ ) {
+       for( i = 2; numBlk > maxNumberOfAllocationBlocks; i++ ) {
                minABlkSz = i * Blk_Size;                                       //      jack up minimum
-               numABlks  = totalSectors / i;                           //      recompute #ablocks, assuming this size
+               numBlk  = totalSectors / i;                             //      recompute #ablocks, assuming this size
         }
 
+       numABlks = (UInt32)numBlk;
        vcb->vcbBlockSize = realAllocationBlockSize;
-       numABlks = totalSectors / ( realAllocationBlockSize / Blk_Size );
+       numABlks = (UInt32)(totalSectors / ( realAllocationBlockSize / Blk_Size ));
        if ( VolumeObjectIsHFSPlus( ) ) {
                // HFS Plus allocation block size must be power of 2
                if ( (realAllocationBlockSize < minABlkSz) || 
@@ -794,7 +796,7 @@ OSErr IVChk( SGlobPtr GPtr )
                bitMapSizeInSectors = ( numABlks + kBitsPerSector - 1 ) / kBitsPerSector;                       //      VBM size in blocks
 
                //¥¥    Calculate the validaty of HFS Allocation blocks, I think realTotalBlocks == numABlks
-               numABlks = (totalSectors - 3 - bitMapSizeInSectors) / (realAllocationBlockSize / Blk_Size);     //      actual # of alloc blks
+               numABlks = (UInt32)((totalSectors - 3 - bitMapSizeInSectors) / (realAllocationBlockSize / Blk_Size));   //      actual # of alloc blks
 
                if ( realTotalBlocks > numABlks ) {
                        RcdError( GPtr, E_NABlks );
@@ -1075,7 +1077,7 @@ OSErr     CreateExtentsBTreeControlBlock( SGlobPtr GPtr )
                btcb->lastLeafNode              = header.lastLeafNode;
 
                btcb->nodeSize                  = header.nodeSize;
-               btcb->totalNodes                = ( GPtr->calculatedExtentsFCB->fcbPhysicalSize / btcb->nodeSize );
+               btcb->totalNodes                = (UInt32)( GPtr->calculatedExtentsFCB->fcbPhysicalSize / btcb->nodeSize );
                btcb->freeNodes                 = btcb->totalNodes;                                                             //      start with everything free
 
                //      Make sure the header nodes size field is correct by looking at the 1st record offset
@@ -1083,7 +1085,7 @@ OSErr     CreateExtentsBTreeControlBlock( SGlobPtr GPtr )
                if ( (err != noErr) && (btcb->nodeSize != 1024) )               //      default HFS+ Extents node size is 1024
                {
                        btcb->nodeSize                  = 1024;
-                       btcb->totalNodes                = ( GPtr->calculatedExtentsFCB->fcbPhysicalSize / btcb->nodeSize );
+                       btcb->totalNodes                = (UInt32)( GPtr->calculatedExtentsFCB->fcbPhysicalSize / btcb->nodeSize );
                        btcb->freeNodes                 = btcb->totalNodes;                                                             //      start with everything free
                        
                        err = CheckNodesFirstOffset( GPtr, btcb );
@@ -1136,7 +1138,7 @@ OSErr     CreateExtentsBTreeControlBlock( SGlobPtr GPtr )
                btcb->lastLeafNode      = header.lastLeafNode;
                
                btcb->nodeSize          = header.nodeSize;
-               btcb->totalNodes        = (GPtr->calculatedExtentsFCB->fcbPhysicalSize / btcb->nodeSize );
+               btcb->totalNodes        = (UInt32)(GPtr->calculatedExtentsFCB->fcbPhysicalSize / btcb->nodeSize );
                btcb->freeNodes         = btcb->totalNodes;                                                                     //      start with everything free
 
                //      Make sure the header nodes size field is correct by looking at the 1st record offset
@@ -1429,7 +1431,7 @@ OSErr     CreateCatalogBTreeControlBlock( SGlobPtr GPtr )
                btcb->keyCompareType            = header.keyCompareType;
                btcb->leafRecords               = header.leafRecords;
                btcb->nodeSize                  = header.nodeSize;
-               btcb->totalNodes                = ( GPtr->calculatedCatalogFCB->fcbPhysicalSize / btcb->nodeSize );
+               btcb->totalNodes                = (UInt32)( GPtr->calculatedCatalogFCB->fcbPhysicalSize / btcb->nodeSize );
                btcb->freeNodes                 = btcb->totalNodes;                                                                     //      start with everything free
                btcb->attributes                |=(kBTBigKeysMask + kBTVariableIndexKeysMask);          //      HFS+ Catalog files have large, variable-sized keys
 
@@ -1444,7 +1446,7 @@ OSErr     CreateCatalogBTreeControlBlock( SGlobPtr GPtr )
                if ( (err != noErr) && (btcb->nodeSize != 4096) )               //      default HFS+ Catalog node size is 4096
                {
                        btcb->nodeSize                  = 4096;
-                       btcb->totalNodes                = ( GPtr->calculatedCatalogFCB->fcbPhysicalSize / btcb->nodeSize );
+                       btcb->totalNodes                = (UInt32)( GPtr->calculatedCatalogFCB->fcbPhysicalSize / btcb->nodeSize );
                        btcb->freeNodes                 = btcb->totalNodes;                                                             //      start with everything free
                        
                        err = CheckNodesFirstOffset( GPtr, btcb );
@@ -1489,7 +1491,7 @@ OSErr     CreateCatalogBTreeControlBlock( SGlobPtr GPtr )
                btcb->keyCompareProc    = (void *) CompareCatalogKeys;
                btcb->leafRecords               = header.leafRecords;
                btcb->nodeSize                  = header.nodeSize;
-               btcb->totalNodes                = (GPtr->calculatedCatalogFCB->fcbPhysicalSize / btcb->nodeSize );
+               btcb->totalNodes                = (UInt32)(GPtr->calculatedCatalogFCB->fcbPhysicalSize / btcb->nodeSize );
                btcb->freeNodes                 = btcb->totalNodes;                                                                     //      start with everything free
 
                btcb->treeDepth         = header.treeDepth;
@@ -2129,7 +2131,7 @@ OSErr     CreateAttributesBTreeControlBlock( SGlobPtr GPtr )
                        btcb->keyCompareProc    = (void *)CompareAttributeKeys;
                        btcb->leafRecords               = header.leafRecords;
                        btcb->nodeSize                  = header.nodeSize;
-                       btcb->totalNodes                = ( GPtr->calculatedAttributesFCB->fcbPhysicalSize / btcb->nodeSize );
+                       btcb->totalNodes                = (UInt32)( GPtr->calculatedAttributesFCB->fcbPhysicalSize / btcb->nodeSize );
                        btcb->freeNodes                 = btcb->totalNodes;                                                                     //      start with everything free
                        btcb->attributes                |=(kBTBigKeysMask + kBTVariableIndexKeysMask);          //      HFS+ Attributes files have large, variable-sized keys
 
index 4372336637f9773187cc1b53133c4f735050fb0e..dde1d925960bc466a3feab2ef385ab2485f1d4fc 100644 (file)
@@ -706,7 +706,7 @@ int CheckVolumeBitMap(SGlobPtr g, Boolean repair)
         * them against the on-disk bitmap.
         */
        for (bit = 0; bit < gTotalBits; bit += kBitsPerSegment) {
-               (void) GetSegmentBitmap(bit, &buffer, kTestingBits);
+               (void) GetSegmentBitmap((UInt32)bit, &buffer, kTestingBits);
 
                /* 
                 * When we cross file block boundries read a new block from disk.
index ed1b0ed2debc4a66e5c36d644b963ad288a243fc..8b6831a7284dbe6d0ae61f18e1ba4431fe8149f3 100644 (file)
@@ -464,6 +464,8 @@ int get_first_link_id(SGlobPtr gptr, CatalogRecord *inode_rec, uint32_t inode_id
                retval = BTSearchRecord(gptr->calculatedAttributesFCB, &iterator, kNoHint, 
                                        &bt_data, NULL, NULL);
                if (retval == 0) {
+            unsigned long link_id;
+
                        /* Attribute should be an inline attribute */
                        if (rec->recordType != kHFSPlusAttrInlineData) {
                                if (fsckGetVerbosity(gptr->context) >= kDebugLog) {
@@ -495,7 +497,16 @@ int get_first_link_id(SGlobPtr gptr, CatalogRecord *inode_rec, uint32_t inode_id
                                }
                        }
 
-                       *first_link_id = strtoul((char *)&rec->attrData[0], NULL, 10);
+            link_id = strtoul((char *)&rec->attrData[0], NULL, 10);
+            if (link_id > UINT32_MAX) {
+                if (fsckGetVerbosity(gptr->context) >= kDebugLog) {
+                    plog ("\tfirst link ID=%lu is > UINT32_MAX for dirinode=%u\n", link_id, inode_id);
+                }
+                *first_link_id = 0;
+                retval = ENOENT;
+                goto out;
+            }
+                       *first_link_id = (uint32_t)link_id;
                        if (*first_link_id < kHFSFirstUserCatalogNodeID) {
                                if (fsckGetVerbosity(gptr->context) >= kDebugLog) {
                                        plog ("\tfirst link ID=%u is < 16 for dirinode=%u\n", *first_link_id, inode_id);
@@ -612,11 +623,21 @@ int inode_check(SGlobPtr gptr, PrimeBuckets *bucket,
                linkCount = rec->hfsPlusFolder.bsdInfo.special.linkCount;
                parentid = gptr->dirlink_priv_dir_id;
        } else {
+        unsigned long ref_num;
+
                inode_id = rec->hfsPlusFile.fileID;
                flags = rec->hfsPlusFile.flags;
                linkCount = rec->hfsPlusFile.bsdInfo.special.linkCount;
                parentid = gptr->filelink_priv_dir_id;
-               link_ref_num = strtoul(&found_name[strlen(HFS_INODE_PREFIX)], NULL, 10);
+        ref_num = strtoul(&found_name[strlen(HFS_INODE_PREFIX)], NULL, 10);
+        if (ref_num > UINT32_MAX) {
+            if (fsckGetVerbosity(gptr->context) >= kDebugLog) {
+                plog ("\tlink reference num=%lu is > UINT32_MAX for inode=%u\n", ref_num, inode_id);
+            }
+            retval = 1;
+            goto out;
+        }
+               link_ref_num = (uint32_t)ref_num;
        }
 
        /* inode should only reside in its corresponding private directory */
index d14410671809b0aeae1ef8229c8b40547de07ec0..8c76d5f7104f9c45a4924ffd5fe05fa26aab8e0a 100644 (file)
@@ -387,7 +387,7 @@ journal_open(int jfd,
        uint32_t        jBlkSize = 0;
 
        if (ioctl(jfd, DKIOCGETBLOCKSIZE, &jBlkSize) == -1) {
-               jBlkSize = min_fs_blksize;
+               jBlkSize = (uint32_t)min_fs_blksize;
        } else {
                if (jBlkSize < min_fs_blksize) {
                        fplog(stderr, "%s:  journal block size %u < min block size %zu for %s\n", __FUNCTION__, jBlkSize, min_fs_blksize, jdev_name);
index 8fdd66d86b7e54b1ade4234b986302e446677453..38fe64c680e1414887ff1737bfefbb1f6611161d 100755 (executable)
@@ -577,7 +577,7 @@ hfs_swap_HFSPlusBTInternalNode (
                        srcKey->nodeName.length*sizeof(srcKey->nodeName.unicode[0]));
                     if (cur_debug_level & d_dump_record) {
                        plog("Record %u (offset 0x%04X):\n", recordIndex, keyOffset);
-                       HexDump(srcKey, recordSize, FALSE);
+                       HexDump(srcKey, (unsigned)recordSize, FALSE);
                     }
                 }
                                WriteError(fcb->fcbVolume->vcbGPtr, E_KeyLen, fcb->fcbFileID, src->blockNum);
index 35d386cbf322b51b3c2377512780090264862ad8..49259b445fc600fe76ab0b49f414d47ce07f7839 100644 (file)
@@ -126,6 +126,7 @@ main(argc, argv)
        extern int optind;
        extern char *optarg;
        char * lastChar;
+       long mode;
 
        if ((progname = strrchr(*argv, '/')))
                ++progname;
@@ -219,10 +220,11 @@ main(argc, argv)
                        
                case 'm':
                        modeSetting++;
-                       lostAndFoundMode = strtol( optarg, NULL, 8 );
-                       if ( lostAndFoundMode == 0 )
+                       mode = strtol( optarg, NULL, 8 );
+                       lostAndFoundMode = (int)mode;
+                       if ( lostAndFoundMode == 0 || mode < INT_MIN || mode > INT_MAX)
                        {
-                               (void) fplog(stderr, "%s: invalid mode argument \n", progname);
+                               (void) fplog(stderr, "%s: %ld is invalid mode argument\n", progname, mode);
                                usage();
                        }
                        break;
@@ -705,7 +707,7 @@ setup( char *dev, int *canWritePtr )
             err(1, "fsck_hfs: fstat %s", dev);
         }
         
-        error = lseek(fswritefd, 0, SEEK_SET);
+        error = (int)lseek(fswritefd, 0, SEEK_SET);
         if (error == -1)
         {
             err(1, "fsck_hfs: Could not seek %d for dev: %s, errorno %d", fswritefd, dev, errno);
index e0c31aa3df664cba0fef1eba44fbf675a9250539..878ad6c4e632c89252c725f81d429035fe0599a2 100644 (file)
@@ -332,7 +332,7 @@ fsck_logging_thread(void *arg)
            }
        }           
 
-       copy_amt = (cur_in_mem_log - in_mem_log);
+       copy_amt = (int)(cur_in_mem_log - in_mem_log);
        if (copy_amt == 0) {
            pthread_mutex_unlock(&mem_buf_lock);
            continue;
@@ -399,7 +399,7 @@ fsck_printing_thread(void *arg)
            }
        }           
 
-       copy_amt = (cur_in_mem_out - in_mem_out);
+       copy_amt = (int)(cur_in_mem_out - in_mem_out);
        if (copy_amt == 0) {
            pthread_mutex_unlock(&mem_buf_lock);
            continue;
index ace6a65cc8cf7fedf2dffde3a05c76014ca5e656..f6998573778467b7c6b98268b78eb86b0c7caadf 100644 (file)
@@ -24,7 +24,6 @@
                        buildPhases = (
                        );
                        dependencies = (
-                               FBA540011B7BF2DF00899E5B /* PBXTargetDependency */,
                                FBC234C41B4EC6AE0002D849 /* PBXTargetDependency */,
                                4DBD523F1548A499007AA736 /* PBXTargetDependency */,
                                4DBD52411548A49A007AA736 /* PBXTargetDependency */,
@@ -72,6 +71,8 @@
                        buildPhases = (
                        );
                        dependencies = (
+                               A6873BA1234287A00045680B /* PBXTargetDependency */,
+                               A6873B9A234280440045680B /* PBXTargetDependency */,
                                9430FE98211658E7009CC8AF /* PBXTargetDependency */,
                        );
                        name = hfs_livefiles;
                900BDEFD1FF9246F002F7EC0 /* lf_hfs_logger.h in Headers */ = {isa = PBXBuildFile; fileRef = 900BDEFB1FF9246F002F7EC0 /* lf_hfs_logger.h */; };
                900BDEFE1FF9246F002F7EC0 /* lf_hfs_logger.c in Sources */ = {isa = PBXBuildFile; fileRef = 900BDEFC1FF9246F002F7EC0 /* lf_hfs_logger.c */; };
                9022D170205EC16900D9A2AE /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9022D16F205EC16900D9A2AE /* CoreFoundation.framework */; };
-               9022D171205EC18500D9A2AE /* livefiles_hfs.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 900BDED41FF919C2002F7EC0 /* livefiles_hfs.dylib */; };
                9022D174205FE5FA00D9A2AE /* lf_hfs_utils.h in Headers */ = {isa = PBXBuildFile; fileRef = 9022D172205FE5FA00D9A2AE /* lf_hfs_utils.h */; };
                9022D175205FE5FA00D9A2AE /* lf_hfs_utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 9022D173205FE5FA00D9A2AE /* lf_hfs_utils.c */; };
                9022D18120600D9E00D9A2AE /* lf_hfs_rangelist.h in Headers */ = {isa = PBXBuildFile; fileRef = 9022D17F20600D9E00D9A2AE /* lf_hfs_rangelist.h */; };
                90F5EBBB2063CC3A004397B2 /* lf_hfs_btree_node_ops.c in Sources */ = {isa = PBXBuildFile; fileRef = 90F5EBBA2063CC3A004397B2 /* lf_hfs_btree_node_ops.c */; };
                90F5EBBF2063CCE0004397B2 /* lf_hfs_btree_misc_ops.c in Sources */ = {isa = PBXBuildFile; fileRef = 90F5EBBD2063CCE0004397B2 /* lf_hfs_btree_misc_ops.c */; };
                90F5EBC12063CE12004397B2 /* lf_hfs_btree_allocate.c in Sources */ = {isa = PBXBuildFile; fileRef = 90F5EBC02063CE12004397B2 /* lf_hfs_btree_allocate.c */; };
+               A64B3BE822E8D388009A2B10 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9022D16F205EC16900D9A2AE /* CoreFoundation.framework */; };
+               A64B3BF522E8D4D6009A2B10 /* lf_cs_logging.h in Headers */ = {isa = PBXBuildFile; fileRef = A64B3BF322E8D4D6009A2B10 /* lf_cs_logging.h */; };
+               A64B3BF722E8D4D6009A2B10 /* lf_cs_logging.c in Sources */ = {isa = PBXBuildFile; fileRef = A64B3BF422E8D4D6009A2B10 /* lf_cs_logging.c */; };
+               A64B3BFB22E8D538009A2B10 /* lf_cs_checksum.h in Headers */ = {isa = PBXBuildFile; fileRef = A64B3BF922E8D538009A2B10 /* lf_cs_checksum.h */; };
+               A64B3BFC22E8D538009A2B10 /* lf_cs_checksum.c in Sources */ = {isa = PBXBuildFile; fileRef = A64B3BFA22E8D538009A2B10 /* lf_cs_checksum.c */; };
+               A64B3C0122E8D6A7009A2B10 /* livefiles_cs_tester.c in Sources */ = {isa = PBXBuildFile; fileRef = A64B3C0022E8D6A7009A2B10 /* livefiles_cs_tester.c */; };
+               A64B3C0622E8D71B009A2B10 /* lf_cs_vfsops.c in Sources */ = {isa = PBXBuildFile; fileRef = A64B3C0422E8D71B009A2B10 /* lf_cs_vfsops.c */; };
+               A64B3C0922E8D9D0009A2B10 /* livefiles_hfs.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 900BDED41FF919C2002F7EC0 /* livefiles_hfs.dylib */; };
+               A64B3C0A22E8D9D0009A2B10 /* livefiles_hfs.dylib in Embed Libraries */ = {isa = PBXBuildFile; fileRef = 900BDED41FF919C2002F7EC0 /* livefiles_hfs.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
+               A64B3C1522E91B50009A2B10 /* test-lf-cs-plugin.c in Sources */ = {isa = PBXBuildFile; fileRef = A64B3C1322E91AF6009A2B10 /* test-lf-cs-plugin.c */; };
+               A64B3C1722EA2C4F009A2B10 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A64B3C1622EA2C4E009A2B10 /* CoreFoundation.framework */; };
+               A64B3C1922EA2C5E009A2B10 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A64B3C1822EA2C5E009A2B10 /* IOKit.framework */; };
+               A6873B9B234286730045680B /* lf_cs_logging.c in Sources */ = {isa = PBXBuildFile; fileRef = A64B3BF422E8D4D6009A2B10 /* lf_cs_logging.c */; };
+               A6873B9C234286780045680B /* lf_cs_checksum.c in Sources */ = {isa = PBXBuildFile; fileRef = A64B3BFA22E8D538009A2B10 /* lf_cs_checksum.c */; };
+               A6873B9D2342868D0045680B /* lf_cs_vfsops.c in Sources */ = {isa = PBXBuildFile; fileRef = A64B3C0422E8D71B009A2B10 /* lf_cs_vfsops.c */; };
+               A6873B9F234287200045680B /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A6873B9E234287200045680B /* IOKit.framework */; };
                A6E6D74020909C72002125B0 /* test-get-volume-create-time.c in Sources */ = {isa = PBXBuildFile; fileRef = A6E6D73F20909C72002125B0 /* test-get-volume-create-time.c */; };
                C1B6FA0810CC0A0A00778D48 /* hfsutil_jnl.c in Sources */ = {isa = PBXBuildFile; fileRef = C1B6FA0610CC0A0A00778D48 /* hfsutil_jnl.c */; };
                C1B6FA0910CC0A0A00778D48 /* hfsutil_main.c in Sources */ = {isa = PBXBuildFile; fileRef = C1B6FA0710CC0A0A00778D48 /* hfsutil_main.c */; };
                FB48E5121BB3853500523121 /* hfs_fsctl.h in Headers */ = {isa = PBXBuildFile; fileRef = FB20E10C1AE9529400CEBE7B /* hfs_fsctl.h */; settings = {ATTRIBUTES = (Private, ); }; };
                FB55AE541B7C271000701D03 /* test-doc-tombstone.c in Sources */ = {isa = PBXBuildFile; fileRef = FB55AE521B7C271000701D03 /* test-doc-tombstone.c */; };
                FB55AE591B7CEB0600701D03 /* test-quotas.c in Sources */ = {isa = PBXBuildFile; fileRef = FB55AE581B7CEB0600701D03 /* test-quotas.c */; };
-               FB6A57E51B5554DE008AB046 /* hfs_fsctl.h in Headers */ = {isa = PBXBuildFile; fileRef = FB20E10C1AE9529400CEBE7B /* hfs_fsctl.h */; settings = {ATTRIBUTES = (Private, ); }; };
                FB75A4061B4AEA20004B5A74 /* hfs_encodings.c in Sources */ = {isa = PBXBuildFile; fileRef = FB20E1051AE9529400CEBE7B /* hfs_encodings.c */; };
                FB75A40B1B4AF025004B5A74 /* hfs_encodings.h in Headers */ = {isa = PBXBuildFile; fileRef = FB20E1061AE9529400CEBE7B /* hfs_encodings.h */; settings = {ATTRIBUTES = (Private, ); }; };
                FB75A40E1B4AF0BE004B5A74 /* hfs_encodings_kext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FB75A40C1B4AF0BA004B5A74 /* hfs_encodings_kext.cpp */; };
                        remoteGlobalIDString = 4DFD94BC15373C2C0039B6BA;
                        remoteInfo = fsck_makestrings;
                };
-               900BDEE51FF919E7002F7EC0 /* PBXContainerItemProxy */ = {
+               9430FE97211658E7009CC8AF /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
                        proxyType = 1;
                        remoteGlobalIDString = 900BDED31FF919C2002F7EC0;
                        remoteInfo = livefiles_hfs;
                };
-               9430FE97211658E7009CC8AF /* PBXContainerItemProxy */ = {
+               A64B3C0B22E8D9D0009A2B10 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
                        proxyType = 1;
                        remoteGlobalIDString = 900BDED31FF919C2002F7EC0;
                        remoteInfo = livefiles_hfs;
                };
+               A6873B99234280440045680B /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = A64B3BE122E8D388009A2B10;
+                       remoteInfo = livefiles_cs_tester;
+               };
+               A6873BA0234287A00045680B /* PBXContainerItemProxy */ = {
+                       isa = PBXContainerItemProxy;
+                       containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+                       proxyType = 1;
+                       remoteGlobalIDString = A64B3B9022E8D36F009A2B10;
+                       remoteInfo = livefiles_cs;
+               };
                FB48E4BB1BB30CC400523121 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
                        remoteGlobalIDString = 4DE6C75A153504C100C11066;
                        remoteInfo = newfs_hfs;
                };
-               FBA540001B7BF2DF00899E5B /* PBXContainerItemProxy */ = {
-                       isa = PBXContainerItemProxy;
-                       containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
-                       proxyType = 1;
-                       remoteGlobalIDString = FB6A57DD1B55544D008AB046;
-                       remoteInfo = "System Framework Headers";
-               };
                FBA95AAE1B5045D400887E82 /* PBXContainerItemProxy */ = {
                        isa = PBXContainerItemProxy;
                        containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
                        );
                        runOnlyForDeploymentPostprocessing = 1;
                };
+               A64B3BE922E8D388009A2B10 /* CopyFiles */ = {
+                       isa = PBXCopyFilesBuildPhase;
+                       buildActionMask = 2147483647;
+                       dstPath = /usr/share/man/man1/;
+                       dstSubfolderSpec = 0;
+                       files = (
+                       );
+                       runOnlyForDeploymentPostprocessing = 1;
+               };
+               A64B3C0D22E8D9D0009A2B10 /* Embed Libraries */ = {
+                       isa = PBXCopyFilesBuildPhase;
+                       buildActionMask = 2147483647;
+                       dstPath = "";
+                       dstSubfolderSpec = 10;
+                       files = (
+                               A64B3C0A22E8D9D0009A2B10 /* livefiles_hfs.dylib in Embed Libraries */,
+                       );
+                       name = "Embed Libraries";
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                FB76B3D01B7A4BE600FA9F2B /* CopyFiles */ = {
                        isa = PBXCopyFilesBuildPhase;
                        buildActionMask = 2147483647;
                9D7AAC861B44874E0001F573 /* mount_hfs.osx.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = mount_hfs.osx.entitlements; sourceTree = "<group>"; };
                9D7AAC871B44880B0001F573 /* hfs_util.osx.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = hfs_util.osx.entitlements; sourceTree = "<group>"; };
                9D9067881B44633C003D2117 /* fsck_hfs.osx.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = fsck_hfs.osx.entitlements; sourceTree = "<group>"; };
+               A601423723205BB00030E611 /* gen-custom-dmg.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = "gen-custom-dmg.sh"; sourceTree = "<group>"; };
+               A601423823205D9D0030E611 /* generate-compressed-image.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = "generate-compressed-image.c"; sourceTree = "<group>"; };
+               A64B3BE022E8D36F009A2B10 /* livefiles_cs.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = livefiles_cs.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
+               A64B3BEE22E8D388009A2B10 /* livefiles_cs_tester */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = livefiles_cs_tester; sourceTree = BUILT_PRODUCTS_DIR; };
+               A64B3BF322E8D4D6009A2B10 /* lf_cs_logging.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = lf_cs_logging.h; sourceTree = "<group>"; };
+               A64B3BF422E8D4D6009A2B10 /* lf_cs_logging.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = lf_cs_logging.c; sourceTree = "<group>"; };
+               A64B3BF922E8D538009A2B10 /* lf_cs_checksum.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = lf_cs_checksum.h; sourceTree = "<group>"; };
+               A64B3BFA22E8D538009A2B10 /* lf_cs_checksum.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = lf_cs_checksum.c; sourceTree = "<group>"; };
+               A64B3BFE22E8D584009A2B10 /* livefiles_cs_tester.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = livefiles_cs_tester.entitlements; sourceTree = "<group>"; };
+               A64B3C0022E8D6A7009A2B10 /* livefiles_cs_tester.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = livefiles_cs_tester.c; sourceTree = "<group>"; };
+               A64B3C0222E8D6D9009A2B10 /* lf_cs_disk_format.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = lf_cs_disk_format.h; sourceTree = "<group>"; };
+               A64B3C0422E8D71B009A2B10 /* lf_cs_vfsops.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = lf_cs_vfsops.c; sourceTree = "<group>"; };
+               A64B3C0822E8D741009A2B10 /* lf_cs.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = lf_cs.h; sourceTree = "<group>"; };
+               A64B3C1322E91AF6009A2B10 /* test-lf-cs-plugin.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = "test-lf-cs-plugin.c"; sourceTree = "<group>"; };
+               A64B3C1622EA2C4E009A2B10 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.Internal.sdk/System/Library/Frameworks/CoreFoundation.framework; sourceTree = DEVELOPER_DIR; };
+               A64B3C1822EA2C5E009A2B10 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.Internal.sdk/System/Library/Frameworks/IOKit.framework; sourceTree = DEVELOPER_DIR; };
+               A6873B9E234287200045680B /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.Internal.sdk/System/Library/Frameworks/IOKit.framework; sourceTree = DEVELOPER_DIR; };
                A6E6D73F20909C72002125B0 /* test-get-volume-create-time.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = "test-get-volume-create-time.c"; sourceTree = "<group>"; };
                C1B6FA0610CC0A0A00778D48 /* hfsutil_jnl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hfsutil_jnl.c; sourceTree = "<group>"; };
                C1B6FA0710CC0A0A00778D48 /* hfsutil_main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hfsutil_main.c; sourceTree = "<group>"; };
                FB55AE521B7C271000701D03 /* test-doc-tombstone.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "test-doc-tombstone.c"; sourceTree = "<group>"; };
                FB55AE581B7CEB0600701D03 /* test-quotas.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "test-quotas.c"; sourceTree = "<group>"; };
                FB55AE5D1B7D219700701D03 /* gen-test-plist.sh */ = {isa = PBXFileReference; lastKnownFileType = text.script.sh; path = "gen-test-plist.sh"; sourceTree = "<group>"; };
-               FB6A57DE1B55544D008AB046 /* hfs-System.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "hfs-System.framework"; sourceTree = BUILT_PRODUCTS_DIR; };
                FB75A4021B4AE765004B5A74 /* HFSEncodings.kext */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = HFSEncodings.kext; sourceTree = BUILT_PRODUCTS_DIR; };
                FB75A4031B4AE765004B5A74 /* HFSEncodings-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "HFSEncodings-Info.plist"; sourceTree = "<group>"; };
                FB75A40C1B4AF0BA004B5A74 /* hfs_encodings_kext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = hfs_encodings_kext.cpp; sourceTree = "<group>"; };
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
-                               D7B2DC81233A3F5B00F12230 /* livefiles_hfs.dylib in Frameworks */,
+                               A64B3C0922E8D9D0009A2B10 /* livefiles_hfs.dylib in Frameworks */,
                                9022D170205EC16900D9A2AE /* CoreFoundation.framework in Frameworks */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               A64B3BB422E8D36F009A2B10 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               A64B3C1722EA2C4F009A2B10 /* CoreFoundation.framework in Frameworks */,
+                               A64B3C1922EA2C5E009A2B10 /* IOKit.framework in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               A64B3BE622E8D388009A2B10 /* Frameworks */ = {
+                       isa = PBXFrameworksBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               A6873B9F234287200045680B /* IOKit.framework in Frameworks */,
+                               A64B3BE822E8D388009A2B10 /* CoreFoundation.framework in Frameworks */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                FB20E0DC1AE950C200CEBE7B /* Frameworks */ = {
                        isa = PBXFrameworksBuildPhase;
                        buildActionMask = 2147483647;
                08FB7794FE84155DC02AAC07 /* hfs */ = {
                        isa = PBXGroup;
                        children = (
+                               A64B3B8822E8D2A6009A2B10 /* livefiles_cs_plugin */,
                                900BDECD1FF91960002F7EC0 /* livefiles_hfs_plugin */,
                                4DFD953D15377C7D0039B6BA /* hfs.xcconfig */,
                                FDD9FA4614A1343D0043D4A9 /* CopyHFSMeta */,
                        path = livefiles_hfs_plugin;
                        sourceTree = "<group>";
                };
+               A64B3B8822E8D2A6009A2B10 /* livefiles_cs_plugin */ = {
+                       isa = PBXGroup;
+                       children = (
+                               A64B3BF322E8D4D6009A2B10 /* lf_cs_logging.h */,
+                               A64B3BF422E8D4D6009A2B10 /* lf_cs_logging.c */,
+                               A64B3BF922E8D538009A2B10 /* lf_cs_checksum.h */,
+                               A64B3BFA22E8D538009A2B10 /* lf_cs_checksum.c */,
+                               A64B3BFE22E8D584009A2B10 /* livefiles_cs_tester.entitlements */,
+                               A64B3C0022E8D6A7009A2B10 /* livefiles_cs_tester.c */,
+                               A64B3C0222E8D6D9009A2B10 /* lf_cs_disk_format.h */,
+                               A64B3C0422E8D71B009A2B10 /* lf_cs_vfsops.c */,
+                               A64B3C0822E8D741009A2B10 /* lf_cs.h */,
+                       );
+                       path = livefiles_cs_plugin;
+                       sourceTree = "<group>";
+               };
                C1B6FD2C10CC0DB200778D48 /* Products */ = {
                        isa = PBXGroup;
                        children = (
                                86CBF37F183186C300A64A93 /* libhfs_metadata.a */,
                                FB20E0E01AE950C200CEBE7B /* HFS.kext */,
                                FB75A4021B4AE765004B5A74 /* HFSEncodings.kext */,
-                               FB6A57DE1B55544D008AB046 /* hfs-System.framework */,
                                FBAA82451B56F24100EE6863 /* hfs_alloc_test */,
                                FBAA82511B56F26A00EE6863 /* hfs_extents_test */,
                                FBAA825D1B56F28C00EE6863 /* rangelist_test */,
                                FB48E5041BB3798500523121 /* Sim_Headers */,
                                900BDED41FF919C2002F7EC0 /* livefiles_hfs.dylib */,
                                900BDEDD1FF919DE002F7EC0 /* livefiles_hfs_tester */,
+                               A64B3BE022E8D36F009A2B10 /* livefiles_cs.dylib */,
+                               A64B3BEE22E8D388009A2B10 /* livefiles_cs_tester */,
                        );
                        name = Products;
                        sourceTree = "<group>";
                                FBD69AF81B91309C0022ECAD /* test-dateadded.c */,
                                09D6B7D61E317ED2003C20DC /* test_disklevel.c */,
                                A6E6D73F20909C72002125B0 /* test-get-volume-create-time.c */,
+                               A64B3C1322E91AF6009A2B10 /* test-lf-cs-plugin.c */,
                        );
                        path = cases;
                        sourceTree = "<group>";
                                FB76B3EF1B7BE67400FA9F2B /* systemx.c */,
                                FB76B3F01B7BE67400FA9F2B /* systemx.h */,
                                FBAA826F1B56F32900EE6863 /* test-utils.h */,
+                               A601423723205BB00030E611 /* gen-custom-dmg.sh */,
+                               A601423823205D9D0030E611 /* generate-compressed-image.c */,
                        );
                        path = tests;
                        sourceTree = "<group>";
                FDD9FA4014A133A50043D4A9 /* Frameworks */ = {
                        isa = PBXGroup;
                        children = (
+                               A64B3C1822EA2C5E009A2B10 /* IOKit.framework */,
+                               A6873B9E234287200045680B /* IOKit.framework */,
                                C1B6FA2210CC0AF400778D48 /* CoreFoundation.framework */,
                                9022D16F205EC16900D9A2AE /* CoreFoundation.framework */,
+                               A64B3C1622EA2C4E009A2B10 /* CoreFoundation.framework */,
                                4DE6C7461535012200C11066 /* IOKit.framework */,
                                FDD9FA5B14A135840043D4A9 /* libz.dylib */,
                                4DE6C74A1535018100C11066 /* libutil.dylib */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               A64B3BB522E8D36F009A2B10 /* Headers */ = {
+                       isa = PBXHeadersBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               A64B3BF522E8D4D6009A2B10 /* lf_cs_logging.h in Headers */,
+                               A64B3BFB22E8D538009A2B10 /* lf_cs_checksum.h in Headers */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                FB20E0DD1AE950C200CEBE7B /* Headers */ = {
                        isa = PBXHeadersBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
-               FB6A57E41B5554D5008AB046 /* Headers */ = {
-                       isa = PBXHeadersBuildPhase;
-                       buildActionMask = 2147483647;
-                       files = (
-                               FB6A57E51B5554DE008AB046 /* hfs_fsctl.h in Headers */,
-                       );
-                       runOnlyForDeploymentPostprocessing = 0;
-               };
                FB75A3DF1B4AE765004B5A74 /* Headers */ = {
                        isa = PBXHeadersBuildPhase;
                        buildActionMask = 2147483647;
                                900BDED91FF919DE002F7EC0 /* Sources */,
                                900BDEDA1FF919DE002F7EC0 /* Frameworks */,
                                900BDEDB1FF919DE002F7EC0 /* CopyFiles */,
+                               A64B3C0D22E8D9D0009A2B10 /* Embed Libraries */,
                        );
                        buildRules = (
                        );
                        dependencies = (
-                               900BDEE61FF919E7002F7EC0 /* PBXTargetDependency */,
+                               A64B3C0C22E8D9D0009A2B10 /* PBXTargetDependency */,
                        );
                        name = livefiles_hfs_tester;
                        productName = livefiles_hfs_tester;
                        productReference = 900BDEDD1FF919DE002F7EC0 /* livefiles_hfs_tester */;
                        productType = "com.apple.product-type.tool";
                };
+               A64B3B9022E8D36F009A2B10 /* livefiles_cs */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = A64B3BDC22E8D36F009A2B10 /* Build configuration list for PBXNativeTarget "livefiles_cs" */;
+                       buildPhases = (
+                               A64B3B9122E8D36F009A2B10 /* Sources */,
+                               A64B3BB422E8D36F009A2B10 /* Frameworks */,
+                               A64B3BB522E8D36F009A2B10 /* Headers */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                       );
+                       name = livefiles_cs;
+                       productName = livefiles_hfs;
+                       productReference = A64B3BE022E8D36F009A2B10 /* livefiles_cs.dylib */;
+                       productType = "com.apple.product-type.library.dynamic";
+               };
+               A64B3BE122E8D388009A2B10 /* livefiles_cs_tester */ = {
+                       isa = PBXNativeTarget;
+                       buildConfigurationList = A64B3BEA22E8D388009A2B10 /* Build configuration list for PBXNativeTarget "livefiles_cs_tester" */;
+                       buildPhases = (
+                               A64B3BE422E8D388009A2B10 /* Sources */,
+                               A64B3BE622E8D388009A2B10 /* Frameworks */,
+                               A64B3BE922E8D388009A2B10 /* CopyFiles */,
+                       );
+                       buildRules = (
+                       );
+                       dependencies = (
+                       );
+                       name = livefiles_cs_tester;
+                       productName = livefiles_cs_tester;
+                       productReference = A64B3BEE22E8D388009A2B10 /* livefiles_cs_tester */;
+                       productType = "com.apple.product-type.tool";
+               };
                FB20E0DF1AE950C200CEBE7B /* kext */ = {
                        isa = PBXNativeTarget;
                        buildConfigurationList = FB20E0E61AE950C200CEBE7B /* Build configuration list for PBXNativeTarget "kext" */;
                        productReference = FB48E5041BB3798500523121 /* Sim_Headers */;
                        productType = "com.apple.product-type.tool";
                };
-               FB6A57DD1B55544D008AB046 /* System Framework Headers */ = {
-                       isa = PBXNativeTarget;
-                       buildConfigurationList = FB6A57E11B55544D008AB046 /* Build configuration list for PBXNativeTarget "System Framework Headers" */;
-                       buildPhases = (
-                               FB6A57E41B5554D5008AB046 /* Headers */,
-                               FB5695F81C0F5ED0004C52F2 /* ShellScript */,
-                       );
-                       buildRules = (
-                       );
-                       dependencies = (
-                       );
-                       name = "System Framework Headers";
-                       productName = test;
-                       productReference = FB6A57DE1B55544D008AB046 /* hfs-System.framework */;
-                       productType = "com.apple.product-type.bundle";
-               };
                FB75A3B11B4AE765004B5A74 /* encodings-kext */ = {
                        isa = PBXNativeTarget;
                        buildConfigurationList = FB75A3FF1B4AE765004B5A74 /* Build configuration list for PBXNativeTarget "encodings-kext" */;
                                                CreatedOnToolsVersion = 10.0;
                                                ProvisioningStyle = Automatic;
                                        };
+                                       A64B3B9022E8D36F009A2B10 = {
+                                               ProvisioningStyle = Automatic;
+                                       };
+                                       A64B3BE122E8D388009A2B10 = {
+                                               ProvisioningStyle = Automatic;
+                                       };
                                        DB1AAB7C20472D140036167F = {
                                                CreatedOnToolsVersion = 9.3;
                                                ProvisioningStyle = Automatic;
                                        FB48E5031BB3798500523121 = {
                                                CreatedOnToolsVersion = 7.0;
                                        };
-                                       FB6A57DD1B55544D008AB046 = {
-                                               CreatedOnToolsVersion = 7.0;
-                                       };
                                        FB76B3D11B7A4BE600FA9F2B = {
                                                CreatedOnToolsVersion = 7.0;
                                        };
                                FBE3F7821AF67748005BB768 /* osx-root */,
                                FBC234B91B4D87A20002D849 /* ios-root */,
                                FBA95AA91B5025E700887E82 /* mk-xnu */,
-                               FB6A57DD1B55544D008AB046 /* System Framework Headers */,
                                FB48E49B1BB3070400523121 /* OSX Kernel Framework Headers */,
                                FBAA82441B56F24100EE6863 /* hfs_alloc_test */,
                                FBAA82501B56F26A00EE6863 /* hfs_extents_test */,
                                900BDED31FF919C2002F7EC0 /* livefiles_hfs */,
                                900BDEDC1FF919DE002F7EC0 /* livefiles_hfs_tester */,
                                9430FE92211658C1009CC8AF /* hfs_livefiles */,
+                               A64B3B9022E8D36F009A2B10 /* livefiles_cs */,
+                               A64B3BE122E8D388009A2B10 /* livefiles_cs_tester */,
                        );
                };
 /* End PBXProject section */
                        shellScript = "\"$SCRIPT_INPUT_FILE_0\" \"$SCRIPT_OUTPUT_FILE_0\"\n";
                        showEnvVarsInLog = 0;
                };
-               FB5695F81C0F5ED0004C52F2 /* ShellScript */ = {
-                       isa = PBXShellScriptBuildPhase;
-                       buildActionMask = 8;
-                       files = (
-                       );
-                       inputPaths = (
-                       );
-                       outputPaths = (
-                       );
-                       runOnlyForDeploymentPostprocessing = 1;
-                       shellPath = /bin/sh;
-                       shellScript = "ditto \"$BUILT_PRODUCTS_DIR/$FULL_PRODUCT_NAME\" \"$DSTROOT\"/System/Library/Frameworks/System.framework\n";
-               };
                FB5695FC1C0F98F2004C52F2 /* Create DMG */ = {
                        isa = PBXShellScriptBuildPhase;
                        buildActionMask = 2147483647;
                        );
                        inputPaths = (
                                "$(SRCROOT)/tests/gen-dmg.sh",
+                               "$(SRCROOT)/tests/gen-custom-dmg.sh",
                        );
                        name = "Create DMG";
                        outputPaths = (
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                        shellPath = /bin/sh;
-                       shellScript = "set -e\n\nif [ $PLATFORM_NAME != macosx ] ; then\n  \"$SCRIPT_INPUT_FILE_0\" \"$DERIVED_SOURCES_DIR/dmg.dat\"\nfi\ntouch \"$SCRIPT_OUTPUT_FILE_0\"\n";
+                       shellScript = "set -e\n\nif [ $PLATFORM_NAME != macosx ] ; then\n  \"$SCRIPT_INPUT_FILE_0\" \"$DERIVED_SOURCES_DIR/dmg.dat\"\nfi\ntouch \"$SCRIPT_OUTPUT_FILE_0\"\n\nif [ $PLATFORM_NAME != macosx ] ; then\nfor FS in JHFS+ APFS FAT32 EXFAT; do\n    \"$SCRIPT_INPUT_FILE_1\" \"$FS\" \"$DERIVED_SOURCES_DIR/$FS-dmg.dat\"\n  done\nfi\n\n";
                        showEnvVarsInLog = 0;
                };
                FB7C14111C2368F4004F8B2C /* ShellScript */ = {
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
+               A64B3B9122E8D36F009A2B10 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               A64B3C0622E8D71B009A2B10 /* lf_cs_vfsops.c in Sources */,
+                               A64B3BFC22E8D538009A2B10 /* lf_cs_checksum.c in Sources */,
+                               A64B3BF722E8D4D6009A2B10 /* lf_cs_logging.c in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
+               A64B3BE422E8D388009A2B10 /* Sources */ = {
+                       isa = PBXSourcesBuildPhase;
+                       buildActionMask = 2147483647;
+                       files = (
+                               A64B3C0122E8D6A7009A2B10 /* livefiles_cs_tester.c in Sources */,
+                               A6873B9B234286730045680B /* lf_cs_logging.c in Sources */,
+                               A6873B9D2342868D0045680B /* lf_cs_vfsops.c in Sources */,
+                               A6873B9C234286780045680B /* lf_cs_checksum.c in Sources */,
+                       );
+                       runOnlyForDeploymentPostprocessing = 0;
+               };
                FB20E0DB1AE950C200CEBE7B /* Sources */ = {
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                                2A9399C11BE15F6800FB075B /* test-msync-16k.c in Sources */,
                                2A9399C21BE15F6800FB075B /* test-readdir.c in Sources */,
                                2A9399C31BE15F6800FB075B /* test-set-create-time.c in Sources */,
+                               A64B3C1522E91B50009A2B10 /* test-lf-cs-plugin.c in Sources */,
                                2A9399C41BE15F6800FB075B /* test-set-protection-class.c in Sources */,
                                2A9399B81BE14AAD00FB075B /* test-scan-range-size.c in Sources */,
                                2A9399B61BE131A400FB075B /* test-resize.m in Sources */,
                        target = 4DFD94BC15373C2C0039B6BA /* fsck_makestrings */;
                        targetProxy = 4DBD52521548A4D4007AA736 /* PBXContainerItemProxy */;
                };
-               900BDEE61FF919E7002F7EC0 /* PBXTargetDependency */ = {
+               9430FE98211658E7009CC8AF /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = 900BDED31FF919C2002F7EC0 /* livefiles_hfs */;
-                       targetProxy = 900BDEE51FF919E7002F7EC0 /* PBXContainerItemProxy */;
+                       targetProxy = 9430FE97211658E7009CC8AF /* PBXContainerItemProxy */;
                };
-               9430FE98211658E7009CC8AF /* PBXTargetDependency */ = {
+               A64B3C0C22E8D9D0009A2B10 /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = 900BDED31FF919C2002F7EC0 /* livefiles_hfs */;
-                       targetProxy = 9430FE97211658E7009CC8AF /* PBXContainerItemProxy */;
+                       targetProxy = A64B3C0B22E8D9D0009A2B10 /* PBXContainerItemProxy */;
+               };
+               A6873B9A234280440045680B /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = A64B3BE122E8D388009A2B10 /* livefiles_cs_tester */;
+                       targetProxy = A6873B99234280440045680B /* PBXContainerItemProxy */;
+               };
+               A6873BA1234287A00045680B /* PBXTargetDependency */ = {
+                       isa = PBXTargetDependency;
+                       target = A64B3B9022E8D36F009A2B10 /* livefiles_cs */;
+                       targetProxy = A6873BA0234287A00045680B /* PBXContainerItemProxy */;
                };
                FB48E4BC1BB30CC400523121 /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = 4DE6C75A153504C100C11066 /* newfs_hfs */;
                        targetProxy = FB81AFB91B83E2B8004E8F76 /* PBXContainerItemProxy */;
                };
-               FBA540011B7BF2DF00899E5B /* PBXTargetDependency */ = {
-                       isa = PBXTargetDependency;
-                       target = FB6A57DD1B55544D008AB046 /* System Framework Headers */;
-                       targetProxy = FBA540001B7BF2DF00899E5B /* PBXContainerItemProxy */;
-               };
                FBA95AAF1B5045D400887E82 /* PBXTargetDependency */ = {
                        isa = PBXTargetDependency;
                        target = FBA95AA91B5025E700887E82 /* mk-xnu */;
                        };
                        name = Coverage;
                };
-               DB1AAB7D20472D140036167F /* Release */ = {
-                       isa = XCBuildConfiguration;
-                       buildSettings = {
-                               CODE_SIGN_STYLE = Automatic;
-                               PRODUCT_NAME = "$(TARGET_NAME)";
-                       };
-                       name = Release;
-               };
-               DB1AAB7E20472D140036167F /* Debug */ = {
-                       isa = XCBuildConfiguration;
-                       buildSettings = {
-                               CODE_SIGN_STYLE = Automatic;
-                               PRODUCT_NAME = "$(TARGET_NAME)";
-                       };
-                       name = Debug;
-               };
-               DB1AAB7F20472D140036167F /* Coverage */ = {
-                       isa = XCBuildConfiguration;
-                       buildSettings = {
-                               CODE_SIGN_STYLE = Automatic;
-                               PRODUCT_NAME = "$(TARGET_NAME)";
-                       };
-                       name = Coverage;
-               };
-               FB20E0E71AE950C200CEBE7B /* Release */ = {
-                       isa = XCBuildConfiguration;
-                       baseConfigurationReference = FB20E1781AE968BD00CEBE7B /* kext.xcconfig */;
-                       buildSettings = {
-                               CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
-                               CLANG_CXX_LIBRARY = "libc++";
-                               CLANG_ENABLE_OBJC_ARC = YES;
-                               CLANG_WARN_ASSIGN_ENUM = YES;
-                               CLANG_WARN_BOOL_CONVERSION = YES;
-                               CLANG_WARN_EMPTY_BODY = YES;
-                               CLANG_WARN_ENUM_CONVERSION = YES;
-                               CLANG_WARN_INT_CONVERSION = YES;
-                               CLANG_WARN_UNREACHABLE_CODE = YES;
-                               CODE_SIGN_IDENTITY = "-";
-                               COMBINE_HIDPI_IMAGES = YES;
-                               COPY_HEADERS_RUN_UNIFDEF = YES;
-                               COPY_HEADERS_UNIFDEF_FLAGS = "-UKERNEL";
-                               DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
-                               GCC_C_LANGUAGE_STANDARD = gnu99;
-                               GCC_SYMBOLS_PRIVATE_EXTERN = YES;
-                               GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES;
-                               GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES;
-                               GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES;
-                               GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
-                               GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
-                               GCC_WARN_ABOUT_RETURN_TYPE = YES;
-                               GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES;
-                               GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES;
-                               GCC_WARN_SHADOW = YES;
-                               GCC_WARN_SIGN_COMPARE = YES;
-                               GCC_WARN_UNINITIALIZED_AUTOS = YES;
-                               GCC_WARN_UNKNOWN_PRAGMAS = YES;
-                               GCC_WARN_UNUSED_FUNCTION = YES;
-                               GCC_WARN_UNUSED_LABEL = YES;
-                               GCC_WARN_UNUSED_VARIABLE = YES;
-                               INFOPLIST_FILE = "$(PROJECT_DERIVED_FILE_DIR)/kext-Info.plist";
-                               INSTALL_MODE_FLAG = "a+rX";
-                               LLVM_LTO = YES;
-                               MODULE_NAME = "com.apple.file-systems.hfs.kext";
-                               MODULE_VERSION = 1.0.0;
-                               PRODUCT_BUNDLE_IDENTIFIER = com.apple.filesystems.hfs.kext;
-                               PRODUCT_NAME = HFS;
-                               SDKROOT = macosx.internal;
-                               WARNING_CFLAGS = (
-                                       "$(inherited)",
-                                       "-Wno-unused-parameter",
-                                       "-Wno-shorten-64-to-32",
-                               );
-                               WRAPPER_EXTENSION = kext;
-                       };
-                       name = Release;
-               };
-               FB48E4A31BB3070500523121 /* Release */ = {
+               A64B3BDD22E8D36F009A2B10 /* Release */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ALWAYS_SEARCH_USER_PATHS = NO;
-                               CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+                               CLANG_ANALYZER_NONNULL = YES;
+                               CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+                               CLANG_ANALYZER_OBJC_UNUSED_IVARS = YES;
+                               CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
                                CLANG_CXX_LIBRARY = "libc++";
+                               CLANG_ENABLE_MODULES = NO;
                                CLANG_ENABLE_OBJC_ARC = YES;
+                               CLANG_ENABLE_OBJC_WEAK = YES;
+                               CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
                                CLANG_WARN_BOOL_CONVERSION = YES;
+                               CLANG_WARN_COMMA = YES;
                                CLANG_WARN_CONSTANT_CONVERSION = YES;
                                CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+                               CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
                                CLANG_WARN_EMPTY_BODY = YES;
                                CLANG_WARN_ENUM_CONVERSION = YES;
+                               CLANG_WARN_INFINITE_RECURSION = YES;
                                CLANG_WARN_INT_CONVERSION = YES;
+                               CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+                               CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
                                CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+                               CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+                               CLANG_WARN_STRICT_PROTOTYPES = YES;
+                               CLANG_WARN_SUSPICIOUS_MOVE = YES;
+                               CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
                                CLANG_WARN_UNREACHABLE_CODE = YES;
                                CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
-                               COMBINE_HIDPI_IMAGES = YES;
-                               COPY_HEADERS_RUN_UNIFDEF = YES;
-                               COPY_HEADERS_UNIFDEF_FLAGS = "-DKERNEL";
-                               COPY_PHASE_STRIP = NO;
+                               CODE_SIGN_IDENTITY = "-";
+                               CODE_SIGN_STYLE = Automatic;
+                               DEAD_CODE_STRIPPING = NO;
                                DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+                               DYLIB_COMPATIBILITY_VERSION = 1;
+                               DYLIB_CURRENT_VERSION = 1;
                                ENABLE_NS_ASSERTIONS = NO;
                                ENABLE_STRICT_OBJC_MSGSEND = YES;
-                               GCC_C_LANGUAGE_STANDARD = gnu99;
+                               EXECUTABLE_PREFIX = "";
+                               FRAMEWORK_SEARCH_PATHS = "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks";
+                               GCC_C_LANGUAGE_STANDARD = gnu11;
                                GCC_NO_COMMON_BLOCKS = YES;
+                               GCC_PREPROCESSOR_DEFINITIONS = "LF_CS_USE_OSLOG=1";
                                GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
                                GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
                                GCC_WARN_UNDECLARED_SELECTOR = YES;
                                GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
-                               GCC_WARN_UNUSED_FUNCTION = YES;
+                               GCC_WARN_UNUSED_FUNCTION = NO;
+                               GCC_WARN_UNUSED_LABEL = NO;
+                               GCC_WARN_UNUSED_PARAMETER = NO;
+                               GCC_WARN_UNUSED_VALUE = NO;
                                GCC_WARN_UNUSED_VARIABLE = YES;
-                               INSTALL_PATH = /System/Library/Frameworks;
-                               MACOSX_DEPLOYMENT_TARGET = 10.11;
+                               HEADER_SEARCH_PATHS = "livefiles_cs_plugin/**";
+                               INSTALL_PATH = /System/Library/PrivateFrameworks/UserFS.framework/PlugIns;
+                               MACOSX_DEPLOYMENT_TARGET = 10.13;
                                MTL_ENABLE_DEBUG_INFO = NO;
-                               PRODUCT_NAME = Kernel;
-                               PUBLIC_HEADERS_FOLDER_PATH = Kernel.framework/Versions/A/Headers/hfs;
-                               WRAPPER_EXTENSION = framework;
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                               SDKROOT = macosx.internal;
+                               SUPPORTS_TEXT_BASED_API = NO;
                        };
                        name = Release;
                };
-               FB48E4A41BB3070500523121 /* Debug */ = {
+               A64B3BDE22E8D36F009A2B10 /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
                                ALWAYS_SEARCH_USER_PATHS = NO;
-                               CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+                               CLANG_ANALYZER_NONNULL = YES;
+                               CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+                               CLANG_ANALYZER_OBJC_UNUSED_IVARS = YES;
+                               CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+                               CLANG_CXX_LIBRARY = "libc++";
+                               CLANG_ENABLE_MODULES = NO;
+                               CLANG_ENABLE_OBJC_ARC = YES;
+                               CLANG_ENABLE_OBJC_WEAK = YES;
+                               CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+                               CLANG_WARN_BOOL_CONVERSION = YES;
+                               CLANG_WARN_COMMA = YES;
+                               CLANG_WARN_CONSTANT_CONVERSION = YES;
+                               CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+                               CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+                               CLANG_WARN_EMPTY_BODY = YES;
+                               CLANG_WARN_ENUM_CONVERSION = YES;
+                               CLANG_WARN_INFINITE_RECURSION = YES;
+                               CLANG_WARN_INT_CONVERSION = YES;
+                               CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+                               CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+                               CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+                               CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+                               CLANG_WARN_STRICT_PROTOTYPES = YES;
+                               CLANG_WARN_SUSPICIOUS_MOVE = YES;
+                               CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+                               CLANG_WARN_UNREACHABLE_CODE = YES;
+                               CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+                               CODE_SIGN_IDENTITY = "-";
+                               CODE_SIGN_STYLE = Automatic;
+                               DEAD_CODE_STRIPPING = NO;
+                               DEBUG_INFORMATION_FORMAT = dwarf;
+                               DYLIB_COMPATIBILITY_VERSION = 1;
+                               DYLIB_CURRENT_VERSION = 1;
+                               ENABLE_STRICT_OBJC_MSGSEND = YES;
+                               EXECUTABLE_PREFIX = "";
+                               FRAMEWORK_SEARCH_PATHS = "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks";
+                               GCC_C_LANGUAGE_STANDARD = gnu11;
+                               GCC_DYNAMIC_NO_PIC = NO;
+                               GCC_NO_COMMON_BLOCKS = YES;
+                               GCC_OPTIMIZATION_LEVEL = 0;
+                               GCC_PREPROCESSOR_DEFINITIONS = (
+                                       "DEBUG=1",
+                                       "LF_CS_USE_OSLOG=1",
+                                       "$(inherited)",
+                               );
+                               GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+                               GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+                               GCC_WARN_UNDECLARED_SELECTOR = YES;
+                               GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+                               GCC_WARN_UNUSED_FUNCTION = NO;
+                               GCC_WARN_UNUSED_LABEL = NO;
+                               GCC_WARN_UNUSED_PARAMETER = NO;
+                               GCC_WARN_UNUSED_VALUE = NO;
+                               GCC_WARN_UNUSED_VARIABLE = YES;
+                               HEADER_SEARCH_PATHS = "livefiles_cs_plugin/**";
+                               INSTALL_PATH = /System/Library/PrivateFrameworks/UserFS.framework/PlugIns;
+                               MACOSX_DEPLOYMENT_TARGET = 10.13;
+                               MTL_ENABLE_DEBUG_INFO = YES;
+                               ONLY_ACTIVE_ARCH = NO;
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                               SDKROOT = macosx.internal;
+                               SUPPORTS_TEXT_BASED_API = NO;
+                       };
+                       name = Debug;
+               };
+               A64B3BDF22E8D36F009A2B10 /* Coverage */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               ALWAYS_SEARCH_USER_PATHS = NO;
+                               CLANG_ANALYZER_NONNULL = YES;
+                               CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+                               CLANG_ANALYZER_OBJC_UNUSED_IVARS = YES;
+                               CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+                               CLANG_CXX_LIBRARY = "libc++";
+                               CLANG_ENABLE_MODULES = NO;
+                               CLANG_ENABLE_OBJC_ARC = YES;
+                               CLANG_ENABLE_OBJC_WEAK = YES;
+                               CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+                               CLANG_WARN_BOOL_CONVERSION = YES;
+                               CLANG_WARN_COMMA = YES;
+                               CLANG_WARN_CONSTANT_CONVERSION = YES;
+                               CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+                               CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+                               CLANG_WARN_EMPTY_BODY = YES;
+                               CLANG_WARN_ENUM_CONVERSION = YES;
+                               CLANG_WARN_INFINITE_RECURSION = YES;
+                               CLANG_WARN_INT_CONVERSION = YES;
+                               CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+                               CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+                               CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+                               CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+                               CLANG_WARN_STRICT_PROTOTYPES = YES;
+                               CLANG_WARN_SUSPICIOUS_MOVE = YES;
+                               CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+                               CLANG_WARN_UNREACHABLE_CODE = YES;
+                               CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+                               CODE_SIGN_IDENTITY = "-";
+                               CODE_SIGN_STYLE = Automatic;
+                               DEAD_CODE_STRIPPING = NO;
+                               DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+                               DYLIB_COMPATIBILITY_VERSION = 1;
+                               DYLIB_CURRENT_VERSION = 1;
+                               ENABLE_NS_ASSERTIONS = NO;
+                               ENABLE_STRICT_OBJC_MSGSEND = YES;
+                               EXECUTABLE_PREFIX = "";
+                               FRAMEWORK_SEARCH_PATHS = "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks";
+                               GCC_C_LANGUAGE_STANDARD = gnu11;
+                               GCC_NO_COMMON_BLOCKS = YES;
+                               GCC_PREPROCESSOR_DEFINITIONS = "LF_CS_USE_OSLOG=1";
+                               GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+                               GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+                               GCC_WARN_UNDECLARED_SELECTOR = YES;
+                               GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+                               GCC_WARN_UNUSED_FUNCTION = NO;
+                               GCC_WARN_UNUSED_LABEL = NO;
+                               GCC_WARN_UNUSED_PARAMETER = NO;
+                               GCC_WARN_UNUSED_VALUE = NO;
+                               GCC_WARN_UNUSED_VARIABLE = YES;
+                               HEADER_SEARCH_PATHS = "livefiles_cs_plugin/**";
+                               INSTALL_PATH = /System/Library/PrivateFrameworks/UserFS.framework/PlugIns;
+                               MACOSX_DEPLOYMENT_TARGET = 10.13;
+                               MTL_ENABLE_DEBUG_INFO = NO;
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                               SDKROOT = macosx.internal;
+                               SUPPORTS_TEXT_BASED_API = NO;
+                       };
+                       name = Coverage;
+               };
+               A64B3BEB22E8D388009A2B10 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               ALWAYS_SEARCH_USER_PATHS = YES;
+                               CLANG_ANALYZER_NONNULL = YES;
+                               CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+                               CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+                               CLANG_CXX_LIBRARY = "libc++";
+                               CLANG_ENABLE_MODULES = NO;
+                               CLANG_ENABLE_OBJC_ARC = YES;
+                               CLANG_ENABLE_OBJC_WEAK = YES;
+                               CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+                               CLANG_WARN_BOOL_CONVERSION = YES;
+                               CLANG_WARN_COMMA = YES;
+                               CLANG_WARN_CONSTANT_CONVERSION = YES;
+                               CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+                               CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+                               CLANG_WARN_EMPTY_BODY = YES;
+                               CLANG_WARN_ENUM_CONVERSION = YES;
+                               CLANG_WARN_INFINITE_RECURSION = YES;
+                               CLANG_WARN_INT_CONVERSION = YES;
+                               CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+                               CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+                               CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+                               CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+                               CLANG_WARN_STRICT_PROTOTYPES = YES;
+                               CLANG_WARN_SUSPICIOUS_MOVE = YES;
+                               CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+                               CLANG_WARN_UNREACHABLE_CODE = YES;
+                               CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+                               CODE_SIGN_ENTITLEMENTS = livefiles_cs_plugin/livefiles_cs_tester.entitlements;
+                               CODE_SIGN_IDENTITY = "-";
+                               CODE_SIGN_STYLE = Automatic;
+                               COPY_PHASE_STRIP = NO;
+                               DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+                               ENABLE_NS_ASSERTIONS = NO;
+                               ENABLE_STRICT_OBJC_MSGSEND = YES;
+                               FRAMEWORK_SEARCH_PATHS = "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks";
+                               GCC_C_LANGUAGE_STANDARD = gnu11;
+                               GCC_NO_COMMON_BLOCKS = YES;
+                               GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+                               GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+                               GCC_WARN_UNDECLARED_SELECTOR = YES;
+                               GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+                               GCC_WARN_UNUSED_FUNCTION = YES;
+                               GCC_WARN_UNUSED_VARIABLE = YES;
+                               HEADER_SEARCH_PATHS = livefiles_cs_plugin/;
+                               INSTALL_PATH = /AppleInternal/CoreOS/tests/hfs;
+                               MACOSX_DEPLOYMENT_TARGET = 10.12;
+                               MTL_ENABLE_DEBUG_INFO = NO;
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                               SDKROOT = macosx.internal;
+                               SUPPORTS_TEXT_BASED_API = NO;
+                       };
+                       name = Release;
+               };
+               A64B3BEC22E8D388009A2B10 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               ALWAYS_SEARCH_USER_PATHS = YES;
+                               CLANG_ANALYZER_NONNULL = YES;
+                               CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+                               CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+                               CLANG_CXX_LIBRARY = "libc++";
+                               CLANG_ENABLE_MODULES = NO;
+                               CLANG_ENABLE_OBJC_ARC = YES;
+                               CLANG_ENABLE_OBJC_WEAK = YES;
+                               CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+                               CLANG_WARN_BOOL_CONVERSION = YES;
+                               CLANG_WARN_COMMA = YES;
+                               CLANG_WARN_CONSTANT_CONVERSION = YES;
+                               CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+                               CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+                               CLANG_WARN_EMPTY_BODY = YES;
+                               CLANG_WARN_ENUM_CONVERSION = YES;
+                               CLANG_WARN_INFINITE_RECURSION = YES;
+                               CLANG_WARN_INT_CONVERSION = YES;
+                               CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+                               CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+                               CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+                               CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+                               CLANG_WARN_STRICT_PROTOTYPES = YES;
+                               CLANG_WARN_SUSPICIOUS_MOVE = YES;
+                               CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+                               CLANG_WARN_UNREACHABLE_CODE = YES;
+                               CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+                               CODE_SIGN_ENTITLEMENTS = livefiles_cs_plugin/livefiles_cs_tester.entitlements;
+                               CODE_SIGN_IDENTITY = "-";
+                               CODE_SIGN_STYLE = Automatic;
+                               COPY_PHASE_STRIP = NO;
+                               DEBUG_INFORMATION_FORMAT = dwarf;
+                               ENABLE_STRICT_OBJC_MSGSEND = YES;
+                               FRAMEWORK_SEARCH_PATHS = "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks";
+                               GCC_C_LANGUAGE_STANDARD = gnu11;
+                               GCC_DYNAMIC_NO_PIC = NO;
+                               GCC_NO_COMMON_BLOCKS = YES;
+                               GCC_OPTIMIZATION_LEVEL = 0;
+                               GCC_PREPROCESSOR_DEFINITIONS = (
+                                       "DEBUG=1",
+                                       "$(inherited)",
+                               );
+                               GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+                               GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+                               GCC_WARN_UNDECLARED_SELECTOR = YES;
+                               GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+                               GCC_WARN_UNUSED_FUNCTION = YES;
+                               GCC_WARN_UNUSED_VARIABLE = YES;
+                               HEADER_SEARCH_PATHS = livefiles_cs_plugin/;
+                               INSTALL_PATH = /AppleInternal/CoreOS/tests/hfs;
+                               MACOSX_DEPLOYMENT_TARGET = 10.12;
+                               MTL_ENABLE_DEBUG_INFO = YES;
+                               ONLY_ACTIVE_ARCH = YES;
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                               SDKROOT = macosx.internal;
+                               SUPPORTS_TEXT_BASED_API = NO;
+                       };
+                       name = Debug;
+               };
+               A64B3BED22E8D388009A2B10 /* Coverage */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               ALWAYS_SEARCH_USER_PATHS = YES;
+                               CLANG_ANALYZER_NONNULL = YES;
+                               CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+                               CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+                               CLANG_CXX_LIBRARY = "libc++";
+                               CLANG_ENABLE_MODULES = NO;
+                               CLANG_ENABLE_OBJC_ARC = YES;
+                               CLANG_ENABLE_OBJC_WEAK = YES;
+                               CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+                               CLANG_WARN_BOOL_CONVERSION = YES;
+                               CLANG_WARN_COMMA = YES;
+                               CLANG_WARN_CONSTANT_CONVERSION = YES;
+                               CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+                               CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+                               CLANG_WARN_EMPTY_BODY = YES;
+                               CLANG_WARN_ENUM_CONVERSION = YES;
+                               CLANG_WARN_INFINITE_RECURSION = YES;
+                               CLANG_WARN_INT_CONVERSION = YES;
+                               CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+                               CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+                               CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+                               CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+                               CLANG_WARN_STRICT_PROTOTYPES = YES;
+                               CLANG_WARN_SUSPICIOUS_MOVE = YES;
+                               CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+                               CLANG_WARN_UNREACHABLE_CODE = YES;
+                               CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+                               CODE_SIGN_ENTITLEMENTS = livefiles_cs_plugin/livefiles_cs_tester.entitlements;
+                               CODE_SIGN_IDENTITY = "-";
+                               CODE_SIGN_STYLE = Automatic;
+                               COPY_PHASE_STRIP = NO;
+                               DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+                               ENABLE_NS_ASSERTIONS = NO;
+                               ENABLE_STRICT_OBJC_MSGSEND = YES;
+                               FRAMEWORK_SEARCH_PATHS = "$(SDKROOT)$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks";
+                               GCC_C_LANGUAGE_STANDARD = gnu11;
+                               GCC_NO_COMMON_BLOCKS = YES;
+                               GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+                               GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+                               GCC_WARN_UNDECLARED_SELECTOR = YES;
+                               GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+                               GCC_WARN_UNUSED_FUNCTION = YES;
+                               GCC_WARN_UNUSED_VARIABLE = YES;
+                               HEADER_SEARCH_PATHS = livefiles_cs_plugin/;
+                               INSTALL_PATH = /AppleInternal/CoreOS/tests/hfs;
+                               MACOSX_DEPLOYMENT_TARGET = 10.12;
+                               MTL_ENABLE_DEBUG_INFO = NO;
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                               SDKROOT = macosx.internal;
+                               SUPPORTS_TEXT_BASED_API = NO;
+                       };
+                       name = Coverage;
+               };
+               DB1AAB7D20472D140036167F /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               CODE_SIGN_STYLE = Automatic;
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Release;
+               };
+               DB1AAB7E20472D140036167F /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               CODE_SIGN_STYLE = Automatic;
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Debug;
+               };
+               DB1AAB7F20472D140036167F /* Coverage */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               CODE_SIGN_STYLE = Automatic;
+                               PRODUCT_NAME = "$(TARGET_NAME)";
+                       };
+                       name = Coverage;
+               };
+               FB20E0E71AE950C200CEBE7B /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       baseConfigurationReference = FB20E1781AE968BD00CEBE7B /* kext.xcconfig */;
+                       buildSettings = {
+                               CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+                               CLANG_CXX_LIBRARY = "libc++";
+                               CLANG_ENABLE_OBJC_ARC = YES;
+                               CLANG_WARN_ASSIGN_ENUM = YES;
+                               CLANG_WARN_BOOL_CONVERSION = YES;
+                               CLANG_WARN_EMPTY_BODY = YES;
+                               CLANG_WARN_ENUM_CONVERSION = YES;
+                               CLANG_WARN_INT_CONVERSION = YES;
+                               CLANG_WARN_UNREACHABLE_CODE = YES;
+                               CODE_SIGN_IDENTITY = "-";
+                               COMBINE_HIDPI_IMAGES = YES;
+                               COPY_HEADERS_RUN_UNIFDEF = YES;
+                               COPY_HEADERS_UNIFDEF_FLAGS = "-UKERNEL";
+                               DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+                               GCC_C_LANGUAGE_STANDARD = gnu99;
+                               GCC_SYMBOLS_PRIVATE_EXTERN = YES;
+                               GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES;
+                               GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES;
+                               GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES;
+                               GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
+                               GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
+                               GCC_WARN_ABOUT_RETURN_TYPE = YES;
+                               GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES;
+                               GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES;
+                               GCC_WARN_SHADOW = YES;
+                               GCC_WARN_SIGN_COMPARE = YES;
+                               GCC_WARN_UNINITIALIZED_AUTOS = YES;
+                               GCC_WARN_UNKNOWN_PRAGMAS = YES;
+                               GCC_WARN_UNUSED_FUNCTION = YES;
+                               GCC_WARN_UNUSED_LABEL = YES;
+                               GCC_WARN_UNUSED_VARIABLE = YES;
+                               INFOPLIST_FILE = "$(PROJECT_DERIVED_FILE_DIR)/kext-Info.plist";
+                               INSTALL_MODE_FLAG = "a+rX";
+                               LLVM_LTO = YES;
+                               MODULE_NAME = "com.apple.file-systems.hfs.kext";
+                               MODULE_VERSION = 1.0.0;
+                               PRODUCT_BUNDLE_IDENTIFIER = com.apple.filesystems.hfs.kext;
+                               PRODUCT_NAME = HFS;
+                               SDKROOT = macosx.internal;
+                               WARNING_CFLAGS = (
+                                       "$(inherited)",
+                                       "-Wno-unused-parameter",
+                                       "-Wno-shorten-64-to-32",
+                               );
+                               WRAPPER_EXTENSION = kext;
+                       };
+                       name = Release;
+               };
+               FB48E4A31BB3070500523121 /* Release */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               ALWAYS_SEARCH_USER_PATHS = NO;
+                               CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+                               CLANG_CXX_LIBRARY = "libc++";
+                               CLANG_ENABLE_OBJC_ARC = YES;
+                               CLANG_WARN_BOOL_CONVERSION = YES;
+                               CLANG_WARN_CONSTANT_CONVERSION = YES;
+                               CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+                               CLANG_WARN_EMPTY_BODY = YES;
+                               CLANG_WARN_ENUM_CONVERSION = YES;
+                               CLANG_WARN_INT_CONVERSION = YES;
+                               CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+                               CLANG_WARN_UNREACHABLE_CODE = YES;
+                               CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+                               COMBINE_HIDPI_IMAGES = YES;
+                               COPY_HEADERS_RUN_UNIFDEF = YES;
+                               COPY_HEADERS_UNIFDEF_FLAGS = "-DKERNEL";
+                               COPY_PHASE_STRIP = NO;
+                               DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+                               ENABLE_NS_ASSERTIONS = NO;
+                               ENABLE_STRICT_OBJC_MSGSEND = YES;
+                               GCC_C_LANGUAGE_STANDARD = gnu99;
+                               GCC_NO_COMMON_BLOCKS = YES;
+                               GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+                               GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+                               GCC_WARN_UNDECLARED_SELECTOR = YES;
+                               GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+                               GCC_WARN_UNUSED_FUNCTION = YES;
+                               GCC_WARN_UNUSED_VARIABLE = YES;
+                               INSTALL_PATH = /System/Library/Frameworks;
+                               MACOSX_DEPLOYMENT_TARGET = 10.11;
+                               MTL_ENABLE_DEBUG_INFO = NO;
+                               PRODUCT_NAME = Kernel;
+                               PUBLIC_HEADERS_FOLDER_PATH = Kernel.framework/Versions/A/Headers/hfs;
+                               WRAPPER_EXTENSION = framework;
+                       };
+                       name = Release;
+               };
+               FB48E4A41BB3070500523121 /* Debug */ = {
+                       isa = XCBuildConfiguration;
+                       buildSettings = {
+                               ALWAYS_SEARCH_USER_PATHS = NO;
+                               CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
                                CLANG_CXX_LIBRARY = "libc++";
                                CLANG_ENABLE_OBJC_ARC = YES;
                                CLANG_WARN_BOOL_CONVERSION = YES;
                        };
                        name = Debug;
                };
-               FB6A57E21B55544D008AB046 /* Release */ = {
-                       isa = XCBuildConfiguration;
-                       buildSettings = {
-                               ALWAYS_SEARCH_USER_PATHS = NO;
-                               CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
-                               CLANG_CXX_LIBRARY = "libc++";
-                               CLANG_ENABLE_MODULES = YES;
-                               CLANG_ENABLE_OBJC_ARC = YES;
-                               CLANG_WARN_BOOL_CONVERSION = YES;
-                               CLANG_WARN_CONSTANT_CONVERSION = YES;
-                               CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
-                               CLANG_WARN_EMPTY_BODY = YES;
-                               CLANG_WARN_ENUM_CONVERSION = YES;
-                               CLANG_WARN_INT_CONVERSION = YES;
-                               CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
-                               CLANG_WARN_UNREACHABLE_CODE = YES;
-                               CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
-                               COMBINE_HIDPI_IMAGES = YES;
-                               COPY_HEADERS_RUN_UNIFDEF = YES;
-                               COPY_HEADERS_UNIFDEF_FLAGS = "-UKERNEL";
-                               COPY_PHASE_STRIP = NO;
-                               DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
-                               ENABLE_NS_ASSERTIONS = NO;
-                               ENABLE_STRICT_OBJC_MSGSEND = YES;
-                               GCC_C_LANGUAGE_STANDARD = gnu99;
-                               GCC_NO_COMMON_BLOCKS = YES;
-                               GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
-                               GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
-                               GCC_WARN_UNDECLARED_SELECTOR = YES;
-                               GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
-                               GCC_WARN_UNUSED_FUNCTION = YES;
-                               GCC_WARN_UNUSED_VARIABLE = YES;
-                               MACOSX_DEPLOYMENT_TARGET = 10.11;
-                               MTL_ENABLE_DEBUG_INFO = NO;
-                               PRIVATE_HEADERS_FOLDER_PATH = "hfs-System.framework/Versions/B/PrivateHeaders/hfs";
-                               PRODUCT_NAME = "hfs-System";
-                               SDKROOT = macosx;
-                               SKIP_INSTALL = YES;
-                               WRAPPER_EXTENSION = framework;
-                       };
-                       name = Release;
-               };
-               FB6A57E31B55544D008AB046 /* Debug */ = {
-                       isa = XCBuildConfiguration;
-                       buildSettings = {
-                               ALWAYS_SEARCH_USER_PATHS = NO;
-                               CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
-                               CLANG_CXX_LIBRARY = "libc++";
-                               CLANG_ENABLE_MODULES = YES;
-                               CLANG_ENABLE_OBJC_ARC = YES;
-                               CLANG_WARN_BOOL_CONVERSION = YES;
-                               CLANG_WARN_CONSTANT_CONVERSION = YES;
-                               CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
-                               CLANG_WARN_EMPTY_BODY = YES;
-                               CLANG_WARN_ENUM_CONVERSION = YES;
-                               CLANG_WARN_INT_CONVERSION = YES;
-                               CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
-                               CLANG_WARN_UNREACHABLE_CODE = YES;
-                               CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
-                               COMBINE_HIDPI_IMAGES = YES;
-                               COPY_HEADERS_RUN_UNIFDEF = YES;
-                               COPY_HEADERS_UNIFDEF_FLAGS = "-UKERNEL";
-                               COPY_PHASE_STRIP = NO;
-                               DEBUG_INFORMATION_FORMAT = dwarf;
-                               ENABLE_STRICT_OBJC_MSGSEND = YES;
-                               GCC_C_LANGUAGE_STANDARD = gnu99;
-                               GCC_DYNAMIC_NO_PIC = NO;
-                               GCC_NO_COMMON_BLOCKS = YES;
-                               GCC_OPTIMIZATION_LEVEL = 0;
-                               GCC_PREPROCESSOR_DEFINITIONS = (
-                                       "DEBUG=1",
-                                       "$(inherited)",
-                               );
-                               GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
-                               GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
-                               GCC_WARN_UNDECLARED_SELECTOR = YES;
-                               GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
-                               GCC_WARN_UNUSED_FUNCTION = YES;
-                               GCC_WARN_UNUSED_VARIABLE = YES;
-                               MACOSX_DEPLOYMENT_TARGET = 10.11;
-                               MTL_ENABLE_DEBUG_INFO = YES;
-                               ONLY_ACTIVE_ARCH = YES;
-                               PRIVATE_HEADERS_FOLDER_PATH = "hfs-System.framework/Versions/B/PrivateHeaders/hfs";
-                               PRODUCT_NAME = "hfs-System";
-                               SDKROOT = macosx;
-                               SKIP_INSTALL = YES;
-                               WRAPPER_EXTENSION = framework;
-                       };
-                       name = Debug;
-               };
                FB75A4001B4AE765004B5A74 /* Release */ = {
                        isa = XCBuildConfiguration;
                        baseConfigurationReference = FB20E1781AE968BD00CEBE7B /* kext.xcconfig */;
                        };
                        name = Coverage;
                };
-               FBD69B291B94E9990022ECAD /* Coverage */ = {
-                       isa = XCBuildConfiguration;
-                       buildSettings = {
-                               ALWAYS_SEARCH_USER_PATHS = NO;
-                               CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
-                               CLANG_CXX_LIBRARY = "libc++";
-                               CLANG_ENABLE_MODULES = YES;
-                               CLANG_ENABLE_OBJC_ARC = YES;
-                               CLANG_WARN_BOOL_CONVERSION = YES;
-                               CLANG_WARN_CONSTANT_CONVERSION = YES;
-                               CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
-                               CLANG_WARN_EMPTY_BODY = YES;
-                               CLANG_WARN_ENUM_CONVERSION = YES;
-                               CLANG_WARN_INT_CONVERSION = YES;
-                               CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
-                               CLANG_WARN_UNREACHABLE_CODE = YES;
-                               CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
-                               COMBINE_HIDPI_IMAGES = YES;
-                               COPY_HEADERS_RUN_UNIFDEF = YES;
-                               COPY_HEADERS_UNIFDEF_FLAGS = "-UKERNEL";
-                               COPY_PHASE_STRIP = NO;
-                               DEBUG_INFORMATION_FORMAT = dwarf;
-                               ENABLE_STRICT_OBJC_MSGSEND = YES;
-                               GCC_C_LANGUAGE_STANDARD = gnu99;
-                               GCC_DYNAMIC_NO_PIC = NO;
-                               GCC_NO_COMMON_BLOCKS = YES;
-                               GCC_OPTIMIZATION_LEVEL = 0;
-                               GCC_PREPROCESSOR_DEFINITIONS = (
-                                       "DEBUG=1",
-                                       "$(inherited)",
-                               );
-                               GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
-                               GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
-                               GCC_WARN_UNDECLARED_SELECTOR = YES;
-                               GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
-                               GCC_WARN_UNUSED_FUNCTION = YES;
-                               GCC_WARN_UNUSED_VARIABLE = YES;
-                               MACOSX_DEPLOYMENT_TARGET = 10.11;
-                               MTL_ENABLE_DEBUG_INFO = YES;
-                               ONLY_ACTIVE_ARCH = YES;
-                               PRIVATE_HEADERS_FOLDER_PATH = "hfs-System.framework/Versions/B/PrivateHeaders/hfs";
-                               PRODUCT_NAME = "hfs-System";
-                               SDKROOT = macosx;
-                               SKIP_INSTALL = YES;
-                               WRAPPER_EXTENSION = framework;
-                       };
-                       name = Coverage;
-               };
                FBD69B2A1B94E9990022ECAD /* Coverage */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
                };
+               A64B3BDC22E8D36F009A2B10 /* Build configuration list for PBXNativeTarget "livefiles_cs" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               A64B3BDD22E8D36F009A2B10 /* Release */,
+                               A64B3BDE22E8D36F009A2B10 /* Debug */,
+                               A64B3BDF22E8D36F009A2B10 /* Coverage */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
+               A64B3BEA22E8D388009A2B10 /* Build configuration list for PBXNativeTarget "livefiles_cs_tester" */ = {
+                       isa = XCConfigurationList;
+                       buildConfigurations = (
+                               A64B3BEB22E8D388009A2B10 /* Release */,
+                               A64B3BEC22E8D388009A2B10 /* Debug */,
+                               A64B3BED22E8D388009A2B10 /* Coverage */,
+                       );
+                       defaultConfigurationIsVisible = 0;
+                       defaultConfigurationName = Release;
+               };
                DB1AAB8020472D140036167F /* Build configuration list for PBXAggregateTarget "Swift_iOS" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (
                        defaultConfigurationIsVisible = 0;
                        defaultConfigurationName = Release;
                };
-               FB6A57E11B55544D008AB046 /* Build configuration list for PBXNativeTarget "System Framework Headers" */ = {
-                       isa = XCConfigurationList;
-                       buildConfigurations = (
-                               FB6A57E21B55544D008AB046 /* Release */,
-                               FB6A57E31B55544D008AB046 /* Debug */,
-                               FBD69B291B94E9990022ECAD /* Coverage */,
-                       );
-                       defaultConfigurationIsVisible = 0;
-                       defaultConfigurationName = Release;
-               };
                FB75A3FF1B4AE765004B5A74 /* Build configuration list for PBXNativeTarget "encodings-kext" */ = {
                        isa = XCConfigurationList;
                        buildConfigurations = (
index 0989d5be39c8754ef9324146469746059d25534a..ee379be030b1143ae9aed7118606da71a8315ad7 100644 (file)
@@ -474,7 +474,7 @@ retry:
        buf = (char *)calloc(block_size, 1);
        if (buf) {
                for(i=0; i < journal_size/block_size; i++) {
-                       ret = write(fd, buf, block_size);
+                       ret = (int)write(fd, buf, block_size);
                        if (ret != block_size) {
                                break;
                        }
@@ -502,7 +502,7 @@ retry:
                        free(buf);
                return 20;
        }
-       jstart_block = (start_block / block_size) - (embedded_offset / block_size);
+       jstart_block = (int32_t)((start_block / block_size) - (embedded_offset / block_size));
 
        memset(&jib, 'Z', sizeof(jib));
        jib.flags  = kJIJournalInFSMask;
@@ -566,7 +566,7 @@ retry:
                        free(buf);
                return 20;
        }
-       jinfo_block = (start_block / block_size) - (embedded_offset / block_size);
+       jinfo_block = (int32_t)((start_block / block_size) - (embedded_offset / block_size));
 
 
        //
@@ -778,7 +778,7 @@ get_journal_info(char *devname, struct JournalInfoBlock *jib)
                disksize = (u_int64_t)mdbp->drEmbedExtent.blockCount *
                        (u_int64_t)mdbp->drAlBlkSiz;
 
-               mdb_offset = (embeddedOffset / blksize) + HFS_PRI_SECTOR(blksize);
+               mdb_offset = (daddr_t)((embeddedOffset / blksize) + HFS_PRI_SECTOR(blksize));
                if (pread(fd, buff, blksize, mdb_offset * blksize) != blksize) {
                        printf("failed to read the embedded vhp @ offset %d\n", mdb_offset * blksize);
                        ret = -1;
@@ -1064,7 +1064,7 @@ restart:
                
                disksize = (u_int64_t)SWAP_BE16(mdbp->drEmbedExtent.blockCount) * (u_int64_t)SWAP_BE32(mdbp->drAlBlkSiz);
                
-               mdb_offset = (embeddedOffset / blksize) + HFS_PRI_SECTOR(blksize);
+               mdb_offset = (daddr_t)((embeddedOffset / blksize) + HFS_PRI_SECTOR(blksize));
                hdr_offset = mdb_offset * blksize;
                if (pread(fd, buff, blksize, hdr_offset) != blksize) {
                        fprintf(stderr, "failed to read the embedded vhp @ offset %d\n", mdb_offset * blksize);
@@ -1095,7 +1095,7 @@ restart:
                
                tmp &= ~kHFSVolumeJournaledMask;
                vhp->attributes = SWAP_BE32(tmp);
-               if ((tmp = pwrite(fd, buff, blksize, hdr_offset)) != blksize) {
+               if ((tmp = (unsigned int)pwrite(fd, buff, blksize, hdr_offset)) != blksize) {
                        fprintf(stderr, "Update of super-block on %s failed! (%d != %d, %s)\n",
                                        devname, tmp, blksize, strerror(errno));
                } else {
@@ -1219,7 +1219,7 @@ SetJournalInFSState(const char *devname, int journal_in_fs)
                blksize  = 512;
            }
 
-           mdb_offset = (embeddedOffset / blksize) + HFS_PRI_SECTOR(blksize);
+           mdb_offset = (daddr_t)((embeddedOffset / blksize) + HFS_PRI_SECTOR(blksize));
            if (pread(fd, buff, blksize, mdb_offset * blksize) != blksize) {
                printf("failed to read the embedded vhp @ offset %d\n", mdb_offset * blksize);
                ret = -1;
index 8d86934b6679f642870db9fa9a97a73488de96a2..35e848bb8f9911c6a770ca4ba814c9204eb043d6 100644 (file)
@@ -55,6 +55,7 @@
 #include <hfs/hfs_format.h>
 #include <hfs/hfs_mount.h>
 #include <err.h>
+#include <assert.h>
 
 #include <ctype.h>
 #include <errno.h>
@@ -280,11 +281,15 @@ static unsigned int __CFStringGetDefaultEncodingForHFSUtil() {
 
         if ((fd = open(buffer, O_RDONLY, 0)) > 0) {
             ssize_t readSize;
+            long encoding;
 
             readSize = read(fd, buffer, MAXPATHLEN);
             buffer[(readSize < 0 ? 0 : readSize)] = '\0';
             close(fd);
-            return strtol(buffer, NULL, 0);
+
+            encoding = strtol(buffer, NULL, 0);
+            assert(encoding > -1 && encoding <= UINT_MAX);
+            return (unsigned int)encoding;
         }
     }
     return 0; // Fallback to smRoman
@@ -803,7 +808,7 @@ DoProbe(char *rawDeviceNamePtr, char *blockDeviceNamePtr)
        /*
         * Read the HFS Master Directory Block from sector 2
         */
-       result = readAt(fd, bufPtr, (off_t)(2 * HFS_BLOCK_SIZE), HFS_BLOCK_SIZE);
+       result = (int)readAt(fd, bufPtr, (off_t)(2 * HFS_BLOCK_SIZE), HFS_BLOCK_SIZE);
        if (FSUR_IO_FAIL == result)
                goto Return;
 
@@ -1129,8 +1134,9 @@ ParseArgs(int argc, const char *argv[], const char ** actionPtr,
        const char ** mountPointPtr, boolean_t * isEjectablePtr,
           boolean_t * isLockedPtr, boolean_t * isSetuidPtr, boolean_t * isDevPtr)
 {
+    size_t      deviceLength;
     int                        result = FSUR_INVAL;
-    int                        deviceLength, doLengthCheck = 1;
+    int                        doLengthCheck = 1;
     int                        index;
     int                mounting = 0;
 
@@ -1196,7 +1202,10 @@ ParseArgs(int argc, const char *argv[], const char ** actionPtr,
                        doLengthCheck = 0;
                        if (isdigit(argv[2][0])) {
                                char *ptr;
-                               gJournalSize = strtoul(argv[2], &ptr, 0);
+                unsigned long size = strtoul(argv[2], &ptr, 0);
+
+                assert(size < INT_MAX);
+                               gJournalSize = (int)size;
                                if (ptr) {
                                        gJournalSize *= get_multiplier(*ptr);
                                }
@@ -1409,7 +1418,7 @@ ReadHeaderBlock(int fd, void *bufPtr, off_t *startOffset, hfs_UUID_t **finderInf
         * Read the HFS Master Directory Block or Volume Header from sector 2
         */
        *startOffset = 0;
-       result = readAt(fd, bufPtr, (off_t)(2 * HFS_BLOCK_SIZE), HFS_BLOCK_SIZE);
+       result = (int)readAt(fd, bufPtr, (off_t)(2 * HFS_BLOCK_SIZE), HFS_BLOCK_SIZE);
        if (result != FSUR_IO_SUCCESS)
                goto Err_Exit;
 
@@ -1422,7 +1431,7 @@ ReadHeaderBlock(int fd, void *bufPtr, off_t *startOffset, hfs_UUID_t **finderInf
                result = GetEmbeddedHFSPlusVol(mdbPtr, startOffset);
                if (result != FSUR_IO_SUCCESS)
                        goto Err_Exit;
-               result = readAt(fd, bufPtr, *startOffset + (off_t)(2*HFS_BLOCK_SIZE), HFS_BLOCK_SIZE);
+               result = (int)readAt(fd, bufPtr, *startOffset + (off_t)(2*HFS_BLOCK_SIZE), HFS_BLOCK_SIZE);
                if (result != FSUR_IO_SUCCESS)
                        goto Err_Exit;
        }
@@ -1644,7 +1653,7 @@ SetVolumeUUIDRaw(const char *deviceNamePtr, hfs_UUID_t *volumeUUIDPtr)
        /*
         * Write the modified MDB or VHB back to disk
         */
-       result = writeAt(fd, bufPtr, startOffset + (off_t)(2*HFS_BLOCK_SIZE), HFS_BLOCK_SIZE);
+       result = (int)writeAt(fd, bufPtr, startOffset + (off_t)(2*HFS_BLOCK_SIZE), HFS_BLOCK_SIZE);
 
 Err_Exit:
        if (fd > 0) close(fd);
@@ -1976,7 +1985,7 @@ GetNameFromHFSPlusVolumeStartingAt(int fd, off_t hfsPlusVolumeOffset, unsigned c
      * Read the Volume Header
      * (This is a little redundant for a pure, unwrapped HFS+ volume)
      */
-    result = readAt( fd, volHdrPtr, hfsPlusVolumeOffset + (off_t)(2*HFS_BLOCK_SIZE), HFS_BLOCK_SIZE );
+    result = (int)readAt( fd, volHdrPtr, hfsPlusVolumeOffset + (off_t)(2*HFS_BLOCK_SIZE), HFS_BLOCK_SIZE );
     if (result == FSUR_IO_FAIL) {
 #if TRACE_HFS_UTIL
         fprintf(stderr, "hfs.util: GetNameFromHFSPlusVolumeStartingAt: readAt failed\n");
@@ -2324,7 +2333,7 @@ static int        LogicalToPhysical(off_t offset, ssize_t length, u_int32_t blockSize,
        u_int32_t       blockCount = 0;
        
        /* Determine allocation block containing logicalOffset */
-       logicalBlock = offset / blockSize;      /* This can't overflow for valid volumes */
+       logicalBlock = (u_int32_t)(offset / blockSize); /* This can't overflow for valid volumes */
        offset %= blockSize;    /* Offset from start of allocation block */
        
        /* Find the extent containing logicalBlock */
@@ -2400,7 +2409,7 @@ static int        ReadFile(int fd, void *buffer, off_t offset, ssize_t length,
                if (result != FSUR_IO_SUCCESS)
                        break;
                
-               result = readAt(fd, buffer, volOffset+physOffset, physLength);
+               result = (int)readAt(fd, buffer, volOffset+physOffset, physLength);
                if (result != FSUR_IO_SUCCESS)
                        break;
                
@@ -2817,7 +2826,7 @@ int ConvertVolumeStatusDB(VolumeStatusDBHandle DBHandle) {
         * converted it then do nothing.
         */
     lseek(dbstateptr->dbfile, 0, SEEK_SET);
-    result = read(dbstateptr->dbfile, &entry64, sizeof(entry64));
+    result = (int)read(dbstateptr->dbfile, &entry64, sizeof(entry64));
     if ((result != sizeof(entry64)) ||
         (entry64.keySeparator != DBKEYSEPARATOR) ||
         (entry64.space != DBBLANKSPACE) ||
@@ -2825,9 +2834,15 @@ int ConvertVolumeStatusDB(VolumeStatusDBHandle DBHandle) {
         result = 0;
         goto ErrExit;
     } else {
+        off_t buf_size = dbinfo.st_size;
+
                /* Read in a giant buffer */
         if ((result = stat(gVSDBPath, &dbinfo)) != 0) goto ErrExit;
-        iobuffersize = dbinfo.st_size;
+        if (buf_size > UINT32_MAX) {
+            result = EINVAL;
+            goto ErrExit;
+        }
+        iobuffersize = (u_int32_t)buf_size;
         iobuffer = malloc(iobuffersize);
         if (iobuffer == NULL) {
             result = ENOMEM;
@@ -2835,7 +2850,7 @@ int ConvertVolumeStatusDB(VolumeStatusDBHandle DBHandle) {
         };
 
         lseek(dbstateptr->dbfile, 0, SEEK_SET);
-        result = read(dbstateptr->dbfile, iobuffer, iobuffersize);
+        result = (int)read(dbstateptr->dbfile, iobuffer, iobuffersize);
         if (result != iobuffersize) {
             result = errno;
             goto ErrExit;
@@ -2860,7 +2875,7 @@ int ConvertVolumeStatusDB(VolumeStatusDBHandle DBHandle) {
             }
 
             ConvertHFSUUIDToUUID(entry64.key.uuid, &volumeID);
-            VolumeStatus = ConvertHexStringToULong(entry64.record.statusFlags, sizeof(entry64.record.statusFlags));
+            VolumeStatus = (u_int32_t)ConvertHexStringToULong(entry64.record.statusFlags, sizeof(entry64.record.statusFlags));
 
             FormatDBEntry(&volumeID, VolumeStatus, &dbentry);
             if ((result = AddVolumeRecord(dbstateptr, &dbentry)) != sizeof(dbentry)) {
@@ -3106,13 +3121,13 @@ static int FindVolumeRecordByUUID(VSDBStatePtr dbstateptr, volUUID_t *volumeID,
 
 static int AddVolumeRecord(VSDBStatePtr dbstateptr, VSDBEntryUUID_t *dbentry) {
        lseek(dbstateptr->dbfile, 0, SEEK_END);
-       return write(dbstateptr->dbfile, dbentry, sizeof(struct VSDBEntryUUID));
+       return (int)write(dbstateptr->dbfile, dbentry, sizeof(struct VSDBEntryUUID));
 }
 
 
 static int UpdateVolumeRecord(VSDBStatePtr dbstateptr, VSDBEntryUUID_t *dbentry) {
        lseek(dbstateptr->dbfile, dbstateptr->recordPosition, SEEK_SET);
-       return write(dbstateptr->dbfile, dbentry, sizeof(*dbentry));
+       return (int)write(dbstateptr->dbfile, dbentry, sizeof(*dbentry));
 }
 
 static int GetVSDBEntry(VSDBStatePtr dbstateptr, VSDBEntryUUID_t *dbentry) {
@@ -3120,7 +3135,7 @@ static int GetVSDBEntry(VSDBStatePtr dbstateptr, VSDBEntryUUID_t *dbentry) {
        int result;
        
        dbstateptr->recordPosition = lseek(dbstateptr->dbfile, 0, SEEK_CUR);
-       result = read(dbstateptr->dbfile, &entry, sizeof(entry));
+       result = (int)read(dbstateptr->dbfile, &entry, sizeof(entry));
        if ((result != sizeof(entry)) ||
                (entry.keySeparator != DBKEYSEPARATOR) ||
                (entry.space != DBBLANKSPACE) ||
diff --git a/livefiles_cs_plugin/lf_cs.h b/livefiles_cs_plugin/lf_cs.h
new file mode 100644 (file)
index 0000000..805cd23
--- /dev/null
@@ -0,0 +1,34 @@
+//
+// Copyright (c) 2019-2019 Apple Inc. All rights reserved.
+//
+// lf_cs.h - Defines macros for livefiles Apple_CoreStorage plugin.
+//
+
+#ifndef _LF_CS_H
+#define _LF_CS_H
+
+#include <UserFS/UserVFS.h>
+
+//
+// Device/Block alignment and rounding.
+//
+#define CS_HOWMANY(_n, _b) howmany(_n, _b)
+#define CS_ALIGN(_n, _b, _up)\
+       (((_up) ? CS_HOWMANY(_n, _b) : ((_n) / (_b))) * (_b))
+
+#define CS_STATUS(_s)           ((_s) & 0x000FFFFF)
+#define CS_STATUS_OK            0x00000000      // No error.
+#define CS_STATUS_NOTCS         0x00000001      // Not a current CS volume.
+#define CS_STATUS_CKSUM         0x00000002      // Cksum mismatch.
+#define CS_STATUS_BLKTYPE       0x00000004      // Incorrect block type.
+#define CS_STATUS_INVALID       0x00000008      // Invalid field value.
+#define CS_STATUS_ADDRESS       0x00000010      // Invalid laddr/vaddr.
+#define CS_STATUS_TXG           0x00000020      // Invalid transaction.
+#define CS_STATUS_UUID          0x00000040      // Inconsistent UUID.
+
+
+#define CS_INFO(_s)             ((_s) & 0xFFF00000)
+#define CS_INFO_VERSIONITIS     0x00100000      // Incompatible CS volume format
+#define CS_INFO_ZERO_VH         0x02000000      // In-progress CS volume forma
+
+#endif /* _LF_CS_H */
diff --git a/livefiles_cs_plugin/lf_cs_checksum.c b/livefiles_cs_plugin/lf_cs_checksum.c
new file mode 100644 (file)
index 0000000..ce52b19
--- /dev/null
@@ -0,0 +1,139 @@
+//
+// Copyright (c) 2009-2019 Apple Inc. All rights reserved.
+//
+// lf_cs_checksum.h - Implements checksum handling for livefiles
+//                    Apple_CoreStorage plugin.
+//
+// This implementation is copied from CoreStorage project.
+//
+
+#include "lf_cs_checksum.h"
+
+//
+// CRC32-C using polynomial 0x1EDC6F41
+//
+static const uint32_t crc32_table[256] = {
+       0x00000000, 0xf26b8303, 0xe13b70f7, 0x1350f3f4,
+       0xc79a971f, 0x35f1141c, 0x26a1e7e8, 0xd4ca64eb,
+       0x8ad958cf, 0x78b2dbcc, 0x6be22838, 0x9989ab3b,
+       0x4d43cfd0, 0xbf284cd3, 0xac78bf27, 0x5e133c24,
+       0x105ec76f, 0xe235446c, 0xf165b798, 0x030e349b,
+       0xd7c45070, 0x25afd373, 0x36ff2087, 0xc494a384,
+       0x9a879fa0, 0x68ec1ca3, 0x7bbcef57, 0x89d76c54,
+       0x5d1d08bf, 0xaf768bbc, 0xbc267848, 0x4e4dfb4b,
+       0x20bd8ede, 0xd2d60ddd, 0xc186fe29, 0x33ed7d2a,
+       0xe72719c1, 0x154c9ac2, 0x061c6936, 0xf477ea35,
+       0xaa64d611, 0x580f5512, 0x4b5fa6e6, 0xb93425e5,
+       0x6dfe410e, 0x9f95c20d, 0x8cc531f9, 0x7eaeb2fa,
+       0x30e349b1, 0xc288cab2, 0xd1d83946, 0x23b3ba45,
+       0xf779deae, 0x05125dad, 0x1642ae59, 0xe4292d5a,
+       0xba3a117e, 0x4851927d, 0x5b016189, 0xa96ae28a,
+       0x7da08661, 0x8fcb0562, 0x9c9bf696, 0x6ef07595,
+       0x417b1dbc, 0xb3109ebf, 0xa0406d4b, 0x522bee48,
+       0x86e18aa3, 0x748a09a0, 0x67dafa54, 0x95b17957,
+       0xcba24573, 0x39c9c670, 0x2a993584, 0xd8f2b687,
+       0x0c38d26c, 0xfe53516f, 0xed03a29b, 0x1f682198,
+       0x5125dad3, 0xa34e59d0, 0xb01eaa24, 0x42752927,
+       0x96bf4dcc, 0x64d4cecf, 0x77843d3b, 0x85efbe38,
+       0xdbfc821c, 0x2997011f, 0x3ac7f2eb, 0xc8ac71e8,
+       0x1c661503, 0xee0d9600, 0xfd5d65f4, 0x0f36e6f7,
+       0x61c69362, 0x93ad1061, 0x80fde395, 0x72966096,
+       0xa65c047d, 0x5437877e, 0x4767748a, 0xb50cf789,
+       0xeb1fcbad, 0x197448ae, 0x0a24bb5a, 0xf84f3859,
+       0x2c855cb2, 0xdeeedfb1, 0xcdbe2c45, 0x3fd5af46,
+       0x7198540d, 0x83f3d70e, 0x90a324fa, 0x62c8a7f9,
+       0xb602c312, 0x44694011, 0x5739b3e5, 0xa55230e6,
+       0xfb410cc2, 0x092a8fc1, 0x1a7a7c35, 0xe811ff36,
+       0x3cdb9bdd, 0xceb018de, 0xdde0eb2a, 0x2f8b6829,
+       0x82f63b78, 0x709db87b, 0x63cd4b8f, 0x91a6c88c,
+       0x456cac67, 0xb7072f64, 0xa457dc90, 0x563c5f93,
+       0x082f63b7, 0xfa44e0b4, 0xe9141340, 0x1b7f9043,
+       0xcfb5f4a8, 0x3dde77ab, 0x2e8e845f, 0xdce5075c,
+       0x92a8fc17, 0x60c37f14, 0x73938ce0, 0x81f80fe3,
+       0x55326b08, 0xa759e80b, 0xb4091bff, 0x466298fc,
+       0x1871a4d8, 0xea1a27db, 0xf94ad42f, 0x0b21572c,
+       0xdfeb33c7, 0x2d80b0c4, 0x3ed04330, 0xccbbc033,
+       0xa24bb5a6, 0x502036a5, 0x4370c551, 0xb11b4652,
+       0x65d122b9, 0x97baa1ba, 0x84ea524e, 0x7681d14d,
+       0x2892ed69, 0xdaf96e6a, 0xc9a99d9e, 0x3bc21e9d,
+       0xef087a76, 0x1d63f975, 0x0e330a81, 0xfc588982,
+       0xb21572c9, 0x407ef1ca, 0x532e023e, 0xa145813d,
+       0x758fe5d6, 0x87e466d5, 0x94b49521, 0x66df1622,
+       0x38cc2a06, 0xcaa7a905, 0xd9f75af1, 0x2b9cd9f2,
+       0xff56bd19, 0x0d3d3e1a, 0x1e6dcdee, 0xec064eed,
+       0xc38d26c4, 0x31e6a5c7, 0x22b65633, 0xd0ddd530,
+       0x0417b1db, 0xf67c32d8, 0xe52cc12c, 0x1747422f,
+       0x49547e0b, 0xbb3ffd08, 0xa86f0efc, 0x5a048dff,
+       0x8ecee914, 0x7ca56a17, 0x6ff599e3, 0x9d9e1ae0,
+       0xd3d3e1ab, 0x21b862a8, 0x32e8915c, 0xc083125f,
+       0x144976b4, 0xe622f5b7, 0xf5720643, 0x07198540,
+       0x590ab964, 0xab613a67, 0xb831c993, 0x4a5a4a90,
+       0x9e902e7b, 0x6cfbad78, 0x7fab5e8c, 0x8dc0dd8f,
+       0xe330a81a, 0x115b2b19, 0x020bd8ed, 0xf0605bee,
+       0x24aa3f05, 0xd6c1bc06, 0xc5914ff2, 0x37faccf1,
+       0x69e9f0d5, 0x9b8273d6, 0x88d28022, 0x7ab90321,
+       0xae7367ca, 0x5c18e4c9, 0x4f48173d, 0xbd23943e,
+       0xf36e6f75, 0x0105ec76, 0x12551f82, 0xe03e9c81,
+       0x34f4f86a, 0xc69f7b69, 0xd5cf889d, 0x27a40b9e,
+       0x79b737ba, 0x8bdcb4b9, 0x988c474d, 0x6ae7c44e,
+       0xbe2da0a5, 0x4c4623a6, 0x5f16d052, 0xad7d5351
+};
+
+//
+// Initialize 'cksum' buffer for the cksum function for a given
+// algorithm 'alg'.  Doubles as alg verification for probe/boot.
+//
+bool
+cksum_init(cksum_alg_t alg, uint8_t cksum[MAX_CKSUM_NBYTES])
+{
+       switch (alg) {
+
+       case CKSUM_NONE:
+               memset(cksum, 0, MAX_CKSUM_NBYTES);
+               break;
+
+       case CKSUM_ALG_CRC_32:
+               memset(cksum, ~0, MAX_CKSUM_NBYTES);
+               break;
+
+       default:
+               return false;
+
+       }
+
+       return true;
+}
+
+//
+// cksum - Apply passed checksum algorithm.
+//
+// Apply checksum algorithm 'alg' to data block 'p' for 'len' bytes and insert
+// the result (to max MAX_CKSUM_NBYTES) into 'cksum'.  To support incremental
+// cksum calculation the caller is responsible for first initialising the
+// 'cksum' buffer (using cksum_init).
+//
+void
+cksum(cksum_alg_t alg, const void *p, size_t len,
+      uint8_t cksum[MAX_CKSUM_NBYTES])
+{
+       const uint8_t *data = (const uint8_t *)p;
+       uint32_t c32;
+
+       switch (alg) {
+
+       case CKSUM_NONE:
+               break;
+
+       case CKSUM_ALG_CRC_32:
+
+               c32 = *(uint32_t *)cksum;
+
+               while (len-- > 0) {
+                       c32 = crc32_table[(c32 ^ *data++) & 0xff] ^
+                               (c32 >> 8);
+               }
+
+               *(uint32_t *)cksum = c32;
+               break;
+       }
+}
diff --git a/livefiles_cs_plugin/lf_cs_checksum.h b/livefiles_cs_plugin/lf_cs_checksum.h
new file mode 100644 (file)
index 0000000..c51e4d8
--- /dev/null
@@ -0,0 +1,64 @@
+//
+// Copyright (c) 2009-2019 Apple Inc. All rights reserved.
+//
+// lf_cs_checksum.h - Defines for checksum handling for livefiles
+//                    Apple_CoreStorage plugin.
+//
+// This header is copied from CoreStorage project.
+//
+
+#ifndef _LF_CS_CHECKSUM_H
+#define _LF_CS_CHECKSUM_H
+
+#include <stdint.h>
+#include <string.h>
+#include <stddef.h>
+#include <stdbool.h>
+
+//
+// Checksum Algorithm
+//
+// Every metadata block has a checksum to check the data integrity.  Different
+// checksum algorithms can be used by CoreStorage, and [[lvg_checksum_alg]] in
+// [[lvg_info_t]] records what checksum algorithm to use.  For the first
+// prototype, I am copying the CRC algorithm from the UDF project.
+//
+// The fletcher 2 algorithm used by ZFS has fundamental flaws.  And a variation
+// of the fletcher 8 algorithm could be used, which is 2 times faster than
+// CRC32 and 4 times faster than fletcher.
+//
+// <cksum definitions>=
+//
+#define MAX_CKSUM_NBYTES 8
+
+enum cksum_alg {
+       CKSUM_NONE,
+       CKSUM_ALG_CRC_32, // CRC-32 algorithm copied from CRC32-C polynomial
+};
+typedef enum cksum_alg cksum_alg_t;
+
+
+#define BITS_PER_BYTE 8L
+#define META_CKSUM_BITS (MAX_CKSUM_NBYTES * BITS_PER_BYTE)
+
+//
+// Initialize checksum for a certain algorithm
+//
+bool cksum_init(cksum_alg_t alg, uint8_t cksum[MAX_CKSUM_NBYTES]);
+
+//
+// cksum - Calculate checksum of data for len bytes
+//
+// Existing value of cksum is also used to calculate the checksum.  In order to
+// calculate cksums of different memory chunks, this function can be called
+// several times:
+//
+//     cksum(alg, data1, len1, cksum);
+//     cksum(alg, data2, len2, cksum);
+//
+// and the resultant cksum is calculated on two chunks
+//
+void cksum(cksum_alg_t alg, const void *data, size_t len,
+               uint8_t cksum[MAX_CKSUM_NBYTES]);
+
+#endif /* _LF_CS_CHECKSUM_H */
diff --git a/livefiles_cs_plugin/lf_cs_disk_format.h b/livefiles_cs_plugin/lf_cs_disk_format.h
new file mode 100644 (file)
index 0000000..e06198d
--- /dev/null
@@ -0,0 +1,452 @@
+//
+// Copyright (c) 2009-2019 Apple Inc. All rights reserved.
+//
+// lf_cs_disk_format.h - Defines on disk format for Apple_CoreStorage physical
+//                       volumes for livefiles Apple_CoreStorage plugin.
+//
+// This header is copied from CoreStorage project.
+//
+
+#ifndef _LF_CS_DISK_FORMAT_H
+#define _LF_CS_DISK_FORMAT_H
+
+#define MAX_CKSUM_NBYTES 8
+#define CORESTORAGE_FORMAT_VERSION 1
+
+//
+// The 'dl_lvg.lvg_signature' in a DiskLabel (mimics 'CORESTOR')
+//
+#define CORE_STORAGE_SIGNATURE 0xC07E5707
+
+//
+// The 'mh_endianness' used to check endianness (non-palindromic 'CS')
+//
+#define BYTE_ORDER_MARK 0x5343
+
+//
+// Metadata block header.
+//
+struct metadata_header {
+
+       //
+       // Block cksum.
+       //
+       uint8_t mh_cksum[MAX_CKSUM_NBYTES];
+
+       //
+       // The on-disk format version of CoreStorage.
+       //
+       uint16_t mh_format_version;
+
+       //
+       // Enum metadata_blk_type (BLK_TYPE_*).
+       //
+       uint8_t mh_blk_type;
+
+       //
+       // Enum metadata_blk_subtype (BLK_SUBTYPE_*), for b-tree/fsck.
+       //
+       uint8_t mh_blk_subtype;
+
+       //
+       // The version of CoreStorage software that wrote this block.
+       //
+       uint32_t mh_bundle_version;
+
+       //
+       // Transaction identification.
+       //
+       uint64_t mh_txg_id;
+       uint64_t mh_vaddr;
+       uint64_t mh_laddr;
+
+       //
+       // Records the owner of the block.  The owner of any blocks in a B-Tree
+       // is the root of the tree.  The owner of any blocks in a list like
+       // structure (DSD list, attribute blocks) is the first block in the
+       // list.  This field can be used for crash recovery by fsck_cs.  For
+       // example, if this field has the B-Tree root vaddr that this block
+       // belongs, fsck_cs could reconstruct the B-Tree based on all leaf
+       // nodes.
+       //
+       uint64_t mh_blk_owner;
+
+       //
+       // Block size (LVG MLV blksz).
+       //
+       uint32_t mh_blk_size;
+
+       //
+       // Flags (BLK_FLAG_*).
+       //
+       uint8_t mh_blk_flags;
+
+       //
+       // Reserved for future extensions
+       // make blk header 64 bytes (crypto alignment)
+       //
+       uint8_t mh_reserved1;
+       uint16_t mh_reserved2;
+       uint64_t mh_reserved8;
+};
+typedef struct metadata_header metadata_header_t;
+
+int check_dk_metadata_header_size[sizeof(metadata_header_t) == 64 ? 1 : -1];
+
+
+#define NUM_VOL_HEADERS 2
+#define VOL_HEADER_NBYTES 512
+#define MAX_DISK_LABELS 4
+#define MAX_WIPEKEY_NBYTES 64
+
+//
+// This structure is padded such that it is of correct size.
+//
+struct dk_vol_header {
+       union {
+               struct {
+                       metadata_header_t vh_header;
+
+                       //
+                       // PV size in bytes, rounded down to VOL_HEADER_NBYTES
+                       // boundary.
+                       //
+                       uint64_t vh_pv_nbytes;
+
+                       //
+                       // If this is not 0, it records a PV resize operation
+                       //
+                       uint64_t vh_pv_resize;
+
+                       //
+                       // If this is not 0, it records the old Volume Header
+                       // location before the PV resize started; it is again 0
+                       // after completion.
+                       //
+                       uint64_t vh_old_pv_nbytes;
+
+                       //
+                       // The cpu-platform endian that formatted this LVG.
+                       //
+                       uint16_t vh_endianness;
+
+                       //
+                       // Checksum algorithm of VolHdr metadata header.
+                       //
+                       uint16_t vh_cksum_alg;
+
+                       //
+                       // Reserved.
+                       //
+                       uint16_t vh_reserved2;
+
+                       //
+                       // Number of disk labels.
+                       //
+                       uint16_t vh_num_labels;
+
+                       //
+                       // Label address uses this block size.
+                       //
+                       uint32_t vh_blksz;
+
+                       //
+                       // Maximum disk label size.
+                       //
+                       uint32_t vh_label_max_nbytes;
+
+                       //
+                       // (Physical) Location of the new/old disk labels.
+                       //
+                       uint64_t vh_label_addr[MAX_DISK_LABELS];
+                       uint64_t vh_move_label_addr[MAX_DISK_LABELS];
+
+                       //
+                       // PV MLV/plist wipe keys ([0] is active, [1] future
+                       // re-key).
+                       //
+                       uint16_t vh_wipe_key_nbytes[2];
+                       uint16_t vh_wipe_key_alg[2];
+                       uint8_t vh_wipe_key[2][MAX_WIPEKEY_NBYTES];
+
+                       //
+                       // UUID of this PV and its LVG (for bootstrap/multi-PV)
+                       //
+                       uint8_t vh_pv_uuid[16];
+                       uint8_t vh_lvg_uuid[16];
+               };
+               uint8_t vh_padding[VOL_HEADER_NBYTES];
+       };
+};
+typedef struct dk_vol_header dk_vol_header_t;
+int check_dk_vol_header_size[sizeof(dk_vol_header_t) == VOL_HEADER_NBYTES ? 1 : -1];
+
+//
+// Existing block types cannot be changed!
+//
+enum metadata_blk_type {
+
+       //
+       // The values of the B-Tree types are important.  They are the results
+       // of the bit operations of BTREE_ROOT, BTREE_NODE, and BTREE_LEAF in
+       // B-Tree code.
+       //
+       BLK_TYPE_BTREE_NODE = 2,      // A B-Tree node that is not a leaf.
+       BLK_TYPE_BTREE_ROOT_NODE = 3, // A non-leaf B-Tree node that is also root.
+       BLK_TYPE_BTREE_LEAF = 4,      // A B-Tree leaf node that is not a root.
+       BLK_TYPE_BTREE_ROOT_LEAF = 5, // A B-Tree leaf node that is also root.
+
+       BLK_TYPE_VOL_HEADER = 16,
+
+       //
+       // Fixed part of disk label (first MLV block size).
+       //
+       BLK_TYPE_DISK_LABEL = 17,
+
+       BLK_TYPE_DISK_LABEL_CONT = 18, // Variable part of disk label.
+
+       //
+       // LFS related blocks
+       //
+
+       //
+       // MLV Partial Segment (PS) header block, first block of the first
+       // PS in a Group of Partial Segments (GPS).
+       //
+       BLK_TYPE_PS_HEADER = 19,
+
+       //
+       // MLV Continuation Partial Segment block, first block of a Partial
+       // Segment (PS) in a Group of Partial Segments (GPS), where the PS
+       // is not the first PS in the GPS.
+       //
+       BLK_TYPE_PS_CONT_HDR = 20,
+
+       //
+       // MLV Partial Segment (PS) Overflow header block, which holds
+       // information about added or deleted virtual blocks.
+       //
+       BLK_TYPE_PS_OVERFLOW_HDR = 21,
+
+       //
+       // MLV Virtual Address Table (VAT) blocks, which holds VAT information.
+       //
+       BLK_TYPE_VAT = 22,
+
+       //
+       // MLV Segment Usage Table (SUT) blocks, which holds SUT information.
+       //
+       BLK_TYPE_SUT = 23,
+
+       //
+       // Metadata in MLV.
+       //
+       // MLV super block, the starting point of all MLV metadata.
+       //
+       BLK_TYPE_MLV_SUPERBLOCK = 24,
+
+       //
+       // Logical Volume Family (LVF) super block.
+       //
+       BLK_TYPE_LV_FAMILY_SUPERBLOCK = 25,
+
+       //
+       // Logical Volume (LV) super block.
+       //
+       BLK_TYPE_LV_SUPERBLOCK = 26,
+
+       //
+       // Hold more LV attributes when they don't fit in the LV superblock.
+       //
+       BLK_TYPE_LV_XATTR = 27,
+
+       //
+       // Holds the Physical Volume (PV) information.
+       //
+       BLK_TYPE_PV_TABLE = 28,
+
+       //
+       // Holds the Physical Volume (PV) Freespace Log (FLOG) table
+       // information.
+       //
+       BLK_TYPE_PV_FLOG_TABLE = 29,
+
+       BLK_TYPE_UNUSED_1 = 30,
+       BLK_TYPE_UNUSED_2 = 31,
+       BLK_TYPE_UNUSED_3 = 32,
+
+       //
+       // Used for space sharing, records the amount of free space not used by
+       // the file system inside the Logical Volume.
+       //
+       BLK_TYPE_LV_FREE_SPACE_SUMMARY_DEPRECATED = 33,
+
+       //
+       // Used for Physical Volume (PV) free space management, records the
+       // amount of free space in each chunk of the PV and has pointers to
+       // the Freespace Log (FLOG).
+       //
+       BLK_TYPE_PV_SUMMARY_TABLE = 34,
+
+       BLK_TYPE_UNUSED_4 = 35,
+
+       //
+       // Hold more LV Family attributes when they don't fit in the
+       // LVF superblock.
+       //
+       BLK_TYPE_LV_FAMILY_XATTR = 36,
+
+       //
+       // Hold more Delayed Secure Deletion (DSD) list entries when
+       // they cannot fit in the LVF superblock.
+       //
+       BLK_TYPE_DSD_LIST = 37,
+
+       //
+       // This block type is used to record information about bad sectors
+       // encountered during background encryption/decryption.
+       //
+       BLK_TYPE_BAD_SECTOR_LIST = 38,
+
+       //
+       // For debugging: block is in dummy tree.
+       //
+       BLK_TYPE_DUMMY = 39,
+
+       //
+       // New types are added here to preserve compatible on-disk format.
+       //
+
+       NUM_BLK_TYPES,
+
+       BLK_TYPE_UNKNOWN = 255, // Not used for on-disk blocks.
+};
+
+//
+// Existing block subtypes cannot be changed!
+//
+enum metadata_blk_subtype {
+
+       //
+       // Metadata in MLV.
+       //
+       BLK_SUBTYPE_NO_SUBTYPE = 0,
+
+       BLK_SUBTYPE_LV_FAMILY_TREE,
+       BLK_SUBTYPE_LV_SNAPSHOT_TREE,
+       BLK_SUBTYPE_LV_ADDR_MAP_TREE,
+       BLK_SUBTYPE_PV_REFCOUNT_TREE,
+       BLK_SUBTYPE_LV_UNUSED_SPACE_TREE,
+       BLK_SUBTYPE_LVF_REFCOUNT_TREE,
+
+       //
+       // The b-tree that holds blocks to populate MLV for testing.
+       //
+       BLK_SUBTYPE_DUMMY_TREE,
+
+       //
+       // New types are added here to preserve compatible on-disk format.
+       //
+
+       NUM_BLK_SUBTYPES,
+
+       BLK_SUBTYPE_UNKNOWN = 255, // Not used for on-disk blocks.
+};
+typedef enum metadata_blk_subtype metadata_blk_subtype_t;
+
+
+//
+// This block should be in the DSD List.  It is not in the DSD list when it
+// is first created.  But when it is modified or killed, it will be included
+// in the DSD list.
+//
+#define BLK_FLAG_IN_DSD_LIST 0x02
+
+//
+// On-disk information of LVG.
+//
+struct lvg_info {
+       uint32_t lvg_signature;     // A signature that CoreStorage recognizes.
+
+       //
+       // Version numbers can help diagnose problems.
+       //
+
+       //
+       // The version of CoreStorage that created the LVG.
+       //
+       uint32_t lvg_creator_version;
+
+       //
+       // The version of CoreStorage that modified the LVG the last time.
+       //
+       uint32_t lvg_writer_version;
+
+       //
+       // The interval to sync MLV metadata in milliseconds.
+       //
+       uint16_t lvg_sync_interval_ms;
+
+       //
+       // Checksum algorithm used for all metadata blocks and data blocks.
+       //
+       uint8_t lvg_metadata_cksum_alg;
+
+       //
+       // Do not punch hole in the LVs on trim, so that the sparse LVs can become
+       // less and less sparse over time.
+       //
+       uint8_t lvg_no_punch_hole_on_trim;
+
+       //
+       // These fields control our forwards/backwards compatibility.
+       // Features fall into three categories: compatible, read-only
+       // compatible, and incompatible.  For any given version of the
+       // file system code, you can mount a file-system with any set
+       // of compatible features.      If the file system encounters bits
+       // that are set in the read-only compatible features field and
+       // it does not know about those features then it must only mount
+       // the file system read-only.  If the file system encounters
+       // any bits set in the incompatible features field that it does
+       // not know about, then it must not mount or modify the file
+       // system in any way.
+       //
+       // The idea for these compatibility fields is rather shamelessly
+       // stolen from rocky and ext2.
+       //
+       //
+       uint64_t lvg_compatible_features;
+       uint64_t lvg_read_only_compatible_features;
+       uint64_t lvg_incompatible_features;
+
+       //
+       // When Soft Snapshot is enabled, this is the minimum granularity the
+       // extents will be updated with new timestamp.  This is OK to be 0, so a
+       // predefined constant will be used.
+       //
+       uint64_t lvg_soft_snapshot_granularity_nbytes;
+
+       //
+       // When LV checksum is enabled, this is the minimum granularity of data
+       // being checksummed.  This is OK to be 0, so a predefined constant will
+       // be used.
+       //
+       uint64_t lvg_checksum_granularity_nbytes;
+
+       //
+       // The min/max versions of CoreStorage that ever wrote to the LVG.
+       //
+       uint32_t lvg_min_writer_version;
+       uint32_t lvg_max_writer_version;
+
+       //
+       // The following unused fields are reserved so we don't need to break
+       // format compatibility too often if we need more per-LVG fields.
+       //
+       uint64_t lvg_unused1;
+       uint64_t lvg_unused2;
+       uint64_t lvg_unused3;
+};
+typedef struct lvg_info lvg_info_t;
+
+#endif /* _LF_CS_DISK_FORMAT_H */
diff --git a/livefiles_cs_plugin/lf_cs_logging.c b/livefiles_cs_plugin/lf_cs_logging.c
new file mode 100644 (file)
index 0000000..56513d4
--- /dev/null
@@ -0,0 +1,57 @@
+//
+// Copyright (c) 2019-2019 Apple Inc. All rights reserved.
+//
+// lf_cs_logging.c - Implemenents routines for logging info, erros, warnings
+//                   and debug for livefiles Apple_CoreStorage plugin.
+//
+
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "lf_cs_logging.h"
+
+#if !LF_CS_USE_OSLOG
+
+#define VPRINTF(fmt, val)       vfprintf(stderr, fmt, val)
+
+void
+log_debug(const char *fmt, ...)
+{
+       va_list va;
+
+       va_start(va, fmt);
+       VPRINTF(fmt, va);
+       va_end(va);
+}
+
+void
+log_info(const char *fmt, ...)
+{
+       va_list va;
+
+       va_start(va, fmt);
+       VPRINTF(fmt, va);
+       va_end(va);
+}
+
+void
+log_warn(const char *fmt, ...)
+{
+       va_list va;
+
+       va_start(va, fmt);
+       VPRINTF(fmt, va);
+       va_end(va);
+}
+
+void
+log_err(const char *fmt, ...)
+{
+       va_list va;
+
+       va_start(va, fmt);
+       VPRINTF(fmt, va);
+       va_end(va);
+}
+
+#endif /* !LF_CS_USE_OSLOG */
diff --git a/livefiles_cs_plugin/lf_cs_logging.h b/livefiles_cs_plugin/lf_cs_logging.h
new file mode 100644 (file)
index 0000000..e399283
--- /dev/null
@@ -0,0 +1,40 @@
+//
+// Copyright (c) 2009-2019 Apple Inc. All rights reserved.
+//
+// lf_cs_logging.h - Defines for helper methods for logging info, error,
+//                   warning and debug messages for livefiles Apple_CoreStorage
+//                   plugin.
+//
+#ifndef _LF_CS_LOGGING_H
+#define _LF_CS_LOGGING_H
+
+#if LF_CS_USE_OSLOG
+#include <os/log.h>
+
+#define debugmsg(fmt, ...) \
+       os_log_debug(OS_LOG_DEFAULT, "%s:%d: " fmt, __func__, __LINE__, ##__VA_ARGS__)
+#define infomsg(fmt, ...)  \
+       os_log_info(OS_LOG_DEFAULT, "%s:%d: " fmt, __func__, __LINE__, ##__VA_ARGS__)
+#define warnmsg(fmt, ...) \
+       os_log(OS_LOG_DEFAULT, "%s:%d: " fmt, __func__, __LINE__, ##__VA_ARGS__)
+#define errmsg(fmt, ...) \
+       os_log_error(OS_LOG_DEFAULT, "%s:%d: " fmt, __func__, __LINE__, ##__VA_ARGS__)
+
+#else /* !LF_CS_USE_OSLOG */
+
+void log_debug(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
+void log_info(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
+void log_warn(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
+void log_err(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
+
+#define debugmsg(fmt, ...) \
+       log_debug("%s:%d: " fmt, __func__, __LINE__, ##__VA_ARGS__)
+#define infomsg(fmt, ...) \
+       log_info("%s:%d: " fmt, __func__, __LINE__, ##__VA_ARGS__)
+#define warnmsg(fmt, ...) \
+       log_warn("%s:%d: " fmt, __func__, __LINE__, ##__VA_ARGS__)
+#define errmsg(fmt, ...) \
+       log_err("%s:%d: " fmt, __func__, __LINE__, ##__VA_ARGS__)
+
+#endif /* LF_CS_USE_OSLOG */
+#endif /* _LF_CS_LOGGING_H */
diff --git a/livefiles_cs_plugin/lf_cs_vfsops.c b/livefiles_cs_plugin/lf_cs_vfsops.c
new file mode 100644 (file)
index 0000000..976f2e9
--- /dev/null
@@ -0,0 +1,656 @@
+//
+// Copyright (c) 2019-2019 Apple Inc. All rights reserved.
+//
+// lf_cs_vfsops.c - Implemenents routines for handling VFS operations for
+//                  livefiles Apple_CoreStorage plugin.
+//
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/disk.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <unistd.h>
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <IOKit/IOKitLib.h>
+#include <IOKit/storage/IOMedia.h>
+#include <MediaKit/GPTTypes.h>
+#include <IOKit/IOBSD.h>
+#include <IOKit/IOTypes.h>
+
+#include "lf_cs_checksum.h"
+#include "lf_cs_disk_format.h"
+#include "lf_cs_logging.h"
+#include "lf_cs.h"
+
+#define VALUE_UNSPECIFIED ((uint64_t)-1)
+
+//
+// Verify the given data checksum.  If no explicit 'chk' area the cksum
+// value to match against is assumed to reside at the beginning of the
+// provided buffer (typically a 'metadata_header_t') and is excluded from
+// the cksum calculation itself.
+//
+static unsigned
+cs_verify_cksum(cksum_alg_t alg, const void *ptr, size_t len,
+               uint8_t *chk)
+{
+       uint8_t c[MAX_CKSUM_NBYTES];
+
+       if (!(alg == CKSUM_NONE) && !(alg == CKSUM_ALG_CRC_32)) {
+               return CS_STATUS_INVALID;
+       }
+
+       cksum_init(alg, c);
+       if (chk == NULL) {
+               cksum(alg, (chk = (uint8_t *)ptr) + MAX_CKSUM_NBYTES,
+                               len - MAX_CKSUM_NBYTES, c);
+       } else {
+               cksum(alg, ptr, len, c);
+       }
+
+       if (memcmp(c, chk, MAX_CKSUM_NBYTES)) {
+               return CS_STATUS_CKSUM;
+       }
+
+       return CS_STATUS_OK;
+}
+
+//
+// These block types must belong to the current transaction; all
+// other types can be referenced from older transactions.
+//
+#define CS_CHKPOINT_BLK(_b) \
+       ((_b)->mh_blk_type >= BLK_TYPE_VOL_HEADER &&\
+               (_b)->mh_blk_type <= BLK_TYPE_SUT)
+
+
+//
+//  These block types are the only ones with Secure Deletion content (LVF).
+//
+#define CS_DSDLIST_BLK(_b) \
+       ((_b)->mh_blk_type == BLK_TYPE_LV_FAMILY_SUPERBLOCK ||\
+               (_b)->mh_blk_type == BLK_TYPE_LV_FAMILY_XATTR)
+
+//
+// cs_verify_blkhdr - Verify standard metadata header fields.
+//
+// Each block begins with a 'metadata_header_t', which often has known/expected
+// values.
+//
+static unsigned
+cs_verify_blkhdr(const metadata_header_t *hdr, uint16_t alg,
+               uint8_t type, uint8_t subtype, uint64_t vaddr,
+               uint64_t laddr, uint64_t txg, uint32_t blksz)
+{
+       unsigned status;
+
+       if (alg != CKSUM_NONE && (status = cs_verify_cksum((cksum_alg_t)alg,
+                                       hdr, blksz, NULL)) != CS_STATUS_OK) {
+               return status;
+       }
+
+       if (type != BLK_TYPE_UNKNOWN && hdr->mh_blk_type != type) {
+               return CS_STATUS_BLKTYPE;
+       }
+
+       if (subtype != BLK_SUBTYPE_UNKNOWN && hdr->mh_blk_subtype != subtype) {
+               return CS_STATUS_INVALID;
+       }
+
+       if (vaddr != VALUE_UNSPECIFIED && hdr->mh_vaddr != vaddr) {
+               return CS_STATUS_ADDRESS;
+       }
+
+       if (laddr != VALUE_UNSPECIFIED && hdr->mh_laddr != laddr) {
+               return CS_STATUS_ADDRESS;
+       }
+
+       if (txg != VALUE_UNSPECIFIED) {
+               if (CS_CHKPOINT_BLK(hdr) && hdr->mh_txg_id != txg)
+                       return CS_STATUS_TXG;
+               else if (hdr->mh_txg_id > txg)
+                       return CS_STATUS_TXG;
+       }
+
+       if (blksz != 0 && hdr->mh_blk_size != blksz) {
+               return CS_STATUS_INVALID;
+       }
+
+       if (!CS_DSDLIST_BLK(hdr) &&
+                       (hdr->mh_blk_flags & BLK_FLAG_IN_DSD_LIST)) {
+               return CS_STATUS_INVALID;
+       }
+
+       return CS_STATUS_OK;
+}
+
+//
+// cs_verify_versions - Verify volume header version.
+//
+static unsigned
+cs_verify_versions(const metadata_header_t *hdr)
+{
+       if (hdr != NULL && hdr->mh_format_version !=
+                       CORESTORAGE_FORMAT_VERSION) {
+               return CS_INFO_VERSIONITIS | CS_STATUS_NOTCS;
+       }
+
+       if (hdr != NULL &&
+                       hdr->mh_blk_type == BLK_TYPE_VOL_HEADER &&
+                       ((dk_vol_header_t *)hdr)->vh_endianness !=
+                       BYTE_ORDER_MARK) {
+               return CS_INFO_VERSIONITIS | CS_STATUS_NOTCS;
+       }
+
+       return CS_STATUS_OK;
+}
+
+//
+// cs_verify_vh - Read and verify the Volume Headers (first/last 512-bytes of
+//                the PV).
+//
+static unsigned
+cs_verify_vh(dk_vol_header_t *hdr, uint32_t blksz)
+{
+       unsigned status;
+
+       status = cs_verify_blkhdr(&hdr->vh_header, hdr->vh_cksum_alg,
+                       BLK_TYPE_VOL_HEADER,
+                       BLK_SUBTYPE_NO_SUBTYPE, 0, 0,
+                       VALUE_UNSPECIFIED, VOL_HEADER_NBYTES);
+       if (status != CS_STATUS_OK) {
+               return status;
+       }
+
+       status = cs_verify_versions(&hdr->vh_header);
+       if (status != CS_STATUS_OK) {
+               return status;
+       }
+
+       if (!hdr->vh_num_labels || hdr->vh_num_labels > MAX_DISK_LABELS) {
+               return CS_STATUS_INVALID;
+       }
+
+       if (hdr->vh_label_max_nbytes % blksz != 0) {
+               return CS_STATUS_INVALID;
+       }
+
+       if (hdr->vh_blksz == 0 || hdr->vh_blksz % blksz != 0) {
+               return CS_STATUS_INVALID;
+       }
+
+       if (hdr->vh_pv_nbytes % blksz != 0 ||
+                       hdr->vh_pv_nbytes < CS_ALIGN(VOL_HEADER_NBYTES,
+                               blksz, true) * NUM_VOL_HEADERS) {
+               return CS_STATUS_INVALID;
+       }
+
+       if (hdr->vh_pv_resize != 0 && (hdr->vh_pv_resize % blksz != 0 ||
+                               hdr->vh_pv_resize < CS_ALIGN(VOL_HEADER_NBYTES,
+                                       blksz, true) * NUM_VOL_HEADERS)) {
+               return CS_STATUS_INVALID;
+       }
+
+       if (hdr->vh_old_pv_nbytes != 0 &&
+                       (hdr->vh_old_pv_nbytes % blksz != 0 ||
+                        hdr->vh_old_pv_nbytes < CS_ALIGN(VOL_HEADER_NBYTES,
+                                blksz, true) * NUM_VOL_HEADERS)) {
+               return CS_STATUS_INVALID;
+       }
+
+       return CS_STATUS_OK;
+}
+
+//
+// cs_get_content_hint_for_pv - get content hint of the disk from IOReg. We
+//                              read the IOReg to check if the passed disk has
+//                              a Apple_CoreStorage content hint.
+//
+static bool
+cs_get_content_hint_for_pv(struct stat *st)
+{
+       bool has_cs_hint;
+       int dev_major, dev_minor;
+       CFMutableDictionaryRef matching;
+
+       has_cs_hint = false;
+       if ((matching = IOServiceMatching(kIOMediaClass))) {
+               CFTypeRef str;
+               io_service_t service;
+
+               if ((matching = IOServiceMatching(kIOMediaClass))) {
+                       CFNumberRef num_ref;
+
+                       dev_major = major(st->st_rdev);
+                       dev_minor = minor(st->st_rdev);
+
+                       num_ref = CFNumberCreate(kCFAllocatorDefault,
+                                       kCFNumberIntType, &dev_major);
+                       if (num_ref) {
+                               CFDictionarySetValue(matching,
+                                               CFSTR(kIOBSDMajorKey),
+                                               num_ref);
+                               CFRelease(num_ref);
+                       }
+
+                       num_ref = CFNumberCreate(kCFAllocatorDefault,
+                                       kCFNumberIntType, &dev_minor);
+                       if (num_ref) {
+                               CFDictionarySetValue(matching,
+                                               CFSTR(kIOBSDMinorKey),
+                                               num_ref);
+                               CFRelease(num_ref);
+                       }
+
+                       service = IOServiceGetMatchingService(
+                                       kIOMasterPortDefault, matching);
+                       if (!service) {
+                               goto out;
+                       }
+
+                       if ((str = IORegistryEntryCreateCFProperty( service,
+                                               CFSTR(kIOMediaContentHintKey),
+                                               kCFAllocatorDefault, 0)) !=
+                                       NULL) {
+
+                               has_cs_hint = CFStringCompare((CFStringRef)str,
+                                       CFSTR(APPLE_CORESTORAGE_UUID), 0) ==
+                                       kCFCompareEqualTo;
+
+                               CFRelease(str);
+                               IOObjectRelease(service);
+                       }
+               }
+       }
+out:
+       return has_cs_hint;
+}
+
+static unsigned
+cs_verify_hdrfields(void *block, uint16_t alg, uint8_t type,
+               uint8_t subtype, uint64_t vaddr, uint64_t laddr,
+               uint32_t blksz)
+{
+       unsigned status;
+
+       if (alg != CKSUM_NONE && (status = cs_verify_cksum((cksum_alg_t)alg,
+                                       block, blksz, NULL)) !=
+                       CS_STATUS_OK) {
+               return status;
+       }
+
+       if (type != BLK_TYPE_VOL_HEADER) {
+               return CS_STATUS_BLKTYPE;
+       }
+
+       if (subtype != BLK_SUBTYPE_NO_SUBTYPE) {
+               return CS_STATUS_INVALID;
+       }
+
+       if (vaddr != 0) {
+               return CS_STATUS_ADDRESS;
+       }
+
+       if (laddr != 0) {
+               return CS_STATUS_ADDRESS;
+       }
+
+       if (blksz != VOL_HEADER_NBYTES) {
+               return CS_STATUS_INVALID;
+       }
+
+       return CS_STATUS_OK;
+}
+
+//
+// Verify if a Volume Header error might actually be due to a stale format.
+// Some historic block layouts were such that they spuriously fail recent
+// validity checks (there was a relocation of some key identifying fields in
+// the v9->v10->v11 switch).  Thus we follow-up a failure by some rudimentary
+// probing (incl cksum) and override error.
+//
+static unsigned
+cs_older_cs_version(dk_vol_header_t *hdr, unsigned status)
+{
+       uint16_t cksum_alg;
+
+       struct {
+               uint8_t         zeroes[VOL_HEADER_NBYTES];
+       } inprogress = {0};
+
+       struct v11_volhdr {
+               uint8_t         mh_cksum[MAX_CKSUM_NBYTES];
+               uint16_t        mh_format_version;
+               uint8_t         mh_blk_type;
+               uint8_t         mh_blk_subtype;
+               uint32_t        mh_bundle_version;
+               uint64_t        mh_txg_id;
+               uint64_t        mh_vaddr;
+               uint64_t        mh_laddr;
+               uint64_t        mh_blk_owner;
+               uint32_t        mh_blk_size;
+               uint8_t         mh_blk_flags;
+               uint8_t         mh_reserved1;
+               uint16_t        mh_reserved2;
+               uint64_t        mh_reserved8;
+               uint64_t        vh_pv_nbytes;
+               uint64_t        vh_pv_resize;
+               uint64_t        vh_old_pv_nbytes;
+               uint16_t        vh_endianness;
+               uint16_t        vh_cksum_alg;
+               uint16_t        vh_reserved2;
+               uint16_t        vh_num_labels;
+               uint32_t        vh_blksz;
+               uint32_t        vh_label_max_nbytes;
+               uint64_t        vh_label_addr[MAX_DISK_LABELS];
+               uint64_t        vh_move_label_addr[MAX_DISK_LABELS];
+               uint16_t        vh_wipe_key_nbytes[2];
+               uint16_t        vh_wipe_key_alg[2];
+               uint8_t         vh_wipe_key[2][MAX_WIPEKEY_NBYTES];
+               uint8_t         vh_pv_uuid[16];
+               uint8_t         vh_lvg_uuid[16];
+       } *v11;
+
+
+       if ((CS_STATUS(status) != CS_STATUS_OK) &&
+                       (hdr->vh_header.mh_format_version !=
+                       CORESTORAGE_FORMAT_VERSION)) {
+
+               //
+               // Ensure that the volume header is not totally empty before
+               // trying to check if this is indeed an older version.
+               //
+               if (!memcmp(hdr, &inprogress, VOL_HEADER_NBYTES)) {
+                       return CS_INFO_ZERO_VH | CS_STATUS_NOTCS;
+               }
+
+               v11 = (struct v11_volhdr *)hdr;
+               if (v11->mh_format_version == 11) {
+
+                       cksum_alg = v11->vh_cksum_alg;
+                       if (cs_verify_hdrfields(v11, cksum_alg,
+                                               v11->mh_blk_type,
+                                               v11->mh_blk_subtype,
+                                               v11->mh_vaddr,
+                                               v11->mh_laddr,
+                                               v11->mh_blk_size) ==
+                                       CS_STATUS_OK) {
+
+                               return CS_INFO_VERSIONITIS | CS_STATUS_NOTCS;
+                       }
+               }
+       }
+
+       return status;
+}
+
+//
+// cs_fd_is_corestorage_pv - taste if the disk is Apple_CoreStorage PV.
+//
+static int
+cs_fd_is_corestorage_pv(int disk_fd, bool *is_cs_pv)
+{
+       struct stat st;
+       bool pv_has_csuuid_hint;
+       int vh_idx, error;
+       uint32_t pv_blksz;
+       uint64_t pv_nblks;
+       uint64_t offset[NUM_VOL_HEADERS + 1];
+       unsigned status[NUM_VOL_HEADERS + 1];
+
+       dk_vol_header_t hdr[NUM_VOL_HEADERS + 1];
+
+       error = 0;
+       pv_blksz = 0;
+       pv_nblks = 0;
+       *is_cs_pv = false;
+       pv_has_csuuid_hint = false;
+
+       infomsg("Tasting Apple_CoreStorage plugin, fd: %d\n", disk_fd);
+
+       //
+       // Userfs corestorage plugin only supports block device. Thus, we
+       // ensure that the passed device is block device before proceeding
+       // further.
+       //
+       fstat(disk_fd, &st);
+       if (!S_ISBLK(st.st_mode)) {
+               errmsg("Apple_CoreStorage plugin only supports block "
+                               "device. Aborting taste.\n");
+               return ENOTSUP;
+       }
+
+       //
+       // Each PV has two volume headers, each has size 512 bytes, and resides
+       // on the first and last 512 bytes of the PV. Each volume header has a
+       // common block header with txg id and checksum, and only the volume
+       // header with the right checksum and largest txg id is used when
+       // mounting the LVG. Thus, to read the last volume header we need to
+       // know the block-size and the number of blocks in the block device.
+       //
+       if (ioctl(disk_fd, DKIOCGETBLOCKSIZE, &pv_blksz) == -1) {
+               error = errno;
+       }
+
+       if (!error && ioctl(disk_fd, DKIOCGETBLOCKCOUNT, &pv_nblks) == -1) {
+               error = errno;
+       }
+
+       //
+       // If we fail to determine the block size and block count, we bail out.
+       //
+       if (!error && (!pv_blksz || !pv_nblks)) {
+               error = ENOTBLK;
+       }
+
+       if (error) {
+               errmsg("Failed to get blocksize and block count "
+                               "for the device. Aborting taste.\n");
+               return error;
+       }
+
+       //
+       // Check if the device is tagged as being Apple_CoreStorage (Content
+       // Hint). If not we bail-out now.
+       //
+       pv_has_csuuid_hint =  cs_get_content_hint_for_pv(&st);
+       if (!pv_has_csuuid_hint) {
+               *is_cs_pv = false;
+               return 0;
+       }
+
+       //
+       // We go through the two volume headers at offset 0 and at offset
+       // (pv_nblks * pv_blksz - VOL_HEADER_NBYTES) and try to verify if
+       // the volume headers are valid core storage physical volume volume
+       // headers.
+       //
+       offset[0] = 0;
+       offset[1] = pv_nblks * pv_blksz - VOL_HEADER_NBYTES;
+
+       //
+       // Initialize status as invalid.
+       //
+       for (vh_idx = 0; vh_idx < NUM_VOL_HEADERS; ++vh_idx ) {
+               status[vh_idx] = CS_STATUS_INVALID;
+       }
+
+       for (vh_idx = 0; vh_idx < NUM_VOL_HEADERS; ++vh_idx) {
+               ssize_t bytes_read;
+
+               //
+               // Read the PV volume header and cache it inside `hdr[vh_idx]`.
+               //
+               bytes_read = pread(disk_fd, &hdr[vh_idx], VOL_HEADER_NBYTES,
+                               offset[vh_idx]);
+
+               if (bytes_read == -1) {
+                       error = errno;
+               }
+
+               if (!error && bytes_read != VOL_HEADER_NBYTES) {
+                       error = EIO;
+               }
+
+               if (error) {
+                       errmsg("Failed to read volume-hearder at offset %llu "
+                               "for disk with fd %d, Aborting taste.\n",
+                               offset[vh_idx], disk_fd);
+                       break;
+               }
+
+               //
+               // Verify read volume-header.
+               //
+               status[vh_idx] = cs_verify_vh(&hdr[vh_idx], pv_blksz);
+               if (CS_STATUS(status[vh_idx]) != CS_STATUS_OK) {
+
+                       //
+                       // Check if this physical volume has an older version
+                       // of header.
+                       //
+                       status[vh_idx] = cs_older_cs_version(&hdr[vh_idx],
+                                       status[vh_idx]);
+                       if (CS_INFO(status[vh_idx]) & CS_INFO_VERSIONITIS) {
+
+                               infomsg("Disk with fd %u has older physical "
+                                               "volume header format.\n",
+                                               disk_fd);
+                               status[vh_idx] = CS_STATUS_OK;
+                       }
+               }
+
+               if (status[vh_idx] != CS_STATUS_OK) {
+                       break;
+               }
+       }
+
+       if (error) {
+               return error;
+       }
+
+       //
+       // If there was no error and both the volume headers passed
+       // verification that means this is a core storage physical volume.
+       //
+       for (vh_idx = 0; vh_idx < NUM_VOL_HEADERS; ++vh_idx ) {
+               if (status[vh_idx] != CS_STATUS_OK) {
+                       break;
+               }
+               *is_cs_pv = true;
+       }
+
+       return 0;
+}
+
+//
+// cs_uvfsop_taste - taste if a given disk is Apple_CoreStorage PV.
+//
+// disk_fd: file descriptor of the disk to taste.
+//
+// Returns:
+//
+// i) 0 if the passed disk is indeed an Apple_CoreStorage PV.
+//
+//  Or
+//
+// ii) ENOTSUP if the passed disk is not an Apple_CoreStorage PV.
+//
+//  Or
+//
+// iii) errno if there was some error attempting to taste the disk.
+//
+static int
+cs_uvfsop_taste(int disk_fd)
+{
+       int error;
+       bool is_cs_pv;
+
+       //
+       // Each PV has two volume headers, each has size 512 bytes, and resides
+       // on the first and last 512 bytes of the PV. Each volume header has a
+       // common block header with transaction-id and checksum, and only the
+       // volume header with the right checksum and largest transaction-id is
+       // used when mounting the LVG(logical volume group). To verify that
+       // the disk with file descriptor is indeed a Apple_CoreStorage PV
+       // (physical volume), we:
+       //
+       // i) Read IOReg to verify that it has `APPLE_CORESTORAGE_UUID` hint.
+       //
+       //    and
+       //
+       // ii) Verify the PV volume headers at the start and end of the disk.
+       //
+       // Please NOTE: This taste function is defensive (strict). We do a
+       // strict match so that we ensure that we don't falsely match some
+       // other volume format.
+       //
+       error = cs_fd_is_corestorage_pv(disk_fd, &is_cs_pv);
+       if (error) {
+               errmsg("Encountered error while tasting disk with file "
+                               "descriptor %d for Apple_CoreStorage "
+                               "plugin (error %d).\n", disk_fd, error);
+               return error;
+
+       }
+
+       //
+       // This is not an Apple_CoreStorage PV.
+       //
+       if (!is_cs_pv) {
+               errmsg("Disk with file descriptor %d is not an corestorage "
+                               "physical volume.\n", disk_fd);
+               return ENOTSUP;
+       }
+
+       //
+       // We have found an Apple_CoreStorage PV, return success.
+       //
+       infomsg("Disk with file descriptor %d is corestorage physical "
+                       "volume.\n", disk_fd);
+
+       return 0;
+}
+
+//
+// Plugin lifecycle functions.
+//
+static int
+cs_uvfsop_init(void)
+{
+       infomsg("Initializing CS UserFS plugin...\n");
+       return 0;
+}
+
+static void
+cs_uvfsop_fini(void)
+{
+       infomsg("Cleaning up CS UserFS plugin...\n");
+}
+
+//
+// Plugin function registration.
+//
+UVFSFSOps cs_fsops = {
+        .fsops_version = UVFS_FSOPS_VERSION_CURRENT,
+        .fsops_init = cs_uvfsop_init,
+        .fsops_fini = cs_uvfsop_fini,
+        .fsops_taste = cs_uvfsop_taste,
+};
+
+__attribute__((visibility("default")))
+void
+livefiles_plugin_init(UVFSFSOps **ops)
+{
+        if (ops) {
+                *ops = &cs_fsops;
+        }
+}
diff --git a/livefiles_cs_plugin/livefiles_cs_tester.c b/livefiles_cs_plugin/livefiles_cs_tester.c
new file mode 100644 (file)
index 0000000..4261bdc
--- /dev/null
@@ -0,0 +1,157 @@
+//
+// Copyright (c) 2019 Apple Inc. All rights reserved.
+//
+// @APPLE_LICENSE_HEADER_START@
+//
+// This file contains Original Code and/or Modifications of Original Code
+// as defined in and that are subject to the Apple Public Source License
+// Version 2.0 (the 'License'). You may not use this file except in
+// compliance with the License. Please obtain a copy of the License at
+// http://www.opensource.apple.com/apsl/ and read it before using this
+// file.
+//
+// The Original Code and all software distributed under the License are
+// distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+// EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+// INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+// Please see the License for the specific language governing rights and
+// limitations under the License.
+//
+// @APPLE_LICENSE_HEADER_END@
+//
+// livefiles_cs_tester.c - Implements unit tests for livefiles
+//                         Apple_CoreStorage plugin.
+//
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <UserFS/UserVFS.h>
+
+extern UVFSFSOps cs_fsops;
+
+//
+// Enums describing file-system formats.
+//
+typedef enum {
+       JHFS = 1,
+       APFS,
+       FAT32,
+       EXFAT,
+       APPLE_CS,
+
+       INVALID_FS_TYPE = INT8_MAX,
+} lf_cspt_fstype_t;
+
+//
+// Array describing file-system name and analogous types.
+//
+const struct {
+       const char *const fs_name;
+       lf_cspt_fstype_t  fs_type;
+} lf_cspt_fstype_arr_t[] = {
+
+       {"JHFS", JHFS},
+       {"APFS", APFS},
+       {"EXFAT",EXFAT},
+       {"FAT32",FAT32},
+       {"APPLE_CS", APPLE_CS},
+
+       {NULL, INVALID_FS_TYPE}
+};
+
+//
+// Validate file-system types that is supported by this program.
+//
+static bool
+is_fstype_valid(const char *fs_name, lf_cspt_fstype_t *fs_type)
+{
+       int idx;
+
+       for (idx = 0; lf_cspt_fstype_arr_t[idx].fs_name != NULL; idx++) {
+               if (strcmp(fs_name, lf_cspt_fstype_arr_t[idx].fs_name) == 0) {
+                       *fs_type = lf_cspt_fstype_arr_t[idx].fs_type;
+                       return true;
+               }
+       }
+
+       return false;
+}
+
+//
+// Usage string returned to user.
+//
+static int
+usage(const char *prog_name)
+{
+       fprintf(stderr, "Usage: %s filesystem-format device-path\n",
+                       prog_name);
+       return EINVAL;
+}
+
+int
+main(int argc, char *argv[])
+{
+       int fd, error;
+       lf_cspt_fstype_t fs_type;
+
+       if (argc != 3) {
+               return usage(argv[0]);
+       }
+
+       if (!is_fstype_valid(argv[1], &fs_type)) {
+               fprintf(stderr, "Unknown file-system type %s\n", argv[1]);
+               return EINVAL;
+       }
+
+       fd = open(argv[2], O_RDWR);
+       if (fd < 0) {
+               fprintf(stderr, "Failed to open device [%s]: %d\n",
+                               argv[2], errno);
+               return EBADF;
+       }
+
+       error = cs_fsops.fsops_init();
+       printf("Init for fs_type %s returned [%d]\n", argv[1], error);
+       if (error) {
+               goto test_end;
+       }
+
+       error = cs_fsops.fsops_taste(fd);
+       switch(fs_type) {
+               case JHFS:
+               case APFS:
+               case EXFAT:
+               case FAT32:
+
+                       //
+                       // Taste with these disk-image is expected to retrun
+                       // ENOTSUP. Thus supress the error here.
+                       //
+                       if (error == ENOTSUP) {
+                               error = 0;
+                       }
+                       break;
+
+               case APPLE_CS:
+                       break;
+
+               //
+               // Control should not come here.
+               //
+               default:
+                       fprintf(stderr, "Bug in test.\n");
+       }
+       printf("Taste for fs_type %s returned [%d]\n", argv[1], error);
+       cs_fsops.fsops_fini();
+
+test_end:
+       printf("Test result [%d]\n", error);
+       close(fd);
+       return EXIT_SUCCESS;
+}
diff --git a/livefiles_cs_plugin/livefiles_cs_tester.entitlements b/livefiles_cs_plugin/livefiles_cs_tester.entitlements
new file mode 100644 (file)
index 0000000..4396b7d
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!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.restricted-block-devices</key>
+       <true/>
+       <key>com.apple.private.security.disk-device-access</key>
+       <true/>
+</dict>
+</plist>
index 8ddb76e491f3692e3e6aae11f420799bcf458184..56b334537914dbd622d3bd5f96445aab2b0eef9c 100644 (file)
@@ -279,8 +279,8 @@ typedef struct hfsmount {
     uuid_t         hfs_full_uuid;
 
     /* Per mount cnode hash variables: */
-    pthread_mutex_t      hfs_chash_mutex;    /* protects access to cnode hash table */
-    u_long         hfs_cnodehash;    /* size of cnode hash table - 1 */
+    pthread_mutex_t      hfs_chash_mutex;  /* protects access to cnode hash table */
+    u_long               hfs_cnodehash;    /* size of cnode hash table - 1 */
     LIST_HEAD(cnodehashhead, cnode) *hfs_cnodehashtbl;    /* base of cnode hash */
 
     /* Per mount fileid hash variables  (protected by catalog lock!) */
index 2c274cef9529cabadd36234470d8fe2aaff80d58..165e08967d4307b1a4889e561a4adf950a955a41 100644 (file)
@@ -3207,12 +3207,12 @@ cat_check_link_ancestry(struct hfsmount *hfsmp, cnid_t cnid, cnid_t pointed_at_c
             break;
         }
         if ((result = getkey(hfsmp, cnid, (CatalogKey *)keyp))) {
-            LFHFS_LOG(LEVEL_ERROR, "cat_check_link_ancestry: getkey failed id=%u, vol=%s\n", cnid, hfsmp->vcbVN);
+            LFHFS_LOG(LEVEL_ERROR, "cat_check_link_ancestry: getkey failed [%d] id=%u, vol=%s\n", result, cnid, hfsmp->vcbVN);
             invalid = 1;  /* On errors, assume an invalid parent */
             break;
         }
         if ((result = BTSearchRecord(fcb, ip, &btdata, NULL, NULL))) {
-            LFHFS_LOG(LEVEL_ERROR, "cat_check_link_ancestry: cannot find id=%u, vol=%s\n", cnid, hfsmp->vcbVN);
+            LFHFS_LOG(LEVEL_ERROR, "cat_check_link_ancestry: cannot find id=%u, vol=%s, [%d]\n", cnid, hfsmp->vcbVN, result);
             invalid = 1;  /* On errors, assume an invalid parent */
             break;
         }
index 60f4fd5237276756b4bef2a6e076a142c9250a53..1eb9ce873e4bf19982573c45a1ad1d76f43ce82f 100644 (file)
@@ -23,13 +23,22 @@ hfs_chash_wait(struct hfsmount *hfsmp, struct cnode  *cp)
     pthread_cond_wait(&cp->c_cacsh_cond, &hfsmp->hfs_chash_mutex);
 }
 
-void
+static void
 hfs_chash_broadcast_and_unlock(struct hfsmount *hfsmp, struct cnode  *cp)
 {
-    pthread_cond_signal(&cp->c_cacsh_cond);
+    if (cp)
+        pthread_cond_signal(&cp->c_cacsh_cond);
     hfs_chash_unlock(hfsmp);
 }
 
+static void
+hfs_chash_wait_and_unlock(struct hfsmount *hfsmp, struct cnode  *cp)
+{
+    SET(cp->c_hflag, H_WAITING);
+    pthread_cond_wait(&cp->c_cacsh_cond, &hfsmp->hfs_chash_mutex);
+    hfs_chash_broadcast_and_unlock(hfsmp, cp);
+}
+
 void
 hfs_chash_raise_OpenLookupCounter(struct cnode *cp)
 {
@@ -175,7 +184,7 @@ loop_with_lock:
             if (hfs_lock(cp, HFS_TRY_EXCLUSIVE_LOCK, HFS_LOCK_ALLOW_NOEXISTS))
             {
                 SET(cp->c_hflag, H_WAITING);
-                hfs_chash_broadcast_and_unlock(hfsmp,cp);
+                hfs_chash_broadcast_and_unlock(hfsmp, cp);
                 usleep(100);
                 goto loop;
             }
@@ -216,6 +225,7 @@ loop_with_lock:
                 *hflags &= ~H_ATTACH;
             }
             
+            pthread_cond_signal(&cp->c_cacsh_cond);
             vp = NULL;
             cp = NULL;
             if (renamed)
@@ -224,8 +234,12 @@ loop_with_lock:
             }
         }
         
-        if (cp) hfs_chash_raise_OpenLookupCounter(cp);
-        hfs_chash_broadcast_and_unlock(hfsmp,cp);
+        if (cp) {
+            hfs_chash_raise_OpenLookupCounter(cp);
+        }
+
+        hfs_chash_broadcast_and_unlock(hfsmp, cp);
+
         *vpp = vp;
         return (cp);
     }
@@ -242,7 +256,6 @@ loop_with_lock:
     if (ncp == NULL)
     {
         hfs_chash_unlock(hfsmp);
-
         ncp = hfs_mallocz(sizeof(struct cnode));
         if (ncp == NULL)
         {
@@ -267,7 +280,7 @@ loop_with_lock:
 
     lf_lck_rw_init(&ncp->c_rwlock);
     lf_cond_init(&ncp->c_cacsh_cond);
-    
+
     if (!skiplock)
     {
         (void) hfs_lock(ncp, HFS_EXCLUSIVE_LOCK, HFS_LOCK_DEFAULT);
@@ -290,10 +303,9 @@ hfs_chashwakeup(struct hfsmount *hfsmp, struct cnode *cp, int hflags)
 
     if (ISSET(cp->c_hflag, H_WAITING)) {
         CLR(cp->c_hflag, H_WAITING);
-        pthread_cond_broadcast(&cp->c_cacsh_cond);
     }
     
-    hfs_chash_unlock(hfsmp);
+    hfs_chash_broadcast_and_unlock(hfsmp, cp);
 }
 
 /*
@@ -312,9 +324,8 @@ hfs_chash_abort(struct hfsmount *hfsmp, struct cnode *cp)
     if (ISSET(cp->c_hflag, H_WAITING))
     {
         CLR(cp->c_hflag, H_WAITING);
-        pthread_cond_broadcast(&cp->c_cacsh_cond);
     }
-    hfs_chash_unlock(hfsmp);
+    hfs_chash_broadcast_and_unlock(hfsmp, cp);
 }
 
 /*
@@ -342,8 +353,7 @@ loop:
         /* Wait if cnode is being created or reclaimed. */
         if (ISSET(cp->c_hflag, H_ALLOC | H_TRANSIT | H_ATTACH)) {
             SET(cp->c_hflag, H_WAITING);
-            hfs_chash_broadcast_and_unlock(hfsmp,cp);
-            usleep(100);
+            hfs_chash_wait_and_unlock(hfsmp,cp);
             goto loop;
         }
         /* Obtain the desired vnode. */
@@ -358,7 +368,7 @@ loop:
             if (hfs_lock(cp, HFS_TRY_EXCLUSIVE_LOCK, HFS_LOCK_ALLOW_NOEXISTS))
             {
                 SET(cp->c_hflag, H_WAITING);
-                hfs_chash_broadcast_and_unlock(hfsmp,cp);
+                hfs_chash_broadcast_and_unlock(hfsmp, cp);
                 usleep(100);
                 goto loop;
             }
@@ -380,9 +390,10 @@ loop:
         }
         
         hfs_chash_raise_OpenLookupCounter(cp);
-        hfs_chash_broadcast_and_unlock(hfsmp,cp);
+        hfs_chash_broadcast_and_unlock(hfsmp, cp);
         return (vp);
     }
+
 exit:
     hfs_chash_unlock(hfsmp);
     return (NULL);
@@ -494,7 +505,7 @@ hfs_chash_set_childlinkbit(struct hfsmount *hfsmp, cnid_t cnid)
             retval = 1;
         }
     }
-    hfs_chash_unlock(hfsmp);
+    hfs_chash_broadcast_and_unlock(hfsmp, cp);
 
     return retval;
 }
@@ -510,7 +521,7 @@ hfs_chashremove(struct hfsmount *hfsmp, struct cnode *cp)
 
     /* Check if a vnode is getting attached */
     if (ISSET(cp->c_hflag, H_ATTACH)) {
-        hfs_chash_unlock(hfsmp);
+        hfs_chash_broadcast_and_unlock(hfsmp, cp);
         return (EBUSY);
     }
     if (cp->c_hash.le_next || cp->c_hash.le_prev) {
@@ -519,7 +530,7 @@ hfs_chashremove(struct hfsmount *hfsmp, struct cnode *cp)
         cp->c_hash.le_prev = NULL;
     }
 
-    hfs_chash_unlock(hfsmp);
+    hfs_chash_broadcast_and_unlock(hfsmp, cp);
 
     return (0);
 }
@@ -534,5 +545,5 @@ hfs_chash_mark_in_transit(struct hfsmount *hfsmp, struct cnode *cp)
     
     SET(cp->c_hflag, H_TRANSIT);
     
-    hfs_chash_unlock(hfsmp);
+    hfs_chash_broadcast_and_unlock(hfsmp, cp);
 }
index 2e15868d5790a39b803bca17f556491039ce2946..1431f983db92dec6edd946e1c8ef5f059f6e0125 100644 (file)
@@ -94,7 +94,6 @@ hfs_getnewvnode(struct hfsmount *hfsmp, struct vnode *dvp, struct componentname
     struct mount *mp = HFSTOVFS(hfsmp);
     struct vnode *vp = NULL;
     struct vnode **cvpp;
-    struct vnode *tvp = NULL;
     struct cnode *cp = NULL;
     struct filefork *fp = NULL;
     struct vnode *provided_vp = NULL;
@@ -439,7 +438,7 @@ hfs_getnewvnode(struct hfsmount *hfsmp, struct vnode *dvp, struct componentname
             }
             cp->c_rsrcfork = fp;
             cvpp = &cp->c_rsrc_vp;
-            if ( (tvp = cp->c_vp) != NULL )
+            if (cp->c_vp != NULL )
             {
                 cp->c_flag |= C_NEED_DVNODE_PUT;
             }
@@ -459,7 +458,7 @@ hfs_getnewvnode(struct hfsmount *hfsmp, struct vnode *dvp, struct componentname
 
             cp->c_datafork = fp;
             cvpp = &cp->c_vp;
-            if ( (tvp = cp->c_rsrc_vp) != NULL)
+            if (cp->c_rsrc_vp != NULL)
             {
                 cp->c_flag |= C_NEED_RVNODE_PUT;
             }
@@ -489,7 +488,7 @@ hfs_getnewvnode(struct hfsmount *hfsmp, struct vnode *dvp, struct componentname
                 retval = ENOMEM;
                 goto gnv_exit;
             }
-
+            bzero(vfsp.vnfs_cnp, sizeof(struct componentname));
             memcpy((void*) vfsp.vnfs_cnp, (void*)cnp, sizeof(struct componentname));
             vfsp.vnfs_cnp->cn_nameptr = lf_hfs_utils_allocate_and_copy_string( (char*) cnp->cn_nameptr, cnp->cn_namelen );
 
@@ -1871,9 +1870,12 @@ hfs_fork_release(struct cnode* cp, struct vnode *vp, bool bIsRsc, int* piErr)
     
     if (vp->sFSParams.vnfs_cnp)
     {
-        if (vp->sFSParams.vnfs_cnp->cn_nameptr)
+        if (vp->sFSParams.vnfs_cnp->cn_nameptr) {
             hfs_free(vp->sFSParams.vnfs_cnp->cn_nameptr);
+            vp->sFSParams.vnfs_cnp->cn_nameptr = NULL;
+        }
         hfs_free(vp->sFSParams.vnfs_cnp);
+        vp->sFSParams.vnfs_cnp = NULL;
     }
     
     
@@ -1931,6 +1933,8 @@ hfs_fork_release(struct cnode* cp, struct vnode *vp, bool bIsRsc, int* piErr)
 int
 hfs_vnop_reclaim(struct vnode *vp)
 {
+    if (!vp) return EINVAL;
+
     struct cnode* cp = VTOC(vp);
     struct hfsmount *hfsmp = VTOHFS(vp);
     struct vnode *altvp = NULL;
index b4bb873f9810b3880c24053ed9bc7ca0387d9f31..09bb5ac570b924ca24c59f3665610ba49a11e06e 100644 (file)
@@ -491,8 +491,11 @@ LFHFS_GetFSAttr ( UVFSFileNode psNode, const char *pcAttr, UVFSFSAttributeValue
             return E2BIG;
         }
         // A string representing the type of file system
-        strcpy(psAttrVal->fsa_string, "HFS");
-        *(psAttrVal->fsa_string+3) = 0; // Must be null terminated
+        size_t n = strlcpy(psAttrVal->fsa_string, "HFS", *puRetLen);
+        if (n >= *puRetLen)
+        {
+             *(psAttrVal->fsa_string + (*puRetLen - 1)) = '\0'; // Must be null terminated
+        }
         goto end;
     }
 
@@ -523,7 +526,7 @@ LFHFS_GetFSAttr ( UVFSFileNode psNode, const char *pcAttr, UVFSFSAttributeValue
             return E2BIG;
         }
 
-        strcpy( psAttrVal->fsa_string, pcFSSubType );
+        strlcpy( psAttrVal->fsa_string, pcFSSubType, *puRetLen);
         goto end;
     }
 
@@ -534,7 +537,7 @@ LFHFS_GetFSAttr ( UVFSFileNode psNode, const char *pcAttr, UVFSFSAttributeValue
         {
             return E2BIG;
         }
-        strcpy(psAttrVal->fsa_string, (char *)psMount->vcbVN);
+        strlcpy(psAttrVal->fsa_string, (char *)psMount->vcbVN, *puRetLen);
         goto end;
     }
 
index 471868ddb683d9ce8fd6afc1617b7c83afea4cb4..cc3522d748d2e93d2669d528b51e3fc344d90963 100644 (file)
@@ -2914,11 +2914,11 @@ static int end_transaction(transaction *tr, int force_it, errno_t (*callback)(vo
     
     lock_oldstart(jnl);
     /*
-     * Because old_start is locked above, we can cast away the volatile qualifier before passing it to memcpy.
+     * Because old_start is locked above, we can cast away the volatile qualifier before passing it to memmove.
      * slide everyone else down and put our latest guy in the last
      * entry in the old_start array
      */
-    memcpy(__CAST_AWAY_QUALIFIER(&jnl->old_start[0], volatile, void *), __CAST_AWAY_QUALIFIER(&jnl->old_start[1], volatile, void *), sizeof(jnl->old_start)-sizeof(jnl->old_start[0]));
+    memmove(__CAST_AWAY_QUALIFIER(&jnl->old_start[0], volatile, void *), __CAST_AWAY_QUALIFIER(&jnl->old_start[1], volatile, void *), sizeof(jnl->old_start)-sizeof(jnl->old_start[0]));
     jnl->old_start[sizeof(jnl->old_start)/sizeof(jnl->old_start[0]) - 1] = tr->journal_start | 0x8000000000000000LL;
     
     unlock_oldstart(jnl);
index f76547637a6cb828a090fe095257ffc4d907c0d2..279788165a8879da148ead1e3386c36400bc9ccb 100644 (file)
@@ -558,7 +558,7 @@ hfs_privatedir_init(struct hfsmount * hfsmp, enum privdirtype type)
 
     /* Get the CNID for use */
     cnid_t new_id;
-    if ((error = cat_acquire_cnid(hfsmp, &new_id))) {
+    if (cat_acquire_cnid(hfsmp, &new_id)) {
         hfs_systemfile_unlock (hfsmp, lockflags);
         goto exit;
     }
index 4689cad2b94f763b47d09f08f269bcc769880d15..3b1c3ccbf874810466451cac2acd2f9eb8e44d9f 100644 (file)
@@ -324,6 +324,7 @@ static int hfs_InitialMount(struct vnode *devvp, struct mount *mp, struct hfs_mo
 
     mntwrapper = 0;
     minblksize = kHFSBlockSize;
+    *hfsmp = NULL;
 
     /* Get the logical block size (treated as physical block size everywhere) */
     if (ioctl(devvp->psFSRecord->iFD, DKIOCGETBLOCKSIZE, &log_blksize))
@@ -361,6 +362,16 @@ static int hfs_InitialMount(struct vnode *devvp, struct mount *mp, struct hfs_mo
         goto error_exit;
     }
 
+       /* Don't let phys_blksize be smaller than the logical  */
+       if (phys_blksize < log_blksize) {
+               /*
+                * In the off chance that the phys_blksize is SMALLER than the logical
+                * then don't let that happen.  Pretend that the PHYSICALBLOCKSIZE
+                * ioctl was not supported.
+                */
+                phys_blksize = log_blksize;
+       }
+
     /* Get the number of physical blocks. */
     if (ioctl(devvp->psFSRecord->iFD, DKIOCGETBLOCKCOUNT, &log_blkcnt))
     {
@@ -1601,180 +1612,6 @@ void hfs_scan_blocks (struct hfsmount *hfsmp)
     hfs_systemfile_unlock(hfsmp, flags);
 }
 
-int
-hfs_GetInfoByID(struct hfsmount *hfsmp, cnid_t cnid, UVFSFileAttributes *file_attrs, char pcName[MAX_UTF8_NAME_LENGTH])
-{
-    u_int32_t linkref = 0;
-    struct vnode *psVnode = NULL;
-    struct cat_desc cndesc;
-    struct cat_attr cnattr;
-    struct cat_fork cnfork;
-    int error = 0;
-
-    /* Check for cnids that should't be exported. */
-    if ((cnid < kHFSFirstUserCatalogNodeID) &&
-        (cnid != kHFSRootFolderID && cnid != kHFSRootParentID)) {
-        return (ENOENT);
-    }
-    /* Don't export our private directories. */
-    if (cnid == hfsmp->hfs_private_desc[FILE_HARDLINKS].cd_cnid ||
-        cnid == hfsmp->hfs_private_desc[DIR_HARDLINKS].cd_cnid) {
-        return (ENOENT);
-    }
-    /*
-     * Check the hash first
-     */
-    psVnode = hfs_chash_getvnode(hfsmp, cnid, 0, 0, 0);
-    if (psVnode) {
-        goto getAttrAndDone;
-    }
-
-    bzero(&cndesc, sizeof(cndesc));
-    bzero(&cnattr, sizeof(cnattr));
-    bzero(&cnfork, sizeof(cnfork));
-
-    /*
-     * Not in hash, lookup in catalog
-     */
-    if (cnid == kHFSRootParentID) {
-        static char hfs_rootname[] = "/";
-
-        cndesc.cd_nameptr = (const u_int8_t *)&hfs_rootname[0];
-        cndesc.cd_namelen = 1;
-        cndesc.cd_parentcnid = kHFSRootParentID;
-        cndesc.cd_cnid = kHFSRootFolderID;
-        cndesc.cd_flags = CD_ISDIR;
-
-        cnattr.ca_fileid = kHFSRootFolderID;
-        cnattr.ca_linkcount = 1;
-        cnattr.ca_entries = 1;
-        cnattr.ca_dircount = 1;
-        cnattr.ca_mode = (S_IFDIR | S_IRWXU | S_IRWXG | S_IRWXO);
-    } else {
-        int lockflags;
-        cnid_t pid;
-        const char *nameptr;
-
-        lockflags = hfs_systemfile_lock(hfsmp, SFL_CATALOG, HFS_SHARED_LOCK);
-        error = cat_idlookup(hfsmp, cnid, 0, 0, &cndesc, &cnattr, &cnfork);
-        hfs_systemfile_unlock(hfsmp, lockflags);
-
-        if (error) {
-            return (error);
-        }
-
-        /*
-         * Check for a raw hardlink inode and save its linkref.
-         */
-        pid = cndesc.cd_parentcnid;
-        nameptr = (const char *)cndesc.cd_nameptr;
-        if ((pid == hfsmp->hfs_private_desc[FILE_HARDLINKS].cd_cnid) &&
-            cndesc.cd_namelen > HFS_INODE_PREFIX_LEN &&
-            (bcmp(nameptr, HFS_INODE_PREFIX, HFS_INODE_PREFIX_LEN) == 0)) {
-            linkref = (uint32_t) strtoul(&nameptr[HFS_INODE_PREFIX_LEN], NULL, 10);
-
-        } else if ((pid == hfsmp->hfs_private_desc[DIR_HARDLINKS].cd_cnid) &&
-                   cndesc.cd_namelen > HFS_DIRINODE_PREFIX_LEN &&
-                   (bcmp(nameptr, HFS_DIRINODE_PREFIX, HFS_DIRINODE_PREFIX_LEN) == 0)) {
-            linkref = (uint32_t) strtoul(&nameptr[HFS_DIRINODE_PREFIX_LEN], NULL, 10);
-
-        } else if ((pid == hfsmp->hfs_private_desc[FILE_HARDLINKS].cd_cnid) &&
-                   cndesc.cd_namelen > HFS_DELETE_PREFIX_LEN &&
-                   (bcmp(nameptr, HFS_DELETE_PREFIX, HFS_DELETE_PREFIX_LEN) == 0)) {
-            cat_releasedesc(&cndesc);
-            return (ENOENT);  /* open unlinked file */
-        }
-    }
-
-    /*
-     * Finish initializing cnode descriptor for hardlinks.
-     *
-     * We need a valid name and parent for reverse lookups.
-     */
-    if (linkref) {
-        cnid_t lastid;
-        struct cat_desc linkdesc;
-        int linkerr = 0;
-
-        cnattr.ca_linkref = linkref;
-        bzero (&linkdesc, sizeof (linkdesc));
-
-        /*
-         * If the caller supplied the raw inode value, then we don't know exactly
-         * which hardlink they wanted. It's likely that they acquired the raw inode
-         * value BEFORE the item became a hardlink, in which case, they probably
-         * want the oldest link.  So request the oldest link from the catalog.
-         *
-         * Unfortunately, this requires that we iterate through all N hardlinks. On the plus
-         * side, since we know that we want the last linkID, we can also have this one
-         * call give us back the name of the last ID, since it's going to have it in-hand...
-         */
-        linkerr = hfs_lookup_lastlink (hfsmp, linkref, &lastid, &linkdesc);
-        if ((linkerr == 0) && (lastid != 0)) {
-            /*
-             * Release any lingering buffers attached to our local descriptor.
-             * Then copy the name and other business into the cndesc
-             */
-            cat_releasedesc (&cndesc);
-            bcopy (&linkdesc, &cndesc, sizeof(linkdesc));
-        }
-        /* If it failed, the linkref code will just use whatever it had in-hand below. */
-
-        int newvnode_flags = 0;
-        error = hfs_getnewvnode(hfsmp, NULL, NULL, &cndesc, 0, &cnattr, &cnfork, &psVnode, &newvnode_flags);
-        if (error == 0) {
-            VTOC(psVnode)->c_flag |= C_HARDLINK;
-        }
-    }
-    else
-    {
-        int newvnode_flags = 0;
-
-        void *buf = hfs_malloc(MAX_UTF8_NAME_LENGTH);
-        if (buf == NULL) {
-            return (ENOMEM);
-        }
-        
-        /* Supply hfs_getnewvnode with a component name. */
-        struct componentname cn = {
-            .cn_nameiop = LOOKUP,
-            .cn_flags    = ISLASTCN,
-            .cn_pnlen    = MAXPATHLEN,
-            .cn_namelen = cndesc.cd_namelen,
-            .cn_pnbuf    = buf,
-            .cn_nameptr = buf
-        };
-
-        bcopy(cndesc.cd_nameptr, cn.cn_nameptr, cndesc.cd_namelen + 1);
-        error = hfs_getnewvnode(hfsmp, NULL, &cn, &cndesc, 0, &cnattr, &cnfork, &psVnode, &newvnode_flags);
-        if (error == 0 && (VTOC(psVnode)->c_flag & C_HARDLINK)) {
-            hfs_savelinkorigin(VTOC(psVnode), cndesc.cd_parentcnid);
-        }
-
-        hfs_free(buf);
-    }
-    cat_releasedesc(&cndesc);
-    
-getAttrAndDone:
-    if (!error) vnode_GetAttrInternal (psVnode, file_attrs);
-    if (psVnode != NULL) hfs_unlock(VTOC(psVnode));
-    
-    if (error || psVnode == NULL || psVnode->sFSParams.vnfs_cnp->cn_nameptr == NULL){
-        hfs_vnop_reclaim(psVnode);
-        return EFAULT;
-    }
-
-    if (cnid == kHFSRootFolderID)
-        pcName[0] = 0;
-    else {
-        strlcpy(pcName, (char*) psVnode->sFSParams.vnfs_cnp->cn_nameptr, MAX_UTF8_NAME_LENGTH);
-    }
-
-    error = hfs_vnop_reclaim(psVnode);
-
-    return (error);
-}
-
 /*
  * Look up an HFS object by ID.
  *
@@ -1952,6 +1789,34 @@ hfs_vget(struct hfsmount *hfsmp, cnid_t cnid, struct vnode **vpp, int skiplock,
     return (error);
 }
 
+int
+hfs_GetInfoByID(struct hfsmount *hfsmp, cnid_t cnid, UVFSFileAttributes *file_attrs, char pcName[MAX_UTF8_NAME_LENGTH])
+{
+    struct vnode *psVnode = NULL;
+    int error = hfs_vget(hfsmp, cnid, &psVnode, 0, 0);
+    if (error || psVnode == NULL) {
+        if (psVnode != NULL) hfs_unlock(VTOC(psVnode));
+        hfs_vnop_reclaim(psVnode);
+        return EFAULT;
+    } else {
+        vnode_GetAttrInternal (psVnode, file_attrs);
+        hfs_unlock(VTOC(psVnode));
+    }
+
+    if (cnid == kHFSRootFolderID)
+        pcName[0] = 0;
+    else {
+        //Make sure we actually have the name in the vnode
+        if (psVnode->sFSParams.vnfs_cnp && psVnode->sFSParams.vnfs_cnp->cn_nameptr)
+            strlcpy(pcName, (char*) psVnode->sFSParams.vnfs_cnp->cn_nameptr, MAX_UTF8_NAME_LENGTH);
+        else
+            return EINVAL;
+    }
+
+    error = hfs_vnop_reclaim(psVnode);
+    return (error);
+}
+
 /*
  * Return the root of a filesystem.
  */
index 0bc73b6eb5b2951fb816c1a3bd36a177c65b82a6..f8b27ed544b5c447978f3fedb77ee0fb56212f00 100644 (file)
@@ -125,10 +125,12 @@ void vnode_update_identity(vnode_t vp, vnode_t dvp, const char *name, int name_l
                 LFHFS_LOG(LEVEL_ERROR, "vnode_update_identity: failed to malloc vnfs_cnp\n");
                 assert(0);
             }
+            bzero(vp->sFSParams.vnfs_cnp, sizeof(struct componentname));
         }
         vp->sFSParams.vnfs_cnp->cn_namelen = name_len;
         if (vp->sFSParams.vnfs_cnp->cn_nameptr) {
             hfs_free(vp->sFSParams.vnfs_cnp->cn_nameptr);
+            vp->sFSParams.vnfs_cnp->cn_nameptr = NULL;
         }
         vp->sFSParams.vnfs_cnp->cn_nameptr = lf_hfs_utils_allocate_and_copy_string( (char*) name, name_len );
         vp->sFSParams.vnfs_cnp->cn_hash = name_hashval;
index e15edaac333452b5eb49f1b37dbc7724d86f720e..17b3f623a9b1e634abd9cf6bee63204232cb2b27 100644 (file)
@@ -168,7 +168,6 @@ hfs_vnop_getxattr(vnode_t vp, const char *attr_name, void *buf, size_t bufsize,
     BTreeIterator * iterator = NULL;
     size_t attrsize = 0;
     HFSPlusAttrRecord *recp = NULL;
-    size_t recp_size = 0;
     FSBufferDescriptor btdata;
     int lockflags = 0;
     u_int16_t datasize = 0;
@@ -196,7 +195,7 @@ hfs_vnop_getxattr(vnode_t vp, const char *attr_name, void *buf, size_t bufsize,
      * big enough to read in all types of attribute records.  It is not big
      * enough to read inline attribute data which is read in later.
      */
-    recp = hfs_malloc(recp_size = sizeof(HFSPlusAttrRecord));
+    recp = hfs_malloc(sizeof(HFSPlusAttrRecord));
     btdata.bufferAddress = recp;
     btdata.itemSize = sizeof(HFSPlusAttrRecord);
     btdata.itemCount = 1;
@@ -250,7 +249,7 @@ hfs_vnop_getxattr(vnode_t vp, const char *attr_name, void *buf, size_t bufsize,
                      */
                     attrsize = sizeof(HFSPlusAttrData) - 2 + recp->attrData.attrSize;
                     hfs_free(recp);
-                    recp = hfs_malloc(recp_size = attrsize);
+                    recp = hfs_malloc(attrsize);
 
                     btdata.bufferAddress = recp;
                     btdata.itemSize = attrsize;
@@ -558,7 +557,6 @@ hfs_vnop_setxattr(vnode_t vp, const char *attr_name, const void *buf, size_t buf
     FSBufferDescriptor btdata;
     HFSPlusAttrRecord attrdata;  /* 90 bytes */
     HFSPlusAttrRecord *recp = NULL;
-    size_t recp_size = 0;
     HFSPlusExtentDescriptor *extentptr = NULL;
     size_t extentbufsize = 0;
     int lockflags = 0;
@@ -674,7 +672,7 @@ hfs_vnop_setxattr(vnode_t vp, const char *attr_name, const void *buf, size_t buf
             }
         }
         /* Create attribute fork data record. */
-        recp = hfs_malloc(recp_size = sizeof(HFSPlusAttrRecord));
+        recp = hfs_malloc(sizeof(HFSPlusAttrRecord));
 
         btdata.bufferAddress = recp;
         btdata.itemCount = 1;
@@ -731,7 +729,7 @@ hfs_vnop_setxattr(vnode_t vp, const char *attr_name, const void *buf, size_t buf
 
         /* Calculate size of record rounded up to multiple of 2 bytes. */
         btdata.itemSize = sizeof(HFSPlusAttrData) - 2 + attrsize + ((attrsize & 1) ? 1 : 0);
-        recp = hfs_malloc(recp_size = btdata.itemSize);
+        recp = hfs_malloc(btdata.itemSize);
 
         recp->recordType = kHFSPlusAttrInlineData;
         recp->attrData.reserved[0] = 0;
index 9e8fcffdd6d76c8e5c6c2647493962c7d86436d6..60e7162d88d07fe6ee30587697edd7ad969590df 100644 (file)
@@ -33,6 +33,7 @@
 #include <sys/wait.h>
 #include <sys/ioctl.h>
 #include <sys/disk.h>
+#include <assert.h>
 
 #include <ctype.h>
 #include <err.h>
@@ -370,7 +371,7 @@ void syncCreateDate(const char *mntpt, u_int32_t localCreateTime)
        if (result) return;
 
        gmtCreateTime = attrReturnBuffer.creationTime.tv_sec;
-       gmtOffset = gmtCreateTime - (int64_t) localCreateTime + 900;
+       gmtOffset = (int32_t)(gmtCreateTime - (int64_t) localCreateTime + 900);
        if (gmtOffset > 0) {
                gmtOffset = 1800 * (gmtOffset / 1800);
        } else {
@@ -747,8 +748,12 @@ a_mask(s)
     done = 0;
     rv = -1;
     if (*s >= '0' && *s <= '7') {
+        long mask;
+
         done = 1;
-        rv = strtol(optarg, &ep, 8);
+        mask = strtol(optarg, &ep, 8);
+        if (mask >= 0 && mask <= INT_MAX)
+            rv = (int)mask;
     }
     if (!done || rv < 0 || *ep)
         errx(1, "invalid file mode: %s", s);
@@ -878,11 +883,14 @@ get_default_encoding()
 
                if ((fd = open(buffer, O_RDONLY, 0)) > 0) {
                        ssize_t readSize;
+            long encoding;
 
                        readSize = read(fd, buffer, MAXPATHLEN);
                        buffer[(readSize < 0 ? 0 : readSize)] = '\0';
                        close(fd);
-                       return strtol(buffer, NULL, 0);
+            encoding = strtol(buffer, NULL, 0);
+            assert(encoding > -1 && encoding <= UINT_MAX);
+                       return (unsigned int)encoding;
                }
        }
        return (0);     /* Fallback to smRoman */
index 724a43dd9b18655978f60f93efd664bd4c59cdc8..3b05d2520511f29415e672683fac96fe69dedad8 100644 (file)
@@ -279,7 +279,7 @@ createExtents(HFSPlusForkData *file,
                 */
                if ((blockStep * numExtents) < blocksLeft) {
                        // Need to adjust the first one.
-                       firstAdjust = blocksLeft - (blockStep * numExtents);
+                       firstAdjust = (int)(blocksLeft - (blockStep * numExtents));
                        if ((firstAdjust % minBlocks) != 0)
                                firstAdjust = ROUNDUP(firstAdjust, minBlocks);
                }
@@ -657,7 +657,7 @@ InitVH(hfsparams_t *defaults, UInt64 sectors, HFSPlusVolumeHeader *hp)
        bzero(hp, kBytesPerSector);
 
        blockSize = defaults->blockSize;
-       blockCount = sectors / (blockSize >> kLog2SectorSize);
+       blockCount = (UInt32)(sectors / (blockSize >> kLog2SectorSize));
 
        /*
         * HFSPlusVolumeHeader is located at sector 2, so we may need
@@ -984,7 +984,7 @@ MarkExtentUsed(const DriveInfo *driveInfo,
                memset(buf, 0, sizeof(buf));
                secNum = curBlock / (bufSize * kBitsPerByte);
                blockOffset = curBlock % (bufSize * kBitsPerByte);
-               numBlocks = MIN((bufSize * kBitsPerByte) - blockOffset, blocksLeft);
+               numBlocks = (uint32_t)MIN((bufSize * kBitsPerByte) - blockOffset, blocksLeft);
 
                /*
                 * Okay, now we've got the block number to read,
@@ -1895,7 +1895,7 @@ WriteBuffer(const DriveInfo *driveInfo, UInt64 startingSector, UInt64 byteCount,
        /* try a buffer size for optimal IO, __UP TO 4MB__. if that
           fails, then try with the minimum allowed buffer size, which
           is equal to physSectorSize */
-       tempbufSizeInPhysSectors = MIN ( (byteCount - 1 + physSectorSize) / physSectorSize,
+       tempbufSizeInPhysSectors = (UInt32)MIN ( (byteCount - 1 + physSectorSize) / physSectorSize,
                                             driveInfo->physSectorsPerIO );
        /* limit at 4MB */
        tempbufSizeInPhysSectors = MIN ( tempbufSizeInPhysSectors, (4 * 1024 * 1024) / physSectorSize );
@@ -1922,9 +1922,9 @@ WriteBuffer(const DriveInfo *driveInfo, UInt64 startingSector, UInt64 byteCount,
        byteOffsetInPhysSector =  (sector % sectorSizeRatio) * kBytesPerSector;
 
        while (byteCount > 0) {
-               numPhysSectorsToIO = MIN ( (byteCount - 1 + physSectorSize) / physSectorSize,
+               numPhysSectorsToIO = (UInt32)MIN ( (byteCount - 1 + physSectorSize) / physSectorSize,
                                       tempbufSizeInPhysSectors );
-               numBytesToIO = MIN(byteCount, (unsigned)((numPhysSectorsToIO * physSectorSize) - byteOffsetInPhysSector));
+               numBytesToIO = (UInt32)MIN(byteCount, (unsigned)((numPhysSectorsToIO * physSectorSize) - byteOffsetInPhysSector));
 
                /* if IO does not align with physical sector boundaries */
                if ((0 != byteOffsetInPhysSector) || ((numBytesToIO % physSectorSize) != 0)) {
index 466fdc1a81825c4892b48f57ca55b8d785d21a45..7b27182d0e0578a049df1bbef6ad1a6bdac89a16 100644 (file)
@@ -299,7 +299,7 @@ main(argc, argv)
                                fatal("%s: bad allocation block size (too small)", optarg);
                        if (tempBlockSize > HFSMAXBSIZE) 
                                fatal("%s: bad allocation block size (too large)", optarg);
-                       gBlockSize = tempBlockSize;
+                       gBlockSize = (uint32_t)tempBlockSize;
                        break;
                }
 
@@ -564,6 +564,8 @@ static void getstartopts(char* optlist)
        char *ndarg;
        char *p;
        unsigned long startat = 0;
+    int pos;
+    UInt32 upos;
 
        startat = strtoul(optlist, &strp, 0);
        if (startat == ULONG_MAX && errno != 0) {
@@ -575,7 +577,7 @@ static void getstartopts(char* optlist)
        if (strp && *strp == ',')
                strp++;
 
-       gFSStartBlock = startat;
+       gFSStartBlock = (UInt32)startat;
 
        while((ndarg = strsep(&strp, ",")) != NULL && *ndarg != '\0') {
 
@@ -584,29 +586,33 @@ static void getstartopts(char* optlist)
                if (p == NULL)
                        usage();
                        
-               startat = atoi(p+1);
-               
+               pos = atoi(p+1);
+        if (pos < 0 || pos > UINT32_MAX) {
+            errx(1, "pos=%d is invalid", pos);
+        }
+        upos = (UInt32)pos;
+
                switch (*ndarg) {
                case 'a':
-                       attrExtStart = startat;
+                       attrExtStart = upos;
                        break;
                case 'b':
-                       blkallocExtStart = startat;
+                       blkallocExtStart = upos;
                        break;
                case 'c':
-                       catExtStart = startat;
+                       catExtStart = upos;
                        break;
                case 'e':
-                       extExtStart = startat;
+                       extExtStart = upos;
                        break;
                case 'j':
-                       jibStart = startat;
+                       jibStart = upos;
                        break;
                case 'J':
-                       jnlStart = startat;
+                       jnlStart = upos;
                        break;
                case 'N':
-                       allocStart = startat;
+                       allocStart = upos;
                        break;
                default:
                        usage();
@@ -656,7 +662,8 @@ a_uid(char *s)
 static mode_t
 a_mask(char *s)
 {
-       int done, rv;
+       int done;
+    long rv;
        char *ep;
 
        done = 0;
@@ -665,9 +672,9 @@ a_mask(char *s)
                done = 1;
                rv = strtol(s, &ep, 8);
        }
-       if (!done || rv < 0 || *ep)
+       if (!done || rv < 0 || rv > INT_MAX || *ep)
                errx(1, "invalid access mask: %s", s);
-       return (rv);
+       return ((int)rv);
 }
 
 /*
@@ -812,7 +819,7 @@ static void validate_hfsplus_block_size(UInt64 sectorCount, UInt32 sectorSize)
                 * value. At 2TB, we grow to the 8K block size.
                 */
                if ((bit_index >= 0) && (bit_index < 22)) {
-                       gBlockSize = alloc_blocksize[bit_index];
+                       gBlockSize = (uint32_t)alloc_blocksize[bit_index];
                }
                
                if (bit_index >= 22) {
@@ -836,7 +843,7 @@ static void validate_hfsplus_block_size(UInt64 sectorCount, UInt32 sectorSize)
 
        if (gFSStartBlock) {
                u_int64_t fs_size = sectorCount * sectorSize;
-               u_int32_t totalBlocks = fs_size/gBlockSize;
+               u_int32_t totalBlocks = (u_int32_t)(fs_size/gBlockSize);
 
                if (gFSStartBlock >= totalBlocks) {
                        warnx("Warning: %u is invalid file system start allocation block number, must be less than total allocation blocks (%u)", (unsigned int)gFSStartBlock, (unsigned int)totalBlocks);
@@ -1013,7 +1020,8 @@ static void hfsplus_params (const DriveInfo* dip, hfsparams_t *defaults)
        defaults->blockSize = gBlockSize;
        defaults->fsStartBlock = gFSStartBlock;
        defaults->nextFreeFileID = gNextCNID;
-       defaults->createDate = createtime + MAC_GMT_FACTOR;     /* Mac OS GMT time */
+    // Value will be bigger than UIN32_MAX in 2040
+       defaults->createDate = (uint32_t)(createtime + MAC_GMT_FACTOR);     /* Mac OS GMT time */
        defaults->hfsAlignment = 0;
        defaults->journaledHFS = gJournaled;
        defaults->journalDevice = gJournalDevice;
@@ -1079,7 +1087,7 @@ static void hfsplus_params (const DriveInfo* dip, hfsparams_t *defaults)
 
                        }
                        /* defaults->journalSize will get reset below if it is 0 */
-                       defaults->journalSize = gJournalSize;
+                       defaults->journalSize = (uint32_t)gJournalSize;
                }
 
                if ((gJournalSize == 0) || (defaults->journalSize == 0)) {
@@ -1271,7 +1279,7 @@ static void hfsplus_params (const DriveInfo* dip, hfsparams_t *defaults)
         * Note: this minimum value may be too large when it counts the
         * space used by the wrapper
         */
-       totalBlocks = sectorCount / (gBlockSize / sectorSize);
+       totalBlocks = (uint32_t)(sectorCount / (gBlockSize / sectorSize));
 
        minClumpSize = totalBlocks >> 3;        /* convert bits to bytes by dividing by 8 */
        if (totalBlocks & 7)
@@ -1454,7 +1462,7 @@ CalcHFSPlusBTreeClumpSize(UInt32 blockSize, UInt32 nodeSize, UInt64 sectors, int
         * it must also be a multiple of the node and block size.
         */
        if (sectors < 0x200000) {
-               clumpSize = sectors << 2;       /*  0.8 %  */
+               clumpSize = (UInt32)(sectors << 2);     /*  0.8 %  */
                if (clumpSize < (8 * nodeSize))
                        clumpSize = 8 * nodeSize;
        } else {
index 6b862368e1d88e5b49328606e830ea6919b57b55..c5542b22c7c76276454f30249b1abbf549b887b6 100644 (file)
 #include "../core/hfs_format.h"
 #include "test-utils.h"
 
-#define DISK_IMAGE_1           "/tmp/external-jnl1.sparseimage"
-#define DISK_IMAGE_2           "/tmp/external-jnl2.sparseimage"
+#define HOST_IMAGE                     "/tmp/external-jnl1.sparseimage"
+#define EXTERNAL_IMAGE "/tmp/external-jnl2.sparseimage"
 
 TEST(external_jnl)
 
 int run_external_jnl(__unused test_ctx_t *ctx)
 {
-       unlink(DISK_IMAGE_1);
-       unlink(DISK_IMAGE_2);
-
-       disk_image_t *di1 = disk_image_create(DISK_IMAGE_1,
-                                                                                 &(disk_image_opts_t){
-                                                                                         .size = 64 * 1024 * 1024
-                                                                                 });
-       disk_image_t *di2
-               = disk_image_create(DISK_IMAGE_2,
+       unlink(HOST_IMAGE);
+       unlink(EXTERNAL_IMAGE);
+
+       /* Since disk image cleanup occurs on a stack, create the external
+        * journal partition first so that the cleanup of the host image
+        * prevents a resource busy error during the journal partition ejection.
+        */
+       disk_image_t *di_ext = disk_image_create(EXTERNAL_IMAGE,
                                                        &(disk_image_opts_t){
                                                                .partition_type = EXTJNL_CONTENT_TYPE_UUID,
                                                                .size = 8 * 1024 * 1024
                                                        });
 
-       unmount(di1->mount_point, 0);
+       disk_image_t *di_host = disk_image_create(HOST_IMAGE,
+                                                       &(disk_image_opts_t){
+                                                               .size = 64 * 1024 * 1024
+                                                       });
+
+       unmount(di_host->mount_point, 0);
 
-       assert(!systemx("/sbin/newfs_hfs", SYSTEMX_QUIET, "-J", "-D", di2->disk, di1->disk, NULL));
+       assert(!systemx("/sbin/newfs_hfs", SYSTEMX_QUIET, "-J", "-D", di_ext->disk, di_host->disk, NULL));
 
-       assert(!systemx("/usr/sbin/diskutil", SYSTEMX_QUIET, "mount", di1->disk, NULL));
+       assert(!systemx("/usr/sbin/diskutil", SYSTEMX_QUIET, "mount", di_host->disk, NULL));
 
-       free((char *)di1->mount_point);
-       di1->mount_point = NULL;
+       free((char *)di_host->mount_point);
+       di_host->mount_point = NULL;
 
        struct statfs *mntbuf;
        int i, n = getmntinfo(&mntbuf, 0);
        for (i = 0; i < n; ++i) {
-               if (!strcmp(mntbuf[i].f_mntfromname, di1->disk)) {
-                       di1->mount_point = strdup(mntbuf[i].f_mntonname);
+               if (!strcmp(mntbuf[i].f_mntfromname, di_host->disk)) {
+                       di_host->mount_point = strdup(mntbuf[i].f_mntonname);
                        break;
                }
        }
@@ -65,7 +69,7 @@ int run_external_jnl(__unused test_ctx_t *ctx)
        assert(i < n);
 
        char *path;
-       asprintf(&path, "%s/test", di1->mount_point);
+       asprintf(&path, "%s/test", di_host->mount_point);
        int fd = open(path, O_RDWR | O_CREAT, 0666);
        assert_with_errno(fd >= 0);
        assert_no_err(close(fd));
index 74dedda27289aeabb54a0e1cfbe01c9af5f548be..42f60cb158deb9d459f77870814ad284986715ee 100644 (file)
@@ -112,7 +112,7 @@ void *append_to_file(void *param)
                assert_no_err(msync(p + total - round, todo + round, 
                                                        MS_ASYNC | MS_INVALIDATE));
 
-               CC_MD5_Update(&md5_ctx, buf1, todo);
+               CC_MD5_Update(&md5_ctx, buf1, (CC_LONG)todo);
 
                total += todo;
        }
@@ -192,10 +192,10 @@ static void fill_disk(int *fd, uint64_t *size)
        struct statfs sfs;
        assert_no_err(fstatfs(*fd, &sfs));
 
-       uint32_t blocks = sfs.f_bfree;
+       uint64_t blocks = sfs.f_bfree;
 
        for (;;) {
-               uint64_t size = (uint64_t)blocks * sfs.f_bsize;
+               uint64_t size = blocks * sfs.f_bsize;
 
                if (!fcntl(*fd, F_SETSIZE, &size))
                        break;
@@ -206,15 +206,15 @@ static void fill_disk(int *fd, uint64_t *size)
        }
 
        // Now increase the size until we hit no space
-       uint32_t upper = sfs.f_bfree + 128;
+       uint64_t upper = sfs.f_bfree + 128;
 
        for (;;) {
-               uint32_t try = (upper + blocks) / 2;
+               uint64_t try = (upper + blocks) / 2;
 
                if (try <= blocks)
                        try = blocks + 1;
 
-               uint64_t size = (uint64_t)try * sfs.f_bsize;
+               uint64_t size = try * sfs.f_bsize;
                if (!fcntl(*fd, F_SETSIZE, &size)) {
                        blocks = try;
                        if (try >= upper) {
@@ -231,7 +231,7 @@ static void fill_disk(int *fd, uint64_t *size)
                }
        }
 
-       *size = (uint64_t)blocks * sfs.f_bsize;
+       *size = blocks * sfs.f_bsize;
 }
 
 volatile int32_t threads_running;
diff --git a/tests/cases/test-lf-cs-plugin.c b/tests/cases/test-lf-cs-plugin.c
new file mode 100644 (file)
index 0000000..c436d31
--- /dev/null
@@ -0,0 +1,350 @@
+//
+// Copyright (c) 2019-2019 Apple Inc. All rights reserved.
+//
+// test-lf-cs-plugin.c - Implements unit test for livefiles Apple_CoreStorage
+//                       plugin.
+//
+
+#include "hfs-tests.h"
+#include "test-utils.h"
+#include "systemx.h"
+
+#include <fcntl.h>
+#include <spawn.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <zlib.h>
+#include <TargetConditionals.h>
+
+//
+// Enable this test on iOS and no other iOS-style platforms.
+//
+#if TARGET_OS_IOS
+
+//
+// Headers generated at build time. Containes compressed disk images for the
+// corresponding file-system formats.
+//
+#include "JHFS+-dmg.dat"
+#include "APFS-dmg.dat"
+#include "EXFAT-dmg.dat"
+#include "FAT32-dmg.dat"
+
+TEST(lf_cs_plugin, .run_as_root = true)
+
+#define LF_CS_PLUGIN_TEST_DMG "/tmp/lf_cs_plugin_test.sparseimage"
+#define LF_CS_PLUGIN_PATH_TO_HDIK "/usr/sbin/hdik"
+#define LF_CS_PLUGIN_INSTALL_PATH "/AppleInternal/CoreOS/tests/hfs/"
+
+//
+// The output of hdik gets truncated, so just search for the leading part of
+// the UUID and partition scheme names.
+//
+#define LF_CSP_HFS_UUID "48465300-0000-11AA-AA11"
+#define LF_CSP_APFS_UUID "7C3457EF-0000-11AA-AA11"
+#define LF_CSP_EXFAT_PART_SCHEME "Windows_NTFS"
+#define LF_CSP_FAT32_PART_SCHEME "DOS_FAT_32"
+
+//
+// Enums describing file-system formats.
+//
+typedef enum {
+       JHFS = 1,
+       APFS,
+       FAT32,
+       EXFAT,
+} lf_csp_fstype_t;
+
+//
+// Local struct describing the disk image on disk.
+//
+typedef struct {
+       char *path;     // Path to disk-image on disk.
+       char *disk;     // Path to dev node after disk-image is attached.
+       char *slice;    // Path to dev node slice after disk-image is attached.
+} lf_csp_disk_image_t;
+
+//
+// lf_csp_disk_image_cleanup - disattach disk image from the DiskImages driver
+//                             and unlink the disk image file on disk.
+//
+static bool
+lf_csp_disk_image_cleanup(lf_csp_disk_image_t *di)
+{
+       pid_t pid;
+       posix_spawn_file_actions_t facts;
+
+       struct stat sb;
+       int ret, status;
+       bool result;
+       char *detach_args[] = { "hdik", "-e", (char *)di->disk, NULL };
+
+       result = false;
+       ret = posix_spawn_file_actions_init(&facts);
+
+       if (!ret) {
+               (void)posix_spawn_file_actions_addopen(&facts, STDOUT_FILENO,
+                       "/dev/null", O_APPEND, 0);
+               (void)posix_spawn_file_actions_addopen(&facts, STDERR_FILENO,
+                       "/dev/null", O_APPEND, 0);
+       }
+
+       assert_no_err(posix_spawn(&pid, LF_CS_PLUGIN_PATH_TO_HDIK, &facts,
+                               NULL, detach_args, NULL));
+
+       if (ret) {
+               posix_spawn_file_actions_destroy(&facts);
+       }
+
+       assert_with_errno(ignore_eintr(waitpid(pid, &status, 0), -1) == pid);
+       errno = 0;
+       if (WIFEXITED(status) &&
+                       !WEXITSTATUS(status) &&
+                       (stat(di->disk, &sb) == -1) &&
+                       (errno == ENOENT)) {
+
+               unlink(di->path);
+               free(di->path);
+               free(di->disk);
+               free(di->slice);
+               free(di);
+               result = true;
+       }
+
+       return result;
+}
+
+//
+// lf_csp_disk_image_create - create a new disk image file on disk and attach
+//                            disk images directly to the DiskImages driver.
+//
+// This routine reads the compressed file system image (generated during build)
+// based on the passed file-system type parameter. The compressed image is
+// decompressd and written to disk and then attached to directly to the
+// DiskImages driver.
+//
+// Please NOTE: The created image is hooked up to the test cleanup list thus
+// gets cleaned up automatically after the test, even on failures. Explicit
+// cleanup is not needed.
+//
+static lf_csp_disk_image_t *
+lf_csp_disk_image_create(const char *path, lf_csp_fstype_t fs_type)
+{
+       pid_t pid;
+       uid_t uid_old;
+       lf_csp_disk_image_t *di;
+       z_stream u_stream;
+       posix_spawn_file_actions_t actions;
+
+       FILE *fp;
+       size_t lnsz;
+       int ret, fd, fds[2], status;
+       void *uncompressed_out_buf;
+       const size_t chunk_size = (1ULL << 20);
+       char *attach_args[4], *line, *part_scheme, *uuid_or_partid_str;
+
+       //
+       // We need to ensure that we are root.
+       //
+       if ((uid_old = geteuid()) != 0) {
+               assert_no_err(seteuid(0));
+       }
+
+       di = calloc(1, sizeof(lf_csp_disk_image_t));
+       assert(di);
+
+       //
+       // We need to extract the compressed image into the passed image
+       // file path, thus we open it for writing.
+       //
+       fd = open(path, O_RDWR | O_TRUNC | O_CREAT, 0666);
+       assert_with_errno(fd != -1);
+
+       u_stream = (z_stream) {
+               .zalloc = Z_NULL,
+               .zfree = Z_NULL,
+               .opaque = Z_NULL,
+       };
+
+       ret = inflateInit(&u_stream);
+       if (ret != Z_OK) {
+               assert_fail("inflateInit failed\n");
+       }
+
+       uncompressed_out_buf = malloc(chunk_size);
+       assert(uncompressed_out_buf);
+
+       uuid_or_partid_str = NULL;
+       part_scheme = NULL;
+       switch(fs_type) {
+               case JHFS:
+                       u_stream.next_in = JHFS_data;
+                       u_stream.avail_in = sizeof(JHFS_data);
+                       uuid_or_partid_str = LF_CSP_HFS_UUID;
+                       part_scheme = "GUID";
+                       break;
+
+               case APFS:
+                       u_stream.next_in = APFS_data;
+                       u_stream.avail_in = sizeof(APFS_data);
+                       uuid_or_partid_str = LF_CSP_APFS_UUID;
+                       part_scheme = "GUID";
+                       break;
+
+               case FAT32:
+                       u_stream.next_in = FAT32_data;
+                       u_stream.avail_in = sizeof(FAT32_data);
+                       uuid_or_partid_str = LF_CSP_FAT32_PART_SCHEME;
+                       part_scheme = "FDisk";
+                       break;
+
+               case EXFAT:
+                       u_stream.next_in = EXFAT_data;
+                       u_stream.avail_in = sizeof(EXFAT_data);
+                       uuid_or_partid_str = LF_CSP_EXFAT_PART_SCHEME;
+                       part_scheme = "FDisk";
+                       break;
+
+               default:
+                       assert_fail("passed unkown file-system type\n");
+       }
+
+       do {
+               ssize_t bytes_to_write;
+
+               u_stream.next_out = uncompressed_out_buf;
+               u_stream.avail_out = chunk_size;
+
+               ret = inflate(&u_stream, Z_NO_FLUSH);
+               assert(ret != Z_STREAM_ERROR);
+
+               bytes_to_write = chunk_size - u_stream.avail_out;
+               assert(write(fd, uncompressed_out_buf, bytes_to_write) ==
+                               (ssize_t)bytes_to_write);
+       } while (ret == Z_OK);
+       assert(ret == Z_STREAM_END);
+       (void)inflateEnd(&u_stream);
+
+       //
+       // Update the disk image path.
+       //
+       di->path = strdup(path);
+
+       //
+       // Attach the created disk image directly to the DiskImage driver.
+       //
+       attach_args[0] = "hdik";
+       attach_args[1] = "-nomount";
+       attach_args[2] = (char *)di->path;
+       attach_args[3] = NULL;
+
+       assert_no_err(pipe(fds));
+       ret = posix_spawn_file_actions_init(&actions);
+       if (ret) {
+               assert_fail("Failed to init file actions, error %d\n", ret);
+       }
+
+       ret = posix_spawn_file_actions_adddup2(&actions, fds[1],
+                       STDOUT_FILENO);
+       if (ret) {
+               assert_fail("Failed to adddup file action, error %d\n",
+                               ret);
+       }
+
+       assert_no_err(posix_spawn(&pid, LF_CS_PLUGIN_PATH_TO_HDIK, &actions,
+                               NULL, attach_args, NULL));
+
+       (void)posix_spawn_file_actions_destroy(&actions);
+       (void)close(fds[1]);
+
+       //
+       // Read the output from `hdik` and populate the disk image's dev node
+       // after it is attached to DiskImage driver.
+       //
+       di->slice = NULL;
+       di->disk = NULL;
+       line = NULL;
+       lnsz = 64;
+       line = malloc(lnsz);
+       assert(line);
+       fp = fdopen(fds[0], "r");
+       while (getline(&line, &lnsz, fp) != -1) {
+               char *disk_path, *uuid_or_partid;
+
+               disk_path = strtok(line, " ");
+               assert(disk_path);
+
+               uuid_or_partid = strtok(NULL, " ");
+               assert(uuid_or_partid);
+
+               if (strstr(uuid_or_partid, part_scheme))
+                       di->disk = strdup(disk_path);
+               else if (strstr(uuid_or_partid, uuid_or_partid_str))
+                       di->slice = strdup(disk_path);
+       }
+
+       assert_with_errno(ignore_eintr(waitpid(pid, &status, 0), -1) == pid);
+       assert(WIFEXITED(status) && !WEXITSTATUS(status));
+
+       assert(di->disk && di->slice);
+       free(line);
+       fclose(fp);
+
+       //
+       // Place this attached image in the cleanup list so that it can be
+       // disattached after the test is run.
+       //
+       test_cleanup(^ bool { return lf_csp_disk_image_cleanup(di); });
+
+       //
+       // Restore back the old uid.
+       //
+       assert_no_err(seteuid(uid_old));
+       return di;
+}
+
+int
+run_lf_cs_plugin(__unused test_ctx_t *ctx)
+{
+       lf_csp_disk_image_t *di;
+       char *tester_path;
+
+       assert(asprintf(&tester_path, "%s/livefiles_cs_tester",
+                               LF_CS_PLUGIN_INSTALL_PATH) > 0);
+
+       //
+       // Call livefiles Apple_CoreStorage plugin with all our file-system
+       // disk-images.
+       //
+       // Kindly NOTE: We don't explicitly free the disk-images after use
+       // because preparing the disk image with lf_csp_disk_image_create() we
+       // place the image in a cleanup list and they get cleaned up after
+       // test, regardless of the test failures.
+       //
+       // Test livefiles Apple_CoreStorage plugin with AFPS disk image.
+       //
+       di = lf_csp_disk_image_create(LF_CS_PLUGIN_TEST_DMG, APFS);
+       assert(!systemx(tester_path, "APFS", di->slice, NULL));
+
+       //
+       // Test livefiles Apple_CoreStorage plugin with HFS+ disk image.
+       //
+       di = lf_csp_disk_image_create(LF_CS_PLUGIN_TEST_DMG, JHFS);
+       assert(!systemx(tester_path, "JHFS", di->slice, NULL));
+
+       //
+       // Test livefiles Apple_CoreStorage plugin with EXFAT disk image.
+       //
+       di = lf_csp_disk_image_create(LF_CS_PLUGIN_TEST_DMG, EXFAT);
+       assert(!systemx(tester_path, "EXFAT", di->slice, NULL));
+
+       //
+       // Test livefiles Apple_CoreStorage plugin with FAT32 disk image.
+       //
+       di = lf_csp_disk_image_create(LF_CS_PLUGIN_TEST_DMG, FAT32);
+       assert(!systemx(tester_path, "FAT32", di->slice, NULL));
+
+       free(tester_path);
+       return 0;
+}
+#endif /* TARGET_OS_IOS */
index 7a370646a1c7055f35249e7e5996935c40e251b4..c0bc434b3a33d9f0107a683336bd3ac39a740e62 100644 (file)
@@ -23,6 +23,8 @@
 #include "test-utils.h"
 #include "systemx.h"
 
+#define RETRY_MAX 3
+
 #if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
 
 #include "dmg.dat"
@@ -31,6 +33,8 @@ bool disk_image_cleanup(disk_image_t *di)
 {
        pid_t pid;
        bool result = false;
+       int eject_retry;
+       int status;
        
        // We need to be root
        assert(seteuid(0) == 0);
@@ -40,27 +44,32 @@ bool disk_image_cleanup(disk_image_t *di)
        
        assert_no_err(posix_spawn(&pid, "/sbin/umount", NULL, NULL, umount_args, NULL));
        
-       int status;
        waitpid(pid, &status, 0);
        
        char *detach_args[]
                = { "hdik", "-e", (char *)di->disk, NULL };
-       
+
        posix_spawn_file_actions_t facts;
        posix_spawn_file_actions_init(&facts);
        posix_spawn_file_actions_addopen(&facts, STDOUT_FILENO, "/dev/null", O_APPEND, 0);
        posix_spawn_file_actions_addopen(&facts, STDERR_FILENO, "/dev/null", O_APPEND, 0);
        
-       assert_no_err(posix_spawn(&pid, "/usr/sbin/hdik", &facts, NULL, detach_args, NULL));
+       for (eject_retry = 0; eject_retry < RETRY_MAX; ++eject_retry) {
+               if (!posix_spawn(&pid, "/usr/sbin/hdik", &facts, NULL, detach_args, NULL)) {
+                       waitpid(pid, &status, 0);
+                       if (WIFEXITED(status) && !WEXITSTATUS(status))
+                               break;
+               }
+               sleep(1);
+       }
        
        posix_spawn_file_actions_destroy(&facts);
        
-       waitpid(pid, &status, 0);
+       assert(eject_retry != RETRY_MAX);
        
        struct stat sb;
        
-       if (WIFEXITED(status) && !WEXITSTATUS(status)
-               && stat(di->disk, &sb) == -1 && errno == ENOENT) {
+       if (stat(di->disk, &sb) == -1 && errno == ENOENT) {
                unlink(di->path);
                result = true;
                // We are the last user of di, so free it.
@@ -117,7 +126,7 @@ disk_image_t *disk_image_create(const char *path, disk_image_opts_t *opts)
        
        do {
                zs.next_out = out_buf;
-               zs.avail_out = buf_size;
+               zs.avail_out = (uInt)buf_size;
                
                ret = inflate(&zs, 0);
                
@@ -255,23 +264,31 @@ bool disk_image_cleanup(disk_image_t *di)
 
        pid_t pid;
        bool result = false;
+       int eject_retry;
+       int status;
 
        posix_spawn_file_actions_t facts;
        posix_spawn_file_actions_init(&facts);
        posix_spawn_file_actions_addopen(&facts, STDOUT_FILENO, "/dev/null", O_APPEND, 0);
        posix_spawn_file_actions_addopen(&facts, STDERR_FILENO, "/dev/null", O_APPEND, 0);
 
-       assert_no_err(posix_spawn(&pid, "/usr/bin/hdiutil", &facts, NULL, detach_args, NULL));
+       for (eject_retry = 0; eject_retry < RETRY_MAX; ++eject_retry) {
+               if (!posix_spawn(&pid, "/usr/bin/hdiutil", &facts, NULL, detach_args, NULL)) {
+                       waitpid(pid, &status, 0);
+                       if (WIFEXITED(status) && !WEXITSTATUS(status)) {
+                               break;
+                       }
+               }
+               sleep(1);
+       }
 
        posix_spawn_file_actions_destroy(&facts);
 
-       int status;
-       waitpid(pid, &status, 0);
+       assert(eject_retry != RETRY_MAX);
 
        struct stat sb;
 
-       if (WIFEXITED(status) && !WEXITSTATUS(status)
-               && stat(di->disk, &sb) == -1 && errno == ENOENT) {
+       if (stat(di->disk, &sb) == -1 && errno == ENOENT) {
                if (unlink(di->path) && errno == EACCES && !seteuid(0))
                        unlink(di->path);
                result = true;
diff --git a/tests/gen-custom-dmg.sh b/tests/gen-custom-dmg.sh
new file mode 100755 (executable)
index 0000000..892192f
--- /dev/null
@@ -0,0 +1,9 @@
+#!/bin/sh
+set -e
+
+mkdir -p "$DERIVED_FILE_DIR"
+env -i xcrun -sdk macosx.internal clang "$SRCROOT"/tests/generate-compressed-image.c -lz -o "$DERIVED_FILE_DIR"/generate-compressed-image
+
+"$DERIVED_FILE_DIR"/generate-compressed-image -size 1g -type SPARSE -fs "$1" -uid 501 -gid 501 >"$2"
+
+echo "Created $2 of type $1"
index b65f3a7701fb8dafd9cad77fd4898eab18d0356b..fd20b251863a232b18fc9e7ee606b0d89a21e507 100755 (executable)
@@ -28,6 +28,10 @@ EOF
 set -e
 set -o pipefail
 
+for FS in JHFS+ APFS FAT32 EXFAT; do
+    touch "$DERIVED_SOURCES_DIR/$FS-dmg.dat"
+done
+
 # The following change is taken directly from the XCBuild changes made for APFS in
 # the commit cf61eef74b8
 if [ "$CURRENT_ARCH" = undefined_arch ]; then
@@ -44,7 +48,7 @@ fi
 # filter out any that aren't applicable to the targeted
 # platform).  Finally grep for the TEST macro again
 grep -l -E '^TEST\(' *.[cm] | xargs xcrun clang -E -D TEST=TEST \
-       -arch "$CURRENT_ARCH" -I.. -F"$SDKROOT""$SYSTEM_LIBRARY_DIR"/PrivateFrameworks | \
+       -arch "$CURRENT_ARCH" -I"$DERIVED_SOURCES_DIR" -I.. -F"$SDKROOT""$SYSTEM_LIBRARY_DIR"/PrivateFrameworks | \
        grep -h -E 'TEST\(' >>"$DERIVED_FILE_DIR"/list-tests.c
 
 # Build an executable for the host platform
diff --git a/tests/generate-compressed-image.c b/tests/generate-compressed-image.c
new file mode 100644 (file)
index 0000000..c7f13c2
--- /dev/null
@@ -0,0 +1,303 @@
+//
+// Copyright (c) 2019-2019 Apple Inc. All rights reserved.
+//
+// generate-compressed-image.c - Generates compressed disk images for
+//                               file-system type passed as argument.
+//
+
+#include <assert.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <spawn.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <sysexits.h>
+#include <err.h>
+#include <errno.h>
+#include <unistd.h>
+#include <zlib.h>
+
+//
+// Rationale: We don't have `hdiutil` in iOS runtime and thus cannot generate
+// disk-images for test inside iOS. We assume that the build enviornment has
+// `hdiutil` and thus generate custom file-system images (passed as argument)
+// during build, compress it using deflate and finally use the compressed byte
+// stream to generate files which can then be be used from iOS runtime.
+//
+
+//
+// Name template for the temporary directory where we create the file-system
+// image before we can compress it.
+//
+#define GEN_COM_IMAGE_TMP_DIR "/tmp/generate_compressed_image.XXXXXXXX"
+
+//
+// Name of the temporary file-system image.
+//
+#define GEN_COM_IMAGE_TMP_FILENAME "img.sparseimage"
+
+//
+// Path to hdiutil utility inside build enviornment.
+//
+#define GEN_COM_IMAGE_HDIUTIL_PATH "/usr/bin/hdiutil"
+
+enum {
+
+       //
+       // Count of fixed number of argumets needed to call hdiutil, additional
+       // options are passed by the caller.
+       //
+       FIXED_NR_ARGUMENTS = 4,
+       ADDITIONAL_NR_ARGUMENTS = 10,
+       BYTES_PER_LINE_MASK = 0xF,
+};
+
+//
+// Valid file-system types that is supported by this program.
+//
+static bool
+is_fstype_valid(const char *fs_type)
+{
+       int idx;
+
+       const char *const VALID_FSTYPES[] = {
+               "JHFS+",
+               "APFS",
+               "EXFAT",
+               "FAT32",
+
+               NULL
+       };
+
+       for (idx = 0; VALID_FSTYPES[idx] != NULL; idx++) {
+               if (strcmp(fs_type, VALID_FSTYPES[idx]) == 0) {
+                       return true;
+               }
+       }
+       return false;
+}
+
+int
+main(int argc, char *argv[])
+{
+       pid_t pid, child_state_changed;
+       z_stream c_stream;
+       int fd, idx, ret, status, flush, offset;
+       char *tmp_dir, *tmp_disk_image_path, *fs_type;
+       unsigned char *compressed_out_buf, *uncompressed_in_buf;
+       const size_t chunk_size = (1ULL << 20);
+       char *args[argc + FIXED_NR_ARGUMENTS];
+       char tmp_dir_name_template[] = GEN_COM_IMAGE_TMP_DIR;
+       const char *progname = (progname = strrchr(argv[0], '/')) ?
+                       progname+=1 : (progname = argv[0]);
+
+       //
+       // Disable stdout buffering.
+       //
+       setvbuf(stdout, NULL, _IONBF, 0);
+
+       //
+       // Validate that we have correct number of arguments passed (minimal,
+       // this is only called from inside build internally).
+       //
+       if (argc != (ADDITIONAL_NR_ARGUMENTS + 1)) {
+
+err_usage:
+               fprintf(stderr, "Usage: %s -size [size-arg] -type "
+                       "[type-arg] -fs [APFS|JHFS+|EXFAT|FAT32] "
+                       "-uid [uid-arg] -gid [gid-arg]\n", progname);
+               return EXIT_FAILURE;
+       }
+
+       //
+       // Just to simplify this program and to avoid parsing input aruments
+       // we assume that the arguments are passed in order and 7th argument
+       // has the file-system type. We confirm this now.
+       //
+       if (!is_fstype_valid(argv[6])) {
+               fprintf(stderr, "Unknown file-system type %s\n", argv[6]);
+               goto err_usage;
+       }
+       fs_type = argv[6];
+       if (!strcmp(argv[6], "JHFS+")) {
+               fs_type = "JHFS";
+       }
+
+       //
+       // First we create a temporary directory to host our newly created
+       // disk image in the build environment.
+       //
+       tmp_dir = mkdtemp(tmp_dir_name_template);
+       if (!tmp_dir)
+               err(EX_NOINPUT, "mkdtemp failed");
+
+       //
+       // Path where we want to keep our temporary disk image.
+       //
+       asprintf(&tmp_disk_image_path, "%s/"GEN_COM_IMAGE_TMP_FILENAME,
+                       tmp_dir);
+
+       //
+       // Set up the fixed command line parameters to be passed to the hdiutil
+       // child process.
+       //
+       //      - program name.
+       //      - create a new disk-image.
+       //      - path of disk-image file to create.
+       //      - silent mode.
+       //
+       args[0] = "hdiutil";
+       args[1] = "create";
+       args[2] = tmp_disk_image_path;
+       args[3] = "-quiet";
+
+       //
+       // Copy the additional arguments passed by the caller needed for
+       // hdiutil.
+       //
+       for (idx = 1; idx < argc; ++idx) {
+               args[idx + FIXED_NR_ARGUMENTS - 1] = argv[idx];
+       }
+       args[idx + FIXED_NR_ARGUMENTS - 1] = NULL;
+
+       //
+       // Spawn the hdiutil as a child process and wait for its completion.
+       //
+       ret = posix_spawn(&pid, GEN_COM_IMAGE_HDIUTIL_PATH, NULL, NULL,
+                       args, NULL);
+       if (ret) {
+               errno = ret;
+               err(EX_OSERR, "posix_spawn failed");
+       }
+
+       //
+       // Wait for the child process to finish.
+       //
+       do {
+               errno = 0;
+               child_state_changed = waitpid(pid, &status, 0);
+       } while (child_state_changed == -1 && errno == EINTR);
+
+       if (child_state_changed == -1) {
+               err(EX_OSERR, "waitpid failed");
+       }
+       if (!WIFEXITED(status) || WEXITSTATUS(status)) {
+               fprintf(stderr, "hdiutil failed, status %d", status);
+               exit(EXIT_FAILURE);
+       }
+
+       //
+       // We have successfully create the disk image, now we have to
+       // open this disk image, read and finally write out a compess
+       // stream of this disk image to a data file.
+       //
+       fd = open(tmp_disk_image_path, O_RDONLY);
+       if (fd == -1) {
+               err(EX_NOINPUT, "open failed for file %s",
+                               tmp_disk_image_path);
+       }
+
+       //
+       // Initialize the compressed stream of bytes we will write out.
+       //
+       c_stream = (z_stream) {
+               .zalloc = Z_NULL,
+               .zfree = Z_NULL,
+               .opaque = Z_NULL,
+       };
+
+       ret = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
+       if (ret != Z_OK) {
+               err(EX_SOFTWARE, "deflateInit faile, ret %d", ret);
+       }
+
+       compressed_out_buf = malloc(chunk_size);
+       if (!compressed_out_buf) {
+               err(EX_OSERR, "malloc faliled for compressed_out_buf");
+       }
+
+       uncompressed_in_buf = malloc(chunk_size);
+       if (!uncompressed_in_buf) {
+               err(EX_OSERR, "malloc faliled for uncompressed_in_buf");
+       }
+
+       fprintf(stdout, "unsigned char %s_data[] = {", fs_type);
+
+       offset = 0;
+       flush = Z_NO_FLUSH;
+       do {
+               ssize_t bytes_read;
+
+               bytes_read = read(fd, uncompressed_in_buf, chunk_size);
+               if (bytes_read == -1) {
+                       (void)deflateEnd(&c_stream);
+                       err(EX_OSERR, "read failed for file %s\n",
+                                       tmp_disk_image_path);
+               }
+
+               //
+               // Set the stream's input buffer and number of input bytes
+               // available to be compressed.
+               //
+               c_stream.next_in = uncompressed_in_buf;
+               c_stream.avail_in = bytes_read;
+
+               //
+               // If we have reached the end of the file, we have to flush the
+               // compressed stream.
+               //
+               if (!bytes_read) {
+                       flush = Z_FINISH;
+               }
+
+               //
+               // Run deflate() on input until output buffer is not full,
+               // finish compression if all of source has been read in.
+               //
+               do {
+                       unsigned written;
+
+                       c_stream.avail_out = chunk_size;
+                       c_stream.next_out = compressed_out_buf;
+
+                       ret = deflate(&c_stream, flush);
+                       assert(ret != Z_STREAM_ERROR);
+
+                       written = chunk_size - c_stream.avail_out;
+                       for (idx = 0; idx < written; ++idx) {
+                               if (!(offset & BYTES_PER_LINE_MASK))
+                                       fprintf(stdout, "\n  ");
+                               fprintf(stdout, "0x%02x, ",
+                                               compressed_out_buf[idx]);
+                               ++offset;
+                       }
+
+               } while (c_stream.avail_out == 0);
+
+               //
+               // All  input should be used.
+               //
+               assert(c_stream.avail_in == 0);
+
+       } while (flush != Z_FINISH);
+
+       //
+       // Stream will be complete.
+       //
+       assert(ret == Z_STREAM_END);
+       (void)close(fd);
+
+       //
+       // stdout is line buffered by default and this should flush it.
+       //
+       fprintf(stdout, "\n};\n");
+
+       //
+       // Clean up
+       //
+       (void)deflateEnd(&c_stream);
+       unlink(tmp_disk_image_path);
+       free(tmp_disk_image_path);
+       rmdir(tmp_dir);
+}
index 994efb83d30d6e78f2792dd8c6e01b65bc41ff37..fc0325f131723de438a90a0fec0eb2894970a7f0 100644 (file)
@@ -2,6 +2,8 @@
 <!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.private.vfs.setsize</key>
+       <true/>
        <key>com.apple.rootless.internal-installer-equivalent</key>
        <true/>
        <key>com.apple.private.security.disk-device-access</key>