1#include <stdio.h> 2#include <stdlib.h> 3#include <errno.h> 4 5#include "iterate_hfs_metadata.h" 6#include "../CopyHFSMeta/Data.h" 7#include "../CopyHFSMeta/hfsmeta.h" 8 9/* 10 * These variables are used by the CopyHFSMeta routines, so we have to define them 11 */ 12 13__private_extern__ int debug = 0; 14__private_extern__ int verbose = 0; 15__private_extern__ int printProgress = 0; 16 17/* 18 * This is essentially the guts of CopyHFSMeta, only without 19 * the ability to write out to a sparse bundle. It also always 20 * wants to get the "other" metadata (symlinks and large EA extents). 21 * 22 * For each extent it finds, it calls the passed-in function pointer, 23 * with the start and length. 24 * 25 * It will go through and get the symlink and EA extents first, and 26 * then go through the rest of the extents. It does not attempt any 27 * sorting past that. 28 */ 29int 30iterate_hfs_metadata(char *device, int (*handle_extent)(int fd, off_t start, off_t length, void *ctx), void *context_ptr) 31{ 32 struct DeviceInfo *devp = NULL; 33 struct VolumeDescriptor *vdp = NULL; 34 VolumeObjects_t *vop = NULL; 35 int retval = 0; 36 37 devp = OpenDevice(device, 0); 38 if (devp == NULL) { 39 retval = errno; 40 goto done; 41 } 42 43 vdp = VolumeInfo(devp); 44 if (vdp == NULL) { 45 retval = errno; 46 goto done; 47 } 48 49 if (CompareVolumeHeaders(vdp) == -1) { 50 retval = EINVAL; 51 goto done; 52 } 53 54 vop = InitVolumeObject(devp, vdp); 55 if (vop == NULL) { 56 retval = errno; 57 goto done; 58 } 59 60 /* 61 * These guys don't have an error. Probably 62 * a mistake. 63 */ 64 AddHeaders(vop, 1); 65 AddJournal(vop); 66 AddFileExtents(vop); 67 68 /* 69 * By this point, vop has all of the system metadata. 70 * The only metadata we don't have would be symlinks (from 71 * the catalog file), and extended attribute fork extents 72 * (from the attributes file). We get those with 73 * FindOtherMetadata(). 74 */ 75 retval = FindOtherMetadata(vop, ^(int fid __unused, off_t start, off_t len) { 76 return (*handle_extent)(devp->fd, start, len, context_ptr); 77 }); 78 79 if (retval != 0) 80 goto done; 81 82 /* 83 * Now, we've handled all of the other metadata, so we need 84 * to go through the rest of our metadata, which is in vop. 85 */ 86 ExtentList_t *extList; 87 for (extList = vop->list; 88 extList; 89 extList = extList->next) { 90 size_t index; 91 92 for (index = 0; index < extList->count; index++) { 93 retval = (*handle_extent)(devp->fd, extList->extents[index].base, extList->extents[index].length, context_ptr); 94 if (retval != 0) 95 goto done; 96 } 97 } 98 99done: 100 if (vop) { 101 ReleaseVolumeObjects(vop); 102 } else { 103 if (vdp) { 104 ReleaseVolumeDescriptor(vdp); 105 } 106 if (devp) { 107 ReleaseDeviceInfo(devp); 108 } 109 } 110 111 return retval; 112 113} 114