Chameleon Applications

Chameleon Applications Svn Source Tree

Root/branches/iFabio/i386/libsaio/ntfs.c

Source at commit 214 created 13 years 5 months ago.
By ifabio, update to chameleon trunk 630, and now the pakage folder is the same as blackosx branch, also add Icon "building" into buildpkg script, and add mint theme info into the English localizable.strings.
1/*
2 * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2004 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25
26#include "libsaio.h"
27#include "sl.h"
28
29#define BYTE_ORDER_MARK0xFEFF
30
31#include "ntfs_private.h"
32
33#define FS_TYPE"ntfs"
34#define FS_NAME_FILE"NTFS"
35
36#define MAX_BLOCK_SIZE2048
37#define MAX_CLUSTER_SIZE32768
38
39#define LABEL_LENGTH1024
40#define UNKNOWN_LABEL"Untitled NTFS"
41
42#define FSUR_IO_FAIL -1
43#define FSUR_UNRECOGNIZED -1
44#define FSUR_RECOGNIZED 0
45
46#define ERROR -1
47
48/*
49 * Process per-sector "fixups" that NTFS uses to detect corruption of
50 * multi-sector data structures, like MFT records.
51 */
52static int
53ntfs_fixup(
54 char *buf,
55 size_t len,
56 u_int32_t magic,
57 u_int32_t bytesPerSector)
58{
59struct fixuphdr *fhp = (struct fixuphdr *) buf;
60int i;
61u_int16_t fixup;
62u_int16_t *fxp;
63u_int16_t *cfxp;
64 u_int32_tfixup_magic;
65 u_int16_tfixup_count;
66 u_int16_tfixup_offset;
67
68 fixup_magic = OSReadLittleInt32(&fhp->fh_magic,0);
69if (fixup_magic != magic) {
70error("ntfs_fixup: magic doesn't match: %08x != %08x\n",
71 fixup_magic, magic);
72return (ERROR);
73}
74 fixup_count = OSReadLittleInt16(&fhp->fh_fnum,0);
75if ((fixup_count - 1) * bytesPerSector != len) {
76error("ntfs_fixup: " \
77 "bad fixups number: %d for %ld bytes block\n",
78 fixup_count, (long)len);/* XXX printf kludge */
79return (ERROR);
80}
81 fixup_offset = OSReadLittleInt16(&fhp->fh_foff,0);
82if (fixup_offset >= len) {
83error("ntfs_fixup: invalid offset: %x", fixup_offset);
84return (ERROR);
85}
86fxp = (u_int16_t *) (buf + fixup_offset);
87cfxp = (u_int16_t *) (buf + bytesPerSector - 2);
88fixup = *fxp++;
89for (i = 1; i < fixup_count; i++, fxp++) {
90if (*cfxp != fixup) {
91error("ntfs_fixup: fixup %d doesn't match\n", i);
92return (ERROR);
93}
94*cfxp = *fxp;
95 cfxp = (u_int16_t *)(((caddr_t)cfxp) + bytesPerSector);
96}
97return (0);
98}
99
100/*
101 * Find a resident attribute of a given type. Returns a pointer to the
102 * attribute data, and its size in bytes.
103 */
104static int
105ntfs_find_attr(
106 char *buf,
107 u_int32_t attrType,
108 void **attrData,
109 size_t *attrSize)
110{
111 struct filerec *filerec;
112 struct attr *attr;
113 u_int16_t offset;
114
115 filerec = (struct filerec *) buf;
116 offset = OSReadLittleInt16(&filerec->fr_attroff,0);
117 attr = (struct attr *) (buf + offset);
118
119
120 while (attr->a_hdr.a_type != 0xFFFFFFFF)/* same for big/little endian */
121 {
122 if (OSReadLittleInt32(&attr->a_hdr.a_type,0) == attrType)
123 {
124 if (attr->a_hdr.a_flag != 0)
125 {
126 //verbose("NTFS: attriubte 0x%X is non-resident\n", attrType);
127 return 1;
128 }
129
130 *attrSize = OSReadLittleInt16(&attr->a_r.a_datalen,0);
131 *attrData = buf + offset + OSReadLittleInt16(&attr->a_r.a_dataoff,0);
132 return 0;/* found it! */
133 }
134
135 /* Skip to the next attribute */
136 offset += OSReadLittleInt32(&attr->a_hdr.reclen,0);
137 attr = (struct attr *) (buf + offset);
138 }
139
140 return 1;/* No matching attrType found */
141}
142
143/*
144 * Examine a volume to see if we recognize it as a mountable.
145 */
146void
147NTFSGetDescription(CICell ih, char *str, long strMaxLen)
148{
149 struct bootfile *boot;
150 unsigned bytesPerSector;
151 unsigned sectorsPerCluster;
152 int mftRecordSize;
153 u_int64_t totalClusters;
154 u_int64_t cluster, mftCluster;
155 size_t mftOffset;
156 void *nameAttr;
157 size_t nameSize;
158 char *buf;
159
160 buf = (char *)malloc(MAX_CLUSTER_SIZE);
161 if (buf == 0) {
162 goto error;
163 }
164
165 /*
166 * Read the boot sector, check signatures, and do some minimal
167 * sanity checking. NOTE: the size of the read below is intended
168 * to be a multiple of all supported block sizes, so we don't
169 * have to determine or change the device's block size.
170 */
171 Seek(ih, 0);
172 Read(ih, (long)buf, MAX_BLOCK_SIZE);
173
174 boot = (struct bootfile *) buf;
175
176 /*
177 * The first three bytes are an Intel x86 jump instruction. I assume it
178 * can be the same forms as DOS FAT:
179 * 0xE9 0x?? 0x??
180 * 0xEC 0x?? 0x90
181 * where 0x?? means any byte value is OK.
182 */
183 if (boot->reserved1[0] != 0xE9
184 && (boot->reserved1[0] != 0xEB || boot->reserved1[2] != 0x90))
185 {
186 goto error;
187 }
188
189 /*
190 * Check the "NTFS " signature.
191 */
192 if (memcmp((const char *)boot->bf_sysid, "NTFS ", 8) != 0)
193 {
194 goto error;
195 }
196
197 /*
198 * Make sure the bytes per sector and sectors per cluster are
199 * powers of two, and within reasonable ranges.
200 */
201 bytesPerSector = OSReadLittleInt16(&boot->bf_bps,0);
202 if ((bytesPerSector & (bytesPerSector-1)) || bytesPerSector < 512 || bytesPerSector > 32768)
203 {
204 //verbose("NTFS: invalid bytes per sector (%d)\n", bytesPerSector);
205 goto error;
206 }
207
208 sectorsPerCluster = boot->bf_spc;/* Just one byte; no swapping needed */
209 if ((sectorsPerCluster & (sectorsPerCluster-1)) || sectorsPerCluster > 128)
210 {
211 //verbose("NTFS: invalid sectors per cluster (%d)\n", bytesPerSector);
212 goto error;
213 }
214
215 /*
216 * Calculate the number of clusters from the number of sectors.
217 * Then bounds check the $MFT and $MFTMirr clusters.
218 */
219 totalClusters = OSReadLittleInt64(&boot->bf_spv,0) / sectorsPerCluster;
220 mftCluster = OSReadLittleInt64(&boot->bf_mftcn,0);
221 if (mftCluster > totalClusters)
222 {
223 ////verbose("NTFS: invalid $MFT cluster (%lld)\n", mftCluster);
224 goto error;
225 }
226 cluster = OSReadLittleInt64(&boot->bf_mftmirrcn,0);
227 if (cluster > totalClusters)
228 {
229 //verbose("NTFS: invalid $MFTMirr cluster (%lld)\n", cluster);
230 goto error;
231 }
232
233 /*
234 * Determine the size of an MFT record.
235 */
236 mftRecordSize = (int8_t) boot->bf_mftrecsz;
237 if (mftRecordSize < 0)
238 mftRecordSize = 1 << -mftRecordSize;
239 else
240 mftRecordSize *= bytesPerSector * sectorsPerCluster;
241 //verbose("NTFS: MFT record size = %d\n", mftRecordSize);
242
243 /*
244 * Read the MFT record for $Volume. This assumes the first four
245 * file records in the MFT are contiguous; if they aren't, we
246 * would have to map the $MFT itself.
247 *
248 * This will fail if the device sector size is larger than the
249 * MFT record size, since the $Volume record won't be aligned
250 * on a sector boundary.
251 */
252 mftOffset = mftCluster * sectorsPerCluster * bytesPerSector;
253 mftOffset += mftRecordSize * NTFS_VOLUMEINO;
254
255 Seek(ih, mftOffset);
256 Read(ih, (long)buf, mftRecordSize);
257#if UNUSED
258 if (lseek(fd, mftOffset, SEEK_SET) == -1)
259 {
260 //verbose("NTFS: lseek to $Volume failed: %s\n", strerror(errno));
261 goto error;
262 }
263 if (read(fd, buf, mftRecordSize) != mftRecordSize)
264 {
265 //verbose("NTFS: error reading MFT $Volume record: %s\n",
266 strerror(errno));
267 goto error;
268 }
269#endif
270
271 if (ntfs_fixup(buf, mftRecordSize, NTFS_FILEMAGIC, bytesPerSector) != 0)
272 {
273 //verbose("NTFS: block fixup failed\n");
274 goto error;
275 }
276
277 /*
278 * Loop over the attributes, looking for $VOLUME_NAME (0x60).
279 */
280 if(ntfs_find_attr(buf, NTFS_A_VOLUMENAME, &nameAttr, &nameSize) != 0)
281 {
282 //verbose("NTFS: $VOLUME_NAME attribute not found\n");
283 goto error;
284 }
285
286 str[0] = '\0';
287
288 utf_encodestr( nameAttr, nameSize / 2, (u_int8_t *)str, strMaxLen, OSLittleEndian );
289
290 free(buf);
291 return;
292
293 error:
294 if (buf) free(buf);
295 return;
296}
297
298long NTFSGetUUID(CICell ih, char *uuidStr)
299{
300bool NTFSProbe(const void*);
301
302struct bootfile *boot;
303void *buf = malloc(MAX_BLOCK_SIZE);
304if ( !buf )
305return -1;
306
307/*
308 * Read the boot sector, check signatures, and do some minimal
309 * sanity checking. NOTE: the size of the read below is intended
310 * to be a multiple of all supported block sizes, so we don't
311 * have to determine or change the device's block size.
312 */
313Seek(ih, 0);
314Read(ih, (long)buf, MAX_BLOCK_SIZE);
315
316boot = (struct bootfile *) buf;
317
318// Check for NTFS signature
319if ( memcmp((void*)boot->bf_sysid, NTFS_BBID, NTFS_BBIDLEN) != 0 )
320return -1;
321
322// Check for non-null volume serial number
323if( !boot->bf_volsn )
324return -1;
325
326// Use UUID like the one you get on Windows
327sprintf(uuidStr, "%04X-%04X",(unsigned short)(boot->bf_volsn >> 16) & 0xFFFF,
328(unsigned short)boot->bf_volsn & 0xFFFF);
329
330return 0;
331}
332
333bool NTFSProbe(const void * buffer)
334{
335bool result = false;
336
337const struct bootfile* part_bootfile = buffer;// NTFS boot sector structure
338
339// Looking for NTFS signature.
340if (strncmp((const char *)part_bootfile->bf_sysid, NTFS_BBID, NTFS_BBIDLEN) == 0)
341result = true;
342
343return result;
344}
345

Archive Download this file

Revision: 214