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

📄 hfs.c

📁 创建一个符合iso-9660标准的iso文件系统
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * hfsutils - tools for reading and writing Macintosh HFS volumes * Copyright (C) 1996, 1997 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. *//* APPLE_HYB James Pearson j.pearson@ps.ucl.ac.uk 16/7/97 */#include <mconfig.h>#include <stdxlib.h>#include <unixstd.h>#include <fcntl.h>#include <errno.h>#include <strdefs.h>#include <time.h>#include <ctype.h>#include <sys/stat.h>#include "internal.h"#include "data.h"#include "block.h"#include "low.h"#include "file.h"#include "btree.h"#include "node.h"#include "record.h"#include "volume.h"char *hfs_error = "no error";	/* static error string */hfsvol *hfs_mounts;		/* linked list of mounted volumes */hfsvol *hfs_curvol;		/* current volume *//* High-Level Volume Routines ============================================== *//* * NAME:	hfs->mount() * DESCRIPTION:	open an HFS volume; return volume descriptor or 0 (error) */#ifdef APPLE_HYBhfsvol *hfs_mount(hce, pnum, flags)	hce_mem	*hce;	int	pnum;	int	flags;#elsehfsvol *hfs_mount(path, pnum, flags)	char	*path;	int	pnum;	int	flags;#endif /* APPLE_HYB */{#ifndef APPLE_HYB  struct stat dev;#endif  hfsvol *vol = 0;#ifndef APPLE_HYB  /* see if the volume is already mounted */  if (stat(path, &dev) >= 0)    {      struct stat mdev;      hfsvol *check;      for (check = hfs_mounts; check; check = check->next)	{	  if (fstat(check->fd, &mdev) >= 0 &&	      mdev.st_dev == dev.st_dev &&	      mdev.st_ino == dev.st_ino &&	      (check->pnum == 0 || check->pnum == pnum))	    {	      /* verify compatible read/write mode */	      if (((check->flags & HFS_READONLY) &&		   ! (flags & O_WRONLY)) ||		  (! (check->flags & HFS_READONLY) &&		   (flags & (O_WRONLY | O_RDWR))))		{		  vol = check;		  break;		}	    }	}    }#endif /* APPLE_HYB */  if (vol == 0)    {      vol = ALLOC(hfsvol, 1);      if (vol == 0)	{	  ERROR(ENOMEM, 0);	  return 0;	}      vol->flags  = 0;      vol->pnum   = pnum;      vol->vstart = 0;      vol->vlen   = 0;      vol->lpa    = 0;      vol->vbm    = 0;      vol->cwd    = HFS_CNID_ROOTDIR;      vol->refs   = 0;      vol->files  = 0;      vol->dirs   = 0;      vol->prev   = 0;      vol->next   = 0;      vol->ext.map     = 0;      vol->ext.mapsz   = 0;      vol->ext.flags   = 0;      vol->ext.compare = r_compareextkeys;      vol->cat.map     = 0;      vol->cat.mapsz   = 0;      vol->cat.flags   = 0;      vol->cat.compare = r_comparecatkeys;      /* open and lock the device */#ifdef APPLE_HYB      vol->fd = 3;			/* any +ve number will do? */      vol->hce = hce;			/* store the extra with the vol info */#else      if (flags & (O_WRONLY | O_RDWR))	{	  vol->fd = open(path, O_RDWR);	  if (vol->fd >= 0 && l_lockvol(vol) < 0)	    {	      close(vol->fd);	      vol->fd = -2;	    }	}      if (! (flags & (O_WRONLY | O_RDWR)) ||	  (vol->fd < 0 &&	   (errno == EROFS || errno == EACCES || errno == EAGAIN) &&	   (flags & O_RDWR)))	{	  vol->flags |= HFS_READONLY;	  vol->fd = open(path, O_RDONLY);	  if (vol->fd >= 0 && l_lockvol(vol) < 0)	    {	      close(vol->fd);	      vol->fd = -2;	    }	}      if (vol->fd < 0)	{	  if (vol->fd != -2)	    ERROR(errno, "error opening device");	  v_destruct(vol);	  return 0;	}#endif /* APPLE_HYB */      /* find out what kind of media this is and read the MDB */      if (l_readblock0(vol) < 0 ||	  l_readmdb(vol) < 0)	{#ifndef APPLE_HYB	  close(vol->fd);	  v_destruct(vol);#endif /* APPLE_HYB */	  return 0;	}      /* verify this is an HFS volume */      if (vol->mdb.drSigWord != 0x4244)	{#ifndef APPLE_HYB	  close(vol->fd);#endif /* APPLE_HYB */	  v_destruct(vol);	  ERROR(EINVAL, "not a Macintosh HFS volume");	  return 0;	}      /* do minimal consistency checks */      if (vol->mdb.drAlBlkSiz % HFS_BLOCKSZ != 0)	{#ifndef APPLE_HYB	  close(vol->fd);#endif /* APPLE_HYB */	  v_destruct(vol);	  ERROR(EINVAL, "bad volume allocation block size");	  return 0;	}      if (vol->vlen == 0)	vol->vlen = vol->mdb.drAlBlSt +	  vol->mdb.drNmAlBlks * (vol->mdb.drAlBlkSiz / HFS_BLOCKSZ) + 2;      /* read the volume bitmap and extents/catalog B*-tree headers */      if (l_readvbm(vol) < 0 ||	  bt_readhdr(&vol->ext) < 0 ||	  bt_readhdr(&vol->cat) < 0)	{#ifndef APPLE_HYB	  close(vol->fd);#endif /* APPLE_HYB */	  v_destruct(vol);	  return 0;	}      if (! (vol->mdb.drAtrb & HFS_ATRB_UMOUNTED))	{	  /* volume was not cleanly unmounted; scavenge free-space */	  if (v_scavenge(vol) < 0)	    {#ifndef APPLE_HYB	      close(vol->fd);#endif /* APPLE_HYB */	      v_destruct(vol);	      return 0;	    }	}      if (vol->flags & HFS_READONLY)	vol->mdb.drAtrb |= HFS_ATRB_HLOCKED;      else	vol->mdb.drAtrb &= ~HFS_ATRB_HLOCKED;      vol->prev = 0;      vol->next = hfs_mounts;      if (hfs_mounts)	hfs_mounts->prev = vol;      hfs_mounts = vol;    }  ++vol->refs;  return hfs_curvol = vol;}/* * NAME:	hfs->flush() * DESCRIPTION:	flush all pending changes to an HFS volume */int hfs_flush(vol)	hfsvol	*vol;{  hfsfile *file;  if (v_getvol(&vol) < 0)    return -1;  for (file = vol->files; file; file = file->next)    {      if (f_flush(file) < 0)	return -1;    }  if (v_flush(vol, 0) < 0)    return -1;  return 0;}/* * NAME:	hfs->flushall() * DESCRIPTION:	flush all pending changes to all mounted HFS volumes */void hfs_flushall(){  hfsvol *vol;  for (vol = hfs_mounts; vol; vol = vol->next)    hfs_flush(vol);}/* * NAME:	hfs->umount() * DESCRIPTION:	close an HFS volume */#ifdef APPLE_HYB/* extra argument used to alter the position of the extents/catalog files */int hfs_umount(vol, end)	hfsvol	*vol;	long	end;#elseint hfs_umount(vol)	hfsvol	*vol;#endif /* APPLE_HYB */{  int result = 0;  if (v_getvol(&vol) < 0)    return -1;  if (--vol->refs)    return v_flush(vol, 0);  /* close all open files and directories */  while (vol->files)#ifdef APPLE_HYB    hfs_close(vol->files, 0, 0);#else    hfs_close(vol->files);#endif /* APPLE_HYB */  while (vol->dirs)    hfs_closedir(vol->dirs);#ifdef APPLE_HYB  if (end)  {	/*  move extents and catalog to end of volume ... */  	long vbmsz = (vol->vlen / vol->lpa + 4095) / 4096;	/* we are adding this "files" to the end of the ISO volume,	   so calculate this address in HFS speak ... *//*	end -= vol->mdb.drAlBlSt; */	end -= (vol->mdb.drAlBlSt + vol->hce->hfs_map_size);	end /= vol->lpa;	/* catalog file ... */	vol->ext.f.cat.u.fil.filExtRec[0].xdrStABN = end; 	vol->mdb.drXTExtRec[0].xdrStABN = end;	/* move postition to start of extents file */	end += vol->cat.f.cat.u.fil.filExtRec[0].xdrStABN;	/* extents file ... */	vol->cat.f.cat.u.fil.filExtRec[0].xdrStABN = end;	vol->mdb.drCTExtRec[0].xdrStABN = end;	/* the volume bitmap is wrong as we have "moved" files	   about - simple just set the whole lot (it's a readonly volume	   anyway!) */	memset(vol->vbm, 0xff, vbmsz*HFS_BLOCKSZ);	/* set the free blocks to zero */	vol->mdb.drFreeBks = 0;	/* flag changes for flushing later */	vol->flags |= HFS_UPDATE_VBM;	vol->flags |= HFS_UPDATE_MDB;	vol->mdb.drAtrb |= HFS_ATRB_HLOCKED;	vol->ext.flags |= HFS_UPDATE_BTHDR;	vol->cat.flags |= HFS_UPDATE_BTHDR;  }#endif /* APPLE_HYB */  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 */  if (vol->prev)    vol->prev->next = vol->next;  if (vol->next)    vol->next->prev = vol->prev;  if (vol == hfs_mounts)    hfs_mounts = vol->next;  if (vol == hfs_curvol)    hfs_curvol = 0;  v_destruct(vol);  return result;}/* * NAME:	hfs->umountall() * DESCRIPTION:	unmount all mounted volumes */void hfs_umountall(){  while (hfs_mounts)#ifdef APPLE_HYB    continue;#else    hfs_umount(hfs_mounts);#endif /* APPLE_HYB */}/* * NAME:	hfs->getvol() * DESCRIPTION:	return a pointer to a mounted volume */hfsvol *hfs_getvol(name)	char	*name;{  hfsvol *vol;  if (name == 0)    return hfs_curvol;  for (vol = hfs_mounts; vol; vol = vol->next)    {      if (d_relstring(name, vol->mdb.drVN) == 0)	return vol;    }  return 0;}/* * NAME:	hfs->setvol() * DESCRIPTION:	change the current volume */void hfs_setvol(vol)	hfsvol	*vol;{  hfs_curvol = vol;}/* * NAME:	hfs->vstat() * DESCRIPTION:	return volume statistics */int hfs_vstat(vol, ent)	hfsvol	*vol;	hfsvolent *ent;{  if (v_getvol(&vol) < 0)    return -1;  strcpy(ent->name, vol->mdb.drVN);  ent->flags     = (vol->flags & HFS_READONLY) ? HFS_ISLOCKED : 0;  ent->totbytes  = vol->mdb.drNmAlBlks * vol->mdb.drAlBlkSiz;  ent->freebytes = vol->mdb.drFreeBks  * vol->mdb.drAlBlkSiz;  ent->crdate    = d_toutime(vol->mdb.drCrDate);  ent->mddate    = d_toutime(vol->mdb.drLsMod);  return 0;}/* * NAME:	hfs->format() * DESCRIPTION:	write a new filesystem */#ifdef APPLE_HYBint hfs_format(hce, pnum, vname)	hce_mem	*hce;	int	pnum;	char	*vname;#elseint hfs_format(path, pnum, vname)	char	*path;	int	pnum;	char	*vname;#endif /* APPLE_HYB */{  hfsvol vol;  btree *ext = &vol.ext;  btree *cat = &vol.cat;  unsigned int vbmsz;  int i, result = 0;  block vbm[16];  char *map;  if (strchr(vname, ':'))    {      ERROR(EINVAL, "volume name may not contain colons");      return -1;    }  i = strlen(vname);  if (i < 1 || i > HFS_MAX_VLEN)    {      ERROR(EINVAL, "volume name must be 1-27 chars");      return -1;    }  vol.flags  = 0;  vol.pnum   = pnum;  vol.vstart = 0;  vol.vlen   = 0;  vol.lpa    = 0;  vol.vbm    = vbm;  vol.cwd    = HFS_CNID_ROOTDIR;  vol.refs   = 0;  vol.files  = 0;  vol.dirs   = 0;  vol.prev   = 0;  vol.next   = 0;#ifndef APPLE_HYB  vol.fd = open(path, O_RDWR);  if (vol.fd < 0)    {      ERROR(errno, "error opening device for writing");      return -1;    }  if (l_lockvol(&vol) < 0)    {      close(vol.fd);      return -1;    }#endif /* APPLE_HYB */  if (pnum > 0)    {      if (l_readpm(&vol) < 0)	{	  close(vol.fd);	  return -1;	}    }  else  /* determine size of entire device */    {#ifdef APPLE_HYB      vol.vlen = hce->hfs_vol_size/HFS_BLOCKSZ;#else      unsigned long low, high, mid;      block b;      for (low = 0, high = 2879; b_readlb(&vol, high, &b) >= 0; high *= 2)	low = high;      while (low < high - 1)	{	  mid = (low + high) / 2;	  if (b_readlb(&vol, mid, &b) < 0)	    high = mid;	  else	    low = mid;	}      vol.vlen = low + 1;#endif /* APPLE_HYB */    }  if (vol.vlen < 800 * 1024 / HFS_BLOCKSZ)    {#ifndef APPLE_HYB      close(vol.fd);#endif /* APPLE_HYB */      ERROR(EINVAL, "volume size must be >= 800K");      return -1;    }  /* initialize volume geometry */#ifdef APPLE_HYB  /* force lpa to be a multiple of 4 (i.e. 2048/512) - as calculated      earlier */  vol.lpa = hce->Csize/HFS_BLOCKSZ;#else  vol.lpa = 1 + vol.vlen / 65536;#endif /* APPLE_HYB */  vbmsz = (vol.vlen / vol.lpa + 4095) / 4096;  vol.mdb.drSigWord  = 0x4244;  vol.mdb.drCrDate   = d_tomtime(time(0));  vol.mdb.drLsMod    = vol.mdb.drCrDate;  vol.mdb.drAtrb     = 0;  vol.mdb.drNmFls    = 0;  vol.mdb.drVBMSt    = 3;  vol.mdb.drAllocPtr = 0;  vol.mdb.drNmAlBlks = (vol.vlen - 5 - vbmsz) / vol.lpa;  vol.mdb.drAlBlkSiz = vol.lpa * HFS_BLOCKSZ;  vol.mdb.drClpSiz   = vol.mdb.drAlBlkSiz * 4;  vol.mdb.drAlBlSt   = 3 + vbmsz;#ifdef APPLE_HYB  /* round up start block to a muliple of lpa - important later *//*vol.mdb.drAlBlSt   = ((vol.mdb.drAlBlSt + vol.lpa -  1) / vol.lpa) * vol.lpa; */  /* take in accout alignment of files wrt HFS volume start i.e we want     drAlBlSt plus hfs_map_size to me a multiple of lpa */  vol.mdb.drAlBlSt   = ((vol.mdb.drAlBlSt + hce->hfs_map_size + vol.lpa -  1) / vol.lpa) * vol.lpa;   vol.mdb.drAlBlSt   -= hce->hfs_map_size;#endif /* APPLE_HYB */  vol.mdb.drNxtCNID  = HFS_CNID_ROOTDIR;  /* modified later */  vol.mdb.drFreeBks  = vol.mdb.drNmAlBlks;  strcpy(vol.mdb.drVN, vname);  vol.mdb.drVolBkUp  = 0;  vol.mdb.drVSeqNum  = 0;  vol.mdb.drWrCnt    = 0;  vol.mdb.drXTClpSiz = vol.mdb.drNmAlBlks / 128 * vol.mdb.drAlBlkSiz;#ifdef APPLE_HYB  /* adjust size of extents/catalog upwards as we may have rounded up     allocation size */  i = 1 + vol.vlen / 65536;  vol.mdb.drXTClpSiz = (vol.mdb.drXTClpSiz * vol.lpa) / i;  /* round up to lpa size */  vol.mdb.drXTClpSiz = ((vol.mdb.drXTClpSiz + vol.mdb.drAlBlkSiz - 1) /				vol.mdb.drAlBlkSiz) * vol.mdb.drAlBlkSiz;  /* ignore above, use what we have already calculated ... */  vol.mdb.drXTClpSiz = hce->XTCsize;  /* make Catalog file CTC (default twice) as big - prevents further allocation     later which we don't want - this seems to work OK ... *//*vol.mdb.drCTClpSiz = vol.mdb.drXTClpSiz * CTC; */  vol.mdb.drCTClpSiz = vol.mdb.drXTClpSiz * hce->ctc_size;  /* we want to put things at the end of the volume later, so we'll     cheat here ... shouldn't matter, as we only need the volume read     only anyway (we won't be adding files later!) - leave some extra     space for the alternative MDB (in the last allocation block) */  vol.mdb.drNmAlBlks = vol.mdb.drFreeBks = vol.vlen / vol.lpa - 1;#else  vol.mdb.drCTClpSiz = vol.mdb.drXTClpSiz;#endif /* APPLE_HYB */  vol.mdb.drNmRtDirs = 0;  vol.mdb.drFilCnt   = 0;  vol.mdb.drDirCnt   = -1;  /* incremented when root folder is created */  for (i = 0; i < 8; ++i)    vol.mdb.drFndrInfo[i] = 0;  vol.mdb.drVCSize   = 0;  vol.mdb.drVBMCSize = 0;  vol.mdb.drCtlCSize = 0;  vol.mdb.drXTFlSize = 0;  vol.mdb.drCTFlSize = 0;  for (i = 0; i < 3; ++i)    {      vol.mdb.drXTExtRec[i].xdrStABN    = 0;      vol.mdb.drXTExtRec[i].xdrNumABlks = 0;      vol.mdb.drCTExtRec[i].xdrStABN    = 0;      vol.mdb.drCTExtRec[i].xdrNumABlks = 0;    }  /* initialize volume bitmap */  memset(vol.vbm, 0, sizeof(vbm));#ifdef APPLE_HYB  /* We don't want to write anything out at the moment, so we allocate     memory to hold the HFS "header" info and extents/catalog files.     Any reads/writes from/to these parts of the volume are trapped and     stored in memory. */  /* blocks up to the first unallocated block == HFS "header" info     This will be placed in the first 32kb of the ISO volume later */  hce->hfs_hdr_size = vol.mdb.drAlBlSt;  /* size of the extents and catalog files. This will be added     to the end of the ISO volume later */  hce->hfs_ce_size =  vol.mdb.drXTClpSiz + vol.mdb.drCTClpSiz;  /* we also allocate space for the Desktop file and the alternative     MDB while we're here */  FREE(hce->hfs_ce);  hce->hfs_ce = ALLOC(unsigned char, (hce->hfs_ce_size + vol.mdb.drClpSiz					+ vol.mdb.drAlBlkSiz));  /* allocate memory for the map and hdr */  FREE(hce->hfs_map);  hce->hfs_map = ALLOC(unsigned char, ((hce->hfs_hdr_size + hce->hfs_map_size)			*HFS_BLOCKSZ));  if (hce->hfs_ce == 0 || hce->hfs_map == 0)    {      ERROR(ENOMEM, 0);      result = -1;    }  /* hfs_hdr is immediately after the hfs_map */  hce->hfs_hdr = hce->hfs_map + hce->hfs_map_size*HFS_BLOCKSZ;  /* size needed in HFS_BLOCKSZ blocks for later use */  hce->hfs_ce_size /= HFS_BLOCKSZ;  /* note size of Desktop file */  hce->hfs_dt_size = vol.mdb.drClpSiz/HFS_BLOCKSZ;  /* total size of catalog/extents and desktop */  hce->hfs_tot_size = hce->hfs_ce_size + hce->hfs_dt_size;  /* alternative MDB in the last alocation block */  hce->hfs_alt_mdb = hce->hfs_ce + hce->hfs_tot_size*HFS_BLOCKSZ;  /* add the MDB to the total size */  hce->hfs_tot_size += vol.lpa;

⌨️ 快捷键说明

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