Chameleon

Chameleon Svn Source Tree

Root/tags/2.0/i386/libsaio/msdos.c

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

Archive Download this file

Revision: 1808