📄 hfs.c
字号:
/* store this info in the volume info */ vol.hce = hce;#endif /* APPLE_HYB */ /* create extents overflow file */ ext->f.vol = &vol; ext->f.parid = 0; strcpy(ext->f.name, "extents overflow"); ext->f.cat.cdrType = cdrFilRec; /* ext->f.cat.cdrResrv2 */ ext->f.cat.u.fil.filFlags = 0; ext->f.cat.u.fil.filTyp = 0; /* ext->f.cat.u.fil.filUsrWds */ ext->f.cat.u.fil.filFlNum = HFS_CNID_EXT; ext->f.cat.u.fil.filStBlk = 0; ext->f.cat.u.fil.filLgLen = 0; ext->f.cat.u.fil.filPyLen = 0; ext->f.cat.u.fil.filRStBlk = 0; ext->f.cat.u.fil.filRLgLen = 0; ext->f.cat.u.fil.filRPyLen = 0; ext->f.cat.u.fil.filCrDat = vol.mdb.drCrDate; ext->f.cat.u.fil.filMdDat = vol.mdb.drLsMod; ext->f.cat.u.fil.filBkDat = 0; /* ext->f.cat.u.fil.filFndrInfo */ ext->f.cat.u.fil.filClpSize = 0; for (i = 0; i < 3; ++i) { ext->f.cat.u.fil.filExtRec[i].xdrStABN = 0; ext->f.cat.u.fil.filExtRec[i].xdrNumABlks = 0; ext->f.cat.u.fil.filRExtRec[i].xdrStABN = 0; ext->f.cat.u.fil.filRExtRec[i].xdrNumABlks = 0; } /* ext->f.cat.u.fil.filResrv */ f_selectfork(&ext->f, 0); ext->f.clump = vol.mdb.drXTClpSiz; ext->f.flags = 0; ext->f.prev = ext->f.next = 0; n_init(&ext->hdrnd, ext, ndHdrNode, 0); ext->hdrnd.nnum = 0; ext->hdrnd.nd.ndNRecs = 3; ext->hdrnd.roff[1] = 0x078; ext->hdrnd.roff[2] = 0x0f8; ext->hdrnd.roff[3] = 0x1f8; memset(HFS_NODEREC(ext->hdrnd, 1), 0, 128); ext->hdr.bthDepth = 0; ext->hdr.bthRoot = 0; ext->hdr.bthNRecs = 0; ext->hdr.bthFNode = 0; ext->hdr.bthLNode = 0; ext->hdr.bthNodeSize = HFS_BLOCKSZ; ext->hdr.bthKeyLen = 0x07; ext->hdr.bthNNodes = 0; ext->hdr.bthFree = 0; for (i = 0; i < 76; ++i) ext->hdr.bthResv[i] = 0; map = ALLOC(char, HFS_MAP1SZ); if (map == 0) { if (result == 0) { ERROR(ENOMEM, 0); result = -1; } } else { memset(map, 0, HFS_MAP1SZ); BMSET(map, 0); } ext->map = map; ext->mapsz = HFS_MAP1SZ; ext->flags = HFS_UPDATE_BTHDR; ext->compare = r_compareextkeys; if (result == 0 && bt_space(ext, 1) < 0) result = -1; --ext->hdr.bthFree; /* create catalog file */ cat->f.vol = &vol; cat->f.parid = 0; strcpy(cat->f.name, "catalog"); cat->f.cat.cdrType = cdrFilRec; /* cat->f.cat.cdrResrv2 */ cat->f.cat.u.fil.filFlags = 0; cat->f.cat.u.fil.filTyp = 0; /* cat->f.cat.u.fil.filUsrWds */ cat->f.cat.u.fil.filFlNum = HFS_CNID_CAT; cat->f.cat.u.fil.filStBlk = 0; cat->f.cat.u.fil.filLgLen = 0; cat->f.cat.u.fil.filPyLen = 0; cat->f.cat.u.fil.filRStBlk = 0; cat->f.cat.u.fil.filRLgLen = 0; cat->f.cat.u.fil.filRPyLen = 0; cat->f.cat.u.fil.filCrDat = vol.mdb.drCrDate; cat->f.cat.u.fil.filMdDat = vol.mdb.drLsMod; cat->f.cat.u.fil.filBkDat = 0; /* cat->f.cat.u.fil.filFndrInfo */ cat->f.cat.u.fil.filClpSize = 0; for (i = 0; i < 3; ++i) { cat->f.cat.u.fil.filExtRec[i].xdrStABN = 0; cat->f.cat.u.fil.filExtRec[i].xdrNumABlks = 0; cat->f.cat.u.fil.filRExtRec[i].xdrStABN = 0; cat->f.cat.u.fil.filRExtRec[i].xdrNumABlks = 0; } /* cat->f.cat.u.fil.filResrv */ f_selectfork(&cat->f, 0); cat->f.clump = vol.mdb.drCTClpSiz; cat->f.flags = 0; cat->f.prev = cat->f.next = 0; n_init(&cat->hdrnd, cat, ndHdrNode, 0); cat->hdrnd.nnum = 0; cat->hdrnd.nd.ndNRecs = 3; cat->hdrnd.roff[1] = 0x078; cat->hdrnd.roff[2] = 0x0f8; cat->hdrnd.roff[3] = 0x1f8; memset(HFS_NODEREC(cat->hdrnd, 1), 0, 128); cat->hdr.bthDepth = 0; cat->hdr.bthRoot = 0; cat->hdr.bthNRecs = 0; cat->hdr.bthFNode = 0; cat->hdr.bthLNode = 0; cat->hdr.bthNodeSize = HFS_BLOCKSZ; cat->hdr.bthKeyLen = 0x25; cat->hdr.bthNNodes = 0; cat->hdr.bthFree = 0; for (i = 0; i < 76; ++i) cat->hdr.bthResv[i] = 0; map = ALLOC(char, HFS_MAP1SZ); if (map == 0) { if (result == 0) { ERROR(ENOMEM, 0); result = -1; } } else { memset(map, 0, HFS_MAP1SZ); BMSET(map, 0); } cat->map = map; cat->mapsz = HFS_MAP1SZ; cat->flags = HFS_UPDATE_BTHDR; cat->compare = r_comparecatkeys; if (result == 0 && bt_space(cat, 1) < 0) result = -1; --cat->hdr.bthFree; /* create root folder */ if (result == 0 && v_newfolder(&vol, HFS_CNID_ROOTPAR, vname) < 0) result = -1; vol.mdb.drNxtCNID = 16; /* finish up */ if (result == 0) { block b; /* write boot blocks */ memset(&b, 0, sizeof(b)); b_writelb(&vol, 0, &b); b_writelb(&vol, 1, &b); /* flush other disk state */ vol.flags |= HFS_UPDATE_MDB | HFS_UPDATE_ALTMDB | HFS_UPDATE_VBM; if (v_flush(&vol, 1) < 0) result = -1; }#ifndef APPLE_HYB if (close(vol.fd) < 0 && result == 0) { ERROR(errno, "error closing device"); result = -1; }#endif /* APPLE_HYB */ FREE(vol.ext.map); FREE(vol.cat.map); return result;}/* High-Level Directory Routines =========================================== *//* * NAME: hfs->chdir() * DESCRIPTION: change current HFS directory */int hfs_chdir(vol, path) hfsvol *vol; char *path;{ CatDataRec data; if (v_getvol(&vol) < 0 || v_resolve(&vol, path, &data, 0, 0, 0) <= 0) return -1; if (data.cdrType != cdrDirRec) { ERROR(ENOTDIR, 0); return -1; } vol->cwd = data.u.dir.dirDirID; return 0;}/* * NAME: hfs->getcwd() * DESCRIPTION: return the current working directory ID */long hfs_getcwd(vol) hfsvol *vol;{ if (v_getvol(&vol) < 0) return 0; return vol->cwd;}/* * NAME: hfs->setcwd() * DESCRIPTION: set the current working directory ID */int hfs_setcwd(vol, id) hfsvol *vol; long id;{ if (v_getvol(&vol) < 0) return -1; if (id == vol->cwd) return 0; /* make sure the directory exists */ if (v_getdthread(vol, id, 0, 0) <= 0) return -1; vol->cwd = id; return 0;}/* * NAME: hfs->dirinfo() * DESCRIPTION: given a directory ID, return its (name and) parent ID */int hfs_dirinfo(vol, id, name) hfsvol *vol; long *id; char *name;{ CatDataRec thread; if (v_getvol(&vol) < 0 || v_getdthread(vol, *id, &thread, 0) <= 0) return -1; *id = thread.u.dthd.thdParID; if (name) strcpy(name, thread.u.dthd.thdCName); return 0;}/* * NAME: hfs->opendir() * DESCRIPTION: prepare to read the contents of a directory */hfsdir *hfs_opendir(vol, path) hfsvol *vol; char *path;{ hfsdir *dir; CatKeyRec key; CatDataRec data; unsigned char pkey[HFS_CATKEYLEN]; if (v_getvol(&vol) < 0) return 0; dir = ALLOC(hfsdir, 1); if (dir == 0) { ERROR(ENOMEM, 0); return 0; } dir->vol = vol; if (*path == 0) { /* meta-directory containing root dirs from all mounted volumes */ dir->dirid = 0; dir->vptr = hfs_mounts; } else { if (v_resolve(&vol, path, &data, 0, 0, 0) <= 0) { FREE(dir); return 0; } if (data.cdrType != cdrDirRec) { FREE(dir); ERROR(ENOTDIR, 0); return 0; } dir->dirid = data.u.dir.dirDirID; dir->vptr = 0; r_makecatkey(&key, dir->dirid, ""); r_packcatkey(&key, pkey, 0); if (bt_search(&vol->cat, pkey, &dir->n) <= 0) { FREE(dir); return 0; } } dir->prev = 0; dir->next = vol->dirs; if (vol->dirs) vol->dirs->prev = dir; vol->dirs = dir; return dir;}/* * NAME: hfs->readdir() * DESCRIPTION: return the next entry in the directory */int hfs_readdir(dir, ent) hfsdir *dir; hfsdirent *ent;{ CatKeyRec key; CatDataRec data; unsigned char *ptr; if (dir->dirid == 0) { hfsvol *vol; char cname[HFS_MAX_FLEN + 1]; for (vol = hfs_mounts; vol; vol = vol->next) { if (vol == dir->vptr) break; } if (vol == 0) { ERROR(ENOENT, "no more entries"); return -1; } if (v_getdthread(vol, HFS_CNID_ROOTDIR, &data, 0) <= 0 || v_catsearch(vol, HFS_CNID_ROOTPAR, data.u.dthd.thdCName, &data, cname, 0) < 0) return -1; r_unpackdirent(HFS_CNID_ROOTPAR, cname, &data, ent); dir->vptr = vol->next; return 0; } if (dir->n.rnum == -1) { ERROR(ENOENT, "no more entries"); return -1; } while (1) { ++dir->n.rnum; while (dir->n.rnum >= dir->n.nd.ndNRecs) { dir->n.nnum = dir->n.nd.ndFLink; if (dir->n.nnum == 0) { dir->n.rnum = -1; ERROR(ENOENT, "no more entries"); return -1; } if (bt_getnode(&dir->n) < 0) { dir->n.rnum = -1; return -1; } dir->n.rnum = 0; } ptr = HFS_NODEREC(dir->n, dir->n.rnum); r_unpackcatkey(ptr, &key); if (key.ckrParID != dir->dirid) { dir->n.rnum = -1; ERROR(ENOENT, "no more entries"); return -1; } r_unpackcatdata(HFS_RECDATA(ptr), &data); switch (data.cdrType) { case cdrDirRec: case cdrFilRec: r_unpackdirent(key.ckrParID, key.ckrCName, &data, ent); return 0; case cdrThdRec: case cdrFThdRec: break; default: dir->n.rnum = -1; ERROR(EIO, "unexpected directory entry found"); return -1; } }}/* * NAME: hfs->closedir() * DESCRIPTION: stop reading a directory */int hfs_closedir(dir) hfsdir *dir;{ hfsvol *vol = dir->vol; if (dir->prev) dir->prev->next = dir->next; if (dir->next) dir->next->prev = dir->prev; if (dir == vol->dirs) vol->dirs = dir->next; FREE(dir); return 0;}/* High-Level File Routines ================================================ *//* * NAME: hfs->open() * DESCRIPTION: prepare a file for I/O */hfsfile *hfs_open(vol, path) hfsvol *vol; char *path;{ hfsfile *file; if (v_getvol(&vol) < 0) return 0; file = ALLOC(hfsfile, 1); if (file == 0) { ERROR(ENOMEM, 0); return 0; } if (v_resolve(&vol, path, &file->cat, &file->parid, file->name, 0) <= 0) { FREE(file); return 0; } if (file->cat.cdrType != cdrFilRec) { FREE(file); ERROR(EISDIR, 0); return 0; } file->vol = vol; file->clump = file->cat.u.fil.filClpSize; file->flags = 0; f_selectfork(file, 0); file->prev = 0; file->next = vol->files; if (vol->files) vol->files->prev = file; vol->files = file; return file;}/* * NAME: hfs->setfork() * DESCRIPTION: select file fork for I/O operations */int hfs_setfork(file, ffork) hfsfile *file; int ffork;{ int result = 0; if (! (file->vol->flags & HFS_READONLY) && f_trunc(file) < 0) result = -1; f_selectfork(file, ffork); return result;}/* * NAME: hfs->getfork() * DESCRIPTION: return the current fork for I/O operations */int hfs_getfork(file) hfsfile *file;{ return file->fork != fkData;}/* * NAME: hfs->read() * DESCRIPTION: read from an open file */long hfs_read(file, buf, len) hfsfile *file; void *buf; unsigned long len;{ unsigned long *lglen, count; unsigned char *ptr = buf; f_getptrs(file, &lglen, 0, 0); if (file->pos + len > *lglen) len = *lglen - file->pos; count = len; while (count) { block b; unsigned long bnum, offs, chunk; bnum = file->pos / HFS_BLOCKSZ; offs = file->pos % HFS_BLOCKSZ; chunk = HFS_BLOCKSZ - offs; if (chunk > count) chunk = count; if (f_getblock(file, bnum, &b) < 0) return -1; memcpy(ptr, b + offs, chunk); ptr += chunk; file->pos += chunk; count -= chunk; } return len;}/* * NAME: hfs->write() * DESCRIPTION: write to an open file */long hfs_write(file, buf, len) hfsfile *file; void *buf; unsigned long len;{ unsigned long *lglen, *pylen, count; unsigned char *ptr = buf; if (file->vol->flags & HFS_READONLY) { ERROR(EROFS, 0); return -1; } f_getptrs(file, &lglen, &pylen, 0); count = len; /* set flag to update (at least) the modification time */ if (count) { file->cat.u.fil.filMdDat = d_tomtime(time(0)); file->flags |= HFS_UPDATE_CATREC; } while (count) { block b; unsigned long bnum, offs, chunk; bnum = file->pos / HFS_BLOCKSZ; offs = file->pos % HFS_BLOCKSZ; chunk = HFS_BLOCKSZ - offs; if (chunk > count) chunk = count; if (file->pos + chunk > *pylen) { if (bt_space(&file->vol->ext, 1) < 0 || f_alloc(file) < 0) return -1; }#ifndef APPLE_HYB /* Ignore this part as we are always writing new files to an empty disk i.e. offs will always be 0 */ if (offs > 0 || chunk < HFS_BLOCKSZ) { if (f_getblock(file, bnum, &b) < 0) return -1; }#endif /* APPLE_HYB */ memcpy(b + offs, ptr, chunk); ptr += chunk; if (f_putblock(file, bnum, &b) < 0) return -1; file->pos += chunk; count -= chunk; if (file->pos > *lglen) *lglen = file->pos; } return len;}/* * NAME: hfs->truncate() * DESCRIPTION: truncate an open file */int hfs_truncate(file, len) hfsfile *file; unsigned long len;{ unsigned long *lglen; f_getptrs(file, &lglen, 0, 0); if (*lglen > len) { if (file->vol->flags & HFS_READONLY) { ERROR(EROFS, 0); return -1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -