]>
git.saurik.com Git - apple/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
[bufSize
];
52 if (debug
) printf("Writing extent <%lld, %lld> to device %s", start
, len
, ctx
->pathname
);
56 size_t amt
= MIN(bufSize
, len
- total
);
57 nread
= pread(devp
->fd
, buffer
, amt
, start
+ total
);
59 warn("Cannot read from device at offset %lld", start
+ total
);
62 (void)pwrite(ctx
->fd
, (char*)buffer
, nread
, start
+ total
);
70 * Device files can't have progress information stored, so we don't do anything.
73 GetProgress(struct IOWrapper
*context
)
78 SetProgress(struct IOWrapper
*context
, off_t progr
)
84 InitDeviceWrapper(const char *path
, DeviceInfo_t
*devp
)
86 struct DeviceWrapperContext ctx
= { 0 };
87 struct DeviceWrapperContext
*retctx
= NULL
;
88 IOWrapper_t
*retval
= NULL
;
91 char rawname
[strlen(path
) + 2]; // /dev/disk5 -> /dev/rdisk5
93 if (strncmp(path
, "/dev/disk", 9) == 0) {
94 // Need to make it into a raw device name
95 sprintf(rawname
, "/dev/rdisk%s", path
+ 9);
97 strcpy(rawname
, path
);
100 if (lstat(rawname
, &sb
) == -1) {
101 warn("cannot examine raw device %s", rawname
);
104 if ((sb
.st_mode
& S_IFMT
) != S_IFCHR
) {
105 warnx("device %s is not a raw device", rawname
);
109 ctx
.pathname
= strdup(rawname
);
111 ctx
.fd
= open(rawname
, O_RDWR
);
113 warn("Cannot open device %s for reading and writing", rawname
);
117 if (ioctl(ctx
.fd
, DKIOCGETBLOCKSIZE
, &ctx
.blockSize
) == -1) {
118 ctx
.blockSize
= 512; // A reasonable default
120 if (ioctl(ctx
.fd
, DKIOCGETBLOCKCOUNT
, &blockCount
) == -1) {
121 warn("Cannot block count for device %s", rawname
);
124 ctx
.devSize
= ctx
.blockSize
* blockCount
;
126 if (ctx
.devSize
!= devp
->size
) {
127 warnx("Device %s is not the same size (%lld) as source device (%lld)", rawname
, ctx
.devSize
, devp
->size
);
131 ctx
.pathname
= strdup(rawname
);
132 retctx
= malloc(sizeof(ctx
));
133 if (retctx
== NULL
) {
134 warn("Cannot allocate space for device context");
138 retval
= malloc(sizeof(*retval
));
139 if (retval
== NULL
) {
140 warn("Cannot allocate space for device wrapper");
143 retval
->context
= retctx
;
144 retval
->reader
= &doRead
;
145 retval
->writer
= &writeExtent
;
146 retval
->getprog
= &GetProgress
;
147 retval
->setprog
= &SetProgress
;
148 retval
->cleanup
= &noClean
;