/* * NAME: vol->readmdb() * DESCRIPTION: load Master Directory Block into memory */ int v_readmdb(hfsvol *vol) { if (l_getmdb(vol, &vol->mdb, 0) == -1) goto fail; if (vol->mdb.drSigWord != HFS_SIGWORD) { if (vol->mdb.drSigWord == HFS_SIGWORD_MFS) ERROR(EINVAL, "MFS volume format not supported"); else ERROR(EINVAL, "not a Macintosh HFS volume"); } if (vol->mdb.drAlBlkSiz % HFS_BLOCKSZ != 0) ERROR(EINVAL, "bad volume allocation block size"); vol->lpa = vol->mdb.drAlBlkSiz >> HFS_BLOCKSZ_BITS; /* extents pseudo-file structs */ vol->ext.f.cat.u.fil.filStBlk = vol->mdb.drXTExtRec[0].xdrStABN; vol->ext.f.cat.u.fil.filLgLen = vol->mdb.drXTFlSize; vol->ext.f.cat.u.fil.filPyLen = vol->mdb.drXTFlSize; vol->ext.f.cat.u.fil.filCrDat = vol->mdb.drCrDate; vol->ext.f.cat.u.fil.filMdDat = vol->mdb.drLsMod; vol->ext.f.cat.u.fil.filClpSize = vol->mdb.drXTClpSiz; memcpy(&vol->ext.f.cat.u.fil.filExtRec, &vol->mdb.drXTExtRec, sizeof(ExtDataRec)); f_selectfork(&vol->ext.f, fkData); /* catalog pseudo-file structs */ vol->cat.f.cat.u.fil.filStBlk = vol->mdb.drCTExtRec[0].xdrStABN; vol->cat.f.cat.u.fil.filLgLen = vol->mdb.drCTFlSize; vol->cat.f.cat.u.fil.filPyLen = vol->mdb.drCTFlSize; vol->cat.f.cat.u.fil.filCrDat = vol->mdb.drCrDate; vol->cat.f.cat.u.fil.filMdDat = vol->mdb.drLsMod; vol->cat.f.cat.u.fil.filClpSize = vol->mdb.drCTClpSiz; memcpy(&vol->cat.f.cat.u.fil.filExtRec, &vol->mdb.drCTExtRec, sizeof(ExtDataRec)); f_selectfork(&vol->cat.f, fkData); return 0; fail: return -1; }
/* * NAME: main() * DESCRIPTION: program entry */ int main(int argc, char *argv[]) { char *path; int nparts, pnum, result; hfsvol vol; suid_init(); if (argc == 2) { if (strcmp(argv[1], "--version") == 0) { printf("%s - %s\n", hfsutils_version, hfsutils_copyright); printf("`%s --license' for licensing information.\n", argv[0]); return 0; } else if (strcmp(argv[1], "--license") == 0) { printf("\n%s", hfsutils_license); return 0; } } options = HFSCK_REPAIR; while (1) { int opt; opt = getopt(argc, argv, "vna"); if (opt == EOF) break; switch (opt) { case '?': return usage(argv); case 'v': options |= HFSCK_VERBOSE; break; case 'n': options &= ~HFSCK_REPAIR; break; case 'a': options |= HFSCK_YES; break; } } if (argc - optind < 1 || argc - optind > 2) return usage(argv); path = argv[optind]; suid_enable(); nparts = hfs_nparts(path); suid_disable(); if (nparts == 0) { fprintf(stderr, "%s: partitioned medium contains no HFS partitions\n", argv[0]); return 1; } if (argc - optind == 2) { pnum = atoi(argv[optind + 1]); if (pnum < 0) { fprintf(stderr, "%s: invalid partition number\n", argv[0]); return 1; } if (nparts == -1 && pnum > 0) { fprintf(stderr, "%s: warning: ignoring partition number for" " non-partitioned medium\n", argv[0]); pnum = 0; } else if (nparts > 0 && pnum == 0) { fprintf(stderr, "%s: cannot specify whole medium" " (has %d partition%s)\n", argv[0], nparts, nparts == 1 ? "" : "s"); return 1; } else if (nparts > 0 && pnum > nparts) { fprintf(stderr, "%s: invalid partition number (only %d available)\n", argv[0], nparts); return 1; } } else { if (nparts > 1) { fprintf(stderr, "%s: must specify partition number (%d available)\n", argv[0], nparts); return 1; } else if (nparts == -1) pnum = 0; else pnum = 1; } v_init(&vol, HFS_OPT_NOCACHE); if (REPAIR) { suid_enable(); result = v_open(&vol, path, HFS_MODE_RDWR); suid_disable(); if (result == -1) { vol.flags |= HFS_VOL_READONLY; suid_enable(); result = v_open(&vol, path, HFS_MODE_RDONLY); suid_disable(); } } if (result == -1) { perror(path); return 1; } if (REPAIR && (vol.flags & HFS_VOL_READONLY)) { fprintf(stderr, "%s: warning: %s not writable; cannot repair\n", argv[0], path); options &= ~HFSCK_REPAIR; } if (v_geometry(&vol, pnum) == -1 || l_getmdb(&vol, &vol.mdb, 0) == -1) { perror(path); v_close(&vol); return 1; } result = hfsck(&vol); vol.flags |= HFS_VOL_MOUNTED; if (v_close(&vol) == -1) { perror("closing volume"); return 1; } return result; }