]> git.saurik.com Git - apple/hfs.git/blob - libhfs_metadata/iterate_hfs_metadata.c
hfs-407.50.6.tar.gz
[apple/hfs.git] / libhfs_metadata / iterate_hfs_metadata.c
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 */
29 int
30 iterate_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
99 done:
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 }