xref: /netbsd-src/external/bsd/pdisk/dist/hfs_misc.c (revision 48a628ae0434c4247b560ad8f2eb1dc06d0dd070)
19428323dSchristos //
29428323dSchristos // hfs_misc.c - hfs routines
39428323dSchristos //
49428323dSchristos // Written by Eryk Vershen
59428323dSchristos //
69428323dSchristos 
79428323dSchristos /*
89428323dSchristos  * Copyright 2000 by Eryk Vershen
99428323dSchristos  */
109428323dSchristos 
119428323dSchristos // for *printf()
129428323dSchristos #include <stdio.h>
139428323dSchristos 
149428323dSchristos // for malloc(), calloc() & free()
159428323dSchristos #ifndef __linux__
169428323dSchristos #include <stdlib.h>
179428323dSchristos #else
189428323dSchristos #include <malloc.h>
199428323dSchristos #endif
209428323dSchristos 
219428323dSchristos // for strncpy() & strcmp()
229428323dSchristos #include <string.h>
239428323dSchristos // for O_RDONLY & O_RDWR
249428323dSchristos #include <fcntl.h>
259428323dSchristos // for errno
269428323dSchristos #include <errno.h>
279428323dSchristos 
28*48a628aeSchristos #include <inttypes.h>
29*48a628aeSchristos 
309428323dSchristos #include "hfs_misc.h"
319428323dSchristos #include "partition_map.h"
329428323dSchristos #include "convert.h"
339428323dSchristos #include "errors.h"
349428323dSchristos 
359428323dSchristos 
369428323dSchristos //
379428323dSchristos // Defines
389428323dSchristos //
399428323dSchristos #define MDB_OFFSET	2
409428323dSchristos #define HFS_SIG		0x4244	/* i.e 'BD' */
419428323dSchristos #define HFS_PLUS_SIG	0x482B	/* i.e 'H+' */
429428323dSchristos 
43*48a628aeSchristos #define get_align_long(x)	(*(uint32_t*)(x))
449428323dSchristos 
459428323dSchristos 
469428323dSchristos //
479428323dSchristos // Types
489428323dSchristos //
499428323dSchristos typedef long long u64;
509428323dSchristos 
519428323dSchristos typedef struct ExtDescriptor {		// extent descriptor
52*48a628aeSchristos     uint16_t	xdrStABN;	// first allocation block
53*48a628aeSchristos     uint16_t	xdrNumABlks;	// number of allocation blocks
549428323dSchristos } ext_descriptor;
559428323dSchristos 
569428323dSchristos typedef struct ExtDataRec {
579428323dSchristos     ext_descriptor	ed[3];	// extent data record
589428323dSchristos } ext_data_rec;
599428323dSchristos 
609428323dSchristos /*
61*48a628aeSchristos  * The crazy "uint16_t x[2]" stuff here is to get around the fact
629428323dSchristos  * that I can't convince the Mac compiler to align on 32 bit
639428323dSchristos  * quantities on 16 bit boundaries...
649428323dSchristos  */
659428323dSchristos struct mdb_record {		// master directory block
66*48a628aeSchristos     uint16_t	drSigWord;	// volume signature
67*48a628aeSchristos     uint16_t	drCrDate[2];	// date and time of volume creation
68*48a628aeSchristos     uint16_t	drLsMod[2];	// date and time of last modification
69*48a628aeSchristos     uint16_t	drAtrb;		// volume attributes
70*48a628aeSchristos     uint16_t	drNmFls;	// number of files in root directory
71*48a628aeSchristos     uint16_t	drVBMSt;	// first block of volume bitmap
72*48a628aeSchristos     uint16_t	drAllocPtr;	// start of next allocation search
73*48a628aeSchristos     uint16_t	drNmAlBlks;	// number of allocation blocks in volume
74*48a628aeSchristos     uint32_t	drAlBlkSiz;	// size (in bytes) of allocation blocks
75*48a628aeSchristos     uint32_t	drClpSiz;	// default clump size
76*48a628aeSchristos     uint16_t	drAlBlSt;	// first allocation block in volume
77*48a628aeSchristos     uint16_t	drNxtCNID[2];	// next unused catalog node ID
78*48a628aeSchristos     uint16_t	drFreeBks;	// number of unused allocation blocks
799428323dSchristos     char	drVN[28];	// volume name
80*48a628aeSchristos     uint16_t	drVolBkUp[2];	// date and time of last backup
81*48a628aeSchristos     uint16_t	drVSeqNum;	// volume backup sequence number
82*48a628aeSchristos     uint16_t	drWrCnt[2];	// volume write count
83*48a628aeSchristos     uint16_t	drXTClpSiz[2];	// clump size for extents overflow file
84*48a628aeSchristos     uint16_t	drCTClpSiz[2];	// clump size for catalog file
85*48a628aeSchristos     uint16_t	drNmRtDirs;	// number of directories in root directory
86*48a628aeSchristos     uint32_t	drFilCnt;	// number of files in volume
87*48a628aeSchristos     uint32_t	drDirCnt;	// number of directories in volume
88*48a628aeSchristos     uint32_t	drFndrInfo[8];	// information used by the Finder
899428323dSchristos #ifdef notdef
90*48a628aeSchristos     uint16_t	drVCSize;	// size (in blocks) of volume cache
91*48a628aeSchristos     uint16_t	drVBMCSize;	// size (in blocks) of volume bitmap cache
92*48a628aeSchristos     uint16_t	drCtlCSize;	// size (in blocks) of common volume cache
939428323dSchristos #else
94*48a628aeSchristos     uint16_t	drEmbedSigWord;	// type of embedded volume
959428323dSchristos     ext_descriptor	drEmbedExtent;	// embedded volume extent
969428323dSchristos #endif
97*48a628aeSchristos     uint16_t	drXTFlSize[2];	// size of extents overflow file
989428323dSchristos     ext_data_rec	drXTExtRec;	// extent record for extents overflow file
99*48a628aeSchristos     uint16_t	drCTFlSize[2];	// size of catalog file
1009428323dSchristos     ext_data_rec	drCTExtRec;	// extent record for catalog file
1019428323dSchristos };
1029428323dSchristos 
1039428323dSchristos 
104*48a628aeSchristos typedef uint32_t HFSCatalogNodeID;
1059428323dSchristos 
1069428323dSchristos typedef struct HFSPlusExtentDescriptor {
107*48a628aeSchristos     uint32_t startBlock;
108*48a628aeSchristos     uint32_t blockCount;
1099428323dSchristos } HFSPlusExtentDescriptor;
1109428323dSchristos 
1119428323dSchristos typedef HFSPlusExtentDescriptor HFSPlusExtentRecord[ 8];
1129428323dSchristos 
1139428323dSchristos typedef struct HFSPlusForkData {
1149428323dSchristos     u64 logicalSize;
115*48a628aeSchristos     uint32_t clumpSize;
116*48a628aeSchristos     uint32_t totalBlocks;
1179428323dSchristos     HFSPlusExtentRecord extents;
1189428323dSchristos } HFSPlusForkData;
1199428323dSchristos 
1209428323dSchristos struct HFSPlusVolumeHeader {
121*48a628aeSchristos     uint16_t signature;
122*48a628aeSchristos     uint16_t version;
123*48a628aeSchristos     uint32_t attributes;
124*48a628aeSchristos     uint32_t lastMountedVersion;
125*48a628aeSchristos     uint32_t reserved;
126*48a628aeSchristos     uint32_t createDate;
127*48a628aeSchristos     uint32_t modifyDate;
128*48a628aeSchristos     uint32_t backupDate;
129*48a628aeSchristos     uint32_t checkedDate;
130*48a628aeSchristos     uint32_t fileCount;
131*48a628aeSchristos     uint32_t folderCount;
132*48a628aeSchristos     uint32_t blockSize;
133*48a628aeSchristos     uint32_t totalBlocks;
134*48a628aeSchristos     uint32_t freeBlocks;
135*48a628aeSchristos     uint32_t nextAllocation;
136*48a628aeSchristos     uint32_t rsrcClumpSize;
137*48a628aeSchristos     uint32_t dataClumpSize;
1389428323dSchristos     HFSCatalogNodeID nextCatalogID;
139*48a628aeSchristos     uint32_t writeCount;
1409428323dSchristos     u64 encodingsBitmap;
141*48a628aeSchristos     uint8_t finderInfo[ 32];
1429428323dSchristos     HFSPlusForkData allocationFile;
1439428323dSchristos     HFSPlusForkData extentsFile;
1449428323dSchristos     HFSPlusForkData catalogFile;
1459428323dSchristos     HFSPlusForkData attributesFile;
1469428323dSchristos     HFSPlusForkData startupFile;
1479428323dSchristos } HFSPlusVolumeHeader;
1489428323dSchristos 
1499428323dSchristos 
1509428323dSchristos //
1519428323dSchristos // Global Constants
1529428323dSchristos //
1539428323dSchristos 
1549428323dSchristos 
1559428323dSchristos //
1569428323dSchristos // Global Variables
1579428323dSchristos //
1589428323dSchristos 
1599428323dSchristos 
1609428323dSchristos //
1619428323dSchristos // Forward declarations
1629428323dSchristos //
163*48a628aeSchristos uint32_t embeded_offset(struct mdb_record *mdb, uint32_t sector);
164*48a628aeSchristos int read_partition_block(partition_map *entry, uint32_t num, char *buf);
1659428323dSchristos 
1669428323dSchristos 
1679428323dSchristos //
1689428323dSchristos // Routines
1699428323dSchristos //
170*48a628aeSchristos uint32_t
embeded_offset(struct mdb_record * mdb,uint32_t sector)171*48a628aeSchristos embeded_offset(struct mdb_record *mdb, uint32_t sector)
1729428323dSchristos {
173*48a628aeSchristos     uint32_t e_offset;
1749428323dSchristos 
1759428323dSchristos     e_offset = mdb->drAlBlSt + mdb->drEmbedExtent.xdrStABN * (mdb->drAlBlkSiz / 512);
1769428323dSchristos 
1779428323dSchristos     return e_offset + sector;
1789428323dSchristos }
1799428323dSchristos 
1809428323dSchristos 
1819428323dSchristos char *
get_HFS_name(partition_map * entry,int * kind)1829428323dSchristos get_HFS_name(partition_map *entry, int *kind)
1839428323dSchristos {
1849428323dSchristos     DPME *data;
1859428323dSchristos     struct mdb_record *mdb;
1869428323dSchristos     //struct HFSPlusVolumeHeader *mdb2;
1879428323dSchristos     char *name = NULL;
1889428323dSchristos     int len;
1899428323dSchristos 
1909428323dSchristos     *kind = kHFS_not;
1919428323dSchristos 
1929428323dSchristos     mdb = (struct mdb_record *) malloc(PBLOCK_SIZE);
1939428323dSchristos     if (mdb == NULL) {
1949428323dSchristos 	error(errno, "can't allocate memory for MDB");
1959428323dSchristos 	return NULL;
1969428323dSchristos     }
1979428323dSchristos 
1989428323dSchristos     data = entry->data;
1999428323dSchristos     if (strcmp(data->dpme_type, kHFSType) == 0) {
2009428323dSchristos 	if (read_partition_block(entry, 2, (char *)mdb) == 0) {
201*48a628aeSchristos 	    error(-1, "Can't read block %d from partition %d", 2, entry->disk_address);
2029428323dSchristos 	    goto not_hfs;
2039428323dSchristos 	}
2049428323dSchristos 	if (mdb->drSigWord == HFS_PLUS_SIG) {
2059428323dSchristos 	    // pure HFS Plus
206*48a628aeSchristos 	    // printf("%lu HFS Plus\n", entry->disk_address);
2079428323dSchristos 	    *kind = kHFS_plus;
2089428323dSchristos 	} else if (mdb->drSigWord != HFS_SIG) {
2099428323dSchristos 	    // not HFS !!!
210*48a628aeSchristos 	    // printf("%"PRIu32" not HFS\n", entry->disk_address);
2119428323dSchristos 	    *kind = kHFS_not;
2129428323dSchristos 	} else if (mdb->drEmbedSigWord != HFS_PLUS_SIG) {
2139428323dSchristos 	    // HFS
214*48a628aeSchristos 	    // printf("%lu HFS\n", entry->disk_address);
2159428323dSchristos 	    *kind = kHFS_std;
2169428323dSchristos 	    len = mdb->drVN[0];
2179428323dSchristos 	    name = (char *) malloc(len+1);
2189428323dSchristos 	    strncpy(name, &mdb->drVN[1], len);
2199428323dSchristos 	    name[len] = 0;
2209428323dSchristos 	} else {
2219428323dSchristos 	    // embedded HFS plus
222*48a628aeSchristos 	    // printf("%lu embedded HFS Plus\n", entry->disk_address);
2239428323dSchristos 	    *kind = kHFS_embed;
2249428323dSchristos 	    len = mdb->drVN[0];
2259428323dSchristos 	    name = (char *) malloc(len+1);
2269428323dSchristos 	    strncpy(name, &mdb->drVN[1], len);
2279428323dSchristos 	    name[len] = 0;
2289428323dSchristos 	}
2299428323dSchristos     }
2309428323dSchristos not_hfs:
2319428323dSchristos     free(mdb);
2329428323dSchristos     return name;
2339428323dSchristos }
2349428323dSchristos 
2359428323dSchristos // really need a function to read block n from partition m
2369428323dSchristos 
2379428323dSchristos int
read_partition_block(partition_map * entry,uint32_t num,char * buf)238*48a628aeSchristos read_partition_block(partition_map *entry, uint32_t num, char *buf)
2399428323dSchristos {
2409428323dSchristos     DPME *data;
2419428323dSchristos     partition_map_header * map;
242*48a628aeSchristos     uint32_t base;
2439428323dSchristos     u64 offset;
2449428323dSchristos 
2459428323dSchristos     map = entry->the_map;
2469428323dSchristos     data = entry->data;
2479428323dSchristos     base = data->dpme_pblock_start;
2489428323dSchristos 
2499428323dSchristos     if (num >= data->dpme_pblocks) {
2509428323dSchristos 	return 0;
2519428323dSchristos     }
2529428323dSchristos     offset = ((long long) base) * map->logical_block + num * 512;
2539428323dSchristos 
2549428323dSchristos     return read_media(map->m, offset, 512, (void *)buf);
2559428323dSchristos }
256