2 * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
30 * fs.c - Generic access to the file system modules.
32 * Copyright (c) 1999-2004 Apple Computer, Inc.
40 typedef long (* FSLoadFile
)(CICell ih
, char *filePath
);
41 typedef long (* FSReadFile
)(CICell ih
, char *filePath
,
42 void *base
, unsigned long offset
,
43 unsigned long length
);
44 typedef long (* FSGetDirEntry
)(CICell ih
, char *dirPath
,
45 unsigned long *dirIndex
, char **name
,
46 long *flags
, long *time
);
47 typedef long (* FSGetUUID
)(CICell ih
, char *uuidStr
);
59 FSGetDirEntry getDirEntry
;
63 typedef struct PartInfo PartInfo
, *PartInfoPtr
;
65 #define kNumPartInfos (16)
66 static PartInfo gParts
[kNumPartInfos
];
67 static char gMakeDirSpec
[1024];
69 // Private function prototypes
70 long LookupPartition(char *devSpec
);
75 long LoadFile(char *fileSpec
)
80 long ret
, length
, partIndex
;
82 ret
= ConvertFileSpec(fileSpec
, devSpec
, &filePath
);
83 if ((ret
== -1) || (filePath
== NULL
)) return -1;
85 // Get the partition index for devSpec.
86 partIndex
= LookupPartition(devSpec
);
87 if (partIndex
== -1) return -1;
89 loadFile
= gParts
[partIndex
].loadFile
;
90 length
= loadFile(gParts
[partIndex
].partIH
, filePath
);
92 // if (length == 0) return -1;
97 long LoadThinFatFile(char *fileSpec
, void **binary
)
103 long ret
, length
, length2
, partIndex
;
105 ret
= ConvertFileSpec(fileSpec
, devSpec
, &filePath
);
106 if ((ret
== -1) || (filePath
== NULL
)) return -1;
108 // Get the partition index for devSpec.
109 partIndex
= LookupPartition(devSpec
);
110 if (partIndex
== -1) return -1;
112 *binary
= (void *)kLoadAddr
;
114 readFile
= gParts
[partIndex
].readFile
;
116 if (readFile
!= NULL
) {
117 // Read the first 4096 bytes (fat header)
118 length
= readFile(gParts
[partIndex
].partIH
, filePath
, *binary
, 0, 0x1000);
120 if (ThinFatBinary(binary
, &length
) == 0) {
121 // We found a fat binary; read only the thin part
122 length
= readFile(gParts
[partIndex
].partIH
, filePath
,
123 (void *)kLoadAddr
, (unsigned long)(*binary
) - kLoadAddr
, length
);
124 *binary
= (void *)kLoadAddr
;
126 // Not a fat binary; read the rest of the file
127 length2
= readFile(gParts
[partIndex
].partIH
, filePath
, (void *)(kLoadAddr
+ length
), length
, 0);
128 if (length2
== -1) return -1;
133 loadFile
= gParts
[partIndex
].loadFile
;
134 length
= loadFile(gParts
[partIndex
].partIH
, filePath
);
136 ThinFatBinary(binary
, &length
);
143 long GetFSUUID(char *spec
, char *uuidStr
)
145 long rval
= -1, partIndex
;
150 if(ConvertFileSpec(spec
, devSpec
, NULL
)) break;
152 // Get the partition index
153 partIndex
= LookupPartition(devSpec
);
154 if (partIndex
== -1) break;
156 getUUID
= gParts
[partIndex
].getUUID
;
158 rval
= getUUID(gParts
[partIndex
].partIH
, uuidStr
);
165 // from our uuid/namespace.h (UFS and HFS uuids can live in the same space?)
166 static unsigned char kFSUUIDNamespaceSHA1
[] = {0xB3,0xE2,0x0F,0x39,0xF2,0x92,0x11,0xD6,0x97,0xA4,0x00,0x30,0x65,0x43,0xEC,0xAC};
168 // filesystem-specific getUUID functions call this shared string generator
169 long CreateUUIDString(uint8_t uubytes
[], int nbytes
, char *uuidStr
)
171 unsigned fmtbase
, fmtidx
, i
;
172 uint8_t uuidfmt
[] = { 4, 2, 2, 2, 6 };
175 uint8_t mdresult
[16];
177 bzero(mdresult
, sizeof(mdresult
));
179 // just like AppleFileSystemDriver
181 MD5Update(&md5c
, kFSUUIDNamespaceSHA1
, sizeof(kFSUUIDNamespaceSHA1
));
182 MD5Update(&md5c
, uubytes
, nbytes
);
183 MD5Final(mdresult
, &md5c
);
185 // this UUID has been made version 3 style (i.e. via namespace)
186 // see "-uuid-urn-" IETF draft (which otherwise copies byte for byte)
187 mdresult
[6] = 0x30 | ( mdresult
[6] & 0x0F );
188 mdresult
[8] = 0x80 | ( mdresult
[8] & 0x3F );
191 // generate the text: e.g. 5EB1869F-C4FA-3502-BDEB-3B8ED5D87292
193 for(fmtidx
= 0; fmtidx
< sizeof(uuidfmt
); fmtidx
++) {
194 for(i
=0; i
< uuidfmt
[fmtidx
]; i
++) {
195 uint8_t byte
= mdresult
[fmtbase
+i
];
199 *p
= nib
+ '0'; // 0x4 -> '4'
200 if(*p
> '9') *p
= (nib
- 9 + ('A'-1)); // 0xB -> 'B'
204 *p
= nib
+ '0'; // 0x4 -> '4'
205 if(*p
> '9') *p
= (nib
- 9 + ('A'-1)); // 0xB -> 'B'
210 if(fmtidx
< sizeof(uuidfmt
)-1)
219 long GetFileInfo(char *dirSpec
, char *name
, long *flags
, long *time
)
222 unsigned long index
= 0;
230 for (idx
= len
; idx
&& (name
[idx
] != '\\'); idx
--) {}
232 strncpy(gMakeDirSpec
, name
, idx
);
234 dirSpec
= gMakeDirSpec
;
238 ret
= GetDirEntry(dirSpec
, &index
, &curName
, flags
, time
);
239 if (ret
== -1) break;
241 if (!strcmp(name
, curName
)) break;
247 long GetDirEntry(char *dirSpec
, unsigned long *dirIndex
, char **name
,
248 long *flags
, long *time
)
252 FSGetDirEntry getDirEntry
;
255 ret
= ConvertFileSpec(dirSpec
, devSpec
, &dirPath
);
256 if ((ret
== -1) || (dirPath
== NULL
)) return -1;
258 // Get the partition index for devSpec.
259 partIndex
= LookupPartition(devSpec
);
260 if (partIndex
== -1) return -1;
262 getDirEntry
= gParts
[partIndex
].getDirEntry
;
263 ret
= getDirEntry(gParts
[partIndex
].partIH
, dirPath
,
264 dirIndex
, name
, flags
, time
);
269 long DumpDir(char *dirSpec
)
271 long ret
, flags
, time
;
272 unsigned long index
= 0;
275 printf("DumpDir on [%s]\n", dirSpec
);
278 ret
= GetDirEntry(dirSpec
, &index
, &name
, &flags
, &time
);
279 if (ret
== -1) break;
281 printf("%x %x [%s]\n", flags
, time
, name
);
290 long LookupPartition(char *devSpec
)
293 long partIndex
, partType
;
296 // See if the devSpec has already been opened.
297 for (partIndex
= 0; partIndex
< kNumPartInfos
; partIndex
++) {
298 if (!strcmp(gParts
[partIndex
].partName
, devSpec
)) break;
301 // If it has not been opened, do so now.
302 if (partIndex
== kNumPartInfos
) {
304 for (partIndex
= 0; partIndex
< kNumPartInfos
; partIndex
++) {
305 if (gParts
[partIndex
].partIH
== 0) break;
307 // No free slots, so return error.
308 if (partIndex
== kNumPartInfos
) return -1;
310 deviceType
= GetDeviceType(devSpec
);
311 switch (deviceType
) {
312 case kNetworkDeviceType
:
313 partIH
= NetInitPartition(devSpec
);
314 if (partIH
== 0) return -1;
318 case kBlockDeviceType
:
319 printf("Opening partition [%s]...\n", devSpec
);
320 partIH
= Open(devSpec
);
322 printf("Failed to open partition [%s].\n", devSpec
);
326 // Find out what kind of partition it is.
327 if (HFSInitPartition(partIH
) != -1) partType
= kPartHFS
;
328 else if (UFSInitPartition(partIH
) != -1) partType
= kPartUFS
;
329 else if (Ext2InitPartition(partIH
) != -1) partType
= kPartExt2
;
337 gParts
[partIndex
].partIH
= partIH
;
338 gParts
[partIndex
].partType
= partType
;
339 strcpy(gParts
[partIndex
].partName
, devSpec
);
343 gParts
[partIndex
].loadFile
= NetLoadFile
;
344 gParts
[partIndex
].readFile
= NULL
;
345 gParts
[partIndex
].getDirEntry
= NetGetDirEntry
;
346 gParts
[partIndex
].getUUID
= NULL
;
350 gParts
[partIndex
].loadFile
= HFSLoadFile
;
351 gParts
[partIndex
].readFile
= HFSReadFile
;
352 gParts
[partIndex
].getDirEntry
= HFSGetDirEntry
;
353 gParts
[partIndex
].getUUID
= HFSGetUUID
;
357 gParts
[partIndex
].loadFile
= UFSLoadFile
;
358 gParts
[partIndex
].readFile
= UFSReadFile
;
359 gParts
[partIndex
].getDirEntry
= UFSGetDirEntry
;
360 gParts
[partIndex
].getUUID
= UFSGetUUID
;
364 gParts
[partIndex
].loadFile
= Ext2LoadFile
;
365 gParts
[partIndex
].readFile
= NULL
;
366 gParts
[partIndex
].getDirEntry
= Ext2GetDirEntry
;
367 gParts
[partIndex
].getUUID
= NULL
;
368 // Ext2GetUUID exists, but there's no kernel support