xref: /netbsd/external/bsd/pdisk/dist/hfs_misc.c (revision 6f993757)
1 //
2 // hfs_misc.c - hfs routines
3 //
4 // Written by Eryk Vershen
5 //
6 
7 /*
8  * Copyright 2000 by Eryk Vershen
9  */
10 
11 // for *printf()
12 #include <stdio.h>
13 
14 // for malloc(), calloc() & free()
15 #ifndef __linux__
16 #include <stdlib.h>
17 #else
18 #include <malloc.h>
19 #endif
20 
21 // for strncpy() & strcmp()
22 #include <string.h>
23 // for O_RDONLY & O_RDWR
24 #include <fcntl.h>
25 // for errno
26 #include <errno.h>
27 
28 #include <inttypes.h>
29 
30 #include "hfs_misc.h"
31 #include "partition_map.h"
32 #include "convert.h"
33 #include "errors.h"
34 
35 
36 //
37 // Defines
38 //
39 #define MDB_OFFSET	2
40 #define HFS_SIG		0x4244	/* i.e 'BD' */
41 #define HFS_PLUS_SIG	0x482B	/* i.e 'H+' */
42 
43 #define get_align_long(x)	(*(uint32_t*)(x))
44 
45 
46 //
47 // Types
48 //
49 typedef long long u64;
50 
51 typedef struct ExtDescriptor {		// extent descriptor
52     uint16_t	xdrStABN;	// first allocation block
53     uint16_t	xdrNumABlks;	// number of allocation blocks
54 } ext_descriptor;
55 
56 typedef struct ExtDataRec {
57     ext_descriptor	ed[3];	// extent data record
58 } ext_data_rec;
59 
60 /*
61  * The crazy "uint16_t x[2]" stuff here is to get around the fact
62  * that I can't convince the Mac compiler to align on 32 bit
63  * quantities on 16 bit boundaries...
64  */
65 struct mdb_record {		// master directory block
66     uint16_t	drSigWord;	// volume signature
67     uint16_t	drCrDate[2];	// date and time of volume creation
68     uint16_t	drLsMod[2];	// date and time of last modification
69     uint16_t	drAtrb;		// volume attributes
70     uint16_t	drNmFls;	// number of files in root directory
71     uint16_t	drVBMSt;	// first block of volume bitmap
72     uint16_t	drAllocPtr;	// start of next allocation search
73     uint16_t	drNmAlBlks;	// number of allocation blocks in volume
74     uint32_t	drAlBlkSiz;	// size (in bytes) of allocation blocks
75     uint32_t	drClpSiz;	// default clump size
76     uint16_t	drAlBlSt;	// first allocation block in volume
77     uint16_t	drNxtCNID[2];	// next unused catalog node ID
78     uint16_t	drFreeBks;	// number of unused allocation blocks
79     char	drVN[28];	// volume name
80     uint16_t	drVolBkUp[2];	// date and time of last backup
81     uint16_t	drVSeqNum;	// volume backup sequence number
82     uint16_t	drWrCnt[2];	// volume write count
83     uint16_t	drXTClpSiz[2];	// clump size for extents overflow file
84     uint16_t	drCTClpSiz[2];	// clump size for catalog file
85     uint16_t	drNmRtDirs;	// number of directories in root directory
86     uint32_t	drFilCnt;	// number of files in volume
87     uint32_t	drDirCnt;	// number of directories in volume
88     uint32_t	drFndrInfo[8];	// information used by the Finder
89 #ifdef notdef
90     uint16_t	drVCSize;	// size (in blocks) of volume cache
91     uint16_t	drVBMCSize;	// size (in blocks) of volume bitmap cache
92     uint16_t	drCtlCSize;	// size (in blocks) of common volume cache
93 #else
94     uint16_t	drEmbedSigWord;	// type of embedded volume
95     ext_descriptor	drEmbedExtent;	// embedded volume extent
96 #endif
97     uint16_t	drXTFlSize[2];	// size of extents overflow file
98     ext_data_rec	drXTExtRec;	// extent record for extents overflow file
99     uint16_t	drCTFlSize[2];	// size of catalog file
100     ext_data_rec	drCTExtRec;	// extent record for catalog file
101 };
102 
103 
104 typedef uint32_t HFSCatalogNodeID;
105 
106 typedef struct HFSPlusExtentDescriptor {
107     uint32_t startBlock;
108     uint32_t blockCount;
109 } HFSPlusExtentDescriptor;
110 
111 typedef HFSPlusExtentDescriptor HFSPlusExtentRecord[ 8];
112 
113 typedef struct HFSPlusForkData {
114     u64 logicalSize;
115     uint32_t clumpSize;
116     uint32_t totalBlocks;
117     HFSPlusExtentRecord extents;
118 } HFSPlusForkData;
119 
120 struct HFSPlusVolumeHeader {
121     uint16_t signature;
122     uint16_t version;
123     uint32_t attributes;
124     uint32_t lastMountedVersion;
125     uint32_t reserved;
126     uint32_t createDate;
127     uint32_t modifyDate;
128     uint32_t backupDate;
129     uint32_t checkedDate;
130     uint32_t fileCount;
131     uint32_t folderCount;
132     uint32_t blockSize;
133     uint32_t totalBlocks;
134     uint32_t freeBlocks;
135     uint32_t nextAllocation;
136     uint32_t rsrcClumpSize;
137     uint32_t dataClumpSize;
138     HFSCatalogNodeID nextCatalogID;
139     uint32_t writeCount;
140     u64 encodingsBitmap;
141     uint8_t finderInfo[ 32];
142     HFSPlusForkData allocationFile;
143     HFSPlusForkData extentsFile;
144     HFSPlusForkData catalogFile;
145     HFSPlusForkData attributesFile;
146     HFSPlusForkData startupFile;
147 } HFSPlusVolumeHeader;
148 
149 
150 //
151 // Global Constants
152 //
153 
154 
155 //
156 // Global Variables
157 //
158 
159 
160 //
161 // Forward declarations
162 //
163 uint32_t embeded_offset(struct mdb_record *mdb, uint32_t sector);
164 int read_partition_block(partition_map *entry, uint32_t num, char *buf);
165 
166 
167 //
168 // Routines
169 //
170 uint32_t
embeded_offset(struct mdb_record * mdb,uint32_t sector)171 embeded_offset(struct mdb_record *mdb, uint32_t sector)
172 {
173     uint32_t e_offset;
174 
175     e_offset = mdb->drAlBlSt + mdb->drEmbedExtent.xdrStABN * (mdb->drAlBlkSiz / 512);
176 
177     return e_offset + sector;
178 }
179 
180 
181 char *
get_HFS_name(partition_map * entry,int * kind)182 get_HFS_name(partition_map *entry, int *kind)
183 {
184     DPME *data;
185     struct mdb_record *mdb;
186     //struct HFSPlusVolumeHeader *mdb2;
187     char *name = NULL;
188     int len;
189 
190     *kind = kHFS_not;
191 
192     mdb = (struct mdb_record *) malloc(PBLOCK_SIZE);
193     if (mdb == NULL) {
194 	error(errno, "can't allocate memory for MDB");
195 	return NULL;
196     }
197 
198     data = entry->data;
199     if (strcmp(data->dpme_type, kHFSType) == 0) {
200 	if (read_partition_block(entry, 2, (char *)mdb) == 0) {
201 	    error(-1, "Can't read block %d from partition %d", 2, entry->disk_address);
202 	    goto not_hfs;
203 	}
204 	if (mdb->drSigWord == HFS_PLUS_SIG) {
205 	    // pure HFS Plus
206 	    // printf("%lu HFS Plus\n", entry->disk_address);
207 	    *kind = kHFS_plus;
208 	} else if (mdb->drSigWord != HFS_SIG) {
209 	    // not HFS !!!
210 	    // printf("%"PRIu32" not HFS\n", entry->disk_address);
211 	    *kind = kHFS_not;
212 	} else if (mdb->drEmbedSigWord != HFS_PLUS_SIG) {
213 	    // HFS
214 	    // printf("%lu HFS\n", entry->disk_address);
215 	    *kind = kHFS_std;
216 	    len = mdb->drVN[0];
217 	    name = (char *) malloc(len+1);
218 	    strncpy(name, &mdb->drVN[1], len);
219 	    name[len] = 0;
220 	} else {
221 	    // embedded HFS plus
222 	    // printf("%lu embedded HFS Plus\n", entry->disk_address);
223 	    *kind = kHFS_embed;
224 	    len = mdb->drVN[0];
225 	    name = (char *) malloc(len+1);
226 	    strncpy(name, &mdb->drVN[1], len);
227 	    name[len] = 0;
228 	}
229     }
230 not_hfs:
231     free(mdb);
232     return name;
233 }
234 
235 // really need a function to read block n from partition m
236 
237 int
read_partition_block(partition_map * entry,uint32_t num,char * buf)238 read_partition_block(partition_map *entry, uint32_t num, char *buf)
239 {
240     DPME *data;
241     partition_map_header * map;
242     uint32_t base;
243     u64 offset;
244 
245     map = entry->the_map;
246     data = entry->data;
247     base = data->dpme_pblock_start;
248 
249     if (num >= data->dpme_pblocks) {
250 	return 0;
251     }
252     offset = ((long long) base) * map->logical_block + num * 512;
253 
254     return read_media(map->m, offset, 512, (void *)buf);
255 }
256