]>
git.saurik.com Git - hfs.git/blob - CopyHFSMeta/DeviceWrapper.c
15 * Functions to wrap around a device.
18 ({ __typeof(a) __a = (a); __typeof(b) __b = (b); \
19 __a < __b ? __a : __b; })
21 struct DeviceWrapperContext
{
29 noClean(struct IOWrapper
*ctx
)
31 // Conceivably, we could erase the entire device
36 doRead(struct IOWrapper
*ctx
, off_t start
, void *buffer
, off_t len
)
38 // For now, just do a pread
39 struct DeviceWrapperContext
*dctx
= (struct DeviceWrapperContext
*)ctx
->context
;
41 return pread(dctx
->fd
, buffer
, (size_t)len
, start
);
45 writeExtent(struct IOWrapper
*context
, DeviceInfo_t
*devp
, off_t start
, off_t len
, void (^bp
)(off_t
))
47 const size_t bufSize
= 1024 * 1024;
48 struct DeviceWrapperContext
*ctx
= (struct DeviceWrapperContext
*)context
->context
;
49 uint8_t *buffer
= NULL
;
53 if (debug
) printf("Writing extent <%lld, %lld> to device %s", start
, len
, ctx
->pathname
);
55 buffer
= malloc(bufSize
);
57 warn("%s(%s): Could not allocate %zu bytes for buffer", __FILE__
, __FUNCTION__
, bufSize
);
64 size_t amt
= MIN(bufSize
, len
- total
);
65 // XXX - currently, DeviceWrapepr isn't used, but it needs to deal wit unaligned I/O when it is.
66 nread
= pread(devp
->fd
, buffer
, amt
, start
+ total
);
68 warn("Cannot read from device at offset %lld", start
+ total
);
72 (void)pwrite(ctx
->fd
, (char*)buffer
, nread
, start
+ total
);
83 * Device files can't have progress information stored, so we don't do anything.
86 GetProgress(struct IOWrapper
*context
)
91 SetProgress(struct IOWrapper
*context
, off_t progr
)
97 InitDeviceWrapper(const char *path
, DeviceInfo_t
*devp
)
99 struct DeviceWrapperContext ctx
= { 0 };
100 struct DeviceWrapperContext
*retctx
= NULL
;
101 IOWrapper_t
*retval
= NULL
;
104 char rawname
[strlen(path
) + 2]; // /dev/disk5 -> /dev/rdisk5
106 if (strncmp(path
, "/dev/disk", 9) == 0) {
107 // Need to make it into a raw device name
108 sprintf(rawname
, "/dev/rdisk%s", path
+ 9);
110 strcpy(rawname
, path
);
113 if (lstat(rawname
, &sb
) == -1) {
114 warn("cannot examine raw device %s", rawname
);
117 if ((sb
.st_mode
& S_IFMT
) != S_IFCHR
) {
118 warnx("device %s is not a raw device", rawname
);
122 ctx
.pathname
= strdup(rawname
);
124 ctx
.fd
= open(rawname
, O_RDWR
);
126 warn("Cannot open device %s for reading and writing", rawname
);
130 if (ioctl(ctx
.fd
, DKIOCGETBLOCKSIZE
, &ctx
.blockSize
) == -1) {
131 ctx
.blockSize
= 512; // A reasonable default
133 if (ioctl(ctx
.fd
, DKIOCGETBLOCKCOUNT
, &blockCount
) == -1) {
134 warn("Cannot block count for device %s", rawname
);
137 ctx
.devSize
= ctx
.blockSize
* blockCount
;
139 if (ctx
.devSize
!= devp
->size
) {
140 warnx("Device %s is not the same size (%lld) as source device (%lld)", rawname
, ctx
.devSize
, devp
->size
);
144 ctx
.pathname
= strdup(rawname
);
145 retctx
= malloc(sizeof(ctx
));
146 if (retctx
== NULL
) {
147 warn("Cannot allocate space for device context");
151 retval
= malloc(sizeof(*retval
));
152 if (retval
== NULL
) {
153 warn("Cannot allocate space for device wrapper");
156 retval
->context
= retctx
;
157 retval
->reader
= &doRead
;
158 retval
->writer
= &writeExtent
;
159 retval
->getprog
= &GetProgress
;
160 retval
->setprog
= &SetProgress
;
161 retval
->cleanup
= &noClean
;