15 ({ __typeof(a) __a = (a); __typeof(b) __b = (b); \
16 __a < __b ? __a : __b; })
19 * Get a block from a given input device.
22 GetBlock(DeviceInfo_t
*devp
, off_t offset
, uint8_t *buffer
)
25 off_t baseOffset
= (offset
/ devp
->blockSize
) * devp
->blockSize
;
27 retval
= pread(devp
->fd
, buffer
, devp
->blockSize
, baseOffset
);
28 if (retval
!= devp
->blockSize
) {
29 warn("GetBlock: pread returned %zd", retval
);
31 if (offset
!= baseOffset
) {
32 size_t off
= offset
% devp
->blockSize
;
33 memmove(buffer
, buffer
+ off
, devp
->blockSize
- off
);
41 * Initialize a VolumeObject. Simple function.
44 InitVolumeObject(struct DeviceInfo
*devp
, struct VolumeDescriptor
*vdp
)
46 VolumeObjects_t
*retval
= NULL
;
48 retval
= malloc(sizeof(*retval
));
53 retval
->byteCount
= 0;
62 * Add an extent (<start, length> pair) to a volume list.
63 * Note that this doesn't try to see if an extent is already
64 * in the list; the presumption is that an fsck_hfs run will
65 * note overlapping extents in that case. It adds the extents
66 * in groups of kExtentCount; the goal here is to minimize the
67 * number of objects we allocate, while still trying to keep
68 * the waste memory allocation low.
71 AddExtent(VolumeObjects_t
*vdp
, off_t start
, off_t length
)
75 ExtentList_t
**ep
= &vdp
->list
;
77 if (debug
) printf("AddExtent(%p, %lld, %lld)\n", vdp
, start
, length
);
79 if ((*ep
)->count
< kExtentCount
) {
81 (*ep
)->extents
[indx
].base
= start
;
82 (*ep
)->extents
[indx
].length
= length
;
90 *ep
= malloc(sizeof(ExtentList_t
));
92 err(1, "cannot allocate a new ExtentList object");
95 (*ep
)->extents
[0].base
= start
;
96 (*ep
)->extents
[0].length
= length
;
100 vdp
->byteCount
+= length
;
106 // Debugging function
108 PrintVolumeObject(VolumeObjects_t
*vop
)
112 printf("Volume Information\n");
114 printf("\tDevice %s\n", vop
->devp
->devname
);
115 printf("\t\tSize %lld\n", vop
->devp
->size
);
116 printf("\t\tBlock size %d\n", vop
->devp
->blockSize
);
117 printf("\t\tBlock Count %lld\n", vop
->devp
->blockCount
);
119 printf("\tObject count %zu\n", vop
->count
);
120 printf("\tByte count %lld\n", vop
->byteCount
);
121 printf("\tExtent list:\n");
122 for (exts
= vop
->list
;
126 for (indx
= 0; indx
< exts
->count
; indx
++) {
127 printf("\t\t<%lld, %lld>\n", exts
->extents
[indx
].base
, exts
->extents
[indx
].length
);
134 * The main routine: given a Volume descriptor, copy the metadata from it
135 * to the given destination object (a device or sparse bundle). It keeps
136 * track of progress, and also takes an amount to skip (which happens if it's
137 * resuming an earlier, interrupted copy).
140 CopyObjectsToDest(VolumeObjects_t
*vop
, struct IOWrapper
*wrapper
, off_t skip
)
146 wrapper
->cleanup(wrapper
);
148 for (exts
= vop
->list
;
152 for (indx
= 0; indx
< exts
->count
; indx
++) {
153 off_t start
= exts
->extents
[indx
].base
;
154 off_t len
= exts
->extents
[indx
].length
;
156 __block off_t totalWritten
;
160 off_t amt
= MIN(skip
, len
);
165 wrapper
->setprog(wrapper
, total
);
167 printf("* * * Wrote %lld of %lld\n", total
, vop
->byteCount
);
169 printf("%d%%\n", (int)((total
* 100) / vop
->byteCount
));
172 totalWritten
= total
;
176 wrapper
->setprog(wrapper
, totalWritten
);
178 printf("* * Wrote %lld of %lld (%d%%)\n", totalWritten
, vop
->byteCount
, (int)((totalWritten
* 100) / vop
->byteCount
));
180 printf("%d%%\n", (int)((totalWritten
* 100) / vop
->byteCount
));
190 if (wrapper
->writer(wrapper
, vop
->devp
, start
, len
, bp
) == -1) {
193 warnx("Writing extent <%lld, %lld> failed", start
, len
);
197 total
= totalWritten
;
202 wrapper
->setprog(wrapper
, total
);
204 printf("Wrote %lld of %lld\n", total
, vop
->byteCount
);
206 printf("%d%%\n", (int)((total
* 100) / vop
->byteCount
));
213 if (total
== vop
->byteCount
) {
214 wrapper
->setprog(wrapper
, 0); // remove progress