mirror of
https://github.com/fadden/ciderpress.git
synced 2024-11-27 08:49:20 +00:00
228 lines
7.5 KiB
C
228 lines
7.5 KiB
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$
|
|
*/
|
|
|
|
# include "hfs.h"
|
|
# include "apple.h"
|
|
|
|
//extern int errno;
|
|
# include <errno.h>
|
|
|
|
# define ERROR(code, str) \
|
|
do { hfs_error = (str), errno = (code); goto fail; } while (0)
|
|
|
|
# ifdef DEBUG
|
|
# define ASSERT(cond) do { if (! (cond)) abort(); } while (0)
|
|
# else
|
|
# define ASSERT(cond) /* nothing */
|
|
# endif
|
|
|
|
# define SIZE(type, n) ((size_t) (sizeof(type) * (n)))
|
|
# define ALLOC(type, n) ((type *) malloc(SIZE(type, n)))
|
|
# define ALLOCX(type, n) ((n) ? ALLOC(type, n) : (type *) 0)
|
|
# define FREE(ptr) ((ptr) ? (void) free((void *) ptr) : (void) 0)
|
|
|
|
# define REALLOC(ptr, type, n) \
|
|
((type *) ((ptr) ? realloc(ptr, SIZE(type, n)) : malloc(SIZE(type, n))))
|
|
# define REALLOCX(ptr, type, n) \
|
|
((n) ? REALLOC(ptr, type, n) : (FREE(ptr), (type *) 0))
|
|
|
|
# define BMTST(bm, num) \
|
|
(((const byte *) (bm))[(num) >> 3] & (0x80 >> ((num) & 0x07)))
|
|
# define BMSET(bm, num) \
|
|
(((byte *) (bm))[(num) >> 3] |= (0x80 >> ((num) & 0x07)))
|
|
# define BMCLR(bm, num) \
|
|
(((byte *) (bm))[(num) >> 3] &= ~(0x80 >> ((num) & 0x07)))
|
|
|
|
# define STRINGIZE(x) #x
|
|
# define STR(x) STRINGIZE(x)
|
|
|
|
typedef unsigned char byte;
|
|
typedef byte block[HFS_BLOCKSZ];
|
|
|
|
typedef struct _bucket_ {
|
|
int flags; /* bit flags */
|
|
unsigned int count; /* number of times this block is requested */
|
|
|
|
unsigned long bnum; /* logical block number */
|
|
block *data; /* pointer to block contents */
|
|
|
|
struct _bucket_ *cnext; /* next bucket in cache chain */
|
|
struct _bucket_ *cprev; /* previous bucket in cache chain */
|
|
|
|
struct _bucket_ *hnext; /* next bucket in hash chain */
|
|
struct _bucket_ **hprev; /* previous bucket's pointer to this bucket */
|
|
} bucket;
|
|
|
|
# define HFS_BUCKET_INUSE 0x01
|
|
# define HFS_BUCKET_DIRTY 0x02
|
|
|
|
# define HFS_CACHESZ 128
|
|
# define HFS_HASHSZ 32
|
|
# define HFS_BLOCKBUFSZ 16
|
|
|
|
typedef struct {
|
|
struct _hfsvol_ *vol; /* volume to which cache belongs */
|
|
bucket *tail; /* end of bucket chain */
|
|
|
|
unsigned int hits; /* number of cache hits */
|
|
unsigned int misses; /* number of cache misses */
|
|
|
|
bucket chain[HFS_CACHESZ]; /* cache bucket chain */
|
|
bucket *hash[HFS_HASHSZ]; /* hash table for bucket chain */
|
|
|
|
block pool[HFS_CACHESZ]; /* physical blocks in cache */
|
|
} bcache;
|
|
|
|
# define HFS_MAP1SZ 256
|
|
# define HFS_MAPXSZ 492
|
|
|
|
# define HFS_NODEREC(nd, rnum) ((nd).data + (nd).roff[rnum])
|
|
# define HFS_RECLEN(nd, rnum) ((nd).roff[(rnum) + 1] - (nd).roff[rnum])
|
|
|
|
# define HFS_RECKEYLEN(ptr) (*(const byte *) (ptr))
|
|
# define HFS_RECKEYSKIP(ptr) ((size_t) ((1 + HFS_RECKEYLEN(ptr) + 1) & ~1))
|
|
# define HFS_RECDATA(ptr) ((ptr) + HFS_RECKEYSKIP(ptr))
|
|
|
|
# define HFS_SETKEYLEN(ptr, x) (*(byte *) (ptr) = (x))
|
|
|
|
# define HFS_CATDATALEN sizeof(CatDataRec)
|
|
# define HFS_EXTDATALEN sizeof(ExtDataRec)
|
|
# define HFS_MAX_DATALEN (HFS_CATDATALEN > HFS_EXTDATALEN ? \
|
|
HFS_CATDATALEN : HFS_EXTDATALEN)
|
|
|
|
# define HFS_CATKEYLEN sizeof(CatKeyRec)
|
|
# define HFS_EXTKEYLEN sizeof(ExtKeyRec)
|
|
# define HFS_MAX_KEYLEN (HFS_CATKEYLEN > HFS_EXTKEYLEN ? \
|
|
HFS_CATKEYLEN : HFS_EXTKEYLEN)
|
|
|
|
# define HFS_MAX_CATRECLEN (HFS_CATKEYLEN + HFS_CATDATALEN)
|
|
# define HFS_MAX_EXTRECLEN (HFS_EXTKEYLEN + HFS_EXTDATALEN)
|
|
# define HFS_MAX_RECLEN (HFS_MAX_KEYLEN + HFS_MAX_DATALEN)
|
|
|
|
# define HFS_SIGWORD 0x4244
|
|
# define HFS_SIGWORD_MFS ((Integer) 0xd2d7)
|
|
|
|
# define HFS_ATRB_BUSY (1 << 6)
|
|
# define HFS_ATRB_HLOCKED (1 << 7)
|
|
# define HFS_ATRB_UMOUNTED (1 << 8)
|
|
# define HFS_ATRB_BBSPARED (1 << 9)
|
|
# define HFS_ATRB_BVINCONSIS (1 << 11)
|
|
# define HFS_ATRB_COPYPROT (1 << 14)
|
|
# define HFS_ATRB_SLOCKED (1 << 15)
|
|
|
|
struct _hfsfile_ {
|
|
struct _hfsvol_ *vol; /* pointer to volume descriptor */
|
|
unsigned long parid; /* parent directory ID of this file */
|
|
char name[HFS_MAX_FLEN + 1]; /* catalog name of this file */
|
|
CatDataRec cat; /* catalog information */
|
|
ExtDataRec ext; /* current extent record */
|
|
unsigned int fabn; /* starting file allocation block number */
|
|
int fork; /* current selected fork for I/O */
|
|
unsigned long pos; /* current file seek pointer */
|
|
int flags; /* bit flags */
|
|
|
|
struct _hfsfile_ *prev;
|
|
struct _hfsfile_ *next;
|
|
};
|
|
|
|
# define HFS_FILE_UPDATE_CATREC 0x01
|
|
|
|
# define HFS_MAX_NRECS 35 /* maximum based on minimum record size */
|
|
|
|
typedef struct _node_ {
|
|
struct _btree_ *bt; /* btree to which this node belongs */
|
|
unsigned long nnum; /* node index */
|
|
NodeDescriptor nd; /* node descriptor */
|
|
int rnum; /* current record index */
|
|
UInteger roff[HFS_MAX_NRECS + 1];
|
|
/* record offsets */
|
|
block data; /* raw contents of node */
|
|
} node;
|
|
|
|
struct _hfsdir_ {
|
|
struct _hfsvol_ *vol; /* associated volume */
|
|
unsigned long dirid; /* directory ID of interest (or 0) */
|
|
|
|
node n; /* current B*-tree node */
|
|
struct _hfsvol_ *vptr; /* current volume pointer */
|
|
|
|
struct _hfsdir_ *prev;
|
|
struct _hfsdir_ *next;
|
|
};
|
|
|
|
typedef void (*keyunpackfunc)(const byte *, void *);
|
|
typedef int (*keycomparefunc)(const void *, const void *);
|
|
|
|
typedef struct _btree_ {
|
|
hfsfile f; /* subset file information */
|
|
node hdrnd; /* header node */
|
|
BTHdrRec hdr; /* header record */
|
|
byte *map; /* usage bitmap */
|
|
unsigned long mapsz; /* number of bytes in bitmap */
|
|
int flags; /* bit flags */
|
|
|
|
keyunpackfunc keyunpack; /* key unpacking function */
|
|
keycomparefunc keycompare; /* key comparison function */
|
|
} btree;
|
|
|
|
# define HFS_BT_UPDATE_HDR 0x01
|
|
|
|
struct _hfsvol_ {
|
|
void *priv; /* OS-dependent private descriptor data */
|
|
int flags; /* bit flags */
|
|
|
|
int pnum; /* ordinal HFS partition number */
|
|
unsigned long vstart; /* logical block offset to start of volume */
|
|
unsigned long vlen; /* number of logical blocks in volume */
|
|
unsigned int lpa; /* number of logical blocks per allocation block */
|
|
|
|
bcache *cache; /* cache of recently used blocks */
|
|
|
|
MDB mdb; /* master directory block */
|
|
block *vbm; /* volume bitmap */
|
|
unsigned short vbmsz; /* number of blocks in bitmap */
|
|
|
|
btree ext; /* B*-tree control block for extents overflow file */
|
|
btree cat; /* B*-tree control block for catalog file */
|
|
|
|
unsigned long cwd; /* directory id of current working directory */
|
|
|
|
int refs; /* number of external references to this volume */
|
|
hfsfile *files; /* list of open files */
|
|
hfsdir *dirs; /* list of open directories */
|
|
|
|
struct _hfsvol_ *prev;
|
|
struct _hfsvol_ *next;
|
|
};
|
|
|
|
# define HFS_VOL_OPEN 0x0001
|
|
# define HFS_VOL_MOUNTED 0x0002
|
|
# define HFS_VOL_READONLY 0x0004
|
|
# define HFS_VOL_USINGCACHE 0x0008
|
|
|
|
# define HFS_VOL_UPDATE_MDB 0x0010
|
|
# define HFS_VOL_UPDATE_ALTMDB 0x0020
|
|
# define HFS_VOL_UPDATE_VBM 0x0040
|
|
|
|
# define HFS_VOL_OPT_MASK 0xff00
|
|
|
|
extern hfsvol *hfs_mounts;
|