Root/
Source at commit 2381 created 10 years 21 days ago. By ifabio, Apply patch: (Credits to Thomas Jansen aka tja) - Reading options from all devices during boot. The options for the boot menu are only read from the devices rd(0,0) or bt(0,0). Consequently, boot menu options (e.g. "Quiet Boot", "Timeout", etc.) in plists on other devices (like most users have) are ignored. This patch extends the list of paths to search for the options plist on all devices that can be found. | |
---|---|
1 | /*␊ |
2 | * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.␊ |
3 | *␊ |
4 | * @APPLE_LICENSE_HEADER_START@␊ |
5 | * ␊ |
6 | * The contents of this file constitute Original Code as defined in and␊ |
7 | * are subject to the Apple Public Source License Version 2.0 (the␊ |
8 | * "License"). You may not use this file except in compliance with the␊ |
9 | * License. Please obtain a copy of the License at␊ |
10 | * http://www.apple.com/publicsource and read it before using this file.␊ |
11 | * ␊ |
12 | * This Original Code and all software distributed under the License are␊ |
13 | * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER␊ |
14 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,␊ |
15 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,␊ |
16 | * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the␊ |
17 | * License for the specific language governing rights and limitations␊ |
18 | * under the License.␊ |
19 | * ␊ |
20 | * @APPLE_LICENSE_HEADER_END@␊ |
21 | */␊ |
22 | /*␊ |
23 | * Copyright (c) 1998 Robert Nordier␊ |
24 | * All rights reserved.␊ |
25 | *␊ |
26 | * Redistribution and use in source and binary forms, with or without␊ |
27 | * modification, are permitted provided that the following conditions␊ |
28 | * are met:␊ |
29 | * 1. Redistributions of source code must retain the above copyright␊ |
30 | * notice, this list of conditions and the following disclaimer.␊ |
31 | * 2. Redistributions in binary form must reproduce the above copyright␊ |
32 | * notice, this list of conditions and the following disclaimer in␊ |
33 | * the documentation and/or other materials provided with the␊ |
34 | * distribution.␊ |
35 | *␊ |
36 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS␊ |
37 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED␊ |
38 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE␊ |
39 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY␊ |
40 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL␊ |
41 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE␊ |
42 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS␊ |
43 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER␊ |
44 | * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR␊ |
45 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN␊ |
46 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.␊ |
47 | */␊ |
48 | ␊ |
49 | #include "libsaio.h"␊ |
50 | #include "sl.h"␊ |
51 | #include "msdos_private.h"␊ |
52 | #include "msdos.h"␊ |
53 | ␊ |
54 | #define LABEL_LENGTH␉␉11␊ |
55 | #define MSDOS_CACHE_BLOCKSIZE BPS␊ |
56 | ␊ |
57 | #define␉CLUST_FIRST␉␉2/* reserved cluster range */␊ |
58 | #define␉CLUST_RSRVD32␉0x0ffffff8␉/* reserved cluster range */␊ |
59 | #define␉CLUST_RSRVD16␉0xfff8␉/* reserved cluster range */␊ |
60 | #define␉CLUST_RSRVD12␉0xff8␉/* reserved cluster range */␊ |
61 | ␊ |
62 | #define tolower(c) (((c)>='A' && c<='Z')?((c) | 0x20):(c))␊ |
63 | ␊ |
64 | static int msdosressector=0;␊ |
65 | static int msdosnfats = 0;␊ |
66 | static int msdosfatsecs = 0;␊ |
67 | static int msdosbps = 0;␊ |
68 | static int msdosclustersize = 0;␊ |
69 | static int msdosrootDirSectors = 0;␊ |
70 | static CICell msdoscurrent = 0;␊ |
71 | static int msdosrootcluster = 0;␊ |
72 | static int msdosfatbits = 0;␊ |
73 | ␊ |
74 | #if UNUSED␊ |
75 | /*␊ |
76 | * Check a volume label.␊ |
77 | */␊ |
78 | static int␊ |
79 | oklabel(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 | ␊ |
92 | void MSDOSFree(CICell ih)␊ |
93 | {␊ |
94 | ␉if(msdoscurrent == ih)␊ |
95 | msdoscurrent = 0;␊ |
96 | free(ih);␊ |
97 | }␊ |
98 | ␊ |
99 | int 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_t␉␉spc;␊ |
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 | ␉␊ |
123 | ␉if (OSSwapLittleToHostInt16(b50->bpbRootDirEnts) == 0) { /* It's FAT32 */␊ |
124 | ␉␉if (!memcmp(((struct extboot *)bsp->bs710.bsExt)->exFileSysType, "FAT32 ", 8))␊ |
125 | ␉␉␉return 32;␊ |
126 | ␉}␊ |
127 | ␉else if (((struct extboot *)bsp->bs50.bsExt)->exBootSignature == EXBOOTSIG) {␊ |
128 | ␉␉if (!memcmp((char *)((struct extboot *)bsp->bs50.bsExt)->exFileSysType, "FAT16 ", 8))␊ |
129 | ␉␉␉return 16;␊ |
130 | ␉␉if (!memcmp((char *)((struct extboot *)bsp->bs50.bsExt)->exFileSysType, "FAT12 ", 8))␊ |
131 | ␉␉␉return 12;␊ |
132 | ␉}␉␊ |
133 | ␉␉␊ |
134 | ␉return 0;␊ |
135 | }␊ |
136 | ␊ |
137 | ␊ |
138 | long␊ |
139 | MSDOSInitPartition (CICell ih)␊ |
140 | {␊ |
141 | union bootsector *bsp;␊ |
142 | struct bpb33 *b33;␊ |
143 | struct bpb50 *b50;␊ |
144 | struct bpb710 *b710;␊ |
145 | u_int8_t␉␉spc;␊ |
146 | char *buf;␊ |
147 | ␉␊ |
148 | ␉if (msdoscurrent == ih)␊ |
149 | ␉{␊ |
150 | ␉␉CacheInit(ih, MSDOS_CACHE_BLOCKSIZE);␊ |
151 | ␉␉return 0;␊ |
152 | ␉}␊ |
153 | ␉␊ |
154 | ␉buf=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 | ␉{␊ |
174 | ␉␉free (buf);␊ |
175 | ␉␉return -1;␊ |
176 | ␉}␊ |
177 | ␉␊ |
178 | /* Check to make sure valid sectors per cluster */␊ |
179 | spc = b33->bpbSecPerClust;␊ |
180 | if ((spc == 0 ) || (spc & (spc - 1))) ␊ |
181 | ␉␉return -1;␊ |
182 | ␉␊ |
183 | ␉if (OSSwapLittleToHostInt16(b50->bpbRootDirEnts) == 0) { /* It's FAT32 */␊ |
184 | ␉␉if (memcmp(((struct extboot *)bsp->bs710.bsExt)->exFileSysType, "FAT32 ", 8))␊ |
185 | ␉␉{␊ |
186 | ␉␉␉free (buf);␊ |
187 | ␉␉␉return -1;␊ |
188 | ␉␉}␊ |
189 | ␉␉msdosressector = OSSwapLittleToHostInt16(b710->bpbResSectors);␊ |
190 | ␉␉msdosnfats = b710->bpbFATs;␊ |
191 | ␉␉msdosfatsecs = OSSwapLittleToHostInt16(b710->bpbBigFATsecs);␊ |
192 | ␉␉msdosrootcluster = OSSwapLittleToHostInt32(b710->bpbRootClust);␊ |
193 | ␉␉msdosrootDirSectors = 0;␊ |
194 | ␉␉msdosfatbits = 32;␊ |
195 | ␉}␊ |
196 | ␉else if (((struct extboot *)bsp->bs50.bsExt)->exBootSignature == EXBOOTSIG) {␊ |
197 | ␉␉if (!memcmp((char *)((struct extboot *)bsp->bs50.bsExt)->exFileSysType, "FAT16 ", 8))␊ |
198 | ␉␉␉msdosfatbits = 16;␊ |
199 | ␉␉else if (!memcmp((char *)((struct extboot *)bsp->bs50.bsExt)->exFileSysType, "FAT12 ", 8))␊ |
200 | ␉␉␉msdosfatbits = 12;␊ |
201 | ␉␉else␊ |
202 | ␉␉{␊ |
203 | ␉␉␉free (buf);␊ |
204 | ␉␉␉return -1;␊ |
205 | ␉␉}␉␉␊ |
206 | ␉␉␊ |
207 | ␉␉msdosressector = OSSwapLittleToHostInt16(b33->bpbResSectors);␊ |
208 | ␉␉msdosnfats = b33->bpbFATs;␊ |
209 | ␉␉msdosfatsecs = OSSwapLittleToHostInt16(b33->bpbFATsecs);␊ |
210 | ␉␉msdosrootcluster = 0;␉␉␊ |
211 | ␉␉msdosrootDirSectors = ((OSSwapLittleToHostInt16(b50->bpbRootDirEnts) * sizeof(struct direntry)) +␊ |
212 | ␉␉␉␉␉␉␉ (msdosbps-1)) / msdosbps;␊ |
213 | ␉} else {␊ |
214 | ␉␉free (buf);␊ |
215 | ␉␉return -1;␊ |
216 | ␉}␊ |
217 | ␉␊ |
218 | ␉msdosclustersize = msdosbps * spc;␊ |
219 | ␉msdoscurrent = ih;␊ |
220 | ␊ |
221 | ␉CacheInit(ih, MSDOS_CACHE_BLOCKSIZE);␊ |
222 | ␉free (buf);␊ |
223 | ␉return 0;␊ |
224 | }␊ |
225 | ␊ |
226 | static int␊ |
227 | readSector(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.␊ |
230 | ␉if (size < BPS)␊ |
231 | ␉{␊ |
232 | ␉␉long long sectorOffset = (uint64_t)readOffset / BPS * BPS;␊ |
233 | ␉␉long relOffset = readOffset % BPS;␊ |
234 | ␉␉char *cacheBuffer;␊ |
235 | ␉␊ |
236 | ␉␉cacheBuffer = malloc(MSDOS_CACHE_BLOCKSIZE);␊ |
237 | ␉␉CacheRead(ih, cacheBuffer, sectorOffset, MSDOS_CACHE_BLOCKSIZE, true);␊ |
238 | ␉␉bcopy(cacheBuffer + relOffset, buf, size);␊ |
239 | ␉␉free(cacheBuffer);␊ |
240 | ␉}␊ |
241 | ␉else␊ |
242 | ␉{␊ |
243 | ␉␉Seek(ih, readOffset);␊ |
244 | ␉␉Read(ih, (long)buf, size);␊ |
245 | ␉}␊ |
246 | ␊ |
247 | ␉return 0;␊ |
248 | }␊ |
249 | ␊ |
250 | static int␊ |
251 | msdosreadcluster (CICell ih, uint8_t *buf, int size, off_t *cluster)␊ |
252 | {␊ |
253 | off_t readOffset;␊ |
254 | ␉char tmpbuf[8];␊ |
255 | ␉off_t clusn;␊ |
256 | ␉␊ |
257 | ␉switch (msdosfatbits) {␊ |
258 | ␉␉case 32:␊ |
259 | ␉␉␉if (*cluster < CLUST_FIRST ||*cluster >= CLUST_RSRVD32)␊ |
260 | ␉␉␉␉return 0;␊ |
261 | ␉␉␉clusn = *cluster - CLUST_FIRST;␊ |
262 | ␉␉␉break;␊ |
263 | ␉␉case 16:␊ |
264 | ␉␉␉if (*cluster < CLUST_FIRST ||*cluster >= CLUST_RSRVD16)␊ |
265 | ␉␉␉␉return 0;␊ |
266 | ␉␉␉clusn = *cluster - CLUST_FIRST;␊ |
267 | ␉␉␉break;␉␉␉␊ |
268 | ␉␉case 12:␊ |
269 | ␉␉␉if (*cluster < CLUST_FIRST ||*cluster >= CLUST_RSRVD12)␊ |
270 | ␉␉␉␉return 0;␊ |
271 | ␉␉␉clusn = *cluster - CLUST_FIRST;␊ |
272 | ␉␉␉break;␊ |
273 | ␉␉default:␊ |
274 | ␉␉␉return 0;␊ |
275 | ␉}␊ |
276 | ␉␊ |
277 | ␉/* Find sector where clusters start */␊ |
278 | ␉readOffset = (msdosressector +␊ |
279 | ␉␉␉␉ (msdosnfats * msdosfatsecs)+msdosrootDirSectors)*msdosbps;␊ |
280 | ␉/* Find sector where "cluster" starts */␊ |
281 | ␉readOffset += clusn * msdosclustersize;␊ |
282 | ␉␊ |
283 | ␉/* Read in "cluster" */␊ |
284 | ␉if (buf)␊ |
285 | ␉{␊ |
286 | ␉␉Seek(ih, readOffset);␊ |
287 | ␉␉Read(ih, (long)buf, size);␊ |
288 | ␉}␊ |
289 | ␊ |
290 | ␉/* Find first sector of FAT */␊ |
291 | ␉readOffset = msdosressector * msdosbps;␊ |
292 | ␊ |
293 | ␉/* Find sector containing "cluster" entry in FAT */␊ |
294 | ␉readOffset += ((uint64_t)*cluster * (uint64_t)msdosfatbits) / 8;␊ |
295 | ␉␊ |
296 | ␉/* Read one sector of the FAT */␊ |
297 | ␉readSector(ih, readOffset, tmpbuf, 4);␊ |
298 | ␉␊ |
299 | ␉switch (msdosfatbits) {␊ |
300 | ␉␉case 32:␊ |
301 | ␉␉␉*cluster = OSReadLittleInt32(tmpbuf, 0);␊ |
302 | ␉␉␉*cluster &= 0x0FFFFFFF;␉// ignore reserved upper bits␊ |
303 | ␉␉␉return 1;␊ |
304 | ␉␉case 16:␊ |
305 | ␉␉␉*cluster = OSReadLittleInt16(tmpbuf, 0);␊ |
306 | ␉␉␉return 1;␉␉␉␊ |
307 | ␉␉case 12:␊ |
308 | ␉␉␉*cluster = OSReadLittleInt16(tmpbuf, 0)>>(((uint64_t)*cluster * (uint64_t)msdosfatbits)%8);␊ |
309 | ␉␉␉*cluster &= 0xfff;␊ |
310 | ␉␉␉return 1;␊ |
311 | ␉␉default:␊ |
312 | ␉␉␉return 0;␊ |
313 | ␉}␊ |
314 | }␊ |
315 | ␊ |
316 | struct msdosdirstate␊ |
317 | {␊ |
318 | ␉struct direntry *buf;␊ |
319 | ␉uint8_t vfatchecksum;␊ |
320 | ␉int root16;␊ |
321 | ␉off_t cluster;␊ |
322 | ␉int nument;␊ |
323 | ␉int vfatnumber;␊ |
324 | };␊ |
325 | ␊ |
326 | static struct direntry *␊ |
327 | getnextdirent (CICell ih, uint16_t *longname, struct msdosdirstate *st)␊ |
328 | {␊ |
329 | ␉struct direntry *dirp;␊ |
330 | ␉while (1)␊ |
331 | ␉{␊ |
332 | ␉␉if (st->root16)␊ |
333 | ␉␉{␊ |
334 | ␉␉␉if (st->cluster >= msdosrootDirSectors && st->nument == 0)␊ |
335 | ␉␉␉␉return 0;␊ |
336 | ␉␉␉if (st->nument == 0)␊ |
337 | ␉␉␉{␊ |
338 | ␉␉␉␉Seek(ih, (msdosressector +␊ |
339 | ␉␉␉␉␉␉ (msdosnfats * msdosfatsecs)+st->cluster)*msdosbps);␊ |
340 | ␉␉␉␉Read(ih, (long)st->buf, msdosbps);␊ |
341 | ␉␉␉␉st->cluster++;␊ |
342 | ␉␉␉}␊ |
343 | ␉␉} else if (st->nument == 0 && !msdosreadcluster (ih, (uint8_t *)st->buf, msdosclustersize, &(st->cluster)))␊ |
344 | ␉␉␉return 0;␊ |
345 | ␉␉␊ |
346 | ␉␉dirp=st->buf+st->nument;␊ |
347 | ␉␉␊ |
348 | ␉␉if (dirp->deName[0] == SLOT_EMPTY)␊ |
349 | ␉␉␉return 0;␊ |
350 | ␉␉else if (dirp->deName[0] == SLOT_DELETED)␊ |
351 | ␉␉␉st->vfatnumber = 0;␊ |
352 | ␉␉else if (dirp->deAttributes == ATTR_WIN95)␊ |
353 | ␉␉{␊ |
354 | ␉␉␉struct winentry *wdirp = (struct winentry *)dirp;␊ |
355 | ␉␉␉int num;␊ |
356 | ␉␉␉if (wdirp->weCnt & 0x80)␊ |
357 | ␉␉␉␉continue;␊ |
358 | ␉␉␉num=(wdirp->weCnt&0x3f);␊ |
359 | ␉␉␉if (WIN_CHARS * num > WIN_MAXLEN)␊ |
360 | ␉␉␉␉continue;␊ |
361 | ␉␉␉if (st->vfatchecksum!=wdirp->weChksum)␊ |
362 | ␉␉␉{␊ |
363 | ␉␉␉␉st->vfatnumber = 0;␊ |
364 | ␉␉␉␉st->vfatchecksum = wdirp->weChksum;␊ |
365 | ␉␉␉}␊ |
366 | ␉␉␉if (st->vfatnumber < num)␊ |
367 | ␉␉␉␉st->vfatnumber = num;␊ |
368 | ␉␉␉bcopy (&(wdirp->wePart1),longname+WIN_CHARS*(num-1),sizeof (wdirp->wePart1));␊ |
369 | ␉␉␉bcopy (&(wdirp->wePart2),longname+WIN_CHARS*(num-1)+5,sizeof (wdirp->wePart2));␊ |
370 | ␉␉␉bcopy (&(wdirp->wePart3),longname+WIN_CHARS*(num-1)+11,sizeof (wdirp->wePart3));␊ |
371 | ␉␉} else {␊ |
372 | ␉␉␉uint8_t labelchecksum;␊ |
373 | ␉␉␉int i;␊ |
374 | ␉␉␉longname[st->vfatnumber*WIN_CHARS]=0;␊ |
375 | ␉␉␉␊ |
376 | ␉␉␉labelchecksum=0;␊ |
377 | ␉␉␉for(i=0;i<LABEL_LENGTH;i++)␊ |
378 | ␉␉␉␉labelchecksum=(labelchecksum>>1)+(labelchecksum<<7)+dirp->deName[i];␊ |
379 | ␉␉␉if (!(labelchecksum==st->vfatchecksum && st->vfatnumber))␊ |
380 | ␉␉␉␉longname[0]=0;␊ |
381 | ␉␉␉st->vfatnumber = 0;␊ |
382 | ␉␉␉st->vfatchecksum = 0;␊ |
383 | ␉␉␉st->vfatnumber = 0;␊ |
384 | ␉␉␉st->nument++;␊ |
385 | ␉␉␉if ((!st->root16 &&st->nument * sizeof (struct direntry)>=msdosclustersize)␊ |
386 | ␉␉␉␉|| (st->root16 &&st->nument * sizeof (struct direntry)>=msdosbps))␊ |
387 | ␉␉␉␉st->nument = 0;␊ |
388 | ␉␉␉return dirp;␊ |
389 | ␉␉}␊ |
390 | ␉␉st->nument++;␊ |
391 | ␉␉if ((!st->root16 &&st->nument * sizeof (struct direntry)>=msdosclustersize)␊ |
392 | ␉␉␉|| (st->root16 &&st->nument * sizeof (struct direntry)>=msdosbps))␊ |
393 | ␉␉␉st->nument = 0;␉␉␊ |
394 | ␉}␊ |
395 | }␊ |
396 | ␊ |
397 | static void␊ |
398 | initRoot (struct msdosdirstate *st)␊ |
399 | {␊ |
400 | ␉if (msdosrootDirSectors) {␉␉␉/* FAT12 or FAT16 */␊ |
401 | ␉␉st->root16 = 1;␊ |
402 | ␉␉st->vfatchecksum = 0;␊ |
403 | ␉␉st->nument = 0;␊ |
404 | ␉␉st->cluster = 0;␊ |
405 | ␉␉st->vfatnumber = 0;␊ |
406 | ␉} else {␉/* FAT32 */␊ |
407 | ␉␉st->root16 = 0;␊ |
408 | ␉␉st->vfatchecksum = 0;␊ |
409 | ␉␉st->nument = 0;␊ |
410 | ␉␉st->cluster = msdosrootcluster;␊ |
411 | ␉␉st->vfatnumber = 0;␊ |
412 | ␉}␊ |
413 | }␊ |
414 | ␊ |
415 | /* First comes lowercase, then uppercase*/␊ |
416 | static 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 | ␊ |
548 | static int␊ |
549 | checkname (uint16_t *ucsname, int ucslen, struct direntry *dirp, uint16_t *vfatname)␊ |
550 | {␊ |
551 | ␉uint16_t tmp[15];␊ |
552 | ␉if (vfatname[0])␊ |
553 | ␉{␊ |
554 | ␉␉int i;␊ |
555 | ␉␉for (i=0;vfatname[i];i++);␊ |
556 | ␉␉return !FastUnicodeCompare (ucsname, ucslen, vfatname, i, OSLittleEndian);␊ |
557 | ␉}␊ |
558 | ␉else␊ |
559 | ␉{␊ |
560 | ␉␉int i, j, k;␊ |
561 | ␉␉for (i=7;i>=0;i--)␊ |
562 | ␉␉␉if (dirp->deName[i]!=' ')␊ |
563 | ␉␉␉␉break;␊ |
564 | ␉␉j=i+1;␊ |
565 | ␉␉tmp[i+1]=0;␊ |
566 | ␉␉for(;i>=0;i--)␊ |
567 | ␉␉␉tmp[i]=SWAP_LE16((dirp->deName[i]>=128)?cp850[dirp->deName[i]-128][0]:tolower(dirp->deName[i]));␊ |
568 | ␉␉for (i=2;i>=0;i--)␊ |
569 | ␉␉␉if (dirp->deName[8+i]!=' ')␊ |
570 | ␉␉␉␉break;␊ |
571 | ␉␉if (i>=0)␊ |
572 | ␉␉{␊ |
573 | ␉␉␉tmp[j++]='.';␊ |
574 | ␉␉␉tmp[j+i+1]=0;␊ |
575 | ␉␉␉k=j+i+1;␊ |
576 | ␉␉␉for(;i>=0;i--)␊ |
577 | ␉␉␉␉tmp[j+i]=SWAP_LE16((dirp->deName[i+8]>=128)?cp850[dirp->deName[i+8]-128][0]:tolower(dirp->deName[i+8]));␊ |
578 | ␉␉␉j=k;␊ |
579 | ␉␉}␊ |
580 | ␉␉return !FastUnicodeCompare (ucsname, ucslen, tmp, j, OSLittleEndian);␊ |
581 | ␉}␊ |
582 | ␉␊ |
583 | }␊ |
584 | ␊ |
585 | static struct direntry *␊ |
586 | getdirpfrompath (CICell ih, char *dirspec, uint8_t *buf)␊ |
587 | {␊ |
588 | ␉struct msdosdirstate st;␊ |
589 | ␉struct direntry *dirp;␊ |
590 | ␉uint8_t * ptr;␊ |
591 | ␉uint8_t *slash;␊ |
592 | ␉char c;␊ |
593 | ␉uint16_t␉␉vfatname[WIN_MAXLEN+2*WIN_CHARS];␊ |
594 | ␉uint16_t ucsname[WIN_MAXLEN+1];␊ |
595 | ␉uint16_t ucslen;␊ |
596 | ␉int ucslenhost;␊ |
597 | ␉initRoot (&st);␊ |
598 | ␉st.buf = (struct direntry *)buf;␊ |
599 | ␉ptr=(uint8_t*)dirspec;␊ |
600 | ␉for (slash=ptr;*slash && *slash!='/';slash++);␊ |
601 | ␉c=*slash;␊ |
602 | ␉*slash=0;␊ |
603 | ␉utf_decodestr (ptr, ucsname, &ucslen, WIN_MAXLEN, OSLittleEndian);␊ |
604 | ␉ucslenhost = OSReadLittleInt16 (&ucslen,0);␊ |
605 | ␉ucsname[ucslenhost]=0;␊ |
606 | ␉*slash=c;␉␊ |
607 | ␉while ((dirp = getnextdirent (ih, vfatname, &st)))␊ |
608 | ␉{␊ |
609 | ␉␉if (checkname (ucsname, ucslenhost, dirp, vfatname))␊ |
610 | ␉␉{␊ |
611 | ␉␉␉for (;*ptr && *ptr!='/';ptr++);␊ |
612 | ␉␉␉if (!*ptr)␊ |
613 | ␉␉␉␉return dirp;␊ |
614 | ␉␉␉ptr++;␊ |
615 | ␉␉␉if (!*ptr)␊ |
616 | ␉␉␉␉return dirp;␊ |
617 | ␉␉␉for (slash=ptr;*slash && *slash!='/';slash++);␊ |
618 | ␉␉␉c=*slash;␊ |
619 | ␉␉␉*slash=0;␊ |
620 | ␉␉␉utf_decodestr (ptr, ucsname, &ucslen, WIN_MAXLEN, OSLittleEndian);␊ |
621 | ␉␉␉ucslenhost = OSReadLittleInt16 (&ucslen,0);␊ |
622 | ␉␉␉ucsname[ucslenhost]=0;␊ |
623 | ␉␉␉*slash=c;␊ |
624 | ␉␉␉if (!(dirp->deAttributes & ATTR_DIRECTORY))␊ |
625 | ␉␉␉␉return 0;␊ |
626 | ␉␉␉st.root16 = 0;␊ |
627 | ␉␉␉st.vfatchecksum = 0;␊ |
628 | ␉␉␉st.nument = 0;␊ |
629 | ␉␉␉st.cluster = OSReadLittleInt16 ((dirp->deStartCluster),0);␊ |
630 | ␉␉␉if (msdosfatbits == 32)␊ |
631 | ␉␉␉␉st.cluster |= ((uint32_t)OSReadLittleInt16 ((dirp->deHighClust),0)) <<16;␊ |
632 | ␉␉␉st.vfatnumber = 0;␊ |
633 | ␉␉}␊ |
634 | ␉}␊ |
635 | ␉return 0;␊ |
636 | }␊ |
637 | ␊ |
638 | long MSDOSGetDirEntry(CICell ih, char * dirPath, long long * dirIndex,␊ |
639 | ␉␉␉␉␉ char ** name, long * flags, long * time,␊ |
640 | ␉␉␉␉␉ FinderInfo * finderInfo, long * infoValid)␊ |
641 | {␊ |
642 | ␉struct msdosdirstate *st;␊ |
643 | ␉struct direntry *dirp;␊ |
644 | ␉uint16_t␉␉vfatname[WIN_MAXLEN+2*WIN_CHARS];␊ |
645 | ␉if (MSDOSInitPartition (ih)<0)␊ |
646 | ␉␉return -1;␊ |
647 | ␉if (dirPath[0] == '/')␊ |
648 | ␉␉dirPath++;␊ |
649 | ␉st = (struct msdosdirstate *)(long) *dirIndex;␊ |
650 | ␉if (!st)␊ |
651 | ␉{␊ |
652 | ␉␉st=malloc (sizeof (*st));␊ |
653 | ␉␉if (dirPath[0])␊ |
654 | ␉␉{␊ |
655 | ␉␉␉uint8_t *buf=malloc(msdosclustersize);␊ |
656 | ␉␉␉dirp = getdirpfrompath (ih, dirPath, buf);␊ |
657 | ␉␉␉if (!dirp || !(dirp->deAttributes & ATTR_DIRECTORY))␊ |
658 | ␉␉␉{␊ |
659 | ␉␉␉␉free (buf);␊ |
660 | ␉␉␉␉free (st);␊ |
661 | ␉␉␉␉return -1;␊ |
662 | ␉␉␉}␊ |
663 | ␉␉␉st->buf = (struct direntry *)buf;␊ |
664 | ␉␉␉st->root16 = 0;␊ |
665 | ␉␉␉st->vfatchecksum = 0;␊ |
666 | ␉␉␉st->nument = 0;␊ |
667 | ␉␉␉st->cluster = OSReadLittleInt16 ((dirp->deStartCluster),0);␊ |
668 | ␉␉␉st->vfatnumber = 0;␊ |
669 | ␉␉␉if (msdosfatbits == 32)␊ |
670 | ␉␉␉␉st->cluster |= ((uint32_t)OSReadLittleInt16 ((dirp->deHighClust),0)) <<16;␊ |
671 | ␉␉}␊ |
672 | ␉␉else␊ |
673 | ␉␉␉initRoot (st);␊ |
674 | ␉␉*dirIndex = (long long) (long) st;␊ |
675 | ␉}␊ |
676 | ␉while((dirp = getnextdirent (ih, vfatname, st))&& (dirp->deAttributes & ATTR_VOLUME));␊ |
677 | ␉if (!dirp)␊ |
678 | ␉{␊ |
679 | ␉␉free (st->buf);␊ |
680 | ␉␉free (st);␊ |
681 | ␉␉return -1;␊ |
682 | ␉}␊ |
683 | ␉if (vfatname[0])␊ |
684 | ␉{␊ |
685 | ␉␉int i;␊ |
686 | ␉␉for (i=0;vfatname[i];i++);␊ |
687 | ␉␉*name = malloc (256);␊ |
688 | ␉␉utf_encodestr(vfatname, i, (u_int8_t *)*name, 255, OSLittleEndian );␉␊ |
689 | ␉}␊ |
690 | ␉else␊ |
691 | ␉{␊ |
692 | ␉␉int i, j, k;␊ |
693 | ␉␉uint16_t tmp[13];␊ |
694 | ␉␉*name = malloc (26);␊ |
695 | ␉␉for (i=7;i>=0;i--)␊ |
696 | ␉␉␉if (dirp->deName[i]!=' ')␊ |
697 | ␉␉␉␉break;␊ |
698 | ␉␉j=i+1;␊ |
699 | ␉␉tmp[i+1]=0;␊ |
700 | ␉␉for(;i>=0;i--)␊ |
701 | ␉␉␉tmp[i]=(dirp->deName[i]>=128)?cp850[dirp->deName[i]-128][0]:tolower(dirp->deName[i]);␊ |
702 | ␉␉for (i=2;i>=0;i--)␊ |
703 | ␉␉␉if (dirp->deName[8+i]!=' ')␊ |
704 | ␉␉␉␉break;␊ |
705 | ␉␉␊ |
706 | ␉␉if (i>=0)␊ |
707 | ␉␉{␊ |
708 | ␉␉␉tmp[j++]='.';␊ |
709 | ␉␉␉tmp[j+i+1]=0;␊ |
710 | ␉␉␉k=j+i+1;␊ |
711 | ␉␉␉for(;i>=0;i--)␊ |
712 | ␉␉␉␉tmp[j+i]=(dirp->deName[i]>=128)?cp850[dirp->deName[i+8]-128][0]:tolower(dirp->deName[i+8]);␊ |
713 | ␉␉␉j=k;␊ |
714 | ␉␉}␊ |
715 | ␉␉␊ |
716 | ␉␉utf_encodestr(tmp, j, (uint8_t*)*name, 25, OSHostByteOrder() );␊ |
717 | ␉}␊ |
718 | ␉if (dirp->deAttributes & ATTR_DIRECTORY)␊ |
719 | ␉␉*flags = kFileTypeDirectory;␊ |
720 | ␉else␊ |
721 | ␉␉*flags = kFileTypeFlat;␊ |
722 | ␉␊ |
723 | ␉// Calculate a fake timestamp using modification date and time values.␊ |
724 | ␉*time = (dirp->deMDate & 0x7FFF) << 16 + dirp->deMTime;␊ |
725 | ␉␊ |
726 | ␉if (infoValid)␊ |
727 | ␉␉*infoValid = 1;␊ |
728 | ␊ |
729 | ␉return 0;␊ |
730 | }␊ |
731 | ␊ |
732 | long ␊ |
733 | MSDOSReadFile(CICell ih, char * filePath, void *base, uint64_t offset, uint64_t length)␊ |
734 | {␊ |
735 | ␉uint8_t *buf;␊ |
736 | ␉off_t cluster;␊ |
737 | ␉uint64_t size;␊ |
738 | ␉uint64_t nskip;␊ |
739 | ␉int toread, wastoread;␊ |
740 | ␉char *ptr = (char *)base;␊ |
741 | ␉struct direntry *dirp;␊ |
742 | ␉int i;␊ |
743 | char devStr[12];␊ |
744 | ␊ |
745 | ␉if (MSDOSInitPartition (ih)<0)␊ |
746 | ␉␉return -1;␊ |
747 | ␉if (filePath[0] == '/')␊ |
748 | ␉␉filePath++;␊ |
749 | ␉buf = malloc(msdosclustersize);␊ |
750 | ␉dirp = getdirpfrompath (ih, filePath, buf);␊ |
751 | ␉␊ |
752 | ␉if (!dirp || (dirp->deAttributes & ATTR_DIRECTORY))␊ |
753 | ␉{␊ |
754 | ␉␉free (buf);␊ |
755 | ␉␉return -1;␊ |
756 | ␉}␊ |
757 | ␉cluster = OSReadLittleInt16 ((dirp->deStartCluster),0);␊ |
758 | ␉if (msdosfatbits == 32)␊ |
759 | ␉␉cluster |= ((uint32_t)OSReadLittleInt16 ((dirp->deHighClust),0)) <<16;␊ |
760 | ␉size = (uint32_t)OSReadLittleInt32 ((dirp->deFileSize),0);␊ |
761 | ␉if (size<=offset)␊ |
762 | ␉␉return -1;␊ |
763 | ␉nskip=offset/msdosclustersize;␊ |
764 | ␉for (i=0;i<nskip;i++)␊ |
765 | ␉␉msdosreadcluster (ih, 0, 0, &cluster);␊ |
766 | ␉msdosreadcluster (ih, buf, msdosclustersize, &cluster);␊ |
767 | ␉toread=length;␊ |
768 | ␉if (length==0 || length>size-offset)␊ |
769 | ␉␉toread=size-offset;␊ |
770 | ␉wastoread=toread;␊ |
771 | ␉bcopy (buf+(offset%msdosclustersize),ptr,MIN(msdosclustersize-(offset%msdosclustersize), toread));␊ |
772 | ␉ptr+=msdosclustersize-(offset%msdosclustersize);␊ |
773 | ␉toread-=msdosclustersize-(offset%msdosclustersize);␊ |
774 | ␉while (toread>0 && msdosreadcluster (ih, (uint8_t *)ptr, MIN(msdosclustersize,toread), &cluster))␊ |
775 | ␉{␊ |
776 | ␉␉ptr+=msdosclustersize;␊ |
777 | ␉␉toread-=msdosclustersize;␊ |
778 | ␉}␊ |
779 | ␉␊ |
780 | getDeviceDescription(ih, devStr);␊ |
781 | ␉verbose("Read FAT%d file: [%s/%s] %d bytes.\n",␊ |
782 | msdosfatbits, devStr, filePath, (uint32_t)( toread<0 ) ? wastoread : wastoread-toread);␊ |
783 | ␉free (buf);␊ |
784 | ␉if (toread<0)␊ |
785 | ␉␉return wastoread;␊ |
786 | ␉else␊ |
787 | ␉␉return wastoread-toread;␊ |
788 | }␊ |
789 | ␊ |
790 | long ␊ |
791 | MSDOSGetFileBlock(CICell ih, char *filePath, unsigned long long *firstBlock)␊ |
792 | {␊ |
793 | ␉uint8_t *buf;␊ |
794 | ␉off_t cluster;␊ |
795 | ␉struct direntry *dirp;␊ |
796 | ␉if (MSDOSInitPartition (ih)<0)␊ |
797 | ␉␉return -1;␊ |
798 | ␉if (filePath[0] == '/')␊ |
799 | ␉␉filePath++;␊ |
800 | ␉buf = malloc(msdosclustersize);␊ |
801 | ␉dirp = getdirpfrompath (ih, filePath, buf);␊ |
802 | ␉if (!dirp || (dirp->deAttributes & ATTR_DIRECTORY))␊ |
803 | ␉{␊ |
804 | ␉␉free (buf);␊ |
805 | ␉␉return -1;␊ |
806 | ␉}␊ |
807 | ␉cluster = OSReadLittleInt16 ((dirp->deStartCluster),0);␊ |
808 | ␉if (msdosfatbits == 32)␊ |
809 | ␉␉cluster |= ((uint32_t)OSReadLittleInt16 ((dirp->deHighClust),0)) <<16;␊ |
810 | ␉␊ |
811 | ␉off_t clusn;␊ |
812 | ␉␊ |
813 | ␉switch (msdosfatbits) {␊ |
814 | ␉␉case 32:␊ |
815 | ␉␉␉if (cluster < CLUST_FIRST ||cluster >= CLUST_RSRVD32)␊ |
816 | ␉␉␉␉return -1;␊ |
817 | ␉␉␉clusn = cluster - CLUST_FIRST;␊ |
818 | ␉␉␉break;␊ |
819 | ␉␉case 16:␊ |
820 | ␉␉␉if (cluster < CLUST_FIRST ||cluster >= CLUST_RSRVD16)␊ |
821 | ␉␉␉␉return 0;␊ |
822 | ␉␉␉clusn = cluster - CLUST_FIRST;␊ |
823 | ␉␉␉break;␉␉␉␊ |
824 | ␉␉case 12:␊ |
825 | ␉␉␉␊ |
826 | ␉␉␉if (cluster < CLUST_FIRST ||cluster >= CLUST_RSRVD12)␊ |
827 | ␉␉␉␉return 0;␊ |
828 | ␉␉␉clusn = cluster - CLUST_FIRST;␊ |
829 | ␉␉␉break;␊ |
830 | ␉␉default:␊ |
831 | ␉␉␉return 0;␊ |
832 | ␉}␊ |
833 | ␉␊ |
834 | ␉*firstBlock = ((msdosressector +␊ |
835 | ␉␉␉␉ (msdosnfats * msdosfatsecs))*msdosbps + clusn * msdosclustersize)/512;␊ |
836 | ␉free (buf);␊ |
837 | ␉return 0;␊ |
838 | }␊ |
839 | ␊ |
840 | ␊ |
841 | long MSDOSLoadFile(CICell ih, char * filePath)␊ |
842 | {␊ |
843 | return MSDOSReadFile(ih, filePath, (void *)gFSLoadAddress, 0, 0);␊ |
844 | }␊ |
845 | ␊ |
846 | /* Fix up volume label. */␊ |
847 | static void␊ |
848 | fixLabel(uint8_t *label, char *str, long strMaxLen)␊ |
849 | {␊ |
850 | int␉␉␉i, len;␊ |
851 | ␉uint16_t␉labelucs[13];␊ |
852 | //unsigned char␉labelUTF8[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 | }␊ |
865 | ␉labelucs[i++]=0;␊ |
866 | ␉len=i;␊ |
867 | ␉for (;i>=0;--i)␊ |
868 | ␉␉labelucs[i]=label[i]>=128?cp850[label[i]-128][1]:(label[i]);␊ |
869 | ␉␊ |
870 | ␉utf_encodestr(labelucs, len, (uint8_t *)str, strMaxLen, OSHostByteOrder() );␊ |
871 | }␊ |
872 | ␊ |
873 | ␊ |
874 | void␊ |
875 | MSDOSGetDescription(CICell ih, char *str, long strMaxLen)␊ |
876 | {␊ |
877 | struct direntry *dirp;␊ |
878 | uint8_t␉ label[LABEL_LENGTH+1];␊ |
879 | ␉uint16_t␉␉vfatlabel[WIN_MAXLEN+2*WIN_CHARS];␊ |
880 | ␉struct msdosdirstate st;␊ |
881 | ␉int labelfound = 0;␊ |
882 | ␊ |
883 | ␉if (MSDOSInitPartition (ih)<0)␊ |
884 | ␉{␊ |
885 | ␉␉str[0]=0;␊ |
886 | ␉␉return;␊ |
887 | ␉}␊ |
888 | ␊ |
889 | ␉label[0] = '\0';␊ |
890 | ␉␊ |
891 | ␉initRoot (&st);␊ |
892 | ␉st.buf = malloc(msdosclustersize);␊ |
893 | ␉while ((dirp = getnextdirent (ih, vfatlabel, &st)))␊ |
894 | ␉␉if (dirp->deAttributes & ATTR_VOLUME) {␊ |
895 | ␉␉␉strncpy((char *)label, (char *)dirp->deName, LABEL_LENGTH);␊ |
896 | ␉␉␉labelfound = 1;␊ |
897 | ␉␉␉break;␊ |
898 | ␉␉}␊ |
899 | ␉␉␊ |
900 | ␉free(st.buf);␉␉␊ |
901 | ␊ |
902 | ␉if (vfatlabel[0] && labelfound)␊ |
903 | ␉{␊ |
904 | ␉␉int i;␊ |
905 | ␉␉for (i=0;vfatlabel[i];i++);␊ |
906 | ␉␉utf_encodestr(vfatlabel, i, (u_int8_t *)str, strMaxLen, OSLittleEndian );␉␉␊ |
907 | ␉}␉␊ |
908 | ␉else if (labelfound)␊ |
909 | ␉␉fixLabel(label, str, strMaxLen);␊ |
910 | ␉␊ |
911 | /* else look in the boot blocks */␊ |
912 | if (!labelfound || str[0] == '\0') {␊ |
913 | ␉␉char *buf = malloc (512);␊ |
914 | ␉␉union bootsector *bsp = (union bootsector *)buf;␊ |
915 | ␉␉Seek(ih, 0);␊ |
916 | ␉␉Read(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 | }␊ |
923 | ␉␉free (buf);␊ |
924 | ␉␉fixLabel(label, str, strMaxLen);␊ |
925 | }␊ |
926 | ␊ |
927 | return;␊ |
928 | }␊ |
929 | ␊ |
930 | long ␊ |
931 | MSDOSGetUUID(CICell ih, char *uuidStr)␊ |
932 | {␊ |
933 | ␉char *buf = malloc (512);␊ |
934 | ␉union bootsector *bsp = (union bootsector *)buf;␊ |
935 | ␉␊ |
936 | ␉if (MSDOSInitPartition (ih)<0)␊ |
937 | ␉{␊ |
938 | ␉␉return -1;␊ |
939 | ␉}␊ |
940 | ␉bzero (uuidStr, 16);␊ |
941 | ␉Seek(ih, 0);␊ |
942 | ␉Read(ih, (long)buf, 512);␊ |
943 | ␉if (msdosfatbits == 32) { /* It's FAT32 */␊ |
944 | ␉␉memcpy(uuidStr+12, (char *)((struct extboot *)bsp->bs710.bsExt)->exVolumeID, 4);␊ |
945 | ␉}␊ |
946 | ␉else if (msdosfatbits == 16) {␊ |
947 | ␉␉memcpy(uuidStr+12, (char *)((struct extboot *)bsp->bs50.bsExt)->exVolumeID, 4);␊ |
948 | ␉}␊ |
949 | ␉free (buf);␊ |
950 | return 0;␊ |
951 | ␉␊ |
952 | }␊ |
953 |