Chameleon Applications

Chameleon Applications Svn Source Tree

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

Archive Download this file

Revision: 214