Annotation of qemu/roms/openbios/fs/hfs/hfs.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * libhfs - library for reading and writing Macintosh HFS volumes
        !             3:  * Copyright (C) 1996-1998 Robert Leslie
        !             4:  *
        !             5:  * This program is free software; you can redistribute it and/or modify
        !             6:  * it under the terms of the GNU General Public License as published by
        !             7:  * the Free Software Foundation; either version 2 of the License, or
        !             8:  * (at your option) any later version.
        !             9:  *
        !            10:  * This program is distributed in the hope that it will be useful,
        !            11:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            12:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            13:  * GNU General Public License for more details.
        !            14:  *
        !            15:  * You should have received a copy of the GNU General Public License
        !            16:  * along with this program; if not, write to the Free Software
        !            17:  * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
        !            18:  * MA 02110-1301, USA.
        !            19:  *
        !            20:  * $Id: hfs.c,v 1.15 1998/11/02 22:09:00 rob Exp $
        !            21:  */
        !            22: 
        !            23: #include "config.h"
        !            24: #include "libhfs.h"
        !            25: #include "data.h"
        !            26: #include "block.h"
        !            27: #include "medium.h"
        !            28: #include "file.h"
        !            29: #include "btree.h"
        !            30: #include "node.h"
        !            31: #include "record.h"
        !            32: #include "volume.h"
        !            33: 
        !            34: const char *hfs_error = "no error";    /* static error string */
        !            35: 
        !            36: hfsvol *hfs_mounts;                    /* linked list of mounted volumes */
        !            37: 
        !            38: static
        !            39: hfsvol *curvol;                                /* current volume */
        !            40: 
        !            41: 
        !            42: /*
        !            43:  * NAME:       getvol()
        !            44:  * DESCRIPTION:        validate a volume reference
        !            45:  */
        !            46: static
        !            47: int getvol(hfsvol **vol)
        !            48: {
        !            49:   if (*vol == NULL)
        !            50:     {
        !            51:       if (curvol == NULL)
        !            52:        ERROR(EINVAL, "no volume is current");
        !            53: 
        !            54:       *vol = curvol;
        !            55:     }
        !            56: 
        !            57:   return 0;
        !            58: 
        !            59: fail:
        !            60:   return -1;
        !            61: }
        !            62: 
        !            63: /* High-Level Volume Routines ============================================== */
        !            64: 
        !            65: /*
        !            66:  * NAME:       hfs->mount()
        !            67:  * DESCRIPTION:        open an HFS volume; return volume descriptor or 0 (error)
        !            68:  */
        !            69: hfsvol *hfs_mount( int os_fd, int pnum)
        !            70: {
        !            71:   hfsvol *vol, *check;
        !            72:   int mode = HFS_MODE_RDONLY;
        !            73: 
        !            74:   /* see if the volume is already mounted */
        !            75:   for (check = hfs_mounts; check; check = check->next)
        !            76:     {
        !            77:       if (check->pnum == pnum && v_same(check, os_fd) == 1)
        !            78:        {
        !            79:            vol = check;
        !            80:            goto done;
        !            81:        }
        !            82:     }
        !            83: 
        !            84:   vol = ALLOC(hfsvol, 1);
        !            85:   if (vol == NULL)
        !            86:     ERROR(ENOMEM, NULL);
        !            87: 
        !            88:   v_init(vol, mode);
        !            89: 
        !            90:   vol->flags |= HFS_VOL_READONLY;
        !            91:   if( v_open(vol, os_fd) == -1 )
        !            92:          goto fail;
        !            93: 
        !            94:   /* mount the volume */
        !            95: 
        !            96:   if (v_geometry(vol, pnum) == -1 ||
        !            97:       v_mount(vol) == -1)
        !            98:     goto fail;
        !            99: 
        !           100:   /* add to linked list of volumes */
        !           101: 
        !           102:   vol->prev = NULL;
        !           103:   vol->next = hfs_mounts;
        !           104: 
        !           105:   if (hfs_mounts)
        !           106:     hfs_mounts->prev = vol;
        !           107: 
        !           108:   hfs_mounts = vol;
        !           109: 
        !           110: done:
        !           111:   ++vol->refs;
        !           112:   curvol = vol;
        !           113: 
        !           114:   return vol;
        !           115: 
        !           116: fail:
        !           117:   if (vol)
        !           118:     {
        !           119:       v_close(vol);
        !           120:       FREE(vol);
        !           121:     }
        !           122: 
        !           123:   return NULL;
        !           124: }
        !           125: 
        !           126: 
        !           127: /*
        !           128:  * NAME:       hfs->umount()
        !           129:  * DESCRIPTION:        close an HFS volume
        !           130:  */
        !           131: int hfs_umount(hfsvol *vol)
        !           132: {
        !           133:   int result = 0;
        !           134: 
        !           135:   if (getvol(&vol) == -1)
        !           136:     goto fail;
        !           137: 
        !           138:   if (--vol->refs)
        !           139:     {
        !           140:       goto done;
        !           141:     }
        !           142: 
        !           143:   /* close all open files and directories */
        !           144: 
        !           145:   while (vol->files)
        !           146:     {
        !           147:       if (hfs_close(vol->files) == -1)
        !           148:        result = -1;
        !           149:     }
        !           150: 
        !           151:   while (vol->dirs)
        !           152:     {
        !           153:       if (hfs_closedir(vol->dirs) == -1)
        !           154:        result = -1;
        !           155:     }
        !           156: 
        !           157:   /* close medium */
        !           158: 
        !           159:   if (v_close(vol) == -1)
        !           160:     result = -1;
        !           161: 
        !           162:   /* remove from linked list of volumes */
        !           163: 
        !           164:   if (vol->prev)
        !           165:     vol->prev->next = vol->next;
        !           166:   if (vol->next)
        !           167:     vol->next->prev = vol->prev;
        !           168: 
        !           169:   if (vol == hfs_mounts)
        !           170:     hfs_mounts = vol->next;
        !           171:   if (vol == curvol)
        !           172:     curvol = NULL;
        !           173: 
        !           174:   FREE(vol);
        !           175: 
        !           176: done:
        !           177:   return result;
        !           178: 
        !           179: fail:
        !           180:   return -1;
        !           181: }
        !           182: 
        !           183: /*
        !           184:  * NAME:       hfs->umountall()
        !           185:  * DESCRIPTION:        unmount all mounted volumes
        !           186:  */
        !           187: void hfs_umountall(void)
        !           188: {
        !           189:   while (hfs_mounts)
        !           190:     hfs_umount(hfs_mounts);
        !           191: }
        !           192: 
        !           193: /*
        !           194:  * NAME:       hfs->getvol()
        !           195:  * DESCRIPTION:        return a pointer to a mounted volume
        !           196:  */
        !           197: hfsvol *hfs_getvol(const char *name)
        !           198: {
        !           199:   hfsvol *vol;
        !           200: 
        !           201:   if (name == NULL)
        !           202:     return curvol;
        !           203: 
        !           204:   for (vol = hfs_mounts; vol; vol = vol->next)
        !           205:     {
        !           206:       if (d_relstring(name, vol->mdb.drVN) == 0)
        !           207:        return vol;
        !           208:     }
        !           209: 
        !           210:   return NULL;
        !           211: }
        !           212: 
        !           213: /*
        !           214:  * NAME:       hfs->setvol()
        !           215:  * DESCRIPTION:        change the current volume
        !           216:  */
        !           217: void hfs_setvol(hfsvol *vol)
        !           218: {
        !           219:   curvol = vol;
        !           220: }
        !           221: 
        !           222: /*
        !           223:  * NAME:       hfs->vstat()
        !           224:  * DESCRIPTION:        return volume statistics
        !           225:  */
        !           226: int hfs_vstat(hfsvol *vol, hfsvolent *ent)
        !           227: {
        !           228:   if (getvol(&vol) == -1)
        !           229:     goto fail;
        !           230: 
        !           231:   strcpy(ent->name, vol->mdb.drVN);
        !           232: 
        !           233:   ent->flags     = (vol->flags & HFS_VOL_READONLY) ? HFS_ISLOCKED : 0;
        !           234: 
        !           235:   ent->totbytes  = vol->mdb.drNmAlBlks * vol->mdb.drAlBlkSiz;
        !           236:   ent->freebytes = vol->mdb.drFreeBks  * vol->mdb.drAlBlkSiz;
        !           237: 
        !           238:   ent->alblocksz = vol->mdb.drAlBlkSiz;
        !           239:   ent->clumpsz   = vol->mdb.drClpSiz;
        !           240: 
        !           241:   ent->numfiles  = vol->mdb.drFilCnt;
        !           242:   ent->numdirs   = vol->mdb.drDirCnt;
        !           243: 
        !           244:   ent->crdate    = d_ltime(vol->mdb.drCrDate);
        !           245:   ent->mddate    = d_ltime(vol->mdb.drLsMod);
        !           246:   ent->bkdate    = d_ltime(vol->mdb.drVolBkUp);
        !           247: 
        !           248:   ent->blessed   = vol->mdb.drFndrInfo[0];
        !           249: 
        !           250:   return 0;
        !           251: 
        !           252: fail:
        !           253:   return -1;
        !           254: }
        !           255: 
        !           256: 
        !           257: /* High-Level Directory Routines =========================================== */
        !           258: 
        !           259: /*
        !           260:  * NAME:       hfs->chdir()
        !           261:  * DESCRIPTION:        change current HFS directory
        !           262:  */
        !           263: int hfs_chdir(hfsvol *vol, const char *path)
        !           264: {
        !           265:   CatDataRec data;
        !           266: 
        !           267:   if (getvol(&vol) == -1 ||
        !           268:       v_resolve(&vol, path, &data, NULL, NULL, NULL) <= 0)
        !           269:     goto fail;
        !           270: 
        !           271:   if (data.cdrType != cdrDirRec)
        !           272:     ERROR(ENOTDIR, NULL);
        !           273: 
        !           274:   vol->cwd = data.u.dir.dirDirID;
        !           275: 
        !           276:   return 0;
        !           277: 
        !           278: fail:
        !           279:   return -1;
        !           280: }
        !           281: 
        !           282: /*
        !           283:  * NAME:       hfs->getcwd()
        !           284:  * DESCRIPTION:        return the current working directory ID
        !           285:  */
        !           286: unsigned long hfs_getcwd(hfsvol *vol)
        !           287: {
        !           288:   if (getvol(&vol) == -1)
        !           289:     return 0;
        !           290: 
        !           291:   return vol->cwd;
        !           292: }
        !           293: 
        !           294: /*
        !           295:  * NAME:       hfs->setcwd()
        !           296:  * DESCRIPTION:        set the current working directory ID
        !           297:  */
        !           298: int hfs_setcwd(hfsvol *vol, unsigned long id)
        !           299: {
        !           300:   if (getvol(&vol) == -1)
        !           301:     goto fail;
        !           302: 
        !           303:   if (id == vol->cwd)
        !           304:     goto done;
        !           305: 
        !           306:   /* make sure the directory exists */
        !           307: 
        !           308:   if (v_getdthread(vol, id, NULL, NULL) <= 0)
        !           309:     goto fail;
        !           310: 
        !           311:   vol->cwd = id;
        !           312: 
        !           313: done:
        !           314:   return 0;
        !           315: 
        !           316: fail:
        !           317:   return -1;
        !           318: }
        !           319: 
        !           320: /*
        !           321:  * NAME:       hfs->dirinfo()
        !           322:  * DESCRIPTION:        given a directory ID, return its (name and) parent ID
        !           323:  */
        !           324: int hfs_dirinfo(hfsvol *vol, unsigned long *id, char *name)
        !           325: {
        !           326:   CatDataRec thread;
        !           327: 
        !           328:   if (getvol(&vol) == -1 ||
        !           329:       v_getdthread(vol, *id, &thread, NULL) <= 0)
        !           330:     goto fail;
        !           331: 
        !           332:   *id = thread.u.dthd.thdParID;
        !           333: 
        !           334:   if (name)
        !           335:     strcpy(name, thread.u.dthd.thdCName);
        !           336: 
        !           337:   return 0;
        !           338: 
        !           339: fail:
        !           340:   return -1;
        !           341: }
        !           342: 
        !           343: /*
        !           344:  * NAME:       hfs->opendir()
        !           345:  * DESCRIPTION:        prepare to read the contents of a directory
        !           346:  */
        !           347: hfsdir *hfs_opendir(hfsvol *vol, const char *path)
        !           348: {
        !           349:   hfsdir *dir = NULL;
        !           350:   CatKeyRec key;
        !           351:   CatDataRec data;
        !           352:   byte pkey[HFS_CATKEYLEN];
        !           353: 
        !           354:   if (getvol(&vol) == -1)
        !           355:     goto fail;
        !           356: 
        !           357:   dir = ALLOC(hfsdir, 1);
        !           358:   if (dir == NULL)
        !           359:     ERROR(ENOMEM, NULL);
        !           360: 
        !           361:   dir->vol = vol;
        !           362: 
        !           363:   if (*path == 0)
        !           364:     {
        !           365:       /* meta-directory containing root dirs from all mounted volumes */
        !           366: 
        !           367:       dir->dirid = 0;
        !           368:       dir->vptr  = hfs_mounts;
        !           369:     }
        !           370:   else
        !           371:     {
        !           372:       if (v_resolve(&vol, path, &data, NULL, NULL, NULL) <= 0)
        !           373:        goto fail;
        !           374: 
        !           375:       if (data.cdrType != cdrDirRec)
        !           376:         ERROR(ENOTDIR, NULL);
        !           377: 
        !           378:       dir->dirid = data.u.dir.dirDirID;
        !           379:       dir->vptr  = NULL;
        !           380: 
        !           381:       r_makecatkey(&key, dir->dirid, "");
        !           382:       r_packcatkey(&key, pkey, NULL);
        !           383: 
        !           384:       if (bt_search(&vol->cat, pkey, &dir->n) <= 0)
        !           385:        goto fail;
        !           386:     }
        !           387: 
        !           388:   dir->prev = NULL;
        !           389:   dir->next = vol->dirs;
        !           390: 
        !           391:   if (vol->dirs)
        !           392:     vol->dirs->prev = dir;
        !           393: 
        !           394:   vol->dirs = dir;
        !           395: 
        !           396:   return dir;
        !           397: 
        !           398: fail:
        !           399:   FREE(dir);
        !           400:   return NULL;
        !           401: }
        !           402: 
        !           403: /*
        !           404:  * NAME:       hfs->readdir()
        !           405:  * DESCRIPTION:        return the next entry in the directory
        !           406:  */
        !           407: int hfs_readdir(hfsdir *dir, hfsdirent *ent)
        !           408: {
        !           409:   CatKeyRec key;
        !           410:   CatDataRec data;
        !           411:   const byte *ptr;
        !           412: 
        !           413:   if (dir->dirid == 0)
        !           414:     {
        !           415:       hfsvol *vol;
        !           416:       char cname[HFS_MAX_FLEN + 1];
        !           417: 
        !           418:       for (vol = hfs_mounts; vol; vol = vol->next)
        !           419:        {
        !           420:          if (vol == dir->vptr)
        !           421:            break;
        !           422:        }
        !           423: 
        !           424:       if (vol == NULL)
        !           425:        ERROR(ENOENT, "no more entries");
        !           426: 
        !           427:       if (v_getdthread(vol, HFS_CNID_ROOTDIR, &data, NULL) <= 0 ||
        !           428:          v_catsearch(vol, HFS_CNID_ROOTPAR, data.u.dthd.thdCName,
        !           429:                       &data, cname, NULL) <= 0)
        !           430:        goto fail;
        !           431: 
        !           432:       r_unpackdirent(HFS_CNID_ROOTPAR, cname, &data, ent);
        !           433: 
        !           434:       dir->vptr = vol->next;
        !           435: 
        !           436:       goto done;
        !           437:     }
        !           438: 
        !           439:   if (dir->n.rnum == -1)
        !           440:     ERROR(ENOENT, "no more entries");
        !           441: 
        !           442:   while (1)
        !           443:     {
        !           444:       ++dir->n.rnum;
        !           445: 
        !           446:       while (dir->n.rnum >= dir->n.nd.ndNRecs)
        !           447:        {
        !           448:          if (dir->n.nd.ndFLink == 0)
        !           449:            {
        !           450:              dir->n.rnum = -1;
        !           451:              ERROR(ENOENT, "no more entries");
        !           452:            }
        !           453: 
        !           454:          if (bt_getnode(&dir->n, dir->n.bt, dir->n.nd.ndFLink) == -1)
        !           455:            {
        !           456:              dir->n.rnum = -1;
        !           457:              goto fail;
        !           458:            }
        !           459: 
        !           460:          dir->n.rnum = 0;
        !           461:        }
        !           462: 
        !           463:       ptr = HFS_NODEREC(dir->n, dir->n.rnum);
        !           464: 
        !           465:       r_unpackcatkey(ptr, &key);
        !           466: 
        !           467:       if (key.ckrParID != dir->dirid)
        !           468:        {
        !           469:          dir->n.rnum = -1;
        !           470:          ERROR(ENOENT, "no more entries");
        !           471:        }
        !           472: 
        !           473:       r_unpackcatdata(HFS_RECDATA(ptr), &data);
        !           474: 
        !           475:       switch (data.cdrType)
        !           476:        {
        !           477:        case cdrDirRec:
        !           478:        case cdrFilRec:
        !           479:          r_unpackdirent(key.ckrParID, key.ckrCName, &data, ent);
        !           480:          goto done;
        !           481: 
        !           482:        case cdrThdRec:
        !           483:        case cdrFThdRec:
        !           484:          break;
        !           485: 
        !           486:        default:
        !           487:          dir->n.rnum = -1;
        !           488:          ERROR(EIO, "unexpected directory entry found");
        !           489:        }
        !           490:     }
        !           491: 
        !           492: done:
        !           493:   return 0;
        !           494: 
        !           495: fail:
        !           496:   return -1;
        !           497: }
        !           498: 
        !           499: /*
        !           500:  * NAME:       hfs->closedir()
        !           501:  * DESCRIPTION:        stop reading a directory
        !           502:  */
        !           503: int hfs_closedir(hfsdir *dir)
        !           504: {
        !           505:   hfsvol *vol = dir->vol;
        !           506: 
        !           507:   if (dir->prev)
        !           508:     dir->prev->next = dir->next;
        !           509:   if (dir->next)
        !           510:     dir->next->prev = dir->prev;
        !           511:   if (dir == vol->dirs)
        !           512:     vol->dirs = dir->next;
        !           513: 
        !           514:   FREE(dir);
        !           515: 
        !           516:   return 0;
        !           517: }
        !           518: 
        !           519: /* High-Level File Routines ================================================ */
        !           520: 
        !           521: /*
        !           522:  * NAME:       hfs->open()
        !           523:  * DESCRIPTION:        prepare a file for I/O
        !           524:  */
        !           525: hfsfile *hfs_open(hfsvol *vol, const char *path)
        !           526: {
        !           527:   hfsfile *file = NULL;
        !           528: 
        !           529:   if (getvol(&vol) == -1)
        !           530:     goto fail;
        !           531: 
        !           532:   file = ALLOC(hfsfile, 1);
        !           533:   if (file == NULL)
        !           534:     ERROR(ENOMEM, NULL);
        !           535: 
        !           536:   if (v_resolve(&vol, path, &file->cat, &file->parid, file->name, NULL) <= 0)
        !           537:     goto fail;
        !           538: 
        !           539:   if (file->cat.cdrType != cdrFilRec)
        !           540:     ERROR(EISDIR, NULL);
        !           541: 
        !           542:   /* package file handle for user */
        !           543: 
        !           544:   file->vol   = vol;
        !           545:   file->flags = 0;
        !           546: 
        !           547:   f_selectfork(file, fkData);
        !           548: 
        !           549:   file->prev = NULL;
        !           550:   file->next = vol->files;
        !           551: 
        !           552:   if (vol->files)
        !           553:     vol->files->prev = file;
        !           554: 
        !           555:   vol->files = file;
        !           556: 
        !           557:   return file;
        !           558: 
        !           559: fail:
        !           560:   FREE(file);
        !           561:   return NULL;
        !           562: }
        !           563: 
        !           564: /*
        !           565:  * NAME:       hfs->setfork()
        !           566:  * DESCRIPTION:        select file fork for I/O operations
        !           567:  */
        !           568: int hfs_setfork(hfsfile *file, int fork)
        !           569: {
        !           570:   int result = 0;
        !           571: 
        !           572:   f_selectfork(file, fork ? fkRsrc : fkData);
        !           573: 
        !           574:   return result;
        !           575: }
        !           576: 
        !           577: /*
        !           578:  * NAME:       hfs->getfork()
        !           579:  * DESCRIPTION:        return the current fork for I/O operations
        !           580:  */
        !           581: int hfs_getfork(hfsfile *file)
        !           582: {
        !           583:   return file->fork != fkData;
        !           584: }
        !           585: 
        !           586: /*
        !           587:  * NAME:       hfs->read()
        !           588:  * DESCRIPTION:        read from an open file
        !           589:  */
        !           590: unsigned long hfs_read(hfsfile *file, void *buf, unsigned long len)
        !           591: {
        !           592:   unsigned long *lglen, count;
        !           593:   byte *ptr = buf;
        !           594: 
        !           595:   f_getptrs(file, NULL, &lglen, NULL);
        !           596: 
        !           597:   if (file->pos + len > *lglen)
        !           598:     len = *lglen - file->pos;
        !           599: 
        !           600:   count = len;
        !           601:   while (count)
        !           602:     {
        !           603:       unsigned long bnum, offs, chunk;
        !           604: 
        !           605:       bnum  = file->pos >> HFS_BLOCKSZ_BITS;
        !           606:       offs  = file->pos & (HFS_BLOCKSZ - 1);
        !           607: 
        !           608:       chunk = HFS_BLOCKSZ - offs;
        !           609:       if (chunk > count)
        !           610:        chunk = count;
        !           611: 
        !           612:       if (offs == 0 && chunk == HFS_BLOCKSZ)
        !           613:        {
        !           614:          if (f_getblock(file, bnum, (block *) ptr) == -1)
        !           615:            goto fail;
        !           616:        }
        !           617:       else
        !           618:        {
        !           619:          block b;
        !           620: 
        !           621:          if (f_getblock(file, bnum, &b) == -1)
        !           622:            goto fail;
        !           623: 
        !           624:          memcpy(ptr, b + offs, chunk);
        !           625:        }
        !           626: 
        !           627:       ptr += chunk;
        !           628: 
        !           629:       file->pos += chunk;
        !           630:       count     -= chunk;
        !           631:     }
        !           632: 
        !           633:   return len;
        !           634: 
        !           635: fail:
        !           636:   return -1;
        !           637: }
        !           638: 
        !           639: /*
        !           640:  * NAME:       hfs->seek()
        !           641:  * DESCRIPTION:        change file seek pointer
        !           642:  */
        !           643: unsigned long hfs_seek(hfsfile *file, long offset, int from)
        !           644: {
        !           645:   unsigned long *lglen, newpos;
        !           646: 
        !           647:   f_getptrs(file, NULL, &lglen, NULL);
        !           648: 
        !           649:   switch (from)
        !           650:     {
        !           651:     case HFS_SEEK_SET:
        !           652:       newpos = (offset < 0) ? 0 : offset;
        !           653:       break;
        !           654: 
        !           655:     case HFS_SEEK_CUR:
        !           656:       if (offset < 0 && (unsigned long) -offset > file->pos)
        !           657:        newpos = 0;
        !           658:       else
        !           659:        newpos = file->pos + offset;
        !           660:       break;
        !           661: 
        !           662:     case HFS_SEEK_END:
        !           663:       if (offset < 0 && (unsigned long) -offset > *lglen)
        !           664:        newpos = 0;
        !           665:       else
        !           666:        newpos = *lglen + offset;
        !           667:       break;
        !           668: 
        !           669:     default:
        !           670:       ERROR(EINVAL, NULL);
        !           671:     }
        !           672: 
        !           673:   if (newpos > *lglen)
        !           674:     newpos = *lglen;
        !           675: 
        !           676:   file->pos = newpos;
        !           677: 
        !           678:   return newpos;
        !           679: 
        !           680: fail:
        !           681:   return -1;
        !           682: }
        !           683: 
        !           684: /*
        !           685:  * NAME:       hfs->close()
        !           686:  * DESCRIPTION:        close a file
        !           687:  */
        !           688: int hfs_close(hfsfile *file)
        !           689: {
        !           690:   hfsvol *vol = file->vol;
        !           691:   int result = 0;
        !           692: 
        !           693:   if (file->prev)
        !           694:     file->prev->next = file->next;
        !           695:   if (file->next)
        !           696:     file->next->prev = file->prev;
        !           697:   if (file == vol->files)
        !           698:     vol->files = file->next;
        !           699: 
        !           700:   FREE(file);
        !           701: 
        !           702:   return result;
        !           703: }
        !           704: 
        !           705: /* High-Level Catalog Routines ============================================= */
        !           706: 
        !           707: /*
        !           708:  * NAME:       hfs->stat()
        !           709:  * DESCRIPTION:        return catalog information for an arbitrary path
        !           710:  */
        !           711: int hfs_stat(hfsvol *vol, const char *path, hfsdirent *ent)
        !           712: {
        !           713:   CatDataRec data;
        !           714:   unsigned long parid;
        !           715:   char name[HFS_MAX_FLEN + 1];
        !           716: 
        !           717:   if (getvol(&vol) == -1 ||
        !           718:       v_resolve(&vol, path, &data, &parid, name, NULL) <= 0)
        !           719:     goto fail;
        !           720: 
        !           721:   r_unpackdirent(parid, name, &data, ent);
        !           722: 
        !           723:   return 0;
        !           724: 
        !           725: fail:
        !           726:   return -1;
        !           727: }
        !           728: 
        !           729: /*
        !           730:  * NAME:       hfs->fstat()
        !           731:  * DESCRIPTION:        return catalog information for an open file
        !           732:  */
        !           733: int hfs_fstat(hfsfile *file, hfsdirent *ent)
        !           734: {
        !           735:   r_unpackdirent(file->parid, file->name, &file->cat, ent);
        !           736: 
        !           737:   return 0;
        !           738: }
        !           739: 
        !           740: /*
        !           741:  * NAME:       hfs->probe()
        !           742:  * DESCRIPTION:        return whether a HFS filesystem is present at the given offset
        !           743:  */
        !           744: int hfs_probe(int fd, long long offset)
        !           745: {
        !           746:   return v_probe(fd, offset);
        !           747: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.