Chameleon Applications

Chameleon Applications Svn Source Tree

Root/branches/trunk/i386/libsaio/msdos.c

Source at commit 173 created 13 years 6 months ago.
By ifabio, upload my branch. Add Blackosx background & icon Merged all the scrax's change
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: 173