⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 volume.c

📁 open source bios with linux platform, very good and can be reused.
💻 C
字号:
/* * 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., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Id: volume.c,v 1.12 1998/11/02 22:09:10 rob Exp $ */#include "openbios/config.h"#include "libhfs.h"#include "volume.h"#include "data.h"#include "block.h"#include "low.h"#include "medium.h"#include "file.h"#include "btree.h"#include "record.h"#include "os.h"/* * NAME:	vol->init() * DESCRIPTION:	initialize volume structure */void v_init(hfsvol *vol, int flags){  btree *ext = &vol->ext;  btree *cat = &vol->cat;  vol->os_fd       = 0;  vol->flags      = flags & HFS_VOL_OPT_MASK;  vol->pnum       = -1;  vol->vstart     = 0;  vol->vlen       = 0;  vol->lpa        = 0;  vol->cache      = 0;  vol->vbm        = 0;  vol->vbmsz      = 0;  f_init(&ext->f, vol, HFS_CNID_EXT, "extents overflow");  ext->map        = 0;  ext->mapsz      = 0;  ext->flags      = 0;  ext->keyunpack  = (keyunpackfunc)  r_unpackextkey;  ext->keycompare = (keycomparefunc) r_compareextkeys;  f_init(&cat->f, vol, HFS_CNID_CAT, "catalog");  cat->map        = 0;  cat->mapsz      = 0;  cat->flags      = 0;  cat->keyunpack  = (keyunpackfunc)  r_unpackcatkey;  cat->keycompare = (keycomparefunc) r_comparecatkeys;  vol->cwd        = HFS_CNID_ROOTDIR;  vol->refs       = 0;  vol->files      = 0;  vol->dirs       = 0;  vol->prev       = 0;  vol->next       = 0;}/* * NAME:	vol->open() * DESCRIPTION:	open volume source and lock against concurrent updates */int v_open(hfsvol *vol, int os_fd ){  if (vol->flags & HFS_VOL_OPEN)    ERROR(EINVAL, "volume already open");  vol->flags |= HFS_VOL_OPEN;  vol->os_fd = os_fd;  /* initialize volume block cache (OK to fail) */  if (! (vol->flags & HFS_OPT_NOCACHE) &&      b_init(vol) != -1)    vol->flags |= HFS_VOL_USINGCACHE;  return 0;fail:  return -1;}/* * NAME:	vol->close() * DESCRIPTION:	close access path to volume source */int v_close(hfsvol *vol){  int result = 0;  if (! (vol->flags & HFS_VOL_OPEN))    goto done;  if ((vol->flags & HFS_VOL_USINGCACHE) &&      b_finish(vol) == -1)    result = -1;  vol->flags &= ~(HFS_VOL_OPEN | HFS_VOL_MOUNTED | HFS_VOL_USINGCACHE);  /* free dynamically allocated structures */  FREE(vol->vbm);  vol->vbm   = 0;  vol->vbmsz = 0;  FREE(vol->ext.map);  FREE(vol->cat.map);  vol->ext.map = 0;  vol->cat.map = 0;done:  return result;}/* * NAME:	vol->same() * DESCRIPTION:	return 1 iff path is same as open volume */int v_same(hfsvol *vol, int os_fd ){  return vol->os_fd == os_fd;}/* * NAME:	vol->geometry() * DESCRIPTION:	determine volume location and size (possibly in a partition) */int v_geometry(hfsvol *vol, int pnum){  Partition map;  unsigned long bnum = 0;  int found;  vol->pnum = pnum;  if (pnum == 0)    {      vol->vstart = 0;      vol->vlen   = b_size(vol);      if (vol->vlen == 0)	goto fail;    }  else    {      while (pnum--)	{	  found = m_findpmentry(vol, "Apple_HFS", &map, &bnum);	  if (found == -1 || ! found)	    goto fail;	}      vol->vstart = map.pmPyPartStart;      vol->vlen   = map.pmPartBlkCnt;      if (map.pmDataCnt)	{	  if ((unsigned long) map.pmLgDataStart +	      (unsigned long) map.pmDataCnt > vol->vlen)	    ERROR(EINVAL, "partition data overflows partition");	  vol->vstart += (unsigned long) map.pmLgDataStart;	  vol->vlen    = map.pmDataCnt;	}      if (vol->vlen == 0)	ERROR(EINVAL, "volume partition is empty");    }  if (vol->vlen < 800 * (1024 >> HFS_BLOCKSZ_BITS))    ERROR(EINVAL, "volume is smaller than 800K");  return 0;fail:  return -1;}/* * 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;  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;  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:	vol->readvbm() * DESCRIPTION:	read volume bitmap into memory */int v_readvbm(hfsvol *vol){  unsigned int vbmst = vol->mdb.drVBMSt;  unsigned int vbmsz = (vol->mdb.drNmAlBlks + 0x0fff) >> 12;  block *bp;  ASSERT(vol->vbm == 0);  if (vol->mdb.drAlBlSt - vbmst < vbmsz)    ERROR(EIO, "volume bitmap collides with volume data");  vol->vbm = ALLOC(block, vbmsz);  if (vol->vbm == 0)    ERROR(ENOMEM, 0);  vol->vbmsz = vbmsz;  for (bp = vol->vbm; vbmsz--; ++bp)    {      if (b_readlb(vol, vbmst++, bp) == -1)	goto fail;    }  return 0;fail:  FREE(vol->vbm);  vol->vbm   = 0;  vol->vbmsz = 0;  return -1;}/* * NAME:	vol->mount() * DESCRIPTION:	load volume information into memory */int v_mount(hfsvol *vol){  /* read the MDB, volume bitmap, and extents/catalog B*-tree headers */  if (v_readmdb(vol) == -1 ||      v_readvbm(vol) == -1 ||      bt_readhdr(&vol->ext) == -1 ||      bt_readhdr(&vol->cat) == -1)    goto fail;  if (vol->mdb.drAtrb & HFS_ATRB_SLOCKED)    vol->flags |= HFS_VOL_READONLY;  else if (vol->flags & HFS_VOL_READONLY)    vol->mdb.drAtrb |= HFS_ATRB_HLOCKED;  else    vol->mdb.drAtrb &= ~HFS_ATRB_HLOCKED;  vol->flags |= HFS_VOL_MOUNTED;  return 0;fail:  return -1;}/* * NAME:	vol->catsearch() * DESCRIPTION:	search catalog tree */int v_catsearch(hfsvol *vol, unsigned long parid, const char *name,		CatDataRec *data, char *cname, node *np){  CatKeyRec key;  byte pkey[HFS_CATKEYLEN];  const byte *ptr;  node n;  int found;  if (np == 0)    np = &n;  r_makecatkey(&key, parid, name);  r_packcatkey(&key, pkey, 0);  found = bt_search(&vol->cat, pkey, np);  if (found <= 0)    return found;  ptr = HFS_NODEREC(*np, np->rnum);  if (cname)    {      r_unpackcatkey(ptr, &key);      strcpy(cname, key.ckrCName);    }  if (data)    r_unpackcatdata(HFS_RECDATA(ptr), data);  return 1;}/* * NAME:	vol->extsearch() * DESCRIPTION:	search extents tree */int v_extsearch(hfsfile *file, unsigned int fabn,		ExtDataRec *data, node *np){  ExtKeyRec key;  ExtDataRec extsave;  unsigned int fabnsave;  byte pkey[HFS_EXTKEYLEN];  const byte *ptr;  node n;  int found;  if (np == 0)    np = &n;  r_makeextkey(&key, file->fork, file->cat.u.fil.filFlNum, fabn);  r_packextkey(&key, pkey, 0);  /* in case bt_search() clobbers these */  memcpy(&extsave, &file->ext, sizeof(ExtDataRec));  fabnsave = file->fabn;  found = bt_search(&file->vol->ext, pkey, np);  memcpy(&file->ext, &extsave, sizeof(ExtDataRec));  file->fabn = fabnsave;  if (found <= 0)    return found;  if (data)    {      ptr = HFS_NODEREC(*np, np->rnum);      r_unpackextdata(HFS_RECDATA(ptr), data);    }  return 1;}/* * NAME:	vol->getthread() * DESCRIPTION:	retrieve catalog thread information for a file or directory */int v_getthread(hfsvol *vol, unsigned long id,		CatDataRec *thread, node *np, int type){  CatDataRec rec;  int found;  if (thread == 0)    thread = &rec;  found = v_catsearch(vol, id, "", thread, 0, np);  if (found == 1 && thread->cdrType != type)    ERROR(EIO, "bad thread record");  return found;fail:  return -1;}/* * NAME:	vol->resolve() * DESCRIPTION:	translate a pathname; return catalog information */int v_resolve(hfsvol **vol, const char *path,	      CatDataRec *data, long *parid, char *fname, node *np){  unsigned long dirid;  char name[HFS_MAX_FLEN + 1], *nptr;  int found = 0;  if (*path == 0)    ERROR(ENOENT, "empty path");  if (parid)    *parid = 0;  nptr = strchr(path, ':');  if (*path == ':' || nptr == 0)    {      dirid = (*vol)->cwd;  /* relative path */      if (*path == ':')	++path;      if (*path == 0)	{	  found = v_getdthread(*vol, dirid, data, 0);	  if (found == -1)	    goto fail;	  if (found)	    {	      if (parid)		*parid = data->u.dthd.thdParID;	      found = v_catsearch(*vol, data->u.dthd.thdParID,				  data->u.dthd.thdCName, data, fname, np);	      if (found == -1)		goto fail;	    }	  goto done;	}    }  else    {      hfsvol *check;      dirid = HFS_CNID_ROOTPAR;  /* absolute path */      if (nptr - path > HFS_MAX_VLEN)	ERROR(ENAMETOOLONG, 0);      strncpy(name, path, nptr - path);      name[nptr - path] = 0;      for (check = hfs_mounts; check; check = check->next)	{	  if (d_relstring(check->mdb.drVN, name) == 0)	    {	      *vol = check;	      break;	    }	}    }  while (1)    {      while (*path == ':')	{	  ++path;	  found = v_getdthread(*vol, dirid, data, 0);	  if (found == -1)	    goto fail;	  else if (! found)	    goto done;	  dirid = data->u.dthd.thdParID;	}      if (*path == 0)	{	  found = v_getdthread(*vol, dirid, data, 0);	  if (found == -1)	    goto fail;	  if (found)	    {	      if (parid)		*parid = data->u.dthd.thdParID;	      found = v_catsearch(*vol, data->u.dthd.thdParID,				  data->u.dthd.thdCName, data, fname, np);	      if (found == -1)		goto fail;	    }	  goto done;	}      nptr = name;      while (nptr < name + sizeof(name) - 1 && *path && *path != ':')	*nptr++ = *path++;      if (*path && *path != ':')	ERROR(ENAMETOOLONG, 0);      *nptr = 0;      if (*path == ':')	++path;      if (parid)	*parid = dirid;      found = v_catsearch(*vol, dirid, name, data, fname, np);      if (found == -1)	goto fail;      if (! found)	{	  if (*path && parid)	    *parid = 0;	  if (*path == 0 && fname)	    strcpy(fname, name);	  goto done;	}      switch (data->cdrType)	{	case cdrDirRec:	  if (*path == 0)	    goto done;	  dirid = data->u.dir.dirDirID;	  break;	case cdrFilRec:	  if (*path == 0)	    goto done;	  ERROR(ENOTDIR, "invalid pathname");	default:	  ERROR(EIO, "unexpected catalog record");	}    }done:  return found;fail:  return -1;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -