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 | * Copyright (c) 1998 Robert Nordier␊ |
24 | * All rights reserved.␊ |
25 | *␊ |
26 | * Redistribution and use in source and binary forms, with or without␊ |
27 | * modification, are permitted provided that the following conditions␊ |
28 | * are met:␊ |
29 | * 1. Redistributions of source code must retain the above copyright␊ |
30 | * notice, this list of conditions and the following disclaimer.␊ |
31 | * 2. Redistributions in binary form must reproduce the above copyright␊ |
32 | * notice, this list of conditions and the following disclaimer in␊ |
33 | * the documentation and/or other materials provided with the␊ |
34 | * distribution.␊ |
35 | *␊ |
36 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS␊ |
37 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED␊ |
38 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE␊ |
39 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY␊ |
40 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL␊ |
41 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE␊ |
42 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS␊ |
43 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER␊ |
44 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR␊ |
45 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN␊ |
46 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.␊ |
47 | */␊ |
48 | ␊ |
49 | #include "libsaio.h"␊ |
50 | #include "sl.h"␊ |
51 | #include "msdos_private.h"␊ |
52 | #include "msdos.h"␊ |
53 | ␊ |
54 | #define LABEL_LENGTH␉␉11␊ |
55 | #define MSDOS_CACHE_BLOCKSIZE␉BPS␊ |
56 | ␊ |
57 | #define␉CLUST_FIRST␉␉2␉␉/* reserved cluster range */␊ |
58 | #define␉CLUST_RSRVD32␉␉0x0ffffff8␉/* reserved cluster range */␊ |
59 | #define␉CLUST_RSRVD16␉␉0xfff8␉␉/* reserved cluster range */␊ |
60 | #define␉CLUST_RSRVD12␉␉0xff8␉␉/* reserved cluster range */␊ |
61 | ␊ |
62 | #define tolower(c) (((c)>='A' && c<='Z')?((c) | 0x20):(c))␊ |
63 | ␊ |
64 | static int msdosressector=0;␊ |
65 | static int msdosnfats = 0;␊ |
66 | static int msdosfatsecs = 0;␊ |
67 | static int msdosbps = 0;␊ |
68 | static int msdosclustersize = 0;␊ |
69 | static int msdosrootDirSectors = 0;␊ |
70 | static CICell msdoscurrent = 0;␊ |
71 | static int msdosrootcluster = 0;␊ |
72 | static int msdosfatbits = 0;␊ |
73 | ␊ |
74 | struct msdosdirstate␊ |
75 | {␊ |
76 | ␉struct direntry *buf;␊ |
77 | ␉uint8_t vfatchecksum;␊ |
78 | ␉int root16;␊ |
79 | ␉off_t cluster;␊ |
80 | ␉int nument;␊ |
81 | ␉int vfatnumber;␊ |
82 | };␊ |
83 | ␊ |
84 | #if UNUSED␊ |
85 | /*␊ |
86 | * Check a volume label.␊ |
87 | */␊ |
88 | static int oklabel(const char *src);␊ |
89 | ␊ |
90 | static int oklabel(const char *src)␊ |
91 | {␊ |
92 | int c, i;␊ |
93 | ␊ |
94 | ␉for (i = 0, c = 0; i <= 11; i++)␊ |
95 | ␉{␊ |
96 | ␉␉c = (u_char)*src++;␊ |
97 | ␉␉if (c < ' ' + !i || strchr("\"*+,./:;<=>?[\\]|", c))␊ |
98 | ␉␉{␊ |
99 | ␉␉␉break;␊ |
100 | ␉␉}␊ |
101 | ␉}␊ |
102 | ␉return i && !c;␊ |
103 | }␊ |
104 | #endif /* UNUSED */␊ |
105 | ␊ |
106 | void MSDOSFree(CICell ih)␊ |
107 | {␊ |
108 | ␉if(msdoscurrent == ih)␊ |
109 | msdoscurrent = 0;␊ |
110 | free(ih);␊ |
111 | }␊ |
112 | ␊ |
113 | int MSDOSProbe(const void * buffer)␊ |
114 | {␊ |
115 | union bootsector *bsp;␊ |
116 | struct bpb33 *b33;␊ |
117 | struct bpb50 *b50;␊ |
118 | struct bpb710 *b710;␊ |
119 | u_int16_t␉ bps;␊ |
120 | u_int8_t␉␉spc;␊ |
121 | ␉␊ |
122 | bsp = (union bootsector *)buffer;␊ |
123 | b33 = (struct bpb33 *)bsp->bs33.bsBPB;␊ |
124 | b50 = (struct bpb50 *)bsp->bs50.bsBPB;␊ |
125 | b710 = (struct bpb710 *)bsp->bs710.bsBPB;␊ |
126 | ␊ |
127 | /* We only work with 512, 1024, and 2048 byte sectors */␊ |
128 | bps = OSSwapLittleToHostInt16(b33->bpbBytesPerSec);␊ |
129 | if ((bps < 0x200) || (bps & (bps - 1)) || (bps > 0x800)) ␊ |
130 | return 0;␊ |
131 | ␊ |
132 | ␉/* Check to make sure valid sectors per cluster */␊ |
133 | spc = b33->bpbSecPerClust;␊ |
134 | if ((spc == 0 ) || (spc & (spc - 1))) ␊ |
135 | return 0;␉␊ |
136 | ␉␊ |
137 | ␉if (OSSwapLittleToHostInt16(b50->bpbRootDirEnts) == 0) { /* It's FAT32 */␊ |
138 | ␉␉if (!memcmp(((struct extboot *)bsp->bs710.bsExt)->exFileSysType, "FAT32 ", 8))␊ |
139 | ␉␉␉return 32;␊ |
140 | ␉}␊ |
141 | ␉else if (((struct extboot *)bsp->bs50.bsExt)->exBootSignature == EXBOOTSIG) {␊ |
142 | ␉␉if (!memcmp((char *)((struct extboot *)bsp->bs50.bsExt)->exFileSysType, "FAT16 ", 8))␊ |
143 | ␉␉␉return 16;␊ |
144 | ␉␉if (!memcmp((char *)((struct extboot *)bsp->bs50.bsExt)->exFileSysType, "FAT12 ", 8))␊ |
145 | ␉␉␉return 12;␊ |
146 | ␉}␉␊ |
147 | ␊ |
148 | ␉return 0;␊ |
149 | }␊ |
150 | ␊ |
151 | ␊ |
152 | long MSDOSInitPartition (CICell ih)␊ |
153 | {␊ |
154 | union bootsector *bsp;␊ |
155 | struct bpb33 *b33;␊ |
156 | struct bpb50 *b50;␊ |
157 | struct bpb710 *b710;␊ |
158 | u_int8_t␉␉spc;␊ |
159 | char *buf;␊ |
160 | ␉␊ |
161 | ␉if (msdoscurrent == ih)␊ |
162 | ␉{␊ |
163 | ␉␉CacheInit(ih, MSDOS_CACHE_BLOCKSIZE);␊ |
164 | ␉␉return 0;␊ |
165 | ␉}␊ |
166 | ␉␊ |
167 | ␉buf=malloc (512);␊ |
168 | ␉if (!buf) ␊ |
169 | ␉{ ␊ |
170 | ␉␉return -1;␊ |
171 | ␉}␊ |
172 | ␊ |
173 | ␉/*␊ |
174 | ␉ * Read the boot sector of the filesystem, and then check the␊ |
175 | ␉ * boot signature. If not a dos boot sector then error out.␊ |
176 | ␉ *␊ |
177 | ␉ * NOTE: 2048 is a maximum sector size in current...␊ |
178 | ␉ */␊ |
179 | ␊ |
180 | ␉Seek(ih, 0);␊ |
181 | ␉Read(ih, (long)buf, 512);␊ |
182 | ␉␊ |
183 | ␉bsp = (union bootsector *)buf;␊ |
184 | ␉b33 = (struct bpb33 *)bsp->bs33.bsBPB;␊ |
185 | ␉b50 = (struct bpb50 *)bsp->bs50.bsBPB;␊ |
186 | ␉b710 = (struct bpb710 *)bsp->bs710.bsBPB;␊ |
187 | ␊ |
188 | ␉␊ |
189 | ␉/* We only work with 512, 1024, and 2048 byte sectors */␊ |
190 | ␉msdosbps = OSSwapLittleToHostInt16(b33->bpbBytesPerSec);␊ |
191 | ␉if ((msdosbps < 0x200) || (msdosbps & (msdosbps - 1)) || (msdosbps > 0x800)) ␊ |
192 | ␉{␊ |
193 | ␉␉free (buf);␊ |
194 | ␉␉return -1;␊ |
195 | ␉}␊ |
196 | ␉␊ |
197 | ␉/* Check to make sure valid sectors per cluster */␊ |
198 | ␉spc = b33->bpbSecPerClust;␊ |
199 | ␉if ((spc == 0 ) || (spc & (spc - 1)))␊ |
200 | ␉{␊ |
201 | ␉␉free (buf);␊ |
202 | ␉␉return -1;␊ |
203 | ␉}␊ |
204 | ␉if (OSSwapLittleToHostInt16(b50->bpbRootDirEnts) == 0)␊ |
205 | ␉{␊ |
206 | ␉␉/* It's FAT32 */␊ |
207 | ␉␉if (memcmp(((struct extboot *)bsp->bs710.bsExt)->exFileSysType, "FAT32 ", 8))␊ |
208 | ␉␉{␊ |
209 | ␉␉␉free (buf);␊ |
210 | ␉␉␉return -1;␊ |
211 | ␉␉}␊ |
212 | ␉␉msdosressector = OSSwapLittleToHostInt16(b710->bpbResSectors);␊ |
213 | ␉␉msdosnfats = b710->bpbFATs;␊ |
214 | ␉␉msdosfatsecs = OSSwapLittleToHostInt16(b710->bpbBigFATsecs);␊ |
215 | ␉␉msdosrootcluster = OSSwapLittleToHostInt32(b710->bpbRootClust);␊ |
216 | ␉␉msdosrootDirSectors = 0;␊ |
217 | ␉␉msdosfatbits = 32;␊ |
218 | ␉}␊ |
219 | ␉else if (((struct extboot *)bsp->bs50.bsExt)->exBootSignature == EXBOOTSIG)␊ |
220 | ␉{␊ |
221 | ␉␉if (!memcmp((char *)((struct extboot *)bsp->bs50.bsExt)->exFileSysType, "FAT16 ", 8))␊ |
222 | ␉␉{␊ |
223 | ␉␉␉msdosfatbits = 16;␊ |
224 | ␉␉}␊ |
225 | ␉␉else if (!memcmp((char *)((struct extboot *)bsp->bs50.bsExt)->exFileSysType, "FAT12 ", 8))␊ |
226 | ␉␉{␊ |
227 | ␉␉␉msdosfatbits = 12;␊ |
228 | ␉␉}␊ |
229 | ␉␉else␊ |
230 | ␉␉{␊ |
231 | ␉␉␉free (buf);␊ |
232 | ␉␉␉return -1;␊ |
233 | ␉␉}␉␉␊ |
234 | ␉␉␊ |
235 | ␉␉msdosressector = OSSwapLittleToHostInt16(b33->bpbResSectors);␊ |
236 | ␉␉msdosnfats = b33->bpbFATs;␊ |
237 | ␉␉msdosfatsecs = OSSwapLittleToHostInt16(b33->bpbFATsecs);␊ |
238 | ␉␉msdosrootcluster = 0;␉␉␊ |
239 | ␉␉msdosrootDirSectors = ((OSSwapLittleToHostInt16(b50->bpbRootDirEnts) * sizeof(struct direntry)) +␊ |
240 | ␉␉␉␉␉␉␉ (msdosbps-1)) / msdosbps;␊ |
241 | ␉} else {␊ |
242 | ␉␉free (buf);␊ |
243 | ␉␉return -1;␊ |
244 | ␉}␊ |
245 | ␉␊ |
246 | ␉msdosclustersize = msdosbps * spc;␊ |
247 | ␉msdoscurrent = ih;␊ |
248 | ␊ |
249 | ␉CacheInit(ih, MSDOS_CACHE_BLOCKSIZE);␊ |
250 | ␉free (buf);␊ |
251 | ␉return 0;␊ |
252 | }␊ |
253 | ␊ |
254 | static int readSector(CICell ih, off_t readOffset, char *buf, int size)␊ |
255 | {␊ |
256 | // Caching only FAT entries (4 bytes) by utlizing the cache with sector aligned read requests.␊ |
257 | ␉if (size < BPS)␊ |
258 | ␉{␊ |
259 | ␉␉long long sectorOffset = (uint64_t)readOffset / BPS * BPS;␊ |
260 | ␉␉long relOffset = readOffset % BPS;␊ |
261 | ␉␉char *cacheBuffer;␊ |
262 | ␉␊ |
263 | ␉␉cacheBuffer = malloc(MSDOS_CACHE_BLOCKSIZE);␊ |
264 | ␉␉if (!cacheBuffer) ␊ |
265 | ␉␉{␊ |
266 | ␉␉␉return -1;␊ |
267 | ␉␉}␊ |
268 | ␉␉CacheRead(ih, cacheBuffer, sectorOffset, MSDOS_CACHE_BLOCKSIZE, true);␊ |
269 | ␉␉bcopy(cacheBuffer + relOffset, buf, size);␊ |
270 | ␉␉free(cacheBuffer);␊ |
271 | ␉}␊ |
272 | ␉else␊ |
273 | ␉{␊ |
274 | ␉␉Seek(ih, readOffset);␊ |
275 | ␉␉Read(ih, (long)buf, size);␊ |
276 | ␉}␊ |
277 | ␊ |
278 | ␉return 0;␊ |
279 | }␊ |
280 | ␊ |
281 | static int msdosreadcluster (CICell ih, uint8_t *buf, int size, off_t *cluster)␊ |
282 | {␊ |
283 | off_t readOffset;␊ |
284 | ␉char tmpbuf[8];␊ |
285 | ␉off_t clusn;␊ |
286 | ␉␊ |
287 | ␉switch (msdosfatbits) {␊ |
288 | ␉␉case 32:␊ |
289 | ␉␉␉if (*cluster < CLUST_FIRST ||*cluster >= CLUST_RSRVD32)␊ |
290 | ␉␉␉␉return 0;␊ |
291 | ␉␉␉clusn = *cluster - CLUST_FIRST;␊ |
292 | ␉␉␉break;␊ |
293 | ␉␉case 16:␊ |
294 | ␉␉␉if (*cluster < CLUST_FIRST ||*cluster >= CLUST_RSRVD16)␊ |
295 | ␉␉␉␉return 0;␊ |
296 | ␉␉␉clusn = *cluster - CLUST_FIRST;␊ |
297 | ␉␉␉break;␉␉␉␊ |
298 | ␉␉case 12:␊ |
299 | ␉␉␉if (*cluster < CLUST_FIRST ||*cluster >= CLUST_RSRVD12)␊ |
300 | ␉␉␉␉return 0;␊ |
301 | ␉␉␉clusn = *cluster - CLUST_FIRST;␊ |
302 | ␉␉␉break;␊ |
303 | ␉␉default:␊ |
304 | ␉␉␉return 0;␊ |
305 | ␉}␊ |
306 | ␉␊ |
307 | ␉/* Find sector where clusters start */␊ |
308 | ␉readOffset = (msdosressector +␊ |
309 | ␉␉␉␉ (msdosnfats * msdosfatsecs)+msdosrootDirSectors)*msdosbps;␊ |
310 | ␉/* Find sector where "cluster" starts */␊ |
311 | ␉readOffset += clusn * msdosclustersize;␊ |
312 | ␉␊ |
313 | ␉/* Read in "cluster" */␊ |
314 | ␉if (buf)␊ |
315 | ␉{␊ |
316 | ␉␉Seek(ih, readOffset);␊ |
317 | ␉␉Read(ih, (long)buf, size);␊ |
318 | ␉}␊ |
319 | ␊ |
320 | ␉/* Find first sector of FAT */␊ |
321 | ␉readOffset = msdosressector * msdosbps;␊ |
322 | ␊ |
323 | ␉/* Find sector containing "cluster" entry in FAT */␊ |
324 | ␉readOffset += ((uint64_t)*cluster * (uint64_t)msdosfatbits) / 8;␊ |
325 | ␉␊ |
326 | ␉/* Read one sector of the FAT */␊ |
327 | ␉if (readSector(ih, readOffset, tmpbuf, 4) != 0) return 0;␊ |
328 | ␉␊ |
329 | ␉switch (msdosfatbits) {␊ |
330 | ␉␉case 32:␊ |
331 | ␉␉␉*cluster = OSReadLittleInt32(tmpbuf, 0);␊ |
332 | ␉␉␉*cluster &= 0x0FFFFFFF;␉// ignore reserved upper bits␊ |
333 | ␉␉␉return 1;␊ |
334 | ␉␉case 16:␊ |
335 | ␉␉␉*cluster = OSReadLittleInt16(tmpbuf, 0);␊ |
336 | ␉␉␉return 1;␉␉␉␊ |
337 | ␉␉case 12:␊ |
338 | ␉␉␉*cluster = OSReadLittleInt16(tmpbuf, 0)>>(((uint64_t)*cluster * (uint64_t)msdosfatbits)%8);␊ |
339 | ␉␉␉*cluster &= 0xfff;␊ |
340 | ␉␉␉return 1;␊ |
341 | ␉␉default:␊ |
342 | ␉␉␉return 0;␊ |
343 | ␉}␊ |
344 | }␊ |
345 | ␊ |
346 | static struct direntry *getnextdirent (CICell ih, uint16_t *longname, struct msdosdirstate *st)␊ |
347 | {␊ |
348 | ␉struct direntry *dirp;␊ |
349 | ␉while (1)␊ |
350 | ␉{␊ |
351 | ␉␉if (st->root16)␊ |
352 | ␉␉{␊ |
353 | ␉␉␉if (st->cluster >= msdosrootDirSectors && st->nument == 0)␊ |
354 | ␉␉␉␉return 0;␊ |
355 | ␉␉␉if (st->nument == 0)␊ |
356 | ␉␉␉{␊ |
357 | ␉␉␉␉Seek(ih, (msdosressector +␊ |
358 | ␉␉␉␉␉␉ (msdosnfats * msdosfatsecs)+st->cluster)*msdosbps);␊ |
359 | ␉␉␉␉Read(ih, (long)st->buf, msdosbps);␊ |
360 | ␉␉␉␉st->cluster++;␊ |
361 | ␉␉␉}␊ |
362 | ␉␉} else if (st->nument == 0 && !msdosreadcluster (ih, (uint8_t *)st->buf, msdosclustersize, &(st->cluster)))␊ |
363 | ␉␉␉return 0;␊ |
364 | ␉␉␊ |
365 | ␉␉dirp=st->buf+st->nument;␊ |
366 | ␉␉␊ |
367 | ␉␉if (dirp->deName[0] == SLOT_EMPTY)␊ |
368 | ␉␉␉return 0;␊ |
369 | ␉␉else if (dirp->deName[0] == SLOT_DELETED)␊ |
370 | ␉␉␉st->vfatnumber = 0;␊ |
371 | ␉␉else if (dirp->deAttributes == ATTR_WIN95)␊ |
372 | ␉␉{␊ |
373 | ␉␉␉struct winentry *wdirp = (struct winentry *)dirp;␊ |
374 | ␉␉␉int num;␊ |
375 | ␉␉␉if (wdirp->weCnt & 0x80)␊ |
376 | ␉␉␉␉continue;␊ |
377 | ␉␉␉num=(wdirp->weCnt&0x3f);␊ |
378 | ␉␉␉if (WIN_CHARS * num > WIN_MAXLEN)␊ |
379 | ␉␉␉␉continue;␊ |
380 | ␉␉␉if (st->vfatchecksum!=wdirp->weChksum)␊ |
381 | ␉␉␉{␊ |
382 | ␉␉␉␉st->vfatnumber = 0;␊ |
383 | ␉␉␉␉st->vfatchecksum = wdirp->weChksum;␊ |
384 | ␉␉␉}␊ |
385 | ␉␉␉if (st->vfatnumber < num)␊ |
386 | ␉␉␉␉st->vfatnumber = num;␊ |
387 | ␉␉␉bcopy (&(wdirp->wePart1),longname+WIN_CHARS*(num-1),sizeof (wdirp->wePart1));␊ |
388 | ␉␉␉bcopy (&(wdirp->wePart2),longname+WIN_CHARS*(num-1)+5,sizeof (wdirp->wePart2));␊ |
389 | ␉␉␉bcopy (&(wdirp->wePart3),longname+WIN_CHARS*(num-1)+11,sizeof (wdirp->wePart3));␊ |
390 | ␉␉}␊ |
391 | ␉␉else␊ |
392 | ␉␉{␊ |
393 | ␉␉␉uint8_t labelchecksum;␊ |
394 | ␉␉␉int i;␊ |
395 | ␉␉␉longname[st->vfatnumber*WIN_CHARS]=0;␊ |
396 | ␉␉␉␊ |
397 | ␉␉␉labelchecksum=0;␊ |
398 | ␉␉␉for(i=0;i<LABEL_LENGTH;i++)␊ |
399 | ␉␉␉␉labelchecksum=(labelchecksum>>1)+(labelchecksum<<7)+dirp->deName[i];␊ |
400 | ␉␉␉if (!(labelchecksum==st->vfatchecksum && st->vfatnumber))␊ |
401 | ␉␉␉␉longname[0]=0;␊ |
402 | ␉␉␉st->vfatnumber = 0;␊ |
403 | ␉␉␉st->vfatchecksum = 0;␊ |
404 | ␉␉␉st->vfatnumber = 0;␊ |
405 | ␉␉␉st->nument++;␊ |
406 | ␉␉␉if ((!st->root16 &&st->nument * sizeof (struct direntry)>=msdosclustersize)␊ |
407 | ␉␉␉␉|| (st->root16 &&st->nument * sizeof (struct direntry)>=msdosbps))␊ |
408 | ␉␉␉␉st->nument = 0;␊ |
409 | ␉␉␉return dirp;␊ |
410 | ␉␉}␊ |
411 | ␉␉st->nument++;␊ |
412 | ␉␉if ((!st->root16 &&st->nument * sizeof (struct direntry)>=msdosclustersize)␊ |
413 | ␉␉␉|| (st->root16 &&st->nument * sizeof (struct direntry)>=msdosbps))␊ |
414 | ␉␉␉st->nument = 0;␉␉␊ |
415 | ␉}␊ |
416 | }␊ |
417 | ␊ |
418 | static void initRoot (struct msdosdirstate *st)␊ |
419 | {␊ |
420 | ␉if (msdosrootDirSectors)␊ |
421 | ␉{␊ |
422 | ␉␉/* FAT12 or FAT16 */␊ |
423 | ␉␉st->root16 = 1;␊ |
424 | ␉␉st->vfatchecksum = 0;␊ |
425 | ␉␉st->nument = 0;␊ |
426 | ␉␉st->cluster = 0;␊ |
427 | ␉␉st->vfatnumber = 0;␊ |
428 | ␉}␊ |
429 | ␉else␊ |
430 | ␉{␊ |
431 | ␉␉/* FAT32 */␊ |
432 | ␉␉st->root16 = 0;␊ |
433 | ␉␉st->vfatchecksum = 0;␊ |
434 | ␉␉st->nument = 0;␊ |
435 | ␉␉st->cluster = msdosrootcluster;␊ |
436 | ␉␉st->vfatnumber = 0;␊ |
437 | ␉}␊ |
438 | }␊ |
439 | ␊ |
440 | /* First comes lowercase, then uppercase*/␊ |
441 | static uint16_t cp850[128][2]=␊ |
442 | {␊ |
443 | ␉{0x00E7,0x00C7},␊ |
444 | ␉{0x00FC,0x00DC},␊ |
445 | ␉{0x00E9,0x00C9},␊ |
446 | ␉{0x00E2,0x00C2},␊ |
447 | ␉{0x00E4,0x00C4},␊ |
448 | ␉{0x00E0,0x00C0},␊ |
449 | ␉{0x00E5,0x00C5},␊ |
450 | ␉{0x00E7,0x00C7},␊ |
451 | ␉{0x00EA,0x00CA},␊ |
452 | ␉{0x00EB,0x00CB},␊ |
453 | ␉{0x00E8,0x00C8},␊ |
454 | ␉{0x00EF,0x00CF},␊ |
455 | ␉{0x00EE,0x00CE},␊ |
456 | ␉{0x00EC,0x00CC},␊ |
457 | ␉{0x00E4,0x00C4},␊ |
458 | ␉{0x00E5,0x00C5},␊ |
459 | ␉{0x00E9,0x00C9},␊ |
460 | ␉{0x00E6,0x00C6},␊ |
461 | ␉{0x00E6,0x00C6},␊ |
462 | ␉{0x00F4,0x00D4},␊ |
463 | ␉{0x00F6,0x00D6},␊ |
464 | ␉{0x00F2,0x00D2},␊ |
465 | ␉{0x00FB,0x00DB},␊ |
466 | ␉{0x00F9,0x00D9},␊ |
467 | ␉{0x00FF,0x0178},␊ |
468 | ␉{0x00F6,0x00D6},␊ |
469 | ␉{0x00FC,0x00DC},␊ |
470 | ␉{0x00F8,0x00D8},␊ |
471 | ␉{0x00A3,0x00A3},␊ |
472 | ␉{0x00F8,0x00D8},␊ |
473 | ␉{0x00D7,0x00D7},␊ |
474 | ␉{0x0192,0x0191},␊ |
475 | ␉{0x00E1,0x00C1},␊ |
476 | ␉{0x00ED,0x00CD},␊ |
477 | ␉{0x00F3,0x00D3},␊ |
478 | ␉{0x00FA,0x00DA},␊ |
479 | ␉{0x00F1,0x00D1},␊ |
480 | ␉{0x00F1,0x00D1},␊ |
481 | ␉{0x00AA,0x00AA},␊ |
482 | ␉{0x00BA,0x00BA},␊ |
483 | ␉{0x00BF,0x00BF},␊ |
484 | ␉{0x00AE,0x00AE},␊ |
485 | ␉{0x00AC,0x00AC},␊ |
486 | ␉{0x00BD,0x00BD},␊ |
487 | ␉{0x00BC,0x00BC},␊ |
488 | ␉{0x00A1,0x00A1},␊ |
489 | ␉{0x00AB,0x00AB},␊ |
490 | ␉{0x00BB,0x00BB},␊ |
491 | ␉{0x2591,0x2591},␊ |
492 | ␉{0x2592,0x2592},␊ |
493 | ␉{0x2593,0x2593},␊ |
494 | ␉{0x2502,0x2502},␊ |
495 | ␉{0x2524,0x2524},␊ |
496 | ␉{0x00E1,0x00C1},␊ |
497 | ␉{0x00E2,0x00C2},␊ |
498 | ␉{0x00E0,0x00C0},␊ |
499 | ␉{0x00A9,0x00A9},␊ |
500 | ␉{0x2563,0x2563},␊ |
501 | ␉{0x2551,0x2551},␊ |
502 | ␉{0x2557,0x2557},␊ |
503 | ␉{0x255D,0x255D},␊ |
504 | ␉{0x00A2,0x00A2},␊ |
505 | ␉{0x00A5,0x00A5},␊ |
506 | ␉{0x2510,0x2510},␊ |
507 | ␉{0x2514,0x2514},␊ |
508 | ␉{0x2534,0x2534},␊ |
509 | ␉{0x252C,0x252C},␊ |
510 | ␉{0x251C,0x251C},␊ |
511 | ␉{0x2500,0x2500},␊ |
512 | ␉{0x253C,0x253C},␊ |
513 | ␉{0x00E3,0x00C3},␊ |
514 | ␉{0x00E3,0x00C3},␊ |
515 | ␉{0x255A,0x255A},␊ |
516 | ␉{0x2554,0x2554},␊ |
517 | ␉{0x2569,0x2569},␊ |
518 | ␉{0x2566,0x2566},␊ |
519 | ␉{0x2560,0x2560},␊ |
520 | ␉{0x2550,0x2550},␊ |
521 | ␉{0x256C,0x256C},␊ |
522 | ␉{0x00A4,0x00A4},␊ |
523 | ␉{0x00F0,0x00D0},␊ |
524 | ␉{0x00F0,0x00D0},␊ |
525 | ␉{0x00EA,0x00CA},␊ |
526 | ␉{0x00EB,0x00CB},␊ |
527 | ␉{0x00E8,0x00C8},␊ |
528 | ␉{0x0131,0x0049},␊ |
529 | ␉{0x00ED,0x00CD},␊ |
530 | ␉{0x00EE,0x00CE},␊ |
531 | ␉{0x00EF,0x00CF},␊ |
532 | ␉{0x2518,0x2518},␊ |
533 | ␉{0x250C,0x250C},␊ |
534 | ␉{0x2588,0x2588},␊ |
535 | ␉{0x2584,0x2584},␊ |
536 | ␉{0x00A6,0x00A6},␊ |
537 | ␉{0x00EC,0x00CC},␊ |
538 | ␉{0x2580,0x2580},␊ |
539 | ␉{0x00F3,0x00D3},␊ |
540 | ␉{0x00DF,0x00DF},␊ |
541 | ␉{0x00F4,0x00D4},␊ |
542 | ␉{0x00F2,0x00D2},␊ |
543 | ␉{0x00F5,0x00D5},␊ |
544 | ␉{0x00F5,0x00D5},␊ |
545 | ␉{0x00B5,0x00B5},␊ |
546 | ␉{0x00FE,0x00DE},␊ |
547 | ␉{0x00FE,0x00DE},␊ |
548 | ␉{0x00FA,0x00DA},␊ |
549 | ␉{0x00FB,0x00DB},␊ |
550 | ␉{0x00F9,0x00D9},␊ |
551 | ␉{0x00FD,0x00DD},␊ |
552 | ␉{0x00FD,0x00DD},␊ |
553 | ␉{0x00AF,0x00AF},␊ |
554 | ␉{0x00B4,0x00B4},␊ |
555 | ␉{0x00AD,0x00AD},␊ |
556 | ␉{0x00B1,0x00B1},␊ |
557 | ␉{0x2017,0x2017},␊ |
558 | ␉{0x00BE,0x00BE},␊ |
559 | ␉{0x00B6,0x00B6},␊ |
560 | ␉{0x00A7,0x00A7},␊ |
561 | ␉{0x00F7,0x00F7},␊ |
562 | ␉{0x00B8,0x00B8},␊ |
563 | ␉{0x00B0,0x00B0},␊ |
564 | ␉{0x00A8,0x00A8},␊ |
565 | ␉{0x00B7,0x00B7},␊ |
566 | ␉{0x00B9,0x00B9},␊ |
567 | ␉{0x00B3,0x00B3},␊ |
568 | ␉{0x00B2,0x00B2},␊ |
569 | ␉{0x25A0,0x25A0},␊ |
570 | ␉{0x00A0,0x00A0}␊ |
571 | };␊ |
572 | ␊ |
573 | static int checkname (uint16_t *ucsname, int ucslen, struct direntry *dirp, uint16_t *vfatname)␊ |
574 | {␊ |
575 | ␉uint16_t tmp[15];␊ |
576 | ␉if (vfatname[0])␊ |
577 | ␉{␊ |
578 | ␉␉int i;␊ |
579 | ␉␉for (i=0;vfatname[i];i++);␊ |
580 | ␉␉return !FastUnicodeCompare (ucsname, ucslen, vfatname, i, OSLittleEndian);␊ |
581 | ␉}␊ |
582 | ␉else␊ |
583 | ␉{␊ |
584 | ␉␉int i, j, k;␊ |
585 | ␉␉for (i=7;i>=0;i--)␊ |
586 | ␉␉␉if (dirp->deName[i]!=' ')␊ |
587 | ␉␉␉␉break;␊ |
588 | ␉␉j=i+1;␊ |
589 | ␉␉tmp[i+1]=0;␊ |
590 | ␉␉for(;i>=0;i--)␊ |
591 | ␉␉␉tmp[i]=SWAP_LE16((dirp->deName[i]>=128)?cp850[dirp->deName[i]-128][0]:tolower(dirp->deName[i]));␊ |
592 | ␉␉for (i=2;i>=0;i--)␊ |
593 | ␉␉␉if (dirp->deName[8+i]!=' ')␊ |
594 | ␉␉␉␉break;␊ |
595 | ␉␉if (i>=0)␊ |
596 | ␉␉{␊ |
597 | ␉␉␉tmp[j++]='.';␊ |
598 | ␉␉␉tmp[j+i+1]=0;␊ |
599 | ␉␉␉k=j+i+1;␊ |
600 | ␉␉␉for(;i>=0;i--)␊ |
601 | ␉␉␉␉tmp[j+i]=SWAP_LE16((dirp->deName[i+8]>=128)?cp850[dirp->deName[i+8]-128][0]:tolower(dirp->deName[i+8]));␊ |
602 | ␉␉␉j=k;␊ |
603 | ␉␉}␊ |
604 | ␉␉return !FastUnicodeCompare (ucsname, ucslen, tmp, j, OSLittleEndian);␊ |
605 | ␉}␊ |
606 | ␉␊ |
607 | }␊ |
608 | ␊ |
609 | static struct direntry *getdirpfrompath (CICell ih, char *dirspec, uint8_t *buf)␊ |
610 | {␊ |
611 | ␉struct msdosdirstate st;␊ |
612 | ␉struct direntry *dirp;␊ |
613 | ␉uint8_t * ptr;␊ |
614 | ␉uint8_t *slash;␊ |
615 | ␉char c;␊ |
616 | ␉uint16_t␉␉vfatname[WIN_MAXLEN+2*WIN_CHARS];␊ |
617 | ␉uint16_t ucsname[WIN_MAXLEN+1];␊ |
618 | ␉uint16_t ucslen;␊ |
619 | ␉int ucslenhost;␊ |
620 | ␉initRoot (&st);␊ |
621 | ␉st.buf = (struct direntry *)buf;␊ |
622 | ␉ptr=(uint8_t*)dirspec;␊ |
623 | ␉for (slash=ptr;*slash && *slash!='/';slash++);␊ |
624 | ␉c=*slash;␊ |
625 | ␉*slash=0;␊ |
626 | ␉utf_decodestr (ptr, ucsname, &ucslen, WIN_MAXLEN, OSLittleEndian);␊ |
627 | ␉ucslenhost = OSReadLittleInt16 (&ucslen,0);␊ |
628 | ␉ucsname[ucslenhost]=0;␊ |
629 | ␉*slash=c;␉␊ |
630 | ␉while ((dirp = getnextdirent (ih, vfatname, &st)))␊ |
631 | ␉{␊ |
632 | ␉␉if (checkname (ucsname, ucslenhost, dirp, vfatname))␊ |
633 | ␉␉{␊ |
634 | ␉␉␉for (;*ptr && *ptr!='/';ptr++);␊ |
635 | ␉␉␉if (!*ptr)␊ |
636 | ␉␉␉{␊ |
637 | ␉␉␉␉return dirp;␊ |
638 | ␉␉␉}␊ |
639 | ␊ |
640 | ␉␉␉ptr++;␊ |
641 | ␉␉␉if (!*ptr)␊ |
642 | ␉␉␉{␊ |
643 | ␉␉␉␉return dirp;␊ |
644 | ␉␉␉}␊ |
645 | ␊ |
646 | ␉␉␉for (slash=ptr;*slash && *slash!='/';slash++);␊ |
647 | ␉␉␉c=*slash;␊ |
648 | ␉␉␉*slash=0;␊ |
649 | ␉␉␉utf_decodestr (ptr, ucsname, &ucslen, WIN_MAXLEN, OSLittleEndian);␊ |
650 | ␉␉␉ucslenhost = OSReadLittleInt16 (&ucslen,0);␊ |
651 | ␉␉␉ucsname[ucslenhost]=0;␊ |
652 | ␉␉␉*slash=c;␊ |
653 | ␉␉␉if (!(dirp->deAttributes & ATTR_DIRECTORY))␊ |
654 | ␉␉␉{␊ |
655 | ␉␉␉␉return 0;␊ |
656 | ␉␉␉}␊ |
657 | ␊ |
658 | ␉␉␉st.root16 = 0;␊ |
659 | ␉␉␉st.vfatchecksum = 0;␊ |
660 | ␉␉␉st.nument = 0;␊ |
661 | ␉␉␉st.cluster = OSReadLittleInt16 ((dirp->deStartCluster),0);␊ |
662 | ␉␉␉if (msdosfatbits == 32)␊ |
663 | ␉␉␉␉st.cluster |= ((uint32_t)OSReadLittleInt16 ((dirp->deHighClust),0)) <<16;␊ |
664 | ␉␉␉st.vfatnumber = 0;␊ |
665 | ␉␉}␊ |
666 | ␉}␊ |
667 | ␉return 0;␊ |
668 | }␊ |
669 | ␊ |
670 | long MSDOSGetDirEntry(CICell ih, char * dirPath, long long * dirIndex,␊ |
671 | ␉␉␉␉␉ char ** name, long * flags, u_int32_t * time,␊ |
672 | ␉␉␉␉␉ FinderInfo * finderInfo, long * infoValid)␊ |
673 | {␊ |
674 | ␉struct msdosdirstate␉*st;␊ |
675 | ␉struct direntry␉␉*dirp;␊ |
676 | ␉uint16_t␉␉vfatname[WIN_MAXLEN+2*WIN_CHARS];␊ |
677 | ␉if (MSDOSInitPartition (ih)<0)␊ |
678 | ␉{␊ |
679 | ␉␉return -1;␊ |
680 | ␉}␊ |
681 | ␊ |
682 | ␉if (dirPath[0] == '/')␊ |
683 | ␉{␊ |
684 | ␉␉dirPath++;␊ |
685 | ␉}␊ |
686 | ␊ |
687 | ␉st = (struct msdosdirstate *)(long) *dirIndex;␊ |
688 | ␉if (!st)␊ |
689 | ␉{␊ |
690 | ␉␉st=malloc (sizeof (struct msdosdirstate));␊ |
691 | ␉␉if (!st)␊ |
692 | ␉␉{␊ |
693 | ␉␉␉return -1;␊ |
694 | ␉␉}␊ |
695 | ␉␉bzero(st,sizeof (struct msdosdirstate) );␊ |
696 | ␉␉if (dirPath[0])␊ |
697 | ␉␉{␊ |
698 | ␉␉␉uint8_t *buf=malloc(msdosclustersize);␊ |
699 | ␉␉␉if (!buf)␊ |
700 | ␉␉␉{␊ |
701 | ␉␉␉␉free (st);␊ |
702 | ␉␉␉␉return -1;␊ |
703 | ␉␉␉}␊ |
704 | ␉␉␉bzero(buf,msdosclustersize );␊ |
705 | ␊ |
706 | ␉␉␉dirp = getdirpfrompath (ih, dirPath, buf);␊ |
707 | ␉␉␉if (!dirp || !(dirp->deAttributes & ATTR_DIRECTORY))␊ |
708 | ␉␉␉{␊ |
709 | ␉␉␉␉free (buf);␊ |
710 | ␉␉␉␉free (st);␊ |
711 | ␉␉␉␉return -1;␊ |
712 | ␉␉␉}␊ |
713 | ␉␉␉st->buf = (struct direntry *)buf;␊ |
714 | ␉␉␉st->root16 = 0;␊ |
715 | ␉␉␉st->vfatchecksum = 0;␊ |
716 | ␉␉␉st->nument = 0;␊ |
717 | ␉␉␉st->cluster = OSReadLittleInt16 ((dirp->deStartCluster),0);␊ |
718 | ␉␉␉st->vfatnumber = 0;␊ |
719 | ␉␉␉if (msdosfatbits == 32)␊ |
720 | ␉␉␉{␊ |
721 | ␉␉␉␉st->cluster |= ((uint32_t)OSReadLittleInt16 ((dirp->deHighClust),0)) <<16;␊ |
722 | ␉␉␉}␊ |
723 | ␊ |
724 | ␉␉}␊ |
725 | ␉␉else␊ |
726 | ␉␉{␊ |
727 | ␉␉␉initRoot (st);␊ |
728 | ␉␉}␊ |
729 | ␊ |
730 | ␉␉*dirIndex = (long long) (long) st;␊ |
731 | ␉}␊ |
732 | ␉while((dirp = getnextdirent (ih, vfatname, st))&& (dirp->deAttributes & ATTR_VOLUME));␊ |
733 | ␉if (!dirp)␊ |
734 | ␉{␊ |
735 | ␉␉free (st->buf);␊ |
736 | ␉␉free (st);␊ |
737 | ␉␉return -1;␊ |
738 | ␉}␊ |
739 | ␉if (vfatname[0])␊ |
740 | ␉{␊ |
741 | ␉␉int i;␊ |
742 | ␉␉for (i=0;vfatname[i];i++);␊ |
743 | ␉␉*name = malloc (256);␊ |
744 | ␉␉if (!*name) ␊ |
745 | ␉␉{␊ |
746 | ␉␉␉free (st->buf);␊ |
747 | ␉␉␉free (st);␊ |
748 | ␉␉␉return -1;␊ |
749 | ␉␉}␊ |
750 | ␉␉utf_encodestr(vfatname, i, (u_int8_t *)*name, 255, OSLittleEndian );␉␊ |
751 | ␉}␊ |
752 | ␉else␊ |
753 | ␉{␊ |
754 | ␉␉int i, j, k;␊ |
755 | ␉␉uint16_t tmp[13];␊ |
756 | ␉␉*name = malloc (26);␊ |
757 | ␉␉if (!*name) ␊ |
758 | ␉␉{␊ |
759 | ␉␉␉free (st->buf);␊ |
760 | ␉␉␉free (st);␊ |
761 | ␉␉␉return -1;␊ |
762 | ␉␉}␊ |
763 | ␊ |
764 | ␉␉for (i=7;i>=0;i--)␊ |
765 | ␉␉{␊ |
766 | ␉␉␉if (dirp->deName[i]!=' ')␊ |
767 | ␉␉␉{␊ |
768 | ␉␉␉␉break;␊ |
769 | ␉␉␉}␊ |
770 | ␉␉}␊ |
771 | ␊ |
772 | ␉␉j=i+1;␊ |
773 | ␉␉tmp[i+1]=0;␊ |
774 | ␉␉for(;i>=0;i--)␊ |
775 | ␉␉␉tmp[i]=(dirp->deName[i]>=128)?cp850[dirp->deName[i]-128][0]:tolower(dirp->deName[i]);␊ |
776 | ␉␉for (i=2;i>=0;i--)␊ |
777 | ␉␉{␊ |
778 | ␉␉␉if (dirp->deName[8+i]!=' ')␊ |
779 | ␉␉␉{␊ |
780 | ␉␉␉␉break;␊ |
781 | ␉␉␉}␊ |
782 | ␉␉}␊ |
783 | ␊ |
784 | ␉␉if (i>=0)␊ |
785 | ␉␉{␊ |
786 | ␉␉␉tmp[j++]='.';␊ |
787 | ␉␉␉tmp[j+i+1]=0;␊ |
788 | ␉␉␉k=j+i+1;␊ |
789 | ␉␉␉for(;i>=0;i--)␊ |
790 | ␉␉␉{␊ |
791 | ␉␉␉␉tmp[j+i]=(dirp->deName[i]>=128)?cp850[dirp->deName[i+8]-128][0]:tolower(dirp->deName[i+8]);␊ |
792 | ␉␉␉}␊ |
793 | ␊ |
794 | ␉␉␉j=k;␊ |
795 | ␉␉}␊ |
796 | ␉␉␊ |
797 | ␉␉utf_encodestr(tmp, j, (uint8_t*)*name, 25, OSHostByteOrder() );␊ |
798 | ␉}␊ |
799 | ␊ |
800 | ␉if (dirp->deAttributes & ATTR_DIRECTORY)␊ |
801 | ␉{␊ |
802 | ␉␉*flags = kFileTypeDirectory;␊ |
803 | ␉}␊ |
804 | ␉else␊ |
805 | ␉{␊ |
806 | ␉␉*flags = kFileTypeFlat;␊ |
807 | ␉}␊ |
808 | ␊ |
809 | ␉// Calculate a fake timestamp using modification date and time values.␊ |
810 | ␉*time = ((dirp->deMDate & 0x7FFF) << 16) + dirp->deMTime;␊ |
811 | ␉␊ |
812 | ␉if (infoValid)␊ |
813 | ␉{␊ |
814 | ␉␉*infoValid = 1;␊ |
815 | ␉}␊ |
816 | ␊ |
817 | ␉return 0;␊ |
818 | }␊ |
819 | ␊ |
820 | long MSDOSReadFile(CICell ih, char * filePath, void *base, uint64_t offset, uint64_t length)␊ |
821 | {␊ |
822 | ␉uint8_t *buf;␊ |
823 | ␉off_t cluster;␊ |
824 | ␉uint64_t size;␊ |
825 | ␉uint64_t nskip;␊ |
826 | ␉int toread, wastoread;␊ |
827 | ␉char *ptr = (char *)base;␊ |
828 | ␉struct direntry *dirp;␊ |
829 | ␉uint64_t i;␊ |
830 | ␉char devStr[12];␊ |
831 | ␊ |
832 | ␉if (MSDOSInitPartition (ih)<0)␊ |
833 | ␉{␊ |
834 | ␉␉return -1;␊ |
835 | ␉}␊ |
836 | ␊ |
837 | ␉if (filePath[0] == '/')␊ |
838 | ␉{␊ |
839 | ␉␉filePath++;␊ |
840 | ␉}␊ |
841 | ␊ |
842 | ␉buf = malloc(msdosclustersize);␊ |
843 | ␊ |
844 | ␉if (!buf)␊ |
845 | ␉{␊ |
846 | ␉␉return -1;␊ |
847 | ␉}␊ |
848 | ␊ |
849 | ␉bzero(buf,msdosclustersize);␊ |
850 | ␉dirp = getdirpfrompath (ih, filePath, buf);␊ |
851 | ␉␊ |
852 | ␉if (!dirp || (dirp->deAttributes & ATTR_DIRECTORY))␊ |
853 | ␉{␊ |
854 | ␉␉free (buf);␊ |
855 | ␉␉return -1;␊ |
856 | ␉}␊ |
857 | ␊ |
858 | ␉cluster = OSReadLittleInt16 ((dirp->deStartCluster),0);␊ |
859 | ␊ |
860 | ␉if (msdosfatbits == 32)␊ |
861 | ␉{␊ |
862 | ␉␉cluster |= ((uint32_t)OSReadLittleInt16 ((dirp->deHighClust),0)) <<16;␊ |
863 | ␉}␊ |
864 | ␊ |
865 | ␉size = (uint32_t)OSReadLittleInt32 ((dirp->deFileSize),0);␊ |
866 | ␊ |
867 | ␉if (size<=offset)␊ |
868 | ␉{␊ |
869 | ␉␉free (buf);␊ |
870 | ␉␉return -1;␊ |
871 | ␉}␊ |
872 | ␊ |
873 | ␉nskip=offset/msdosclustersize;␊ |
874 | ␊ |
875 | ␉for (i = 0; i < nskip; i++)␊ |
876 | ␉{␊ |
877 | ␉␉msdosreadcluster (ih, 0, 0, &cluster);␊ |
878 | ␉}␊ |
879 | ␊ |
880 | ␉msdosreadcluster (ih, buf, msdosclustersize, &cluster);␊ |
881 | ␉toread=length;␊ |
882 | ␊ |
883 | ␉if (length==0 || length>size-offset)␊ |
884 | ␉{␊ |
885 | ␉␉toread=size-offset;␊ |
886 | ␉}␊ |
887 | ␊ |
888 | ␉wastoread=toread;␊ |
889 | ␉bcopy (buf+(offset%msdosclustersize),ptr,MIN((msdosclustersize-(offset%msdosclustersize)),(unsigned)toread));␊ |
890 | ␉ptr+=msdosclustersize-(offset%msdosclustersize);␊ |
891 | ␉toread-=msdosclustersize-(offset%msdosclustersize);␊ |
892 | ␉while (toread>0 && msdosreadcluster (ih, (uint8_t *)ptr, MIN(msdosclustersize,toread), &cluster))␊ |
893 | ␉{␊ |
894 | ␉␉ptr+=msdosclustersize;␊ |
895 | ␉␉toread-=msdosclustersize;␊ |
896 | ␉}␊ |
897 | ␉␊ |
898 | ␉getDeviceDescription(ih, devStr);␊ |
899 | ␉verbose("Read FAT%d file: [%s/%s] %d bytes.\n", msdosfatbits, devStr, filePath, (uint32_t)( toread<0 ) ? wastoread : wastoread-toread);␊ |
900 | ␉free (buf);␊ |
901 | ␉if (toread<0)␊ |
902 | ␉{␊ |
903 | ␉␉return wastoread;␊ |
904 | ␉}␊ |
905 | ␉else␊ |
906 | ␉{␊ |
907 | ␉␉return wastoread-toread;␊ |
908 | ␉}␊ |
909 | }␊ |
910 | ␊ |
911 | long MSDOSGetFileBlock(CICell ih, char *filePath, unsigned long long *firstBlock)␊ |
912 | {␊ |
913 | ␉uint8_t *buf;␊ |
914 | ␉off_t cluster;␊ |
915 | ␉struct direntry *dirp;␊ |
916 | ␊ |
917 | ␉if (MSDOSInitPartition (ih)<0)␊ |
918 | ␉{␊ |
919 | ␉␉return -1;␊ |
920 | ␉}␊ |
921 | ␊ |
922 | ␉if (filePath[0] == '/')␊ |
923 | ␉{␊ |
924 | ␉␉filePath++;␊ |
925 | ␉}␊ |
926 | ␊ |
927 | ␉buf = malloc(msdosclustersize);␊ |
928 | ␊ |
929 | ␉if (!buf)␊ |
930 | ␉{␊ |
931 | ␉␉return -1;␊ |
932 | ␉}␊ |
933 | ␉bzero(buf,msdosclustersize);␊ |
934 | ␊ |
935 | ␉dirp = getdirpfrompath (ih, filePath, buf);␊ |
936 | ␊ |
937 | ␉if (!dirp || (dirp->deAttributes & ATTR_DIRECTORY))␊ |
938 | ␉{␊ |
939 | ␉␉free (buf);␊ |
940 | ␉␉return -1;␊ |
941 | ␉}␊ |
942 | ␊ |
943 | ␉cluster = OSReadLittleInt16 ((dirp->deStartCluster),0);␊ |
944 | ␊ |
945 | ␉if (msdosfatbits == 32)␊ |
946 | ␉{␊ |
947 | ␉␉cluster |= ((uint32_t)OSReadLittleInt16 ((dirp->deHighClust),0)) <<16;␊ |
948 | ␉}␊ |
949 | ␊ |
950 | ␉off_t clusn;␊ |
951 | ␉␊ |
952 | ␉switch (msdosfatbits)␊ |
953 | ␉{␊ |
954 | ␉␉case 32:␊ |
955 | ␉␉␉if (cluster < CLUST_FIRST ||cluster >= CLUST_RSRVD32)␊ |
956 | ␉␉␉{␊ |
957 | ␉␉␉␉return -1;␊ |
958 | ␉␉␉}␊ |
959 | ␊ |
960 | ␉␉␉clusn = cluster - CLUST_FIRST;␊ |
961 | ␉␉␉break;␊ |
962 | ␉␉case 16:␊ |
963 | ␉␉␉if (cluster < CLUST_FIRST ||cluster >= CLUST_RSRVD16)␊ |
964 | ␉␉␉{␊ |
965 | ␉␉␉␉return 0;␊ |
966 | ␉␉␉}␊ |
967 | ␊ |
968 | ␉␉␉clusn = cluster - CLUST_FIRST;␊ |
969 | ␉␉␉break;␉␉␉␊ |
970 | ␉␉case 12:␊ |
971 | ␉␉␉␊ |
972 | ␉␉␉if (cluster < CLUST_FIRST ||cluster >= CLUST_RSRVD12)␊ |
973 | ␉␉␉{␊ |
974 | ␉␉␉␉return 0;␊ |
975 | ␉␉␉}␊ |
976 | ␊ |
977 | ␉␉␉clusn = cluster - CLUST_FIRST;␊ |
978 | ␉␉␉break;␊ |
979 | ␉␉default:␊ |
980 | ␉␉␉return 0;␊ |
981 | ␉}␊ |
982 | ␉␊ |
983 | ␉*firstBlock = ((msdosressector +␊ |
984 | ␉␉␉␉ (msdosnfats * msdosfatsecs))*msdosbps + clusn * msdosclustersize)/512;␊ |
985 | ␉free (buf);␊ |
986 | ␉return 0;␊ |
987 | }␊ |
988 | ␊ |
989 | ␊ |
990 | long MSDOSLoadFile(CICell ih, char * filePath)␊ |
991 | {␊ |
992 | ␉return MSDOSReadFile(ih, filePath, (void *)gFSLoadAddress, 0, 0);␊ |
993 | }␊ |
994 | ␊ |
995 | /* Fix up volume label. */␊ |
996 | static void fixLabel(uint8_t *label, char *str, long strMaxLen)␊ |
997 | {␊ |
998 | ␉int␉␉␉i, len;␊ |
999 | ␉uint16_t␉␉labelucs[13];␊ |
1000 | ␉//unsigned char␉␉labelUTF8[LABEL_LENGTH*3];␊ |
1001 | ␉␊ |
1002 | ␉/* Convert leading 0x05 to 0xE5 for multibyte languages like Japanese */␊ |
1003 | ␉if (label[0] == 0x05)␊ |
1004 | ␉label[0] = 0xE5;␊ |
1005 | ␉␊ |
1006 | ␉/* Remove any trailing spaces */␊ |
1007 | ␉for (i=LABEL_LENGTH-1; i>=0; --i)␊ |
1008 | ␉{␊ |
1009 | ␉␉if (label[i] == ' ')␊ |
1010 | ␉␉{␊ |
1011 | ␉ label[i] = 0;␊ |
1012 | ␉␉}␊ |
1013 | ␉␉else␊ |
1014 | ␉␉{␊ |
1015 | ␉␉␉break;␊ |
1016 | ␉␉}␊ |
1017 | ␉}␊ |
1018 | ␊ |
1019 | ␉labelucs[i++]=0;␊ |
1020 | ␉len=i;␊ |
1021 | ␉for (;i>=0;--i)␊ |
1022 | ␉{␊ |
1023 | ␉␉labelucs[i]=label[i]>=128?cp850[label[i]-128][1]:(label[i]);␊ |
1024 | ␉}␊ |
1025 | ␊ |
1026 | ␉utf_encodestr(labelucs, len, (uint8_t *)str, strMaxLen, OSHostByteOrder() );␊ |
1027 | }␊ |
1028 | ␊ |
1029 | void MSDOSGetDescription(CICell ih, char *str, long strMaxLen)␊ |
1030 | {␊ |
1031 | ␉struct direntry *dirp;␊ |
1032 | ␉uint8_t label[LABEL_LENGTH+1];␊ |
1033 | ␉uint16_t vfatlabel[WIN_MAXLEN+2*WIN_CHARS];␊ |
1034 | ␉struct msdosdirstate st;␊ |
1035 | ␉int labelfound = 0;␊ |
1036 | ␊ |
1037 | ␉if (MSDOSInitPartition(ih) < 0)␊ |
1038 | ␉{␊ |
1039 | ␉␉str[0]=0;␊ |
1040 | ␉␉return;␊ |
1041 | ␉}␊ |
1042 | ␊ |
1043 | ␉bzero(label,sizeof(label));␊ |
1044 | ␉bzero(vfatlabel,sizeof(vfatlabel));␊ |
1045 | ␊ |
1046 | ␉label[0] = '\0';␊ |
1047 | ␉␊ |
1048 | ␉initRoot(&st);␊ |
1049 | ␉st.buf = malloc(msdosclustersize);␊ |
1050 | ␉if (!st.buf)␊ |
1051 | ␉{␊ |
1052 | ␉␉return;␊ |
1053 | ␉}␊ |
1054 | ␉bzero(st.buf,msdosclustersize);␊ |
1055 | ␊ |
1056 | ␉while ((dirp = getnextdirent (ih, vfatlabel, &st)))␊ |
1057 | ␉␉if (dirp->deAttributes & ATTR_VOLUME)␊ |
1058 | ␉␉{␊ |
1059 | ␉␉␉strncpy((char *)label, (char *)dirp->deName, LABEL_LENGTH);␊ |
1060 | ␉␉␉labelfound = 1;␊ |
1061 | ␉␉␉break;␊ |
1062 | ␉␉}␊ |
1063 | ␊ |
1064 | ␉free(st.buf);␉␉␊ |
1065 | ␊ |
1066 | ␉if (vfatlabel[0] && labelfound)␊ |
1067 | ␉{␊ |
1068 | ␉␉int i;␊ |
1069 | ␉␉for (i=0;vfatlabel[i];i++);␊ |
1070 | ␉␉utf_encodestr(vfatlabel, i, (u_int8_t *)str, strMaxLen, OSLittleEndian );␉␉␊ |
1071 | ␉}␉␊ |
1072 | ␉else if (labelfound)␊ |
1073 | ␉{␊ |
1074 | ␉␉fixLabel(label, str, strMaxLen);␊ |
1075 | ␉}␊ |
1076 | ␊ |
1077 | ␉/* else look in the boot blocks */␊ |
1078 | ␉if (!labelfound || str[0] == '\0')␊ |
1079 | ␉{␊ |
1080 | ␉␉char *buf = malloc (512);␊ |
1081 | ␉␉if (!buf)␊ |
1082 | ␉␉{␊ |
1083 | ␉␉␉return;␊ |
1084 | ␉␉}␊ |
1085 | ␉␉union bootsector *bsp = (union bootsector *)buf;␊ |
1086 | ␉␉Seek(ih, 0);␊ |
1087 | ␉␉Read(ih, (long)buf, 512);␊ |
1088 | ␉␉if (msdosfatbits == 32)␊ |
1089 | ␉␉{␊ |
1090 | ␉␉␉/* It's FAT32 */␊ |
1091 | ␉␉␉strncpy((char *)label, (char *)((struct extboot *)bsp->bs710.bsExt)->exVolumeLabel, LABEL_LENGTH);␊ |
1092 | ␉␉}␊ |
1093 | ␉␉else if (msdosfatbits == 16)␊ |
1094 | ␉␉{␊ |
1095 | ␉␉␉strncpy((char *)label, (char *)((struct extboot *)bsp->bs50.bsExt)->exVolumeLabel, LABEL_LENGTH);␊ |
1096 | ␉␉}␊ |
1097 | ␉␉free (buf);␊ |
1098 | ␉␉fixLabel(label, str, strMaxLen);␊ |
1099 | ␉}␊ |
1100 | ␉verbose("MSDOS: label=%s\n", str);␊ |
1101 | ␊ |
1102 | ␉return;␊ |
1103 | }␊ |
1104 | ␊ |
1105 | long MSDOSGetUUID(CICell ih, char *uuidStr)␊ |
1106 | {␊ |
1107 | ␉char *buf = malloc (512);␊ |
1108 | ␉if (!buf)␊ |
1109 | ␉{␊ |
1110 | ␉␉return -1;␊ |
1111 | ␉}␊ |
1112 | ␉union bootsector *bsp = (union bootsector *)buf;␊ |
1113 | ␊ |
1114 | ␉if (MSDOSInitPartition (ih)<0)␊ |
1115 | ␉{␊ |
1116 | ␉␉free (buf);␊ |
1117 | ␉␉return -1;␊ |
1118 | ␉}␊ |
1119 | ␉bzero (uuidStr, 16);␊ |
1120 | ␉Seek(ih, 0);␊ |
1121 | ␉Read(ih, (long)buf, 512);␊ |
1122 | ␉if (msdosfatbits == 32) { /* It's FAT32 */␊ |
1123 | ␉␉memcpy(uuidStr+12, (char *)((struct extboot *)bsp->bs710.bsExt)->exVolumeID, 4);␊ |
1124 | ␉}␊ |
1125 | ␉else if (msdosfatbits == 16)␊ |
1126 | ␉{␊ |
1127 | ␉␉memcpy(uuidStr+12, (char *)((struct extboot *)bsp->bs50.bsExt)->exVolumeID, 4);␊ |
1128 | ␉}␊ |
1129 | ␉free (buf);␊ |
1130 | ␉return 0;␊ |
1131 | }␊ |
1132 | |