Chameleon

Chameleon Svn Source Tree

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

Source at commit 429 created 13 years 9 months ago.
By meklort, Updated module system. Hooks can now be used within modules when cetaion functions are called in chameleon. Note that onle two hooks currently exist, more need to be added. I also updated the HelloWorld module to use a hook instead of print out right away.
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 MAX_DOS_BLOCKSIZE2048
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, msdosclustersize);
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;
223
224msdoscurrent = ih;
225CacheInit(ih, msdosclustersize);
226free (buf);
227return 0;
228}
229
230static int
231msdosreadcluster (CICell ih, uint8_t *buf, int size, off_t *cluster)
232{
233 off_t readOffset;
234char tmpbuf[8];
235off_t clusn;
236
237switch (msdosfatbits) {
238case 32:
239if (*cluster < CLUST_FIRST ||*cluster >= CLUST_RSRVD32)
240return 0;
241clusn = *cluster - CLUST_FIRST;
242break;
243case 16:
244if (*cluster < CLUST_FIRST ||*cluster >= CLUST_RSRVD16)
245return 0;
246clusn = *cluster - CLUST_FIRST;
247break;
248case 12:
249if (*cluster < CLUST_FIRST ||*cluster >= CLUST_RSRVD12)
250return 0;
251clusn = *cluster - CLUST_FIRST;
252break;
253default:
254return 0;
255}
256
257/* Find sector where clusters start */
258readOffset = (msdosressector +
259 (msdosnfats * msdosfatsecs)+msdosrootDirSectors)*msdosbps;
260/* Find sector where "cluster" starts */
261readOffset += clusn * msdosclustersize;
262
263/* Read in "cluster" */
264if (buf)
265{
266Seek(ih, readOffset);
267Read(ih, (long)buf, size);
268}
269
270/* Find first sector of FAT */
271readOffset = msdosressector*msdosbps;
272/* Find sector containing "cluster" entry in FAT */
273readOffset += ((uint64_t)*cluster * (uint64_t)msdosfatbits)/8;
274
275/* Read one sector of the FAT */
276Seek(ih, readOffset);
277Read(ih, (long)tmpbuf, 4);
278
279switch (msdosfatbits) {
280case 32:
281*cluster = OSReadLittleInt32(tmpbuf, 0);
282*cluster &= 0x0FFFFFFF;// ignore reserved upper bits
283return 1;
284case 16:
285*cluster = OSReadLittleInt16(tmpbuf, 0);
286return 1;
287case 12:
288*cluster = OSReadLittleInt16(tmpbuf, 0)>>(((uint64_t)*cluster * (uint64_t)msdosfatbits)%8);
289*cluster &= 0xfff;
290return 1;
291default:
292return 0;
293}
294}
295
296struct msdosdirstate
297{
298struct direntry *buf;
299uint8_t vfatchecksum;
300int root16;
301off_t cluster;
302int nument;
303int vfatnumber;
304};
305
306static struct direntry *
307getnextdirent (CICell ih, uint16_t *longname, struct msdosdirstate *st)
308{
309struct direntry *dirp;
310while (1)
311{
312if (st->root16)
313{
314if (st->cluster >= msdosrootDirSectors && st->nument == 0)
315return 0;
316if (st->nument == 0)
317{
318Seek(ih, (msdosressector +
319 (msdosnfats * msdosfatsecs)+st->cluster)*msdosbps);
320Read(ih, (long)st->buf, msdosbps);
321st->cluster++;
322}
323} else if (st->nument == 0 && !msdosreadcluster (ih, (uint8_t *)st->buf, msdosclustersize, &(st->cluster)))
324return 0;
325
326dirp=st->buf+st->nument;
327
328if (dirp->deName[0] == SLOT_EMPTY)
329return 0;
330else if (dirp->deName[0] == SLOT_DELETED)
331st->vfatnumber = 0;
332else if (dirp->deAttributes == ATTR_WIN95)
333{
334struct winentry *wdirp = (struct winentry *)dirp;
335int num;
336if (wdirp->weCnt & 0x80)
337continue;
338num=(wdirp->weCnt&0x3f);
339if (WIN_CHARS * num > WIN_MAXLEN)
340continue;
341if (st->vfatchecksum!=wdirp->weChksum)
342{
343st->vfatnumber = 0;
344st->vfatchecksum = wdirp->weChksum;
345}
346if (st->vfatnumber < num)
347st->vfatnumber = num;
348bcopy (&(wdirp->wePart1),longname+WIN_CHARS*(num-1),sizeof (wdirp->wePart1));
349bcopy (&(wdirp->wePart2),longname+WIN_CHARS*(num-1)+5,sizeof (wdirp->wePart2));
350bcopy (&(wdirp->wePart3),longname+WIN_CHARS*(num-1)+11,sizeof (wdirp->wePart3));
351} else {
352uint8_t labelchecksum;
353int i;
354longname[st->vfatnumber*WIN_CHARS]=0;
355
356labelchecksum=0;
357for(i=0;i<LABEL_LENGTH;i++)
358labelchecksum=(labelchecksum>>1)+(labelchecksum<<7)+dirp->deName[i];
359if (!(labelchecksum==st->vfatchecksum && st->vfatnumber))
360longname[0]=0;
361st->vfatnumber = 0;
362st->vfatchecksum = 0;
363st->vfatnumber = 0;
364st->nument++;
365if ((!st->root16 &&st->nument * sizeof (struct direntry)>=msdosclustersize)
366|| (st->root16 &&st->nument * sizeof (struct direntry)>=msdosbps))
367st->nument = 0;
368return dirp;
369}
370st->nument++;
371if ((!st->root16 &&st->nument * sizeof (struct direntry)>=msdosclustersize)
372|| (st->root16 &&st->nument * sizeof (struct direntry)>=msdosbps))
373st->nument = 0;
374}
375}
376
377static void
378initRoot (struct msdosdirstate *st)
379{
380if (msdosrootDirSectors) {/* FAT12 or FAT16 */
381st->root16 = 1;
382st->vfatchecksum = 0;
383st->nument = 0;
384st->cluster = 0;
385st->vfatnumber = 0;
386} else {/* FAT32 */
387st->root16 = 0;
388st->vfatchecksum = 0;
389st->nument = 0;
390st->cluster = msdosrootcluster;
391st->vfatnumber = 0;
392}
393}
394
395/* First comes lowercase, then uppercase*/
396static uint16_t cp850[128][2]=
397{
398{0x00E7,0x00C7},
399{0x00FC,0x00DC},
400{0x00E9,0x00C9},
401{0x00E2,0x00C2},
402{0x00E4,0x00C4},
403{0x00E0,0x00C0},
404{0x00E5,0x00C5},
405{0x00E7,0x00C7},
406{0x00EA,0x00CA},
407{0x00EB,0x00CB},
408{0x00E8,0x00C8},
409{0x00EF,0x00CF},
410{0x00EE,0x00CE},
411{0x00EC,0x00CC},
412{0x00E4,0x00C4},
413{0x00E5,0x00C5},
414{0x00E9,0x00C9},
415{0x00E6,0x00C6},
416{0x00E6,0x00C6},
417{0x00F4,0x00D4},
418{0x00F6,0x00D6},
419{0x00F2,0x00D2},
420{0x00FB,0x00DB},
421{0x00F9,0x00D9},
422{0x00FF,0x0178},
423{0x00F6,0x00D6},
424{0x00FC,0x00DC},
425{0x00F8,0x00D8},
426{0x00A3,0x00A3},
427{0x00F8,0x00D8},
428{0x00D7,0x00D7},
429{0x0192,0x0191},
430{0x00E1,0x00C1},
431{0x00ED,0x00CD},
432{0x00F3,0x00D3},
433{0x00FA,0x00DA},
434{0x00F1,0x00D1},
435{0x00F1,0x00D1},
436{0x00AA,0x00AA},
437{0x00BA,0x00BA},
438{0x00BF,0x00BF},
439{0x00AE,0x00AE},
440{0x00AC,0x00AC},
441{0x00BD,0x00BD},
442{0x00BC,0x00BC},
443{0x00A1,0x00A1},
444{0x00AB,0x00AB},
445{0x00BB,0x00BB},
446{0x2591,0x2591},
447{0x2592,0x2592},
448{0x2593,0x2593},
449{0x2502,0x2502},
450{0x2524,0x2524},
451{0x00E1,0x00C1},
452{0x00E2,0x00C2},
453{0x00E0,0x00C0},
454{0x00A9,0x00A9},
455{0x2563,0x2563},
456{0x2551,0x2551},
457{0x2557,0x2557},
458{0x255D,0x255D},
459{0x00A2,0x00A2},
460{0x00A5,0x00A5},
461{0x2510,0x2510},
462{0x2514,0x2514},
463{0x2534,0x2534},
464{0x252C,0x252C},
465{0x251C,0x251C},
466{0x2500,0x2500},
467{0x253C,0x253C},
468{0x00E3,0x00C3},
469{0x00E3,0x00C3},
470{0x255A,0x255A},
471{0x2554,0x2554},
472{0x2569,0x2569},
473{0x2566,0x2566},
474{0x2560,0x2560},
475{0x2550,0x2550},
476{0x256C,0x256C},
477{0x00A4,0x00A4},
478{0x00F0,0x00D0},
479{0x00F0,0x00D0},
480{0x00EA,0x00CA},
481{0x00EB,0x00CB},
482{0x00E8,0x00C8},
483{0x0131,0x0049},
484{0x00ED,0x00CD},
485{0x00EE,0x00CE},
486{0x00EF,0x00CF},
487{0x2518,0x2518},
488{0x250C,0x250C},
489{0x2588,0x2588},
490{0x2584,0x2584},
491{0x00A6,0x00A6},
492{0x00EC,0x00CC},
493{0x2580,0x2580},
494{0x00F3,0x00D3},
495{0x00DF,0x00DF},
496{0x00F4,0x00D4},
497{0x00F2,0x00D2},
498{0x00F5,0x00D5},
499{0x00F5,0x00D5},
500{0x00B5,0x00B5},
501{0x00FE,0x00DE},
502{0x00FE,0x00DE},
503{0x00FA,0x00DA},
504{0x00FB,0x00DB},
505{0x00F9,0x00D9},
506{0x00FD,0x00DD},
507{0x00FD,0x00DD},
508{0x00AF,0x00AF},
509{0x00B4,0x00B4},
510{0x00AD,0x00AD},
511{0x00B1,0x00B1},
512{0x2017,0x2017},
513{0x00BE,0x00BE},
514{0x00B6,0x00B6},
515{0x00A7,0x00A7},
516{0x00F7,0x00F7},
517{0x00B8,0x00B8},
518{0x00B0,0x00B0},
519{0x00A8,0x00A8},
520{0x00B7,0x00B7},
521{0x00B9,0x00B9},
522{0x00B3,0x00B3},
523{0x00B2,0x00B2},
524{0x25A0,0x25A0},
525{0x00A0,0x00A0}
526};
527
528static int
529checkname (uint16_t *ucsname, int ucslen, struct direntry *dirp, uint16_t *vfatname)
530{
531uint16_t tmp[15];
532if (vfatname[0])
533{
534int i;
535for (i=0;vfatname[i];i++);
536return !FastUnicodeCompare (ucsname, ucslen, vfatname, i, OSLittleEndian);
537}
538else
539{
540int i, j, k;
541for (i=7;i>=0;i--)
542if (dirp->deName[i]!=' ')
543break;
544j=i+1;
545tmp[i+1]=0;
546for(;i>=0;i--)
547tmp[i]=SWAP_LE16((dirp->deName[i]>=128)?cp850[dirp->deName[i]-128][0]:tolower(dirp->deName[i]));
548for (i=2;i>=0;i--)
549if (dirp->deName[8+i]!=' ')
550break;
551if (i>=0)
552{
553tmp[j++]='.';
554tmp[j+i+1]=0;
555k=j+i+1;
556for(;i>=0;i--)
557tmp[j+i]=SWAP_LE16((dirp->deName[i+8]>=128)?cp850[dirp->deName[i+8]-128][0]:tolower(dirp->deName[i+8]));
558j=k;
559}
560return !FastUnicodeCompare (ucsname, ucslen, tmp, j, OSLittleEndian);
561}
562
563}
564
565static struct direntry *
566getdirpfrompath (CICell ih, char *dirspec, uint8_t *buf)
567{
568struct msdosdirstate st;
569struct direntry *dirp;
570uint8_t * ptr;
571uint8_t *slash;
572char c;
573uint16_tvfatname[WIN_MAXLEN+2*WIN_CHARS];
574uint16_t ucsname[WIN_MAXLEN+1];
575uint16_t ucslen;
576int ucslenhost;
577initRoot (&st);
578st.buf = (struct direntry *)buf;
579ptr=(uint8_t*)dirspec;
580for (slash=ptr;*slash && *slash!='/';slash++);
581c=*slash;
582*slash=0;
583utf_decodestr (ptr, ucsname, &ucslen, WIN_MAXLEN, OSLittleEndian);
584ucslenhost = OSReadLittleInt16 (&ucslen,0);
585ucsname[ucslenhost]=0;
586*slash=c;
587while ((dirp = getnextdirent (ih, vfatname, &st)))
588{
589if (checkname (ucsname, ucslenhost, dirp, vfatname))
590{
591for (;*ptr && *ptr!='/';ptr++);
592if (!*ptr)
593return dirp;
594ptr++;
595if (!*ptr)
596return dirp;
597for (slash=ptr;*slash && *slash!='/';slash++);
598c=*slash;
599*slash=0;
600utf_decodestr (ptr, ucsname, &ucslen, WIN_MAXLEN, OSLittleEndian);
601ucslenhost = OSReadLittleInt16 (&ucslen,0);
602ucsname[ucslenhost]=0;
603*slash=c;
604if (!(dirp->deAttributes & ATTR_DIRECTORY))
605return 0;
606st.root16 = 0;
607st.vfatchecksum = 0;
608st.nument = 0;
609st.cluster = OSReadLittleInt16 ((dirp->deStartCluster),0);
610if (msdosfatbits == 32)
611st.cluster |= ((uint32_t)OSReadLittleInt16 ((dirp->deHighClust),0)) <<16;
612st.vfatnumber = 0;
613}
614}
615return 0;
616}
617
618long MSDOSGetDirEntry(CICell ih, char * dirPath, long * dirIndex,
619 char ** name, long * flags, long * time,
620 FinderInfo * finderInfo, long * infoValid)
621{
622struct msdosdirstate *st;
623struct direntry *dirp;
624uint16_tvfatname[WIN_MAXLEN+2*WIN_CHARS];
625if (MSDOSInitPartition (ih)<0)
626return -1;
627if (dirPath[0] == '/')
628dirPath++;
629st = (struct msdosdirstate *)*dirIndex;
630if (!st)
631{
632st=malloc (sizeof (*st));
633if (dirPath[0])
634{
635uint8_t *buf=malloc(msdosclustersize);
636dirp = getdirpfrompath (ih, dirPath, buf);
637if (!dirp || !(dirp->deAttributes & ATTR_DIRECTORY))
638{
639free (buf);
640free (st);
641return -1;
642}
643st->buf = (struct direntry *)buf;
644st->root16 = 0;
645st->vfatchecksum = 0;
646st->nument = 0;
647st->cluster = OSReadLittleInt16 ((dirp->deStartCluster),0);
648st->vfatnumber = 0;
649if (msdosfatbits == 32)
650st->cluster |= ((uint32_t)OSReadLittleInt16 ((dirp->deHighClust),0)) <<16;
651}
652else
653initRoot (st);
654*dirIndex = (long)st;
655}
656while((dirp = getnextdirent (ih, vfatname, st))&& (dirp->deAttributes & ATTR_VOLUME));
657if (!dirp)
658{
659free (st->buf);
660free (st);
661return -1;
662}
663if (vfatname[0])
664{
665int i;
666for (i=0;vfatname[i];i++);
667*name = malloc (256);
668utf_encodestr(vfatname, i, (u_int8_t *)*name, 255, OSLittleEndian );
669}
670else
671{
672int i, j, k;
673uint16_t tmp[13];
674*name = malloc (26);
675for (i=7;i>=0;i--)
676if (dirp->deName[i]!=' ')
677break;
678j=i+1;
679tmp[i+1]=0;
680for(;i>=0;i--)
681tmp[i]=(dirp->deName[i]>=128)?cp850[dirp->deName[i]-128][0]:tolower(dirp->deName[i]);
682for (i=2;i>=0;i--)
683if (dirp->deName[8+i]!=' ')
684break;
685
686if (i>=0)
687{
688tmp[j++]='.';
689tmp[j+i+1]=0;
690k=j+i+1;
691for(;i>=0;i--)
692tmp[j+i]=(dirp->deName[i]>=128)?cp850[dirp->deName[i+8]-128][0]:tolower(dirp->deName[i+8]);
693j=k;
694}
695
696utf_encodestr(tmp, j, (uint8_t*)*name, 25, OSHostByteOrder() );
697}
698if (dirp->deAttributes & ATTR_DIRECTORY)
699*flags = kFileTypeDirectory;
700else
701*flags = kFileTypeFlat;
702
703// Calculate a fake timestamp using modification date and time values.
704*time = (dirp->deMDate & 0x7FFF) << 16 + dirp->deMTime;
705
706if (infoValid)
707*infoValid = 1;
708
709return 0;
710}
711
712long
713MSDOSReadFile(CICell ih, char * filePath, void *base, uint64_t offset, uint64_t length)
714{
715uint8_t *buf;
716off_t cluster;
717uint64_t size;
718uint64_t nskip;
719int toread, wastoread;
720char *ptr = (char *)base;
721struct direntry *dirp;
722int i;
723if (MSDOSInitPartition (ih)<0)
724return -1;
725if (filePath[0] == '/')
726filePath++;
727buf = malloc(msdosclustersize);
728dirp = getdirpfrompath (ih, filePath, buf);
729
730if (!dirp || (dirp->deAttributes & ATTR_DIRECTORY))
731{
732free (buf);
733return -1;
734}
735cluster = OSReadLittleInt16 ((dirp->deStartCluster),0);
736if (msdosfatbits == 32)
737cluster |= ((uint32_t)OSReadLittleInt16 ((dirp->deHighClust),0)) <<16;
738size = (uint32_t)OSReadLittleInt32 ((dirp->deFileSize),0);
739if (size<=offset)
740return -1;
741nskip=offset/msdosclustersize;
742for (i=0;i<nskip;i++)
743msdosreadcluster (ih, 0, 0, &cluster);
744msdosreadcluster (ih, buf, msdosclustersize, &cluster);
745toread=length;
746if (length==0 || length>size-offset)
747toread=size-offset;
748wastoread=toread;
749bcopy (buf+(offset%msdosclustersize),ptr,min(msdosclustersize-(offset%msdosclustersize), toread));
750ptr+=msdosclustersize-(offset%msdosclustersize);
751toread-=msdosclustersize-(offset%msdosclustersize);
752while (toread>0 && msdosreadcluster (ih, (uint8_t *)ptr, min(msdosclustersize,toread), &cluster))
753{
754ptr+=msdosclustersize;
755toread-=msdosclustersize;
756}
757verbose("Loaded FAT%d file: [%s] %d bytes from %x.\n",
758 msdosfatbits, filePath, (uint32_t)( toread<0 ) ? wastoread : wastoread-toread, ih);
759free (buf);
760if (toread<0)
761return wastoread;
762else
763return wastoread-toread;
764}
765
766long
767MSDOSGetFileBlock(CICell ih, char *filePath, unsigned long long *firstBlock)
768{
769uint8_t *buf;
770off_t cluster;
771struct direntry *dirp;
772if (MSDOSInitPartition (ih)<0)
773return -1;
774if (filePath[0] == '/')
775filePath++;
776buf = malloc(msdosclustersize);
777dirp = getdirpfrompath (ih, filePath, buf);
778if (!dirp || (dirp->deAttributes & ATTR_DIRECTORY))
779{
780free (buf);
781return -1;
782}
783cluster = OSReadLittleInt16 ((dirp->deStartCluster),0);
784if (msdosfatbits == 32)
785cluster |= ((uint32_t)OSReadLittleInt16 ((dirp->deHighClust),0)) <<16;
786
787off_t clusn;
788
789switch (msdosfatbits) {
790case 32:
791if (cluster < CLUST_FIRST ||cluster >= CLUST_RSRVD32)
792return -1;
793clusn = cluster - CLUST_FIRST;
794break;
795case 16:
796if (cluster < CLUST_FIRST ||cluster >= CLUST_RSRVD16)
797return 0;
798clusn = cluster - CLUST_FIRST;
799break;
800case 12:
801
802if (cluster < CLUST_FIRST ||cluster >= CLUST_RSRVD12)
803return 0;
804clusn = cluster - CLUST_FIRST;
805break;
806default:
807return 0;
808}
809
810*firstBlock = ((msdosressector +
811 (msdosnfats * msdosfatsecs))*msdosbps + clusn * msdosclustersize)/512;
812free (buf);
813return 0;
814}
815
816
817long MSDOSLoadFile(CICell ih, char * filePath)
818{
819 return MSDOSReadFile(ih, filePath, (void *)gFSLoadAddress, 0, 0);
820}
821
822/* Fix up volume label. */
823static void
824fixLabel(uint8_t *label, char *str, long strMaxLen)
825{
826 inti, len;
827uint16_tlabelucs[13];
828 //unsigned charlabelUTF8[LABEL_LENGTH*3];
829
830 /* Convert leading 0x05 to 0xE5 for multibyte languages like Japanese */
831 if (label[0] == 0x05)
832 label[0] = 0xE5;
833
834 /* Remove any trailing spaces */
835 for (i=LABEL_LENGTH-1; i>=0; --i) {
836 if (label[i] == ' ')
837 label[i] = 0;
838 else
839 break;
840 }
841labelucs[i++]=0;
842len=i;
843for (;i>=0;--i)
844labelucs[i]=label[i]>=128?cp850[label[i]-128][1]:(label[i]);
845
846utf_encodestr(labelucs, len, (uint8_t *)str, strMaxLen, OSHostByteOrder() );
847}
848
849
850void
851MSDOSGetDescription(CICell ih, char *str, long strMaxLen)
852{
853 struct direntry *dirp;
854 uint8_t label[LABEL_LENGTH+1];
855uint16_tvfatlabel[WIN_MAXLEN+2*WIN_CHARS];
856struct msdosdirstate st;
857int labelfound = 0;
858
859if (MSDOSInitPartition (ih)<0)
860{
861str[0]=0;
862return;
863}
864
865label[0] = '\0';
866
867initRoot (&st);
868st.buf = malloc(msdosclustersize);
869while ((dirp = getnextdirent (ih, vfatlabel, &st)))
870if (dirp->deAttributes & ATTR_VOLUME) {
871strncpy((char *)label, (char *)dirp->deName, LABEL_LENGTH);
872labelfound = 1;
873break;
874}
875
876free(st.buf);
877
878if (vfatlabel[0] && labelfound)
879{
880int i;
881for (i=0;vfatlabel[i];i++);
882utf_encodestr(vfatlabel, i, (u_int8_t *)str, strMaxLen, OSLittleEndian );
883}
884else if (labelfound)
885fixLabel(label, str, strMaxLen);
886
887 /* else look in the boot blocks */
888 if (!labelfound || str[0] == '\0') {
889char *buf = malloc (512);
890union bootsector *bsp = (union bootsector *)buf;
891Seek(ih, 0);
892Read(ih, (long)buf, 512);
893 if (msdosfatbits == 32) { /* It's FAT32 */
894 strncpy((char *)label, (char *)((struct extboot *)bsp->bs710.bsExt)->exVolumeLabel, LABEL_LENGTH);
895 }
896 else if (msdosfatbits == 16) {
897 strncpy((char *)label, (char *)((struct extboot *)bsp->bs50.bsExt)->exVolumeLabel, LABEL_LENGTH);
898 }
899free (buf);
900fixLabel(label, str, strMaxLen);
901 }
902
903 return;
904}
905
906long
907MSDOSGetUUID(CICell ih, char *uuidStr)
908{
909char *buf = malloc (512);
910union bootsector *bsp = (union bootsector *)buf;
911
912if (MSDOSInitPartition (ih)<0)
913{
914return -1;
915}
916bzero (uuidStr, 16);
917Seek(ih, 0);
918Read(ih, (long)buf, 512);
919if (msdosfatbits == 32) { /* It's FAT32 */
920memcpy(uuidStr+12, (char *)((struct extboot *)bsp->bs710.bsExt)->exVolumeID, 4);
921}
922else if (msdosfatbits == 16) {
923memcpy(uuidStr+12, (char *)((struct extboot *)bsp->bs50.bsExt)->exVolumeID, 4);
924}
925free (buf);
926 return 0;
927
928}
929

Archive Download this file

Revision: 429