]> git.saurik.com Git - apple/hfs.git/blame - CopyHFSMeta/Gather.c
hfs-556.100.11.tar.gz
[apple/hfs.git] / CopyHFSMeta / Gather.c
CommitLineData
a56bdb9d
A
1#include <stdio.h>
2#include <stdlib.h>
3#include <unistd.h>
4#include <fcntl.h>
5#include <err.h>
6#include <errno.h>
7#include <zlib.h>
927b7b56
A
8#include <limits.h>
9#include <assert.h>
a56bdb9d
A
10
11#include "hfsmeta.h"
12#include "Data.h"
13
14struct HFSDataObject {
15 int64_t offset;
16 int64_t size;
17};
18typedef struct HFSDataObject HFSDataObject;
19
20enum {
21 kHFSInfoHeaderVersion = 1,
22};
23
24
25#define MIN(a, b) \
26 ({ __typeof(a) __a = (a); __typeof(b) __b = (b); \
27 __a < __b ? __a : __b; })
28
29struct HFSInfoHeader {
30 uint32_t version;
31 uint32_t deviceBlockSize;
32 int64_t rawDeviceSize;
33 int32_t size; // Size of header
34 int32_t objectCount;
35};
36
37static ssize_t
38WriteExtent(gzFile outf, DeviceInfo_t *devp, off_t start, off_t len)
39{
40 const size_t bufSize = 1024 * 1024;
41 uint8_t buffer[bufSize];
42 off_t total = 0;
43
44 while (total < len) {
45 ssize_t nread;
46 size_t amt = MIN(bufSize, len - total);
47 ssize_t nwritten;
48 nread = pread(devp->fd, buffer, amt, start + total);
49 if (nread == -1) {
50 warn("Cannot read from device at offset %lld", start + total);
51 return -1;
52 }
53 if (nread != amt) {
54 warnx("Tried to read %zu bytes, only read %zd", amt, nread);
55 }
927b7b56 56 nwritten = gzwrite(outf, (char*)buffer, (unsigned)amt);
a56bdb9d
A
57 if (nwritten == -1) {
58 warn("tried to gzwrite %zu bytes", amt);
59 return -1;
60 } else if (nwritten != amt) {
61 warnx("tried to gzwrite %zu bytes, only wrote %u", amt, nwritten);
62 total += nwritten;
63 } else
64 total += amt;
65 }
66 return 0;
67}
68
69void
70WriteGatheredData(const char *pathname, VolumeObjects_t *vop)
71{
72 int fd;
73 gzFile outf;
74 struct HFSInfoHeader hdr = { 0 };
75 HFSDataObject *objs = NULL, *op;
76 ExtentList_t *ep;
77 int i;
927b7b56 78 size_t len;
a56bdb9d
A
79
80 hdr.version = S32(kHFSInfoHeaderVersion);
81 hdr.deviceBlockSize = S32((uint32_t)vop->devp->blockSize);
82 hdr.rawDeviceSize = S64(vop->devp->size);
83 hdr.objectCount = S32(vop->count);
84 hdr.size = S32(sizeof(hdr) + sizeof(HFSDataObject) * vop->count);
85
86 objs = malloc(sizeof(HFSDataObject) * vop->count);
87 if (objs == NULL) {
88 warn("Unable to allocate space for data objects (%zu bytes)", sizeof(HFSDataObject)* vop->count);
89 goto done;
90 }
91
92 op = objs;
93 for (ep = vop->list;
94 ep;
95 ep = ep->next) {
96 int i;
97 for (i = 0; i < ep->count; i++) {
98 op->offset = S64(ep->extents[i].base);
99 op->size = S64(ep->extents[i].length);
100 op++;
101 }
102 }
103
104 fd = open(pathname, O_WRONLY | O_CREAT | O_TRUNC, 0666);
105 if (fd == -1) {
106 warn("cannot create gather file %s", pathname);
107 goto done;
108 }
109 outf = gzdopen(fd, "wb");
110 if (outf == NULL) {
111 warn("Cannot create gz descriptor from file %s", pathname);
112 close(fd);
113 goto done;
114 }
115
116 gzwrite(outf, &hdr, sizeof(hdr));
927b7b56
A
117 len = sizeof(HFSDataObject) * vop->count;
118 assert(len < UINT_MAX);
119 gzwrite(outf, objs, (unsigned)len);
a56bdb9d
A
120
121 int count = 0;
122 for (ep = vop->list;
123 ep;
124 ep = ep->next) {
125 int i;
126 for (i = 0; i < ep->count; i++) {
127 if (verbose)
128 fprintf(stderr, "Writing extent <%lld, %lld>\n", ep->extents[i].base, ep->extents[i].length);
129 if (WriteExtent(outf, vop->devp, ep->extents[i].base, ep->extents[i].length) == -1) {
130 if (verbose)
131 fprintf(stderr, "\tWrite failed\n");
132 break;
133 }
134 count++;
135 }
136 }
137 gzclose(outf);
138 if (count != vop->count)
139 fprintf(stderr, "WHOAH! we're short by %zd objects!\n", vop->count - count);
140
141
142done:
143 if (objs)
144 free(objs);
145 return;
146
147}