X-Git-Url: https://git.saurik.com/apple/hfs.git/blobdiff_plain/a56bdb9dd68c843a17a0658b5250e0cc67c22fe8..246784f7dc26d498d36b5dbe514331e0b88c00c2:/CopyHFSMeta/main.c?ds=sidebyside diff --git a/CopyHFSMeta/main.c b/CopyHFSMeta/main.c index ba830fd..235f0e8 100644 --- a/CopyHFSMeta/main.c +++ b/CopyHFSMeta/main.c @@ -66,6 +66,44 @@ OpenDevice(const char *devname) if (stat(devname, &sb) == -1) { err(kBadExit, "cannot open device %s", devname); } + /* + * Attempt to flush the journal. If it fails, we just warn, but don't abort. + */ + if (getvfsbyname("hfs", &vfc) == 0) { + int rv; + int mib[4]; + char block_device[MAXPATHLEN+1]; + int jfd; + + /* + * The journal replay code, sadly, requires a block device. + * So we need to go from the raw device to block device, if + * necessary. + */ + if (strncmp(devname, "/dev/rdisk", 10) == 0) { + snprintf(block_device, sizeof(block_device), "/dev/%s", devname+6); + } else { + snprintf(block_device, sizeof(block_device), "%s", devname); + } + jfd = open(block_device, O_RDWR); + if (jfd == -1) { + warn("Cannot open block device %s for read-write", block_device); + } else { + mib[0] = CTL_VFS; + mib[1] = vfc.vfc_typenum; + mib[2] = HFS_REPLAY_JOURNAL; + mib[3] = jfd; + if (debug) + fprintf(stderr, "about to replay journal\n"); + rv = sysctl(mib, 4, NULL, NULL, NULL, 0); + if (rv == -1) { + warn("cannot replay journal"); + } + /* This is probably not necessary, but we couldn't prove it. */ + (void)fcntl(jfd, F_FULLFSYNC, 0); + close(jfd); + } + } /* * We only allow a character device (e.g., /dev/rdisk1s2) * If we're given a non-character device, we'll try to turn @@ -88,7 +126,7 @@ OpenDevice(const char *devname) errx(kBadExit, "device name `%s' does not fit pattern", devname); } // Only use an exclusive open if we're not debugging. - fd = open(dev.devname, O_RDONLY | (debug ? 0 : O_EXLOCK)); + fd = open(dev.devname, O_RDWR | (debug ? 0 : O_EXLOCK)); if (fd == -1) { err(kBadExit, "cannot open raw device %s", dev.devname); } @@ -99,25 +137,6 @@ OpenDevice(const char *devname) if (ioctl(fd, DKIOCGETBLOCKCOUNT, &dev.blockCount) == -1) { err(kBadExit, "cannot get size of device %s", dev.devname); } - /* - * Attempt to flush the buffer. This works even with a file descriptor - * opened for read-only. If it fails, we just warn, but don't abort. - */ - if (getvfsbyname("hfs", &vfc) == 0) { - int rv; - int mib[4]; - - mib[0] = CTL_VFS; - mib[1] = vfc.vfc_typenum; - mib[2] = HFS_REPLAY_JOURNAL; - mib[3] = fd; - if (debug) - fprintf(stderr, "about to replay journal\n"); - rv = sysctl(mib, 4, NULL, NULL, NULL, 0); - if (rv == -1) { - warn("cannot replay journal"); - } - } dev.size = dev.blockCount * dev.blockSize; dev.fd = fd;