| /* |
| * libhfs - library for reading and writing Macintosh HFS volumes |
| * Copyright (C) 1996-1998 Robert Leslie |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, |
| * MA 02110-1301, USA. |
| * |
| * $Id: file.c,v 1.9 1998/11/02 22:08:59 rob Exp $ |
| */ |
| |
| #include "config.h" |
| #include "libhfs.h" |
| #include "file.h" |
| #include "btree.h" |
| #include "record.h" |
| #include "volume.h" |
| |
| /* |
| * NAME: file->init() |
| * DESCRIPTION: initialize file structure |
| */ |
| void f_init(hfsfile *file, hfsvol *vol, long cnid, const char *name) |
| { |
| int i; |
| |
| file->vol = vol; |
| file->parid = 0; |
| |
| strcpy(file->name, name); |
| |
| file->cat.cdrType = cdrFilRec; |
| file->cat.cdrResrv2 = 0; |
| |
| file->cat.u.fil.filFlags = 0; |
| file->cat.u.fil.filTyp = 0; |
| |
| file->cat.u.fil.filUsrWds.fdType = 0; |
| file->cat.u.fil.filUsrWds.fdCreator = 0; |
| file->cat.u.fil.filUsrWds.fdFlags = 0; |
| file->cat.u.fil.filUsrWds.fdLocation.v = 0; |
| file->cat.u.fil.filUsrWds.fdLocation.h = 0; |
| file->cat.u.fil.filUsrWds.fdFldr = 0; |
| |
| file->cat.u.fil.filFlNum = cnid; |
| file->cat.u.fil.filStBlk = 0; |
| file->cat.u.fil.filLgLen = 0; |
| file->cat.u.fil.filPyLen = 0; |
| file->cat.u.fil.filRStBlk = 0; |
| file->cat.u.fil.filRLgLen = 0; |
| file->cat.u.fil.filRPyLen = 0; |
| file->cat.u.fil.filCrDat = 0; |
| file->cat.u.fil.filMdDat = 0; |
| file->cat.u.fil.filBkDat = 0; |
| |
| file->cat.u.fil.filFndrInfo.fdIconID = 0; |
| for (i = 0; i < 4; ++i) |
| file->cat.u.fil.filFndrInfo.fdUnused[i] = 0; |
| file->cat.u.fil.filFndrInfo.fdComment = 0; |
| file->cat.u.fil.filFndrInfo.fdPutAway = 0; |
| |
| file->cat.u.fil.filClpSize = 0; |
| |
| for (i = 0; i < 3; ++i) |
| { |
| file->cat.u.fil.filExtRec[i].xdrStABN = 0; |
| file->cat.u.fil.filExtRec[i].xdrNumABlks = 0; |
| |
| file->cat.u.fil.filRExtRec[i].xdrStABN = 0; |
| file->cat.u.fil.filRExtRec[i].xdrNumABlks = 0; |
| } |
| |
| file->cat.u.fil.filResrv = 0; |
| |
| f_selectfork(file, fkData); |
| |
| file->flags = 0; |
| |
| file->prev = NULL; |
| file->next = NULL; |
| } |
| |
| /* |
| * NAME: file->selectfork() |
| * DESCRIPTION: choose a fork for file operations |
| */ |
| void f_selectfork(hfsfile *file, int fork) |
| { |
| file->fork = fork; |
| |
| memcpy(&file->ext, fork == fkData ? |
| &file->cat.u.fil.filExtRec : &file->cat.u.fil.filRExtRec, |
| sizeof(ExtDataRec)); |
| |
| file->fabn = 0; |
| file->pos = 0; |
| } |
| |
| /* |
| * NAME: file->getptrs() |
| * DESCRIPTION: make pointers to the current fork's lengths and extents |
| */ |
| void f_getptrs(hfsfile *file, ExtDataRec **extrec, |
| unsigned long **lglen, unsigned long **pylen) |
| { |
| if (file->fork == fkData) |
| { |
| if (extrec) |
| *extrec = &file->cat.u.fil.filExtRec; |
| if (lglen) |
| *lglen = &file->cat.u.fil.filLgLen; |
| if (pylen) |
| *pylen = &file->cat.u.fil.filPyLen; |
| } |
| else |
| { |
| if (extrec) |
| *extrec = &file->cat.u.fil.filRExtRec; |
| if (lglen) |
| *lglen = &file->cat.u.fil.filRLgLen; |
| if (pylen) |
| *pylen = &file->cat.u.fil.filRPyLen; |
| } |
| } |
| |
| /* |
| * NAME: file->doblock() |
| * DESCRIPTION: read or write a numbered block from a file |
| */ |
| int f_doblock(hfsfile *file, unsigned long num, block *bp, |
| int (*func)(hfsvol *, unsigned int, unsigned int, block *)) |
| { |
| unsigned int abnum; |
| unsigned int blnum; |
| unsigned int fabn; |
| int i; |
| |
| abnum = num / file->vol->lpa; |
| blnum = num % file->vol->lpa; |
| |
| /* locate the appropriate extent record */ |
| |
| fabn = file->fabn; |
| |
| if (abnum < fabn) |
| { |
| ExtDataRec *extrec; |
| |
| f_getptrs(file, &extrec, NULL, NULL); |
| |
| fabn = file->fabn = 0; |
| memcpy(&file->ext, extrec, sizeof(ExtDataRec)); |
| } |
| else |
| abnum -= fabn; |
| |
| while (1) |
| { |
| unsigned int n; |
| |
| for (i = 0; i < 3; ++i) |
| { |
| n = file->ext[i].xdrNumABlks; |
| |
| if (abnum < n) |
| return func(file->vol, file->ext[i].xdrStABN + abnum, blnum, bp); |
| |
| fabn += n; |
| abnum -= n; |
| } |
| |
| if (v_extsearch(file, fabn, &file->ext, NULL) <= 0) |
| goto fail; |
| |
| file->fabn = fabn; |
| } |
| |
| fail: |
| return -1; |
| } |