1 | /*␊ |
2 | * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.␊ |
3 | *␊ |
4 | * @APPLE_LICENSE_HEADER_START@␊ |
5 | * ␊ |
6 | * The contents of this file constitute Original Code as defined in and␊ |
7 | * are subject to the Apple Public Source License Version 2.0 (the␊ |
8 | * "License"). You may not use this file except in compliance with the␊ |
9 | * License. Please obtain a copy of the License at␊ |
10 | * http://www.apple.com/publicsource and read it before using this file.␊ |
11 | * ␊ |
12 | * This Original Code and all software distributed under the License are␊ |
13 | * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER␊ |
14 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,␊ |
15 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,␊ |
16 | * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the␊ |
17 | * License for the specific language governing rights and limitations␊ |
18 | * under the License.␊ |
19 | * ␊ |
20 | * @APPLE_LICENSE_HEADER_END@␊ |
21 | */␊ |
22 | /*␊ |
23 | * Written by Paul Popelka (paulp@uts.amdahl.com)␊ |
24 | *␊ |
25 | * You can do anything you want with this software, just don't say you wrote␊ |
26 | * it, and don't remove this notice.␊ |
27 | *␊ |
28 | * This software is provided "as is".␊ |
29 | *␊ |
30 | * The author supplies this software to be publicly redistributed on the␊ |
31 | * understanding that the author is not responsible for the correct␊ |
32 | * functioning of this software in any circumstances and is not liable for␊ |
33 | * any damages caused by this software.␊ |
34 | *␊ |
35 | * October 1992␊ |
36 | */␊ |
37 | ␊ |
38 | /*␊ |
39 | * Format of a boot sector. This is the first sector on a DOS floppy disk␊ |
40 | * or the fist sector of a partition on a hard disk. But, it is not the␊ |
41 | * first sector of a partitioned hard disk.␊ |
42 | */␊ |
43 | struct bootsector33 {␊ |
44 | ␉u_int8_t␉bsJump[3];␉␉/* jump inst E9xxxx or EBxx90 */␊ |
45 | ␉int8_t␉␉bsOemName[8];␉␉/* OEM name and version */␊ |
46 | ␉int8_t␉␉bsBPB[19];␉␉/* BIOS parameter block */␊ |
47 | ␉int8_t␉␉bsDriveNumber;␉␉/* drive number (0x80) */␊ |
48 | ␉int8_t␉␉bsBootCode[479];␉/* pad so struct is 512b */␊ |
49 | ␉u_int8_t␉bsBootSectSig0;␊ |
50 | ␉u_int8_t␉bsBootSectSig1;␊ |
51 | #define␉BOOTSIG0␉0x55␊ |
52 | #define␉BOOTSIG1␉0xaa␊ |
53 | };␊ |
54 | ␊ |
55 | struct extboot {␊ |
56 | ␉int8_t␉␉exDriveNumber;␉␉/* drive number (0x80) */␊ |
57 | ␉int8_t␉␉exReserved1;␉␉/* reserved */␊ |
58 | ␉int8_t␉␉exBootSignature;␉/* ext. boot signature (0x29) */␊ |
59 | #define␉EXBOOTSIG␉0x29␊ |
60 | ␉int8_t␉␉exVolumeID[4];␉␉/* volume ID number */␊ |
61 | ␉int8_t␉␉exVolumeLabel[11];␉/* volume label */␊ |
62 | ␉int8_t␉␉exFileSysType[8];␉/* fs type (FAT12 or FAT16) */␊ |
63 | };␊ |
64 | ␊ |
65 | struct bootsector50 {␊ |
66 | ␉u_int8_t␉bsJump[3];␉␉/* jump inst E9xxxx or EBxx90 */␊ |
67 | ␉int8_t␉␉bsOemName[8];␉␉/* OEM name and version */␊ |
68 | ␉int8_t␉␉bsBPB[25];␉␉/* BIOS parameter block */␊ |
69 | ␉int8_t␉␉bsExt[26];␉␉/* Bootsector Extension */␊ |
70 | ␉int8_t␉␉bsBootCode[448];␉/* pad so structure is 512b */␊ |
71 | ␉u_int8_t␉bsBootSectSig0;␊ |
72 | ␉u_int8_t␉bsBootSectSig1;␊ |
73 | #define␉BOOTSIG0␉0x55␊ |
74 | #define␉BOOTSIG1␉0xaa␊ |
75 | };␊ |
76 | ␊ |
77 | struct bootsector710 {␊ |
78 | ␉u_int8_t␉bsJump[3];␉␉/* jump inst E9xxxx or EBxx90 */␊ |
79 | ␉int8_t␉␉bsOEMName[8];␉␉/* OEM name and version */␊ |
80 | ␉int8_t␉␉bsBPB[53];␉␉/* BIOS parameter block */␊ |
81 | ␉int8_t␉␉bsExt[26];␉␉/* Bootsector Extension */␊ |
82 | ␉int8_t␉␉bsBootCode[420];␉/* pad so structure is 512b */␊ |
83 | ␉u_int8_t␉bsBootSectSig0;␊ |
84 | ␉u_int8_t␉bsBootSectSig1;␊ |
85 | #define␉BOOTSIG0␉0x55␊ |
86 | #define␉BOOTSIG1␉0xaa␊ |
87 | };␊ |
88 | ␊ |
89 | union bootsector {␊ |
90 | ␉struct bootsector33 bs33;␊ |
91 | ␉struct bootsector50 bs50;␊ |
92 | ␉struct bootsector710 bs710;␊ |
93 | };␊ |
94 | ␊ |
95 | ␊ |
96 | /* BPB */␊ |
97 | ␊ |
98 | /*␊ |
99 | * BIOS Parameter Block (BPB) for DOS 3.3␊ |
100 | */␊ |
101 | struct bpb33 {␊ |
102 | ␉u_int16_t␉bpbBytesPerSec;␉/* bytes per sector */␊ |
103 | ␉u_int8_t␉bpbSecPerClust;␉/* sectors per cluster */␊ |
104 | ␉u_int16_t␉bpbResSectors;␉/* number of reserved sectors */␊ |
105 | ␉u_int8_t␉bpbFATs;␉/* number of FATs */␊ |
106 | ␉u_int16_t␉bpbRootDirEnts;␉/* number of root directory entries */␊ |
107 | ␉u_int16_t␉bpbSectors;␉/* total number of sectors */␊ |
108 | ␉u_int8_t␉bpbMedia;␉/* media descriptor */␊ |
109 | ␉u_int16_t␉bpbFATsecs;␉/* number of sectors per FAT */␊ |
110 | ␉u_int16_t␉bpbSecPerTrack;␉/* sectors per track */␊ |
111 | ␉u_int16_t␉bpbHeads;␉/* number of heads */␊ |
112 | ␉u_int16_t␉bpbHiddenSecs;␉/* number of hidden sectors */␊ |
113 | } __attribute__((packed));␊ |
114 | ␊ |
115 | /*␊ |
116 | * BPB for DOS 5.0 The difference is bpbHiddenSecs is a short for DOS 3.3,␊ |
117 | * and bpbHugeSectors is not in the 3.3 bpb.␊ |
118 | */␊ |
119 | struct bpb50 {␊ |
120 | ␉u_int16_t␉bpbBytesPerSec;␉/* bytes per sector */␊ |
121 | ␉u_int8_t␉bpbSecPerClust;␉/* sectors per cluster */␊ |
122 | ␉u_int16_t␉bpbResSectors;␉/* number of reserved sectors */␊ |
123 | ␉u_int8_t␉bpbFATs;␉/* number of FATs */␊ |
124 | ␉u_int16_t␉bpbRootDirEnts;␉/* number of root directory entries */␊ |
125 | ␉u_int16_t␉bpbSectors;␉/* total number of sectors */␊ |
126 | ␉u_int8_t␉bpbMedia;␉/* media descriptor */␊ |
127 | ␉u_int16_t␉bpbFATsecs;␉/* number of sectors per FAT */␊ |
128 | ␉u_int16_t␉bpbSecPerTrack;␉/* sectors per track */␊ |
129 | ␉u_int16_t␉bpbHeads;␉/* number of heads */␊ |
130 | ␉u_int32_t␉bpbHiddenSecs;␉/* # of hidden sectors */␊ |
131 | ␉u_int32_t␉bpbHugeSectors;␉/* # of sectors if bpbSectors == 0 */␊ |
132 | } __attribute__((packed));␊ |
133 | ␊ |
134 | /*␊ |
135 | * BPB for DOS 7.10 (FAT32). This one has a few extensions to bpb50.␊ |
136 | */␊ |
137 | struct bpb710 {␊ |
138 | ␉u_int16_t␉bpbBytesPerSec;␉/* bytes per sector */␊ |
139 | ␉u_int8_t␉bpbSecPerClust;␉/* sectors per cluster */␊ |
140 | ␉u_int16_t␉bpbResSectors;␉/* number of reserved sectors */␊ |
141 | ␉u_int8_t␉bpbFATs;␉/* number of FATs */␊ |
142 | ␉u_int16_t␉bpbRootDirEnts;␉/* number of root directory entries */␊ |
143 | ␉u_int16_t␉bpbSectors;␉/* total number of sectors */␊ |
144 | ␉u_int8_t␉bpbMedia;␉/* media descriptor */␊ |
145 | ␉u_int16_t␉bpbFATsecs;␉/* number of sectors per FAT */␊ |
146 | ␉u_int16_t␉bpbSecPerTrack;␉/* sectors per track */␊ |
147 | ␉u_int16_t␉bpbHeads;␉/* number of heads */␊ |
148 | ␉u_int32_t␉bpbHiddenSecs;␉/* # of hidden sectors */␊ |
149 | ␉u_int32_t␉bpbHugeSectors;␉/* # of sectors if bpbSectors == 0 */␊ |
150 | ␉u_int32_t␉bpbBigFATsecs;␉/* like bpbFATsecs for FAT32 */␊ |
151 | ␉u_int16_t␉bpbExtFlags;␉/* extended flags: */␊ |
152 | #define␉FATNUM␉␉0xf␉␉/* mask for numbering active FAT */␊ |
153 | #define␉FATMIRROR␉0x80␉␉/* FAT is mirrored (like it always was) */␊ |
154 | ␉u_int16_t␉bpbFSVers;␉/* filesystem version */␊ |
155 | #define␉FSVERS␉␉0␉␉/* currently only 0 is understood */␊ |
156 | ␉u_int32_t␉bpbRootClust;␉/* start cluster for root directory */␊ |
157 | ␉u_int16_t␉bpbFSInfo;␉/* filesystem info structure sector */␊ |
158 | ␉u_int16_t␉bpbBackup;␉/* backup boot sector */␊ |
159 | ␉/* There is a 12 byte filler here, but we ignore it */␊ |
160 | } __attribute__((packed));␊ |
161 | ␊ |
162 | #if 0␊ |
163 | /*␊ |
164 | * BIOS Parameter Block (BPB) for DOS 3.3␊ |
165 | */␊ |
166 | struct byte_bpb33 {␊ |
167 | ␉int8_t bpbBytesPerSec[2];␉/* bytes per sector */␊ |
168 | ␉int8_t bpbSecPerClust;␉␉/* sectors per cluster */␊ |
169 | ␉int8_t bpbResSectors[2];␉/* number of reserved sectors */␊ |
170 | ␉int8_t bpbFATs;␉␉␉/* number of FATs */␊ |
171 | ␉int8_t bpbRootDirEnts[2];␉/* number of root directory entries */␊ |
172 | ␉int8_t bpbSectors[2];␉␉/* total number of sectors */␊ |
173 | ␉int8_t bpbMedia;␉␉/* media descriptor */␊ |
174 | ␉int8_t bpbFATsecs[2];␉␉/* number of sectors per FAT */␊ |
175 | ␉int8_t bpbSecPerTrack[2];␉/* sectors per track */␊ |
176 | ␉int8_t bpbHeads[2];␉␉/* number of heads */␊ |
177 | ␉int8_t bpbHiddenSecs[2];␉/* number of hidden sectors */␊ |
178 | };␊ |
179 | ␊ |
180 | /*␊ |
181 | * BPB for DOS 5.0 The difference is bpbHiddenSecs is a short for DOS 3.3,␊ |
182 | * and bpbHugeSectors is not in the 3.3 bpb.␊ |
183 | */␊ |
184 | struct byte_bpb50 {␊ |
185 | ␉int8_t bpbBytesPerSec[2];␉/* bytes per sector */␊ |
186 | ␉int8_t bpbSecPerClust;␉␉/* sectors per cluster */␊ |
187 | ␉int8_t bpbResSectors[2];␉/* number of reserved sectors */␊ |
188 | ␉int8_t bpbFATs;␉␉␉/* number of FATs */␊ |
189 | ␉int8_t bpbRootDirEnts[2];␉/* number of root directory entries */␊ |
190 | ␉int8_t bpbSectors[2];␉␉/* total number of sectors */␊ |
191 | ␉int8_t bpbMedia;␉␉/* media descriptor */␊ |
192 | ␉int8_t bpbFATsecs[2];␉␉/* number of sectors per FAT */␊ |
193 | ␉int8_t bpbSecPerTrack[2];␉/* sectors per track */␊ |
194 | ␉int8_t bpbHeads[2];␉␉/* number of heads */␊ |
195 | ␉int8_t bpbHiddenSecs[4];␉/* number of hidden sectors */␊ |
196 | ␉int8_t bpbHugeSectors[4];␉/* # of sectors if bpbSectors == 0 */␊ |
197 | };␊ |
198 | ␊ |
199 | /*␊ |
200 | * BPB for DOS 7.10 (FAT32). This one has a few extensions to bpb50.␊ |
201 | */␊ |
202 | struct byte_bpb710 {␊ |
203 | ␉u_int8_t bpbBytesPerSec[2];␉/* bytes per sector */␊ |
204 | ␉u_int8_t bpbSecPerClust;␉/* sectors per cluster */␊ |
205 | ␉u_int8_t bpbResSectors[2];␉/* number of reserved sectors */␊ |
206 | ␉u_int8_t bpbFATs;␉␉/* number of FATs */␊ |
207 | ␉u_int8_t bpbRootDirEnts[2];␉/* number of root directory entries */␊ |
208 | ␉u_int8_t bpbSectors[2];␉␉/* total number of sectors */␊ |
209 | ␉u_int8_t bpbMedia;␉␉/* media descriptor */␊ |
210 | ␉u_int8_t bpbFATsecs[2];␉␉/* number of sectors per FAT */␊ |
211 | ␉u_int8_t bpbSecPerTrack[2];␉/* sectors per track */␊ |
212 | ␉u_int8_t bpbHeads[2];␉␉/* number of heads */␊ |
213 | ␉u_int8_t bpbHiddenSecs[4];␉/* # of hidden sectors */␊ |
214 | ␉u_int8_t bpbHugeSectors[4];␉/* # of sectors if bpbSectors == 0 */␊ |
215 | ␉u_int8_t bpbBigFATsecs[4];␉/* like bpbFATsecs for FAT32 */␊ |
216 | ␉u_int8_t bpbExtFlags[2];␉/* extended flags: */␊ |
217 | ␉u_int8_t bpbFSVers[2];␉␉/* filesystem version */␊ |
218 | ␉u_int8_t bpbRootClust[4];␉/* start cluster for root directory */␊ |
219 | ␉u_int8_t bpbFSInfo[2];␉␉/* filesystem info structure sector */␊ |
220 | ␉u_int8_t bpbBackup[2];␉␉/* backup boot sector */␊ |
221 | ␉/* There is a 12 byte filler here, but we ignore it */␊ |
222 | };␊ |
223 | #endif␊ |
224 | ␊ |
225 | /*␊ |
226 | * FAT32 FSInfo block.␊ |
227 | */␊ |
228 | struct fsinfo {␊ |
229 | ␉u_int8_t fsisig1[4];␊ |
230 | ␉u_int8_t fsifill1[480];␊ |
231 | ␉u_int8_t fsisig2[4];␊ |
232 | ␉u_int8_t fsinfree[4];␊ |
233 | ␉u_int8_t fsinxtfree[4];␊ |
234 | ␉u_int8_t fsifill2[12];␊ |
235 | ␉u_int8_t fsisig3[4];␊ |
236 | };␊ |
237 | ␊ |
238 | ␊ |
239 | /* direntry */␊ |
240 | ␊ |
241 | /*-␊ |
242 | * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank.␊ |
243 | * Copyright (C) 1994, 1995, 1997 TooLs GmbH.␊ |
244 | * All rights reserved.␊ |
245 | * Original code by Paul Popelka (paulp@uts.amdahl.com) (see above).␊ |
246 | *␊ |
247 | * Redistribution and use in source and binary forms, with or without␊ |
248 | * modification, are permitted provided that the following conditions␊ |
249 | * are met:␊ |
250 | * 1. Redistributions of source code must retain the above copyright␊ |
251 | * notice, this list of conditions and the following disclaimer.␊ |
252 | * 2. Redistributions in binary form must reproduce the above copyright␊ |
253 | * notice, this list of conditions and the following disclaimer in the␊ |
254 | * documentation and/or other materials provided with the distribution.␊ |
255 | * 3. All advertising materials mentioning features or use of this software␊ |
256 | * must display the following acknowledgement:␊ |
257 | *␉This product includes software developed by TooLs GmbH.␊ |
258 | * 4. The name of TooLs GmbH may not be used to endorse or promote products␊ |
259 | * derived from this software without specific prior written permission.␊ |
260 | *␊ |
261 | * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR␊ |
262 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES␊ |
263 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.␊ |
264 | * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,␊ |
265 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,␊ |
266 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;␊ |
267 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,␊ |
268 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR␊ |
269 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF␊ |
270 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.␊ |
271 | */␊ |
272 | ␊ |
273 | /*␊ |
274 | * Structure of a dos directory entry.␊ |
275 | */␊ |
276 | struct direntry {␊ |
277 | ␉u_int8_t␉deName[8];␉/* filename, blank filled */␊ |
278 | #define␉SLOT_EMPTY␉0x00␉␉/* slot has never been used */␊ |
279 | #define␉SLOT_E5␉␉0x05␉␉/* the real value is 0xe5 */␊ |
280 | #define␉SLOT_DELETED␉0xe5␉␉/* file in this slot deleted */␊ |
281 | ␉u_int8_t␉deExtension[3];␉/* extension, blank filled */␊ |
282 | ␉u_int8_t␉deAttributes;␉/* file attributes */␊ |
283 | #define␉ATTR_NORMAL␉0x00␉␉/* normal file */␊ |
284 | #define␉ATTR_READONLY␉0x01␉␉/* file is read-only (immutable) */␊ |
285 | #define␉ATTR_HIDDEN␉0x02␉␉/* file is hidden */␊ |
286 | #define␉ATTR_SYSTEM␉0x04␉␉/* file is a system file */␊ |
287 | #define␉ATTR_VOLUME␉0x08␉␉/* entry is a volume label */␊ |
288 | #define␉ATTR_DIRECTORY␉0x10␉␉/* entry is a directory name */␊ |
289 | #define␉ATTR_ARCHIVE␉0x20␉␉/* file is new or modified */␊ |
290 | ␉u_int8_t␉deLowerCase;␉/* NT VFAT lower case flags */␊ |
291 | #define␉LCASE_BASE␉0x08␉␉/* filename base in lower case */␊ |
292 | #define␉LCASE_EXT␉0x10␉␉/* filename extension in lower case */␊ |
293 | ␉u_int8_t␉deCHundredth;␉/* hundredth of seconds in CTime */␊ |
294 | ␉u_int8_t␉deCTime[2];␉/* create time */␊ |
295 | ␉u_int8_t␉deCDate[2];␉/* create date */␊ |
296 | ␉u_int8_t␉deADate[2];␉/* access date */␊ |
297 | ␉u_int8_t␉deHighClust[2];␉/* high bytes of cluster number */␊ |
298 | ␉u_int16_t␉deMTime;␉/* last update time */␊ |
299 | ␉u_int16_t␉deMDate;␉/* last update date */␊ |
300 | ␉u_int8_t␉deStartCluster[2]; /* starting cluster of file */␊ |
301 | ␉u_int8_t␉deFileSize[4];␉/* size of file in bytes */␊ |
302 | };␊ |
303 | ␊ |
304 | /*␊ |
305 | * Structure of a Win95 long name directory entry␊ |
306 | */␊ |
307 | struct winentry {␊ |
308 | ␉u_int8_t␉weCnt;␊ |
309 | #define␉WIN_LAST␉0x40␊ |
310 | #define␉WIN_CNT␉␉0x3f␊ |
311 | ␉u_int8_t␉wePart1[10];␊ |
312 | ␉u_int8_t␉weAttributes;␊ |
313 | #define␉ATTR_WIN95␉0x0f␊ |
314 | ␉u_int8_t␉weReserved1;␊ |
315 | ␉u_int8_t␉weChksum;␊ |
316 | ␉u_int8_t␉wePart2[12];␊ |
317 | ␉u_int16_t␉weReserved2;␊ |
318 | ␉u_int8_t␉wePart3[4];␊ |
319 | };␊ |
320 | #define␉WIN_CHARS␉13␉/* Number of chars per winentry */␊ |
321 | ␊ |
322 | /*␊ |
323 | * Maximum filename length in Win95␊ |
324 | * Note: Must be < sizeof(dirent.d_name)␊ |
325 | */␊ |
326 | #define␉WIN_MAXLEN␉255␊ |
327 | ␊ |
328 | /*␊ |
329 | * This is the format of the contents of the deTime field in the direntry␊ |
330 | * structure.␊ |
331 | * We don't use bitfields because we don't know how compilers for␊ |
332 | * arbitrary machines will lay them out.␊ |
333 | */␊ |
334 | #define DT_2SECONDS_MASK␉0x1F␉/* seconds divided by 2 */␊ |
335 | #define DT_2SECONDS_SHIFT␉0␊ |
336 | #define DT_MINUTES_MASK␉␉0x7E0␉/* minutes */␊ |
337 | #define DT_MINUTES_SHIFT␉5␊ |
338 | #define DT_HOURS_MASK␉␉0xF800␉/* hours */␊ |
339 | #define DT_HOURS_SHIFT␉␉11␊ |
340 | ␊ |
341 | /*␊ |
342 | * This is the format of the contents of the deDate field in the direntry␊ |
343 | * structure.␊ |
344 | */␊ |
345 | #define DD_DAY_MASK␉␉0x1F␉/* day of month */␊ |
346 | #define DD_DAY_SHIFT␉␉0␊ |
347 | #define DD_MONTH_MASK␉␉0x1E0␉/* month */␊ |
348 | #define DD_MONTH_SHIFT␉␉5␊ |
349 | #define DD_YEAR_MASK␉␉0xFE00␉/* year - 1980 */␊ |
350 | #define DD_YEAR_SHIFT␉␉9␊ |
351 | ␊ |
352 | |