📄 hfs.c
字号:
} *lglen = len; file->cat.u.fil.filMdDat = d_tomtime(time(0)); file->flags |= HFS_UPDATE_CATREC; if (file->pos > len) file->pos = len; } return 0;}/* * NAME: hfs->lseek() * DESCRIPTION: change file seek pointer */long hfs_lseek(file, offset, from) hfsfile *file; long offset; int from;{ unsigned long *lglen; long newpos; f_getptrs(file, &lglen, 0, 0); switch (from) { case SEEK_SET: newpos = offset; break; case SEEK_CUR: newpos = file->pos + offset; break; case SEEK_END: newpos = *lglen + offset; break; default: ERROR(EINVAL, 0); return -1; } if (newpos < 0) newpos = 0; else if (newpos > *lglen) newpos = *lglen; file->pos = newpos; return newpos;}/* * NAME: hfs->close() * DESCRIPTION: close a file */#ifdef APPLE_HYB/* extra args are used to set the start of the forks in the ISO volume */int hfs_close(file, dext, rext) hfsfile *file; long dext; long rext;{ int offset;#elseint hfs_close(hfsfile *file){#endif /* APPLE_HYB */ hfsvol *vol = file->vol; int result = 0; if (f_trunc(file) < 0 || f_flush(file) < 0) result = -1;#ifdef APPLE_HYB /* "start" of file is relative to the first available block */ offset = vol->hce->hfs_hdr_size + vol->hce->hfs_map_size; /* update the "real" starting extent and re-flush the file */ if (dext) file->cat.u.fil.filExtRec[0].xdrStABN = (dext - offset)/vol->lpa; if (rext) file->cat.u.fil.filRExtRec[0].xdrStABN = (rext - offset)/vol->lpa; if (dext || rext) file->flags |= HFS_UPDATE_CATREC; if (f_flush(file) < 0) result = -1;#endif /*APPLE_HYB */ if (file->prev) file->prev->next = file->next; if (file->next) file->next->prev = file->prev; if (file == vol->files) vol->files = file->next; FREE(file); return result;}/* High-Level Catalog Routines ============================================= *//* * NAME: hfs->stat() * DESCRIPTION: return catalog information for an arbitrary path */int hfs_stat(vol, path, ent) hfsvol *vol; char *path; hfsdirent *ent;{ CatDataRec data; long parid; char name[HFS_MAX_FLEN + 1]; if (v_getvol(&vol) < 0 || v_resolve(&vol, path, &data, &parid, name, 0) <= 0) return -1; r_unpackdirent(parid, name, &data, ent); return 0;}/* * NAME: hfs->fstat() * DESCRIPTION: return catalog information for an open file */int hfs_fstat(file, ent) hfsfile *file; hfsdirent *ent;{ r_unpackdirent(file->parid, file->name, &file->cat, ent); return 0;}/* * NAME: hfs->setattr() * DESCRIPTION: change a file's attributes */int hfs_setattr(vol, path, ent) hfsvol *vol; char *path; hfsdirent *ent;{ CatDataRec data; node n; if (v_getvol(&vol) < 0 || v_resolve(&vol, path, &data, 0, 0, &n) <= 0) return -1; if (vol->flags & HFS_READONLY) { ERROR(EROFS, 0); return -1; } r_packdirent(&data, ent); if (v_putcatrec(&data, &n) < 0) return -1; return 0;}/* * NAME: hfs->fsetattr() * DESCRIPTION: change an open file's attributes */int hfs_fsetattr(file, ent) hfsfile *file; hfsdirent *ent;{ if (file->vol->flags & HFS_READONLY) { ERROR(EROFS, 0); return -1; } r_packdirent(&file->cat, ent); file->flags |= HFS_UPDATE_CATREC; return 0;}/* * NAME: hfs->mkdir() * DESCRIPTION: create a new directory */int hfs_mkdir(vol, path) hfsvol *vol; char *path;{ CatDataRec data; long parid; char name[HFS_MAX_FLEN + 1]; int found; if (v_getvol(&vol) < 0) return -1; found = v_resolve(&vol, path, &data, &parid, name, 0); if (found < 0 || parid == 0) return -1; else if (found) { ERROR(EEXIST, 0); return -1; } if (parid == HFS_CNID_ROOTPAR) { ERROR(EINVAL, 0); return -1; } if (vol->flags & HFS_READONLY) { ERROR(EROFS, 0); return -1; } if (v_newfolder(vol, parid, name) < 0) return -1; return 0;}/* * NAME: hfs->rmdir() * DESCRIPTION: delete an empty directory */int hfs_rmdir(vol, path) hfsvol *vol; char *path;{ CatKeyRec key; CatDataRec data; long parid; char name[HFS_MAX_FLEN + 1]; unsigned char pkey[HFS_CATKEYLEN]; if (v_getvol(&vol) < 0 || v_resolve(&vol, path, &data, &parid, name, 0) <= 0) return -1; if (data.cdrType != cdrDirRec) { ERROR(ENOTDIR, 0); return -1; } if (data.u.dir.dirVal != 0) { ERROR(ENOTEMPTY, 0); return -1; } if (parid == HFS_CNID_ROOTPAR) { ERROR(EINVAL, 0); return -1; } if (vol->flags & HFS_READONLY) { ERROR(EROFS, 0); return -1; } /* delete directory record */ r_makecatkey(&key, parid, name); r_packcatkey(&key, pkey, 0); if (bt_delete(&vol->cat, pkey) < 0) return -1; /* delete thread record */ r_makecatkey(&key, data.u.dir.dirDirID, ""); r_packcatkey(&key, pkey, 0); if (bt_delete(&vol->cat, pkey) < 0 || v_adjvalence(vol, parid, 1, -1) < 0) return -1; return 0;}/* * NAME: hfs->create() * DESCRIPTION: create a new file */int hfs_create(vol, path, type, creator) hfsvol *vol; char *path; char *type; char *creator;{ CatKeyRec key; CatDataRec data; long id, parid; char name[HFS_MAX_FLEN + 1]; unsigned char record[HFS_CATRECMAXLEN]; int found, i, reclen; if (v_getvol(&vol) < 0) return -1; found = v_resolve(&vol, path, &data, &parid, name, 0); if (found < 0 || parid == 0) return -1; else if (found) { ERROR(EEXIST, 0); return -1; } if (parid == HFS_CNID_ROOTPAR) { ERROR(EINVAL, 0); return -1; } if (vol->flags & HFS_READONLY) { ERROR(EROFS, 0); return -1; } /* create file `name' in parent `parid' */ if (bt_space(&vol->cat, 1) < 0) return -1; id = vol->mdb.drNxtCNID++; vol->flags |= HFS_UPDATE_MDB; /* create file record */ data.cdrType = cdrFilRec; data.cdrResrv2 = 0; data.u.fil.filFlags = 0; data.u.fil.filTyp = 0; memset(&data.u.fil.filUsrWds, 0, sizeof(data.u.fil.filUsrWds)); data.u.fil.filUsrWds.fdType = d_getl((unsigned char *) type); data.u.fil.filUsrWds.fdCreator = d_getl((unsigned char *) creator); data.u.fil.filFlNum = id; data.u.fil.filStBlk = 0; data.u.fil.filLgLen = 0; data.u.fil.filPyLen = 0; data.u.fil.filRStBlk = 0; data.u.fil.filRLgLen = 0; data.u.fil.filRPyLen = 0; data.u.fil.filCrDat = d_tomtime(time(0)); data.u.fil.filMdDat = data.u.fil.filCrDat; data.u.fil.filBkDat = 0; memset(&data.u.fil.filFndrInfo, 0, sizeof(data.u.fil.filFndrInfo)); data.u.fil.filClpSize = 0; for (i = 0; i < 3; ++i) { data.u.fil.filExtRec[i].xdrStABN = 0; data.u.fil.filExtRec[i].xdrNumABlks = 0; data.u.fil.filRExtRec[i].xdrStABN = 0; data.u.fil.filRExtRec[i].xdrNumABlks = 0; } data.u.fil.filResrv = 0; r_makecatkey(&key, parid, name); r_packcatkey(&key, record, &reclen); r_packcatdata(&data, HFS_RECDATA(record), &reclen); if (bt_insert(&vol->cat, record, reclen) < 0 || v_adjvalence(vol, parid, 0, 1) < 0) return -1; return 0;}/* * NAME: hfs->delete() * DESCRIPTION: remove both forks of a file */int hfs_delete(vol, path) hfsvol *vol; char *path;{ hfsfile file; CatKeyRec key; unsigned char pkey[HFS_CATKEYLEN]; int found; if (v_getvol(&vol) < 0 || v_resolve(&vol, path, &file.cat, &file.parid, file.name, 0) <= 0) return -1; if (file.cat.cdrType != cdrFilRec) { ERROR(EISDIR, 0); return -1; } if (file.parid == HFS_CNID_ROOTPAR) { ERROR(EINVAL, 0); return -1; } if (vol->flags & HFS_READONLY) { ERROR(EROFS, 0); return -1; } /* free disk blocks */ file.vol = vol; file.flags = 0; file.cat.u.fil.filLgLen = 0; file.cat.u.fil.filRLgLen = 0; f_selectfork(&file, 0); if (f_trunc(&file) < 0) return -1; f_selectfork(&file, 1); if (f_trunc(&file) < 0) return -1; /* delete file record */ r_makecatkey(&key, file.parid, file.name); r_packcatkey(&key, pkey, 0); if (bt_delete(&vol->cat, pkey) < 0 || v_adjvalence(vol, file.parid, 0, -1) < 0) return -1; /* delete file thread, if any */ found = v_getfthread(vol, file.cat.u.fil.filFlNum, 0, 0); if (found < 0) return -1; if (found) { r_makecatkey(&key, file.cat.u.fil.filFlNum, ""); r_packcatkey(&key, pkey, 0); if (bt_delete(&vol->cat, pkey) < 0) return -1; } return 0;}/* * NAME: hfs->rename() * DESCRIPTION: change the name of and/or move a file or directory */int hfs_rename(vol, srcpath, dstpath) hfsvol *vol; char *srcpath; char *dstpath;{ hfsvol *srcvol; CatDataRec src, dst; long srcid, dstid; CatKeyRec key; char srcname[HFS_MAX_FLEN + 1], dstname[HFS_MAX_FLEN + 1]; unsigned char record[HFS_CATRECMAXLEN]; int found, isdir, moving, reclen; node n; if (v_getvol(&vol) < 0 || v_resolve(&vol, srcpath, &src, &srcid, srcname, 0) <= 0) return -1; isdir = (src.cdrType == cdrDirRec); srcvol = vol; found = v_resolve(&vol, dstpath, &dst, &dstid, dstname, 0); if (found < 0) return -1; if (vol != srcvol) { ERROR(EINVAL, "can't move across volumes"); return -1; } if (dstid == 0) { ERROR(ENOENT, "bad destination path"); return -1; } if (found && dst.cdrType == cdrDirRec && dst.u.dir.dirDirID != src.u.dir.dirDirID) { dstid = dst.u.dir.dirDirID; strcpy(dstname, srcname); found = v_catsearch(vol, dstid, dstname, 0, 0, 0); if (found < 0) return -1; } moving = (srcid != dstid); if (found) { char *ptr; ptr = strrchr(dstpath, ':'); if (ptr == 0) ptr = dstpath; else ++ptr; if (*ptr) strcpy(dstname, ptr); if (! moving && strcmp(srcname, dstname) == 0) return 0; /* source and destination are the same */ if (moving || d_relstring(srcname, dstname)) { ERROR(EEXIST, "can't use destination name"); return -1; } } /* can't move anything into the root directory's parent */ if (moving && dstid == HFS_CNID_ROOTPAR) { ERROR(EINVAL, "can't move above root directory"); return -1; } if (moving && isdir) { long id; /* can't move root directory anywhere */ if (src.u.dir.dirDirID == HFS_CNID_ROOTDIR) { ERROR(EINVAL, "can't move root directory"); return -1; } /* make sure we aren't trying to move a directory inside itself */ for (id = dstid; id != HFS_CNID_ROOTDIR; id = dst.u.dthd.thdParID) { if (id == src.u.dir.dirDirID) { ERROR(EINVAL, "can't move directory inside itself"); return -1; } if (v_getdthread(vol, id, &dst, 0) <= 0) return -1; } } if (vol->flags & HFS_READONLY) { ERROR(EROFS, 0); return -1; } /* change volume name */ if (dstid == HFS_CNID_ROOTPAR) { if (strlen(dstname) > HFS_MAX_VLEN) { ERROR(ENAMETOOLONG, 0); return -1; } strcpy(vol->mdb.drVN, dstname); vol->flags |= HFS_UPDATE_MDB; } /* remove source record */ r_makecatkey(&key, srcid, srcname); r_packcatkey(&key, record, 0); if (bt_delete(&vol->cat, record) < 0) return -1; /* insert destination record */ r_makecatkey(&key, dstid, dstname); r_packcatkey(&key, record, &reclen); r_packcatdata(&src, HFS_RECDATA(record), &reclen); if (bt_insert(&vol->cat, record, reclen) < 0) return -1; /* update thread record */ if (isdir) { if (v_getdthread(vol, src.u.dir.dirDirID, &dst, &n) <= 0) return -1; dst.u.dthd.thdParID = dstid; strcpy(dst.u.dthd.thdCName, dstname); if (v_putcatrec(&dst, &n) < 0) return -1; } else { found = v_getfthread(vol, src.u.fil.filFlNum, &dst, &n); if (found < 0) return -1; if (found) { dst.u.fthd.fthdParID = dstid; strcpy(dst.u.fthd.fthdCName, dstname); if (v_putcatrec(&dst, &n) < 0) return -1; } } /* update directory valences */ if (moving) { if (v_adjvalence(vol, srcid, isdir, -1) < 0 || v_adjvalence(vol, dstid, isdir, 1) < 0) return -1; } return 0;}#ifdef APPLE_HYB/* * NAME: hfs->hfs_get_drAllocPtr() * DESCRIPTION: get the current start of next allocation search */unsigned shorthfs_get_drAllocPtr(file) hfsfile *file;{ return(file->vol->mdb.drAllocPtr);}/* * NAME: hfs->hfs_set_drAllocPtr() * DESCRIPTION: set the current start of next allocation search */#ifdef PROTOTYPESinthfs_set_drAllocPtr(hfsfile *file, unsigned short drAllocPtr, int size)#elseinthfs_set_drAllocPtr(file, drAllocPtr, size) hfsfile *file; unsigned short drAllocPtr; int size;#endif{ hfsvol *vol = file->vol; int result = 0; /* truncate the current fork */ if (f_trunc(file) < 0 || f_flush(file) < 0) result = -1; /* convert the fork size into allocation blocks */ size = (size + vol->mdb.drAlBlkSiz - 1)/vol->mdb.drAlBlkSiz; /* set the start of next allocation search to be after this fork */ vol->mdb.drAllocPtr = drAllocPtr + size; vol->flags |= HFS_UPDATE_MDB; return result;}#endif /* APPLE_HYB */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -