Subversion Repositories freemyipod

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
46 theseven 1
/***************************************************************************
2
 *             __________               __   ___.
3
 *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
4
 *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
5
 *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
6
 *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
7
 *                     \/            \/     \/    \/            \/
8
 * $Id: fat.c 25459 2010-04-03 22:02:09Z gevaerts $
9
 *
10
 * Copyright (C) 2002 by Linus Nielsen Feltzing
11
 *
12
 * This program is free software; you can redistribute it and/or
13
 * modify it under the terms of the GNU General Public License
14
 * as published by the Free Software Foundation; either version 2
15
 * of the License, or (at your option) any later version.
16
 *
17
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18
 * KIND, either express or implied.
19
 *
20
 ****************************************************************************/
21
#include <stdio.h>
22
#include <string.h>
23
#include <stdlib.h>
24
#include <ctype.h>
25
#include <stdbool.h>
26
#include "fat.h"
27
#include "storage.h"
28
#include "debug.h"
29
#include "panic.h"
30
#include "system.h"
31
#include "timefuncs.h"
32
#include "kernel.h"
33
#include "rbunicode.h"
34
 
35
#define BYTES2INT16(array,pos) \
36
          (array[pos] | (array[pos+1] << 8 ))
37
#define BYTES2INT32(array,pos) \
38
    ((long)array[pos] | ((long)array[pos+1] << 8 ) | \
39
    ((long)array[pos+2] << 16 ) | ((long)array[pos+3] << 24 ))
40
 
41
#define FATTYPE_FAT12       0
42
#define FATTYPE_FAT16       1
43
#define FATTYPE_FAT32       2
44
 
45
/* BPB offsets; generic */
46
#define BS_JMPBOOT          0
47
#define BS_OEMNAME          3
48
#define BPB_BYTSPERSEC      11
49
#define BPB_SECPERCLUS      13
50
#define BPB_RSVDSECCNT      14
51
#define BPB_NUMFATS         16
52
#define BPB_ROOTENTCNT      17
53
#define BPB_TOTSEC16        19
54
#define BPB_MEDIA           21
55
#define BPB_FATSZ16         22
56
#define BPB_SECPERTRK       24
57
#define BPB_NUMHEADS        26
58
#define BPB_HIDDSEC         28
59
#define BPB_TOTSEC32        32
60
 
61
/* fat12/16 */
62
#define BS_DRVNUM           36
63
#define BS_RESERVED1        37
64
#define BS_BOOTSIG          38
65
#define BS_VOLID            39
66
#define BS_VOLLAB           43
67
#define BS_FILSYSTYPE       54
68
 
69
/* fat32 */
70
#define BPB_FATSZ32         36
71
#define BPB_EXTFLAGS        40
72
#define BPB_FSVER           42
73
#define BPB_ROOTCLUS        44
74
#define BPB_FSINFO          48
75
#define BPB_BKBOOTSEC       50
76
#define BS_32_DRVNUM        64
77
#define BS_32_BOOTSIG       66
78
#define BS_32_VOLID         67
79
#define BS_32_VOLLAB        71
80
#define BS_32_FILSYSTYPE    82
81
 
82
#define BPB_LAST_WORD       510
83
 
84
 
85
/* attributes */
86
#define FAT_ATTR_LONG_NAME   (FAT_ATTR_READ_ONLY | FAT_ATTR_HIDDEN | \
87
                              FAT_ATTR_SYSTEM | FAT_ATTR_VOLUME_ID)
88
#define FAT_ATTR_LONG_NAME_MASK (FAT_ATTR_READ_ONLY | FAT_ATTR_HIDDEN | \
89
                                 FAT_ATTR_SYSTEM | FAT_ATTR_VOLUME_ID | \
90
                                 FAT_ATTR_DIRECTORY | FAT_ATTR_ARCHIVE )
91
 
92
/* NTRES flags */
93
#define FAT_NTRES_LC_NAME    0x08
94
#define FAT_NTRES_LC_EXT     0x10
95
 
96
#define FATDIR_NAME          0
97
#define FATDIR_ATTR          11
98
#define FATDIR_NTRES         12
99
#define FATDIR_CRTTIMETENTH  13
100
#define FATDIR_CRTTIME       14
101
#define FATDIR_CRTDATE       16
102
#define FATDIR_LSTACCDATE    18
103
#define FATDIR_FSTCLUSHI     20
104
#define FATDIR_WRTTIME       22
105
#define FATDIR_WRTDATE       24
106
#define FATDIR_FSTCLUSLO     26
107
#define FATDIR_FILESIZE      28
108
 
109
#define FATLONG_ORDER        0
110
#define FATLONG_TYPE         12
111
#define FATLONG_CHKSUM       13
112
#define FATLONG_LAST_LONG_ENTRY 0x40
113
#define FATLONG_NAME_BYTES_PER_ENTRY 26
114
/* at most 20 LFN entries, keep coherent with fat_dir->longname size ! */
115
#define FATLONG_MAX_ORDER    20
116
 
117
#define FATLONG_NAME_CHUNKS 3
118
static unsigned char FATLONG_NAME_POS[FATLONG_NAME_CHUNKS] = {1, 14, 28};
119
static unsigned char FATLONG_NAME_SIZE[FATLONG_NAME_CHUNKS] = {10, 12, 4};
120
 
121
#define CLUSTERS_PER_FAT_SECTOR (SECTOR_SIZE / 4)
122
#define CLUSTERS_PER_FAT16_SECTOR (SECTOR_SIZE / 2)
123
#define DIR_ENTRIES_PER_SECTOR  (SECTOR_SIZE / DIR_ENTRY_SIZE)
124
#define DIR_ENTRY_SIZE       32
125
#define NAME_BYTES_PER_ENTRY 13
126
#define FAT_BAD_MARK         0x0ffffff7
127
#define FAT_EOF_MARK         0x0ffffff8
128
#define FAT_LONGNAME_PAD_BYTE 0xff
129
#define FAT_LONGNAME_PAD_UCS 0xffff
130
 
131
struct fsinfo {
132
    unsigned long freecount; /* last known free cluster count */
133
    unsigned long nextfree;  /* first cluster to start looking for free
134
                               clusters, or 0xffffffff for no hint */
135
};
136
/* fsinfo offsets */
137
#define FSINFO_FREECOUNT 488
138
#define FSINFO_NEXTFREE  492
139
 
140
/* Note: This struct doesn't hold the raw values after mounting if
141
 * bpb_bytspersec isn't 512. All sector counts are normalized to 512 byte
142
 * physical sectors. */
143
struct bpb
144
{
145
    int bpb_bytspersec;  /* Bytes per sector, typically 512 */
146
    unsigned int bpb_secperclus;  /* Sectors per cluster */
147
    int bpb_rsvdseccnt;  /* Number of reserved sectors */
148
    int bpb_numfats;     /* Number of FAT structures, typically 2 */
149
    int bpb_totsec16;    /* Number of sectors on the volume (old 16-bit) */
150
    int bpb_media;       /* Media type (typically 0xf0 or 0xf8) */
151
    int bpb_fatsz16;     /* Number of used sectors per FAT structure */
152
    unsigned long bpb_totsec32;    /* Number of sectors on the volume
153
                                     (new 32-bit) */
154
    unsigned int last_word;       /* 0xAA55 */
155
 
156
    /**** FAT32 specific *****/
157
    long bpb_fatsz32;
158
    long bpb_rootclus;
159
    long bpb_fsinfo;
160
 
161
    /* variables for internal use */
162
    unsigned long fatsize;
163
    unsigned long totalsectors;
164
    unsigned long rootdirsector;
165
    unsigned long firstdatasector;
166
    unsigned long startsector;
167
    unsigned long dataclusters;
168
    struct fsinfo fsinfo;
169
#ifdef HAVE_FAT16SUPPORT
170
    int bpb_rootentcnt;  /* Number of dir entries in the root */
171
    /* internals for FAT16 support */
172
    bool is_fat16; /* true if we mounted a FAT16 partition, false if FAT32 */
173
    unsigned int rootdiroffset; /* sector offset of root dir relative to start
174
                                 * of first pseudo cluster */
175
#endif /* #ifdef HAVE_FAT16SUPPORT */
176
#ifdef HAVE_MULTIVOLUME
177
#ifdef HAVE_MULTIDRIVE
178
    int drive; /* on which physical device is this located */
179
#endif
180
    bool mounted; /* flag if this volume is mounted */
181
#endif
182
};
183
 
184
static struct bpb fat_bpbs[NUM_VOLUMES]; /* mounted partition info */
185
static bool initialized = false;
186
 
187
static int update_fsinfo(IF_MV_NONVOID(struct bpb* fat_bpb));
188
static int flush_fat(IF_MV_NONVOID(struct bpb* fat_bpb));
189
static int bpb_is_sane(IF_MV_NONVOID(struct bpb* fat_bpb));
190
static void *cache_fat_sector(IF_MV2(struct bpb* fat_bpb,)
191
                              long secnum, bool dirty);
192
static void create_dos_name(const unsigned char *name, unsigned char *newname);
193
static void randomize_dos_name(unsigned char *name);
194
static unsigned long find_free_cluster(IF_MV2(struct bpb* fat_bpb,)
195
                                       unsigned long start);
196
static int transfer(IF_MV2(struct bpb* fat_bpb,) unsigned long start,
197
                    long count, char* buf, bool write );
198
 
199
#define FAT_CACHE_SIZE 0x20
200
#define FAT_CACHE_MASK (FAT_CACHE_SIZE-1)
201
 
202
struct fat_cache_entry
203
{
204
    long secnum;
205
    bool inuse;
206
    bool dirty;
207
#ifdef HAVE_MULTIVOLUME
208
    struct bpb* fat_vol ; /* shared cache for all volumes */
209
#endif
210
};
211
 
212
static char fat_cache_sectors[FAT_CACHE_SIZE][SECTOR_SIZE];
213
static struct fat_cache_entry fat_cache[FAT_CACHE_SIZE];
214
static struct mutex cache_mutex SHAREDBSS_ATTR;
215
 
216
#if defined(HAVE_HOTSWAP) && !(CONFIG_STORAGE & STORAGE_MMC) /* A better condition ?? */
217
void fat_lock(void)
218
{
219
    mutex_lock(&cache_mutex);
220
}
221
 
222
void fat_unlock(void)
223
{
224
    mutex_unlock(&cache_mutex);
225
}
226
#endif
227
 
228
static long cluster2sec(IF_MV2(struct bpb* fat_bpb,) long cluster)
229
{
230
#ifndef HAVE_MULTIVOLUME
231
    struct bpb* fat_bpb = &fat_bpbs[0];
232
#endif
233
#ifdef HAVE_FAT16SUPPORT
234
    /* negative clusters (FAT16 root dir) don't get the 2 offset */
235
    int zerocluster = cluster < 0 ? 0 : 2;
236
#else
237
    const long zerocluster = 2;
238
#endif
239
 
240
    if (cluster > (long)(fat_bpb->dataclusters + 1))
241
    {
242
      DEBUGF( "cluster2sec() - Bad cluster number (%ld)\n", cluster);
243
        return -1;
244
    }
245
 
246
    return (cluster - zerocluster) * fat_bpb->bpb_secperclus 
247
           + fat_bpb->firstdatasector;
248
}
249
 
250
void fat_size(IF_MV2(int volume,) unsigned long* size, unsigned long* free)
251
{
252
#ifndef HAVE_MULTIVOLUME
253
    const int volume = 0;
254
#endif
255
    struct bpb* fat_bpb = &fat_bpbs[volume];
256
    if (size)
257
      *size = fat_bpb->dataclusters * (fat_bpb->bpb_secperclus * SECTOR_SIZE / 1024);
258
    if (free)
259
      *free = fat_bpb->fsinfo.freecount * (fat_bpb->bpb_secperclus * SECTOR_SIZE / 1024);
260
}
261
 
262
void fat_init(void)
263
{
264
    unsigned int i;
265
 
266
    if (!initialized)
267
    {
268
        initialized = true;
269
        mutex_init(&cache_mutex);
270
    }
271
 
272
#ifdef HAVE_PRIORITY_SCHEDULING
273
    /* Disable this because it is dangerous due to the assumption that
274
     * mutex_unlock won't yield */
275
    mutex_set_preempt(&cache_mutex, false);
276
#endif
277
 
278
    /* mark the FAT cache as unused */
279
    for(i = 0;i < FAT_CACHE_SIZE;i++)
280
    {
281
        fat_cache[i].secnum = 8; /* We use a "safe" sector just in case */
282
        fat_cache[i].inuse = false;
283
        fat_cache[i].dirty = false;
284
#ifdef HAVE_MULTIVOLUME
285
        fat_cache[i].fat_vol = NULL;
286
#endif
287
    }
288
#ifdef HAVE_MULTIVOLUME
289
    /* mark the possible volumes as not mounted */
290
    for (i=0; i<NUM_VOLUMES;i++)
291
    {
292
        fat_bpbs[i].mounted = false;
293
    }
294
#endif
295
}
296
 
297
int fat_mount(IF_MV2(int volume,) IF_MD2(int drive,) long startsector)
298
{
299
#ifndef HAVE_MULTIVOLUME
300
    const int volume = 0;
301
#endif
302
    struct bpb* fat_bpb = &fat_bpbs[volume];
303
    unsigned char buf[SECTOR_SIZE];
304
    int rc;
305
    int secmult;
306
    long datasec;
307
#ifdef HAVE_FAT16SUPPORT
308
    int rootdirsectors;
309
#endif
310
 
311
    /* Read the sector */
312
    rc = storage_read_sectors(IF_MD2(drive,) startsector,1,buf);
313
    if(rc)
314
    {
315
        DEBUGF( "fat_mount() - Couldn't read BPB (error code %d)\n", rc);
316
        return rc * 10 - 1;
317
    }
318
 
319
    memset(fat_bpb, 0, sizeof(struct bpb));
320
    fat_bpb->startsector    = startsector;
321
#ifdef HAVE_MULTIDRIVE
322
    fat_bpb->drive          = drive;
323
#endif
324
 
325
    fat_bpb->bpb_bytspersec = BYTES2INT16(buf,BPB_BYTSPERSEC);
326
    secmult = fat_bpb->bpb_bytspersec / SECTOR_SIZE; 
327
    /* Sanity check is performed later */
328
 
329
    fat_bpb->bpb_secperclus = secmult * buf[BPB_SECPERCLUS];
330
    fat_bpb->bpb_rsvdseccnt = secmult * BYTES2INT16(buf,BPB_RSVDSECCNT);
331
    fat_bpb->bpb_numfats    = buf[BPB_NUMFATS];
332
    fat_bpb->bpb_media      = buf[BPB_MEDIA];
333
    fat_bpb->bpb_fatsz16    = secmult * BYTES2INT16(buf,BPB_FATSZ16);
334
    fat_bpb->bpb_fatsz32    = secmult * BYTES2INT32(buf,BPB_FATSZ32);
335
    fat_bpb->bpb_totsec16   = secmult * BYTES2INT16(buf,BPB_TOTSEC16);
336
    fat_bpb->bpb_totsec32   = secmult * BYTES2INT32(buf,BPB_TOTSEC32);
337
    fat_bpb->last_word      = BYTES2INT16(buf,BPB_LAST_WORD);
338
 
339
    /* calculate a few commonly used values */
340
    if (fat_bpb->bpb_fatsz16 != 0)
341
        fat_bpb->fatsize = fat_bpb->bpb_fatsz16;
342
    else
343
        fat_bpb->fatsize = fat_bpb->bpb_fatsz32;
344
 
345
    if (fat_bpb->bpb_totsec16 != 0)
346
        fat_bpb->totalsectors = fat_bpb->bpb_totsec16;
347
    else
348
        fat_bpb->totalsectors = fat_bpb->bpb_totsec32;
349
 
350
#ifdef HAVE_FAT16SUPPORT
351
    fat_bpb->bpb_rootentcnt = BYTES2INT16(buf,BPB_ROOTENTCNT);
352
    if (!fat_bpb->bpb_bytspersec)
353
        return -2;
354
    rootdirsectors = secmult * ((fat_bpb->bpb_rootentcnt * DIR_ENTRY_SIZE
355
                     + fat_bpb->bpb_bytspersec - 1) / fat_bpb->bpb_bytspersec);
356
#endif /* #ifdef HAVE_FAT16SUPPORT */
357
 
358
    fat_bpb->firstdatasector = fat_bpb->bpb_rsvdseccnt
359
#ifdef HAVE_FAT16SUPPORT
360
        + rootdirsectors
361
#endif
362
        + fat_bpb->bpb_numfats * fat_bpb->fatsize;
363
 
364
    /* Determine FAT type */
365
    datasec = fat_bpb->totalsectors - fat_bpb->firstdatasector;
366
    if (fat_bpb->bpb_secperclus)
367
        fat_bpb->dataclusters = datasec / fat_bpb->bpb_secperclus;
368
    else
369
       return -2;
370
 
371
#ifdef TEST_FAT
372
    /*
373
      we are sometimes testing with "illegally small" fat32 images,
374
      so we don't use the proper fat32 test case for test code
375
    */
376
    if ( fat_bpb->bpb_fatsz16 )
377
#else
378
    if ( fat_bpb->dataclusters < 65525 )
379
#endif
380
    { /* FAT16 */
381
#ifdef HAVE_FAT16SUPPORT
382
        fat_bpb->is_fat16 = true;
383
        if (fat_bpb->dataclusters < 4085)
384
        { /* FAT12 */
385
            DEBUGF("This is FAT12. Go away!\n");
386
            return -2;
387
        }
388
#else /* #ifdef HAVE_FAT16SUPPORT */
389
        DEBUGF("This is not FAT32. Go away!\n");
390
        return -2;
391
#endif /* #ifndef HAVE_FAT16SUPPORT */
392
    }
393
 
394
#ifdef HAVE_FAT16SUPPORT
395
    if (fat_bpb->is_fat16)
396
    { /* FAT16 specific part of BPB */
397
        int dirclusters;  
398
        fat_bpb->rootdirsector = fat_bpb->bpb_rsvdseccnt
399
            + fat_bpb->bpb_numfats * fat_bpb->bpb_fatsz16;
400
        dirclusters = ((rootdirsectors + fat_bpb->bpb_secperclus - 1)
401
            / fat_bpb->bpb_secperclus); /* rounded up, to full clusters */
402
        /* I assign negative pseudo cluster numbers for the root directory,
403
           their range is counted upward until -1. */
404
        fat_bpb->bpb_rootclus = 0 - dirclusters; /* backwards, before the data*/
405
        fat_bpb->rootdiroffset = dirclusters * fat_bpb->bpb_secperclus
406
            - rootdirsectors;
407
    }
408
    else
409
#endif /* #ifdef HAVE_FAT16SUPPORT */
410
    { /* FAT32 specific part of BPB */
411
        fat_bpb->bpb_rootclus  = BYTES2INT32(buf,BPB_ROOTCLUS);
412
        fat_bpb->bpb_fsinfo    = secmult * BYTES2INT16(buf,BPB_FSINFO);
413
        fat_bpb->rootdirsector = cluster2sec(IF_MV2(fat_bpb,)
414
                                             fat_bpb->bpb_rootclus);
415
    }
416
 
417
    rc = bpb_is_sane(IF_MV(fat_bpb));
418
    if (rc < 0)
419
    {
420
        DEBUGF( "fat_mount() - BPB is not sane\n");
421
        return rc * 10 - 3;
422
    }
423
 
424
#ifdef HAVE_FAT16SUPPORT
425
    if (fat_bpb->is_fat16)
426
    {
427
        fat_bpb->fsinfo.freecount = 0xffffffff; /* force recalc below */
428
        fat_bpb->fsinfo.nextfree = 0xffffffff;
429
    }
430
    else
431
#endif /* #ifdef HAVE_FAT16SUPPORT */
432
    {
433
        /* Read the fsinfo sector */
434
        rc = storage_read_sectors(IF_MD2(drive,)
435
            startsector + fat_bpb->bpb_fsinfo, 1, buf);
436
        if (rc < 0)
437
        {
438
            DEBUGF( "fat_mount() - Couldn't read FSInfo (error code %d)\n", rc);
439
            return rc * 10 - 4;
440
        }
441
        fat_bpb->fsinfo.freecount = BYTES2INT32(buf, FSINFO_FREECOUNT);
442
        fat_bpb->fsinfo.nextfree = BYTES2INT32(buf, FSINFO_NEXTFREE);
443
    }
444
 
445
    /* calculate freecount if unset */
446
    if ( fat_bpb->fsinfo.freecount == 0xffffffff )
447
    {
448
        fat_recalc_free(IF_MV(volume));
449
    }
450
 
47 farthen 451
    DEBUGF("Freecount: %ld\n",fat_bpb->fsinfo.freecount);
452
    DEBUGF("Nextfree: 0x%lx\n",fat_bpb->fsinfo.nextfree);
453
    DEBUGF("Cluster count: 0x%lx\n",fat_bpb->dataclusters);
454
    DEBUGF("Sectors per cluster: %d\n",fat_bpb->bpb_secperclus);
455
    DEBUGF("FAT sectors: 0x%lx\n",fat_bpb->fatsize);
46 theseven 456
 
457
#ifdef HAVE_MULTIVOLUME
458
    fat_bpb->mounted = true;
459
#endif
460
 
461
    return 0;
462
}
463
 
464
#ifdef HAVE_HOTSWAP
465
int fat_unmount(int volume, bool flush)
466
{
467
    int rc;
468
#ifdef HAVE_MULTIVOLUME
469
    struct bpb* fat_bpb = &fat_bpbs[volume];
470
#else
471
    (void)volume;
472
#endif
473
 
474
    if(flush)
475
    {
476
        rc = flush_fat(IF_MV(fat_bpb)); /* the clean way, while still alive */
477
    }
478
    else
479
    {   /* volume is not accessible any more, e.g. MMC removed */
480
        int i;
481
        mutex_lock(&cache_mutex);
482
        for(i = 0;i < FAT_CACHE_SIZE;i++)
483
        {
484
            struct fat_cache_entry *fce = &fat_cache[i];
485
            if(fce->inuse
486
#ifdef HAVE_MULTIVOLUME
487
               && fce->fat_vol == fat_bpb
488
#endif
489
              )
490
            {
491
                fce->inuse = false; /* discard all from that volume */
492
                fce->dirty = false;
493
            }
494
        }
495
        mutex_unlock(&cache_mutex);
496
        rc = 0;
497
    }
498
#ifdef HAVE_MULTIVOLUME
499
    fat_bpb->mounted = false;
500
#endif
501
    return rc;
502
}
503
#endif /* #ifdef HAVE_HOTSWAP */
504
 
505
void fat_recalc_free(IF_MV_NONVOID(int volume))
506
{
507
#ifndef HAVE_MULTIVOLUME
508
    const int volume = 0;
509
#endif
510
    struct bpb* fat_bpb = &fat_bpbs[volume];
511
    long free = 0;
512
    unsigned long i;
513
#ifdef HAVE_FAT16SUPPORT
514
    if (fat_bpb->is_fat16)
515
    {
516
        for (i = 0; i<fat_bpb->fatsize; i++) {
517
            unsigned int j;
518
            unsigned short* fat = cache_fat_sector(IF_MV2(fat_bpb,) i, false);
519
            for (j = 0; j < CLUSTERS_PER_FAT16_SECTOR; j++) {
520
                unsigned int c = i * CLUSTERS_PER_FAT16_SECTOR + j;
521
                if ( c > fat_bpb->dataclusters+1 ) /* nr 0 is unused */
522
                    break;
523
 
524
                if (letoh16(fat[j]) == 0x0000) {
525
                    free++;
526
                    if ( fat_bpb->fsinfo.nextfree == 0xffffffff )
527
                        fat_bpb->fsinfo.nextfree = c;
528
                }
529
            }
530
        }
531
    }
532
    else
533
#endif /* #ifdef HAVE_FAT16SUPPORT */
534
    {
535
        for (i = 0; i<fat_bpb->fatsize; i++) {
536
            unsigned int j;
537
            unsigned long* fat = cache_fat_sector(IF_MV2(fat_bpb,) i, false);
538
            for (j = 0; j < CLUSTERS_PER_FAT_SECTOR; j++) {
539
                unsigned long c = i * CLUSTERS_PER_FAT_SECTOR + j;
540
                if ( c > fat_bpb->dataclusters+1 ) /* nr 0 is unused */
541
                    break;
542
 
543
                if (!(letoh32(fat[j]) & 0x0fffffff)) {
544
                    free++;
545
                    if ( fat_bpb->fsinfo.nextfree == 0xffffffff )
546
                        fat_bpb->fsinfo.nextfree = c;
547
                }
548
            }
549
        }
550
    }
551
    fat_bpb->fsinfo.freecount = free;
552
    update_fsinfo(IF_MV(fat_bpb));
553
}
554
 
555
static int bpb_is_sane(IF_MV_NONVOID(struct bpb* fat_bpb))
556
{
557
#ifndef HAVE_MULTIVOLUME
558
    struct bpb* fat_bpb = &fat_bpbs[0];
559
#endif
560
    if(fat_bpb->bpb_bytspersec % SECTOR_SIZE)
561
    {
562
        DEBUGF( "bpb_is_sane() - Error: sector size is not sane (%d)\n",
563
                fat_bpb->bpb_bytspersec);
564
        return -1;
565
    }
566
    if((long)fat_bpb->bpb_secperclus * (long)fat_bpb->bpb_bytspersec
567
                                                                   > 128L*1024L)
568
    {
569
        DEBUGF( "bpb_is_sane() - Error: cluster size is larger than 128K "
570
                "(%d * %d = %d)\n",
571
                fat_bpb->bpb_bytspersec, fat_bpb->bpb_secperclus,
572
                fat_bpb->bpb_bytspersec * fat_bpb->bpb_secperclus);
573
        return -2;
574
    }
575
    if(fat_bpb->bpb_numfats != 2)
576
    {
577
        DEBUGF( "bpb_is_sane() - Warning: NumFATS is not 2 (%d)\n",
578
                fat_bpb->bpb_numfats);
579
    }
580
    if(fat_bpb->bpb_media != 0xf0 && fat_bpb->bpb_media < 0xf8)
581
    {
582
        DEBUGF( "bpb_is_sane() - Warning: Non-standard "
583
                "media type (0x%02x)\n",
584
                fat_bpb->bpb_media);
585
    }
586
    if(fat_bpb->last_word != 0xaa55)
587
    {
588
        DEBUGF( "bpb_is_sane() - Error: Last word is not "
589
                "0xaa55 (0x%04x)\n", fat_bpb->last_word);
590
        return -3;
591
    }
592
 
593
    if (fat_bpb->fsinfo.freecount >
594
        (fat_bpb->totalsectors - fat_bpb->firstdatasector)/
595
        fat_bpb->bpb_secperclus)
596
    {
597
        DEBUGF( "bpb_is_sane() - Error: FSInfo.Freecount > disk size "
598
                 "(0x%04lx)\n", fat_bpb->fsinfo.freecount);
599
        return -4;
600
    }
601
 
602
    return 0;
603
}
604
 
605
static void flush_fat_sector(struct fat_cache_entry *fce,
606
                             unsigned char *sectorbuf)
607
{
608
    int rc;
609
    long secnum;
610
 
611
    /* With multivolume, use only the FAT info from the cached sector! */
612
#ifdef HAVE_MULTIVOLUME
613
    secnum = fce->secnum + fce->fat_vol->startsector;
614
#else
615
    secnum = fce->secnum + fat_bpbs[0].startsector;
616
#endif
617
 
618
    /* Write to the first FAT */
619
    rc = storage_write_sectors(IF_MD2(fce->fat_vol->drive,)
620
                           secnum, 1,
621
                           sectorbuf);
622
    if(rc < 0)
623
    {
624
        panicf("flush_fat_sector() - Could not write sector %ld"
625
               " (error %d)\n",
626
               secnum, rc);
627
    }
628
#ifdef HAVE_MULTIVOLUME
629
    if(fce->fat_vol->bpb_numfats > 1)
630
#else
631
    if(fat_bpbs[0].bpb_numfats > 1)
632
#endif
633
    {
634
        /* Write to the second FAT */
635
#ifdef HAVE_MULTIVOLUME
636
        secnum += fce->fat_vol->fatsize;
637
#else
638
        secnum += fat_bpbs[0].fatsize;
639
#endif
640
        rc = storage_write_sectors(IF_MD2(fce->fat_vol->drive,)
641
                               secnum, 1, sectorbuf);
642
        if(rc < 0)
643
        {
644
            panicf("flush_fat_sector() - Could not write sector %ld"
645
                   " (error %d)\n",
646
                   secnum, rc);
647
        }
648
    }
649
    fce->dirty = false;
650
}
651
 
652
/* Note: The returned pointer is only safely valid until the next
653
         task switch! (Any subsequent ata read/write may yield.) */
654
static void *cache_fat_sector(IF_MV2(struct bpb* fat_bpb,)
655
                              long fatsector, bool dirty)
656
{
657
#ifndef HAVE_MULTIVOLUME
658
    struct bpb* fat_bpb = &fat_bpbs[0];
659
#endif
660
    long secnum = fatsector + fat_bpb->bpb_rsvdseccnt;
661
    int cache_index = secnum & FAT_CACHE_MASK;
662
    struct fat_cache_entry *fce = &fat_cache[cache_index];
663
    unsigned char *sectorbuf = &fat_cache_sectors[cache_index][0];
664
    int rc;
665
 
666
    mutex_lock(&cache_mutex); /* make changes atomic */
667
 
668
    /* Delete the cache entry if it isn't the sector we want */
669
    if(fce->inuse && (fce->secnum != secnum
670
#ifdef HAVE_MULTIVOLUME
671
        || fce->fat_vol != fat_bpb
672
#endif
673
    ))
674
    {
675
        /* Write back if it is dirty */
676
        if(fce->dirty)
677
        {
678
            flush_fat_sector(fce, sectorbuf);
679
        }
680
        fce->inuse = false;
681
    }
682
 
683
    /* Load the sector if it is not cached */
684
    if(!fce->inuse)
685
    {
686
        rc = storage_read_sectors(IF_MD2(fat_bpb->drive,)
687
                              secnum + fat_bpb->startsector,1,
688
                              sectorbuf);
689
        if(rc < 0)
690
        {
691
            DEBUGF( "cache_fat_sector() - Could not read sector %ld"
692
                    " (error %d)\n", secnum, rc);
693
            mutex_unlock(&cache_mutex);
694
            return NULL;
695
        }
696
        fce->inuse = true;
697
        fce->secnum = secnum;
698
#ifdef HAVE_MULTIVOLUME
699
        fce->fat_vol = fat_bpb;
700
#endif
701
    }
702
    if (dirty)
703
        fce->dirty = true; /* dirt remains, sticky until flushed */
704
    mutex_unlock(&cache_mutex);
705
    return sectorbuf;
706
}
707
 
708
static unsigned long find_free_cluster(IF_MV2(struct bpb* fat_bpb,)
709
                                       unsigned long startcluster)
710
{
711
#ifndef HAVE_MULTIVOLUME
712
    struct bpb* fat_bpb = &fat_bpbs[0];
713
#endif
714
    unsigned long sector;
715
    unsigned long offset;
716
    unsigned long i;
717
 
718
#ifdef HAVE_FAT16SUPPORT
719
    if (fat_bpb->is_fat16)
720
    {
721
        sector = startcluster / CLUSTERS_PER_FAT16_SECTOR;
722
        offset = startcluster % CLUSTERS_PER_FAT16_SECTOR;
723
 
724
        for (i = 0; i<fat_bpb->fatsize; i++) {
725
            unsigned int j;
726
            unsigned int nr = (i + sector) % fat_bpb->fatsize;
727
            unsigned short* fat = cache_fat_sector(IF_MV2(fat_bpb,) nr, false);
728
            if ( !fat )
729
                break;
730
            for (j = 0; j < CLUSTERS_PER_FAT16_SECTOR; j++) {
731
                int k = (j + offset) % CLUSTERS_PER_FAT16_SECTOR;
732
                if (letoh16(fat[k]) == 0x0000) {
733
                    unsigned int c = nr * CLUSTERS_PER_FAT16_SECTOR + k;
734
                     /* Ignore the reserved clusters 0 & 1, and also
735
                        cluster numbers out of bounds */
736
                    if ( c < 2 || c > fat_bpb->dataclusters+1 )
737
                        continue;
47 farthen 738
                    DEBUGF("find_free_cluster(%x) == %x\n",startcluster,c);
46 theseven 739
                    fat_bpb->fsinfo.nextfree = c;
740
                    return c;
741
                }
742
            }
743
            offset = 0;
744
        }
745
    }
746
    else
747
#endif /* #ifdef HAVE_FAT16SUPPORT */
748
    {
749
        sector = startcluster / CLUSTERS_PER_FAT_SECTOR;
750
        offset = startcluster % CLUSTERS_PER_FAT_SECTOR;
751
 
752
        for (i = 0; i<fat_bpb->fatsize; i++) {
753
            unsigned int j;
754
            unsigned long nr = (i + sector) % fat_bpb->fatsize;
755
            unsigned long* fat = cache_fat_sector(IF_MV2(fat_bpb,) nr, false);
756
            if ( !fat )
757
                break;
758
            for (j = 0; j < CLUSTERS_PER_FAT_SECTOR; j++) {
759
                int k = (j + offset) % CLUSTERS_PER_FAT_SECTOR;
760
                if (!(letoh32(fat[k]) & 0x0fffffff)) {
761
                    unsigned long c = nr * CLUSTERS_PER_FAT_SECTOR + k;
762
                     /* Ignore the reserved clusters 0 & 1, and also
763
                        cluster numbers out of bounds */
764
                    if ( c < 2 || c > fat_bpb->dataclusters+1 )
765
                        continue;
47 farthen 766
                    DEBUGF("find_free_cluster(%lx) == %lx\n",startcluster,c);
46 theseven 767
                    fat_bpb->fsinfo.nextfree = c;
768
                    return c;
769
                }
770
            }
771
            offset = 0;
772
        }
773
    }
774
 
47 farthen 775
    DEBUGF("find_free_cluster(%lx) == 0\n",startcluster);
46 theseven 776
    return 0; /* 0 is an illegal cluster number */
777
}
778
 
779
static int update_fat_entry(IF_MV2(struct bpb* fat_bpb,) unsigned long entry,
780
                            unsigned long val)
781
{
782
#ifndef HAVE_MULTIVOLUME
783
    struct bpb* fat_bpb = &fat_bpbs[0];
784
#endif
785
#ifdef HAVE_FAT16SUPPORT
786
    if (fat_bpb->is_fat16)
787
    {
788
        int sector = entry / CLUSTERS_PER_FAT16_SECTOR;
789
        int offset = entry % CLUSTERS_PER_FAT16_SECTOR;
790
        unsigned short* sec;
791
 
792
        val &= 0xFFFF;
793
 
47 farthen 794
        DEBUGF("update_fat_entry(%x,%x)\n",entry,val);
46 theseven 795
 
796
        if (entry==val)
797
            panicf("Creating FAT loop: %lx,%lx\n",entry,val);
798
 
799
        if ( entry < 2 )
800
            panicf("Updating reserved FAT entry %ld.\n",entry);
801
 
802
        sec = cache_fat_sector(IF_MV2(fat_bpb,) sector, true);
803
        if (!sec)
804
        {
805
            DEBUGF( "update_fat_entry() - Could not cache sector %d\n", sector);
806
            return -1;
807
        }
808
 
809
        if ( val ) {
810
            if (letoh16(sec[offset]) == 0x0000 && fat_bpb->fsinfo.freecount > 0)
811
                fat_bpb->fsinfo.freecount--;
812
        }
813
        else {
814
            if (letoh16(sec[offset]))
815
                fat_bpb->fsinfo.freecount++;
816
        }
817
 
47 farthen 818
        DEBUGF("update_fat_entry: %d free clusters\n",
46 theseven 819
                fat_bpb->fsinfo.freecount);
820
 
821
        sec[offset] = htole16(val);
822
    }
823
    else
824
#endif /* #ifdef HAVE_FAT16SUPPORT */
825
    {
826
        long sector = entry / CLUSTERS_PER_FAT_SECTOR;
827
        int offset = entry % CLUSTERS_PER_FAT_SECTOR;
828
        unsigned long* sec;
829
 
47 farthen 830
        DEBUGF("update_fat_entry(%lx,%lx)\n",entry,val);
46 theseven 831
 
832
        if (entry==val)
833
            panicf("Creating FAT loop: %lx,%lx\n",entry,val);
834
 
835
        if ( entry < 2 )
836
            panicf("Updating reserved FAT entry %ld.\n",entry);
837
 
838
        sec = cache_fat_sector(IF_MV2(fat_bpb,) sector, true);
839
        if (!sec)
840
        {
841
            DEBUGF("update_fat_entry() - Could not cache sector %ld\n", sector);
842
            return -1;
843
        }
844
 
845
        if ( val ) {
846
            if (!(letoh32(sec[offset]) & 0x0fffffff) &&
847
                fat_bpb->fsinfo.freecount > 0)
848
                fat_bpb->fsinfo.freecount--;
849
        }
850
        else {
851
            if (letoh32(sec[offset]) & 0x0fffffff)
852
                fat_bpb->fsinfo.freecount++;
853
        }
854
 
47 farthen 855
        DEBUGF("update_fat_entry: %ld free clusters\n",
46 theseven 856
                fat_bpb->fsinfo.freecount);
857
 
858
        /* don't change top 4 bits */
859
        sec[offset] &= htole32(0xf0000000);
860
        sec[offset] |= htole32(val & 0x0fffffff);
861
    }
862
 
863
    return 0;
864
}
865
 
866
static long read_fat_entry(IF_MV2(struct bpb* fat_bpb,) unsigned long entry)
867
{
868
#ifdef HAVE_FAT16SUPPORT
869
#ifndef HAVE_MULTIVOLUME
870
    struct bpb* fat_bpb = &fat_bpbs[0];
871
#endif
872
    if (fat_bpb->is_fat16)
873
    {
874
        int sector = entry / CLUSTERS_PER_FAT16_SECTOR;
875
        int offset = entry % CLUSTERS_PER_FAT16_SECTOR;
876
        unsigned short* sec;
877
 
878
        sec = cache_fat_sector(IF_MV2(fat_bpb,) sector, false);
879
        if (!sec)
880
        {
881
            DEBUGF( "read_fat_entry() - Could not cache sector %d\n", sector);
882
            return -1;
883
        }
884
 
885
        return letoh16(sec[offset]);
886
    }
887
    else
888
#endif /* #ifdef HAVE_FAT16SUPPORT */
889
    {
890
        long sector = entry / CLUSTERS_PER_FAT_SECTOR;
891
        int offset = entry % CLUSTERS_PER_FAT_SECTOR;
892
        unsigned long* sec;
893
 
894
        sec = cache_fat_sector(IF_MV2(fat_bpb,) sector, false);
895
        if (!sec)
896
        {
897
            DEBUGF( "read_fat_entry() - Could not cache sector %ld\n", sector);
898
            return -1;
899
        }
900
 
901
        return letoh32(sec[offset]) & 0x0fffffff;
902
    }
903
}
904
 
905
static long get_next_cluster(IF_MV2(struct bpb* fat_bpb,) long cluster)
906
{
907
    long next_cluster;
908
    long eof_mark = FAT_EOF_MARK;
909
 
910
#ifdef HAVE_FAT16SUPPORT
911
#ifndef HAVE_MULTIVOLUME
912
    struct bpb* fat_bpb = &fat_bpbs[0];
913
#endif
914
    if (fat_bpb->is_fat16)
915
    {
916
        eof_mark &= 0xFFFF; /* only 16 bit */
917
        if (cluster < 0) /* FAT16 root dir */
918
            return cluster + 1; /* don't use the FAT */
919
    }
920
#endif
921
    next_cluster = read_fat_entry(IF_MV2(fat_bpb,) cluster);
922
 
923
    /* is this last cluster in chain? */
924
    if ( next_cluster >= eof_mark )
925
        return 0;
926
    else
927
        return next_cluster;
928
}
929
 
930
static int update_fsinfo(IF_MV_NONVOID(struct bpb* fat_bpb))
931
{
932
#ifndef HAVE_MULTIVOLUME
933
    struct bpb* fat_bpb = &fat_bpbs[0];
934
#endif
935
    unsigned char fsinfo[SECTOR_SIZE];
936
    unsigned long* intptr;
937
    int rc;
938
 
939
#ifdef HAVE_FAT16SUPPORT
940
    if (fat_bpb->is_fat16)
941
        return 0; /* FAT16 has no FsInfo */
942
#endif /* #ifdef HAVE_FAT16SUPPORT */
943
 
944
    /* update fsinfo */
945
    rc = storage_read_sectors(IF_MD2(fat_bpb->drive,)
946
                          fat_bpb->startsector + fat_bpb->bpb_fsinfo, 1,fsinfo);
947
    if (rc < 0)
948
    {
949
        DEBUGF( "flush_fat() - Couldn't read FSInfo (error code %d)\n", rc);
950
        return rc * 10 - 1;
951
    }
952
    intptr = (long*)&(fsinfo[FSINFO_FREECOUNT]);
953
    *intptr = htole32(fat_bpb->fsinfo.freecount);
954
 
955
    intptr = (long*)&(fsinfo[FSINFO_NEXTFREE]);
956
    *intptr = htole32(fat_bpb->fsinfo.nextfree);
957
 
958
    rc = storage_write_sectors(IF_MD2(fat_bpb->drive,)
959
                           fat_bpb->startsector + fat_bpb->bpb_fsinfo,1,fsinfo);
960
    if (rc < 0)
961
    {
962
        DEBUGF( "flush_fat() - Couldn't write FSInfo (error code %d)\n", rc);
963
        return rc * 10 - 2;
964
    }
965
 
966
    return 0;
967
}
968
 
969
static int flush_fat(IF_MV_NONVOID(struct bpb* fat_bpb))
970
{
971
    int i;
972
    int rc;
973
    unsigned char *sec;
47 farthen 974
    DEBUGF("flush_fat()\n");
46 theseven 975
 
976
    mutex_lock(&cache_mutex);
977
    for(i = 0;i < FAT_CACHE_SIZE;i++)
978
    {
979
        struct fat_cache_entry *fce = &fat_cache[i];
980
        if(fce->inuse 
981
#ifdef HAVE_MULTIVOLUME
982
            && fce->fat_vol == fat_bpb
983
#endif
984
            && fce->dirty)
985
        {
986
            sec = fat_cache_sectors[i];
987
            flush_fat_sector(fce, sec);
988
        }
989
    }
990
    mutex_unlock(&cache_mutex);
991
 
992
    rc = update_fsinfo(IF_MV(fat_bpb));
993
    if (rc < 0)
994
        return rc * 10 - 3;
995
 
996
    return 0;
997
}
998
 
999
static void fat_time(unsigned short* date,
1000
                     unsigned short* time,
1001
                     unsigned short* tenth )
1002
{
1003
#if CONFIG_RTC
1004
    struct tm* tm = get_time();
1005
 
1006
    if (date)
1007
        *date = ((tm->tm_year - 80) << 9) |
1008
            ((tm->tm_mon + 1) << 5) |
1009
            tm->tm_mday;
1010
 
1011
    if (time)
1012
        *time = (tm->tm_hour << 11) |
1013
            (tm->tm_min << 5) |
1014
            (tm->tm_sec >> 1);
1015
 
1016
    if (tenth)
1017
        *tenth = (tm->tm_sec & 1) * 100;
1018
#else
1019
    /* non-RTC version returns an increment from the supplied time, or a
1020
     * fixed standard time/date if no time given as input */
1021
 
1022
/* Macros to convert a 2-digit string to a decimal constant.
1023
   (YEAR), MONTH and DAY are set by the date command, which outputs
1024
   DAY as 00..31 and MONTH as 01..12. The leading zero would lead to
1025
   misinterpretation as an octal constant. */
1026
#define S100(x) 1 ## x
1027
#define C2DIG2DEC(x) (S100(x)-100)
1028
/* The actual build date, as FAT date constant */
1029
#define BUILD_DATE_FAT (((YEAR - 1980) << 9) \
1030
                        | (C2DIG2DEC(MONTH) << 5) \
1031
                        | C2DIG2DEC(DAY))
1032
 
1033
    bool date_forced = false;
1034
    bool next_day = false;
1035
    unsigned time2 = 0; /* double time, for CRTTIME with 1s precision */
1036
 
1037
    if (date && *date < BUILD_DATE_FAT)
1038
    {
1039
        *date = BUILD_DATE_FAT;
1040
        date_forced = true;
1041
    }
1042
 
1043
    if (time)
1044
    {
1045
        time2 = *time << 1;
1046
        if (time2 == 0 || date_forced)
1047
        {
1048
            time2 = (11 < 6) | 11; /* set to 00:11:11 */
1049
        }
1050
        else
1051
        {
1052
            unsigned mins  = (time2 >> 6) & 0x3f;
1053
            unsigned hours = (time2 >> 12) & 0x1f;
1054
 
1055
            mins = 11 * ((mins/11) + 1); /* advance to next multiple of 11 */
1056
            if (mins > 59)
1057
            {
1058
                mins = 11; /* 00 would be a bad marker */
1059
                if (++hours > 23)
1060
                {
1061
                    hours = 0;
1062
                    next_day = true;
1063
                }
1064
            }
1065
            time2 = (hours << 12) | (mins << 6) | mins; /* secs = mins */
1066
        }
1067
        *time = time2 >> 1;
1068
    }
1069
 
1070
    if (tenth)
1071
        *tenth = (time2 & 1) * 100;
1072
 
1073
    if (date && next_day)
1074
    {
1075
        static const unsigned char daysinmonth[] =
1076
                              {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1077
        unsigned day   = *date & 0x1f;
1078
        unsigned month = (*date >> 5) & 0x0f;
1079
        unsigned year  = (*date >> 9) & 0x7f;
1080
 
1081
        /* simplification: ignore leap years */
1082
        if (++day > daysinmonth[month-1])
1083
        {
1084
            day = 1;
1085
            if (++month > 12)
1086
            {
1087
                month = 1;
1088
                year++;
1089
            }
1090
        }
1091
        *date = (year << 9) | (month << 5) | day;
1092
    }
1093
 
1094
#endif /* CONFIG_RTC */
1095
}
1096
 
1097
static int write_long_name(struct fat_file* file,
1098
                           unsigned int firstentry,
1099
                           unsigned int numentries,
1100
                           const unsigned char* name,
1101
                           const unsigned char* shortname,
1102
                           bool is_directory)
1103
{
1104
    unsigned char buf[SECTOR_SIZE];
1105
    unsigned char* entry;
1106
    unsigned int idx = firstentry % DIR_ENTRIES_PER_SECTOR;
1107
    unsigned int sector = firstentry / DIR_ENTRIES_PER_SECTOR;
1108
    unsigned char chksum = 0;
1109
    unsigned int i, j=0;
1110
    unsigned int nameidx=0, namelen = utf8length(name);
1111
    int rc;
1112
    unsigned short name_utf16[namelen + 1];
1113
 
47 farthen 1114
    DEBUGF("write_long_name(file:%lx, first:%d, num:%d, name:%s)\n",
46 theseven 1115
            file->firstcluster, firstentry, numentries, name);
1116
 
1117
    rc = fat_seek(file, sector);
1118
    if (rc<0)
1119
        return rc * 10 - 1;
1120
 
1121
    rc = fat_readwrite(file, 1, buf, false);
1122
    if (rc<1)
1123
        return rc * 10 - 2;
1124
 
1125
    /* calculate shortname checksum */
1126
    for (i=11; i>0; i--)
1127
        chksum = ((chksum & 1) ? 0x80 : 0) + (chksum >> 1) + shortname[j++];
1128
 
1129
    /* calc position of last name segment */
1130
    if ( namelen > NAME_BYTES_PER_ENTRY )
1131
        for (nameidx=0;
1132
             nameidx < (namelen - NAME_BYTES_PER_ENTRY);
1133
             nameidx += NAME_BYTES_PER_ENTRY);
1134
 
1135
    /* we need to convert the name first    */
1136
    /* since it is written in reverse order */
1137
    for (i = 0; i <= namelen; i++)
1138
        name = utf8decode(name, &name_utf16[i]);
1139
 
1140
    for (i=0; i < numentries; i++) {
1141
        /* new sector? */
1142
        if ( idx >= DIR_ENTRIES_PER_SECTOR ) {
1143
            /* update current sector */
1144
            rc = fat_seek(file, sector);
1145
            if (rc<0)
1146
                return rc * 10 - 3;
1147
 
1148
            rc = fat_readwrite(file, 1, buf, true);
1149
            if (rc<1)
1150
                return rc * 10 - 4;
1151
 
1152
            /* read next sector */
1153
            rc = fat_readwrite(file, 1, buf, false);
1154
            if (rc<0) {
47 farthen 1155
                DEBUGF("Failed writing new sector: %d\n",rc);
46 theseven 1156
                return rc * 10 - 5;
1157
            }
1158
            if (rc==0)
1159
                /* end of dir */
1160
                memset(buf, 0, sizeof buf);
1161
 
1162
            sector++;
1163
            idx = 0;
1164
        }
1165
 
1166
        entry = buf + idx * DIR_ENTRY_SIZE;
1167
 
1168
        /* verify this entry is free */
1169
        if (entry[0] && entry[0] != 0xe5 )
1170
            panicf("Dir entry %d in sector %x is not free! "
1171
                   "%02x %02x %02x %02x",
1172
                   idx, sector,
1173
                   entry[0], entry[1], entry[2], entry[3]);
1174
 
1175
        memset(entry, 0, DIR_ENTRY_SIZE);
1176
        if ( i+1 < numentries ) {
1177
            /* longname entry */
1178
            unsigned int k, l = nameidx;
1179
 
1180
            entry[FATLONG_ORDER] = numentries-i-1;
1181
            if (i==0) {
1182
                /* mark this as last long entry */
1183
                entry[FATLONG_ORDER] |= FATLONG_LAST_LONG_ENTRY;
1184
 
1185
                /* pad name with 0xffff  */
1186
                for (k=1; k<11; k++) entry[k] = FAT_LONGNAME_PAD_BYTE;
1187
                for (k=14; k<26; k++) entry[k] = FAT_LONGNAME_PAD_BYTE;
1188
                for (k=28; k<32; k++) entry[k] = FAT_LONGNAME_PAD_BYTE;
1189
            };
1190
            /* set name */
1191
            for (k=0; k<5 && l <= namelen; k++) {
1192
                entry[k*2 + 1] = (unsigned char)(name_utf16[l] & 0xff);
1193
                entry[k*2 + 2] = (unsigned char)(name_utf16[l++] >> 8);
1194
            }
1195
            for (k=0; k<6 && l <= namelen; k++) {
1196
                entry[k*2 + 14] = (unsigned char)(name_utf16[l] & 0xff);
1197
                entry[k*2 + 15] = (unsigned char)(name_utf16[l++] >> 8);
1198
            }
1199
            for (k=0; k<2 && l <= namelen; k++) {
1200
                entry[k*2 + 28] = (unsigned char)(name_utf16[l] & 0xff);
1201
                entry[k*2 + 29] = (unsigned char)(name_utf16[l++] >> 8);
1202
            }
1203
 
1204
            entry[FATDIR_ATTR] = FAT_ATTR_LONG_NAME;
1205
            entry[FATDIR_FSTCLUSLO] = 0;
1206
            entry[FATLONG_TYPE] = 0;
1207
            entry[FATLONG_CHKSUM] = chksum;
47 farthen 1208
            DEBUGF("Longname entry %d: %s\n", idx, name+nameidx);
46 theseven 1209
        }
1210
        else {
1211
            /* shortname entry */
1212
            unsigned short date=0, time=0, tenth=0;
47 farthen 1213
            DEBUGF("Shortname entry: %s\n", shortname);
46 theseven 1214
            memcpy(entry + FATDIR_NAME, shortname, 11);
1215
            entry[FATDIR_ATTR] = is_directory?FAT_ATTR_DIRECTORY:0;
1216
            entry[FATDIR_NTRES] = 0;
1217
 
1218
            fat_time(&date, &time, &tenth);
1219
            entry[FATDIR_CRTTIMETENTH] = tenth;
1220
            *(unsigned short*)(entry + FATDIR_CRTTIME) = htole16(time);
1221
            *(unsigned short*)(entry + FATDIR_WRTTIME) = htole16(time);
1222
            *(unsigned short*)(entry + FATDIR_CRTDATE) = htole16(date);
1223
            *(unsigned short*)(entry + FATDIR_WRTDATE) = htole16(date);
1224
            *(unsigned short*)(entry + FATDIR_LSTACCDATE) = htole16(date);
1225
        }
1226
        idx++;
1227
        nameidx -= NAME_BYTES_PER_ENTRY;
1228
    }
1229
 
1230
    /* update last sector */
1231
    rc = fat_seek(file, sector);
1232
    if (rc<0)
1233
        return rc * 10 - 6;
1234
 
1235
    rc = fat_readwrite(file, 1, buf, true);
1236
    if (rc<1)
1237
        return rc * 10 - 7;
1238
 
1239
    return 0;
1240
}
1241
 
1242
static int fat_checkname(const unsigned char* newname)
1243
{
1244
    static const char invalid_chars[] = "\"*/:<>?\\|";
1245
    int len = strlen(newname);
1246
    /* More sanity checks are probably needed */
1247
    if (len > 255 || newname[len - 1] == '.')
1248
    {
1249
        return -1;
1250
    }
1251
    while (*newname)
1252
    {
1253
        if (*newname < ' ' || strchr(invalid_chars, *newname) != NULL)
1254
            return -1;
1255
        newname++;
1256
    }
1257
    /* check trailing space(s) */
1258
    if(*(--newname) == ' ')
1259
        return -1;
1260
 
1261
    return 0;
1262
}
1263
 
1264
static int add_dir_entry(struct fat_dir* dir,
1265
                         struct fat_file* file,
1266
                         const char* name,
1267
                         bool is_directory,
1268
                         bool dotdir)
1269
{
1270
#ifdef HAVE_MULTIVOLUME
1271
    struct bpb* fat_bpb = &fat_bpbs[dir->file.volume];
1272
#else
1273
    struct bpb* fat_bpb = &fat_bpbs[0];
1274
#endif
1275
    unsigned char buf[SECTOR_SIZE];
1276
    unsigned char shortname[12];
1277
    int rc;
1278
    unsigned int sector;
1279
    bool done = false;
1280
    int entries_needed, entries_found = 0;
1281
    int firstentry;
1282
 
47 farthen 1283
    DEBUGF( "add_dir_entry(%s,%lx)\n",
46 theseven 1284
             name, file->firstcluster);
1285
 
1286
    /* Don't check dotdirs name for validity */
1287
    if (dotdir == false) {
1288
        rc = fat_checkname(name);
1289
        if (rc < 0) {
1290
            /* filename is invalid */
1291
            return rc * 10 - 1;
1292
        }
1293
    }
1294
 
1295
#ifdef HAVE_MULTIVOLUME
1296
    file->volume = dir->file.volume; /* inherit the volume, to make sure */
1297
#endif
1298
 
1299
    /* The "." and ".." directory entries must not be long names */
1300
    if(dotdir) {
1301
        int i;
1302
        strlcpy(shortname, name, 12);
1303
        for(i = strlen(shortname); i < 12; i++)
1304
            shortname[i] = ' ';
1305
 
1306
        entries_needed = 1;
1307
    } else {
1308
        create_dos_name(name, shortname);
1309
 
1310
        /* one dir entry needed for every 13 bytes of filename,
1311
           plus one entry for the short name */
1312
        entries_needed = (utf8length(name) + (NAME_BYTES_PER_ENTRY-1))
1313
                         / NAME_BYTES_PER_ENTRY + 1;
1314
    }
1315
 
1316
  restart:
1317
    firstentry = -1;
1318
 
1319
    rc = fat_seek(&dir->file, 0);
1320
    if (rc < 0)
1321
        return rc * 10 - 2;
1322
 
1323
    /* step 1: search for free entries and check for duplicate shortname */
1324
    for (sector = 0; !done; sector++)
1325
    {
1326
        unsigned int i;
1327
 
1328
        rc = fat_readwrite(&dir->file, 1, buf, false);
1329
        if (rc < 0) {
1330
            DEBUGF( "add_dir_entry() - Couldn't read dir"
1331
                    " (error code %d)\n", rc);
1332
            return rc * 10 - 3;
1333
        }
1334
 
1335
        if (rc == 0) { /* current end of dir reached */
47 farthen 1336
            DEBUGF("End of dir on cluster boundary\n");
46 theseven 1337
            break;
1338
        }
1339
 
1340
        /* look for free slots */
1341
        for (i = 0; i < DIR_ENTRIES_PER_SECTOR; i++)
1342
        {
1343
            switch (buf[i * DIR_ENTRY_SIZE]) {
1344
              case 0:
1345
                entries_found += DIR_ENTRIES_PER_SECTOR - i;
47 farthen 1346
                DEBUGF("Found end of dir %d\n",
46 theseven 1347
                        sector * DIR_ENTRIES_PER_SECTOR + i);
1348
                i = DIR_ENTRIES_PER_SECTOR - 1;
1349
                done = true;
1350
                break;
1351
 
1352
              case 0xe5:
1353
                entries_found++;
47 farthen 1354
                DEBUGF("Found free entry %d (%d/%d)\n",
46 theseven 1355
                        sector * DIR_ENTRIES_PER_SECTOR + i,
1356
                        entries_found, entries_needed);
1357
                break;
1358
 
1359
              default:
1360
                entries_found = 0;
1361
 
1362
                /* check that our intended shortname doesn't already exist */
1363
                if (!strncmp(shortname, buf + i * DIR_ENTRY_SIZE, 11)) {
1364
                    /* shortname exists already, make a new one */
1365
                    randomize_dos_name(shortname);
47 farthen 1366
                    DEBUGF("Duplicate shortname, changing to %s\n",
46 theseven 1367
                            shortname);
1368
 
1369
                    /* name has changed, we need to restart search */
1370
                    goto restart;
1371
                }
1372
                break;
1373
            }
1374
            if (firstentry < 0 && (entries_found >= entries_needed))
1375
                firstentry = sector * DIR_ENTRIES_PER_SECTOR + i + 1
1376
                             - entries_found;
1377
        }
1378
    }
1379
 
1380
    /* step 2: extend the dir if necessary */
1381
    if (firstentry < 0)
1382
    {
47 farthen 1383
        DEBUGF("Adding new sector(s) to dir\n");
46 theseven 1384
        rc = fat_seek(&dir->file, sector);
1385
        if (rc < 0)
1386
            return rc * 10 - 4;
1387
        memset(buf, 0, sizeof buf);
1388
 
1389
        /* we must clear whole clusters */
1390
        for (; (entries_found < entries_needed) ||
1391
               (dir->file.sectornum < (int)fat_bpb->bpb_secperclus); sector++)
1392
        {
1393
            if (sector >= (65536/DIR_ENTRIES_PER_SECTOR))
1394
                return -5; /* dir too large -- FAT specification */
1395
 
1396
            rc = fat_readwrite(&dir->file, 1, buf, true);
1397
            if (rc < 1)  /* No more room or something went wrong */
1398
                return rc * 10 - 6;
1399
 
1400
            entries_found += DIR_ENTRIES_PER_SECTOR;
1401
        }
1402
 
1403
        firstentry = sector * DIR_ENTRIES_PER_SECTOR - entries_found;
1404
    }
1405
 
1406
    /* step 3: add entry */
1407
    sector = firstentry / DIR_ENTRIES_PER_SECTOR;
47 farthen 1408
    DEBUGF("Adding longname to entry %d in sector %d\n",
46 theseven 1409
            firstentry, sector);
1410
 
1411
    rc = write_long_name(&dir->file, firstentry,
1412
                         entries_needed, name, shortname, is_directory);
1413
    if (rc < 0)
1414
        return rc * 10 - 7;
1415
 
1416
    /* remember where the shortname dir entry is located */
1417
    file->direntry = firstentry + entries_needed - 1;
1418
    file->direntries = entries_needed;
1419
    file->dircluster = dir->file.firstcluster;
47 farthen 1420
    DEBUGF("Added new dir entry %d, using %d slots.\n",
46 theseven 1421
            file->direntry, file->direntries);
1422
 
1423
    return 0;
1424
}
1425
 
1426
static unsigned char char2dos(unsigned char c, int* randomize)
1427
{
1428
    static const char invalid_chars[] = "\"*+,./:;<=>?[\\]|";
1429
 
1430
    if (c <= 0x20)
1431
        c = 0;   /* Illegal char, remove */
1432
    else if (strchr(invalid_chars, c) != NULL)
1433
    {
1434
        /* Illegal char, replace */
1435
        c = '_';
1436
        *randomize = 1; /* as per FAT spec */
1437
    }
1438
    else
1439
        c = toupper(c);
1440
 
1441
    return c;
1442
}
1443
 
1444
static void create_dos_name(const unsigned char *name, unsigned char *newname)
1445
{
1446
    int i;
1447
    unsigned char *ext;
1448
    int randomize = 0;
1449
 
1450
    /* Find extension part */
1451
    ext = strrchr(name, '.');
1452
    if (ext == name)         /* handle .dotnames */
1453
        ext = NULL;
1454
 
1455
    /* needs to randomize? */
1456
    if((ext && (strlen(ext) > 4)) ||
1457
       ((ext ? (unsigned int)(ext-name) : strlen(name)) > 8) )
1458
        randomize = 1;
1459
 
1460
    /* Name part */
1461
    for (i = 0; *name && (!ext || name < ext) && (i < 8); name++)
1462
    {
1463
        unsigned char c = char2dos(*name, &randomize);
1464
        if (c)
1465
            newname[i++] = c;
1466
    }
1467
 
1468
    /* Pad both name and extension */
1469
    while (i < 11)
1470
        newname[i++] = ' ';
1471
 
1472
    if (newname[0] == 0xe5) /* Special kanji character */
1473
        newname[0] = 0x05;
1474
 
1475
    if (ext)
1476
    {   /* Extension part */
1477
        ext++;
1478
        for (i = 8; *ext && (i < 11); ext++)
1479
        {
1480
            unsigned char c = char2dos(*ext, &randomize);
1481
            if (c)
1482
                newname[i++] = c;
1483
        }
1484
    }
1485
 
1486
    if(randomize)
1487
        randomize_dos_name(newname);
1488
}
1489
 
1490
static void randomize_dos_name(unsigned char *name)
1491
{
1492
    unsigned char* tilde = NULL;    /* ~ location */
1493
    unsigned char* lastpt = NULL;   /* last point of filename */
1494
    unsigned char* nameptr = name;  /* working copy of name pointer */
1495
    unsigned char num[9];           /* holds number as string */
1496
    int i = 0;
1497
    int cnt = 1;
1498
    int numlen;
1499
    int offset;
1500
 
1501
    while(i++ < 8)
1502
    {
1503
        /* hunt for ~ and where to put it */
1504
        if((!tilde) && (*nameptr == '~'))
1505
            tilde = nameptr;
1506
        if((!lastpt) && ((*nameptr == ' ' || *nameptr == '~')))
1507
            lastpt = nameptr;
1508
        nameptr++;
1509
    }
1510
    if(tilde)
1511
    {
1512
        /* extract current count and increment */
1513
        memcpy(num,tilde+1,7-(unsigned int)(tilde-name));
1514
        num[7-(unsigned int)(tilde-name)] = 0;
1515
        cnt = atoi(num) + 1;
1516
    }
1517
    cnt %= 10000000; /* protection */
1518
    snprintf(num, 9, "~%d", cnt);   /* allow room for trailing zero */
1519
    numlen = strlen(num);           /* required space */
1520
    offset = (unsigned int)(lastpt ? lastpt - name : 8); /* prev startpoint */
1521
    if(offset > (8-numlen)) offset = 8-numlen;  /* correct for new numlen */
1522
 
1523
    memcpy(&name[offset], num, numlen);
1524
 
1525
    /* in special case of counter overflow: pad with spaces */
1526
    for(offset = offset+numlen; offset < 8; offset++)
1527
        name[offset] = ' ';
1528
}
1529
 
1530
static int update_short_entry( struct fat_file* file, long size, int attr )
1531
{
1532
    unsigned char buf[SECTOR_SIZE];
1533
    int sector = file->direntry / DIR_ENTRIES_PER_SECTOR;
1534
    unsigned char* entry =
1535
        buf + DIR_ENTRY_SIZE * (file->direntry % DIR_ENTRIES_PER_SECTOR);
1536
    unsigned long* sizeptr;
1537
    unsigned short* clusptr;
1538
    struct fat_file dir;
1539
    int rc;
1540
 
47 farthen 1541
    DEBUGF("update_file_size(cluster:%lx entry:%d size:%ld)\n",
46 theseven 1542
            file->firstcluster, file->direntry, size);
1543
 
1544
    /* create a temporary file handle for the dir holding this file */
1545
    rc = fat_open(IF_MV2(file->volume,) file->dircluster, &dir, NULL);
1546
    if (rc < 0)
1547
        return rc * 10 - 1;
1548
 
1549
    rc = fat_seek( &dir, sector );
1550
    if (rc<0)
1551
        return rc * 10 - 2;
1552
 
1553
    rc = fat_readwrite(&dir, 1, buf, false);
1554
    if (rc < 1)
1555
        return rc * 10 - 3;
1556
 
1557
    if (!entry[0] || entry[0] == 0xe5)
1558
        panicf("Updating size on empty dir entry %d\n", file->direntry);
1559
 
1560
    entry[FATDIR_ATTR] = attr & 0xFF;
1561
 
1562
    clusptr = (short*)(entry + FATDIR_FSTCLUSHI);
1563
    *clusptr = htole16(file->firstcluster >> 16);
1564
 
1565
    clusptr = (short*)(entry + FATDIR_FSTCLUSLO);
1566
    *clusptr = htole16(file->firstcluster & 0xffff);
1567
 
1568
    sizeptr = (long*)(entry + FATDIR_FILESIZE);
1569
    *sizeptr = htole32(size);
1570
 
1571
    {
1572
#if CONFIG_RTC
1573
        unsigned short time = 0;
1574
        unsigned short date = 0;
1575
#else
1576
        /* get old time to increment from */
1577
        unsigned short time = htole16(*(unsigned short*)(entry+FATDIR_WRTTIME));
1578
        unsigned short date = htole16(*(unsigned short*)(entry+FATDIR_WRTDATE));
1579
#endif
1580
        fat_time(&date, &time, NULL);
1581
        *(unsigned short*)(entry + FATDIR_WRTTIME) = htole16(time);
1582
        *(unsigned short*)(entry + FATDIR_WRTDATE) = htole16(date);
1583
        *(unsigned short*)(entry + FATDIR_LSTACCDATE) = htole16(date);
1584
    }
1585
 
1586
    rc = fat_seek( &dir, sector );
1587
    if (rc < 0)
1588
        return rc * 10 - 4;
1589
 
1590
    rc = fat_readwrite(&dir, 1, buf, true);
1591
    if (rc < 1)
1592
        return rc * 10 - 5;
1593
 
1594
    return 0;
1595
}
1596
 
1597
static int parse_direntry(struct fat_direntry *de, const unsigned char *buf)
1598
{
1599
    int i=0,j=0;
1600
    unsigned char c;
1601
    bool lowercase;
1602
 
1603
    memset(de, 0, sizeof(struct fat_direntry));
1604
    de->attr = buf[FATDIR_ATTR];
1605
    de->crttimetenth = buf[FATDIR_CRTTIMETENTH];
1606
    de->crtdate = BYTES2INT16(buf,FATDIR_CRTDATE);
1607
    de->crttime = BYTES2INT16(buf,FATDIR_CRTTIME);
1608
    de->wrtdate = BYTES2INT16(buf,FATDIR_WRTDATE);
1609
    de->wrttime = BYTES2INT16(buf,FATDIR_WRTTIME);
1610
    de->filesize = BYTES2INT32(buf,FATDIR_FILESIZE);
1611
    de->firstcluster = ((long)(unsigned)BYTES2INT16(buf,FATDIR_FSTCLUSLO)) |
1612
        ((long)(unsigned)BYTES2INT16(buf,FATDIR_FSTCLUSHI) << 16);
1613
    /* The double cast is to prevent a sign-extension to be done on CalmRISC16.
1614
       (the result of the shift is always considered signed) */
1615
 
1616
    /* fix the name */
1617
    lowercase = (buf[FATDIR_NTRES] & FAT_NTRES_LC_NAME);
1618
    c = buf[FATDIR_NAME];
1619
    if (c == 0x05)  /* special kanji char */
1620
        c = 0xe5;
1621
    i = 0;
1622
    while (c != ' ') {
1623
        de->name[j++] = lowercase ? tolower(c) : c;
1624
        if (++i >= 8)
1625
            break;
1626
        c = buf[FATDIR_NAME+i];
1627
    }
1628
    if (buf[FATDIR_NAME+8] != ' ') {
1629
        lowercase = (buf[FATDIR_NTRES] & FAT_NTRES_LC_EXT);
1630
        de->name[j++] = '.';
1631
        for (i = 8; (i < 11) && ((c = buf[FATDIR_NAME+i]) != ' '); i++)
1632
            de->name[j++] = lowercase ? tolower(c) : c;
1633
    }
1634
    return 1;
1635
}
1636
 
1637
int fat_open(IF_MV2(int volume,)
1638
             long startcluster,
1639
             struct fat_file *file,
1640
             const struct fat_dir* dir)
1641
{
1642
    /* Remember where the file's dir entry is located
1643
     * Do it before assigning other fields so that fat_open
1644
     * can be called with file == &dir->file (see fat_opendir) */
1645
    if ( dir ) {
1646
        file->direntry = dir->entry - 1;
1647
        file->direntries = dir->entrycount;
1648
        file->dircluster = dir->file.firstcluster;
1649
    }
1650
 
1651
    file->firstcluster = startcluster;
1652
    file->lastcluster = startcluster;
1653
    file->lastsector = 0;
1654
    file->clusternum = 0;
1655
    file->sectornum = 0;
1656
    file->eof = false;
1657
#ifdef HAVE_MULTIVOLUME
1658
    file->volume = volume;
1659
    /* fixme: remove error check when done */
1660
    if (volume >= NUM_VOLUMES || !fat_bpbs[volume].mounted)
1661
    {
47 farthen 1662
        DEBUGF("fat_open() illegal volume %d\n", volume);
46 theseven 1663
        return -1;
1664
    }
1665
#endif
1666
 
47 farthen 1667
    DEBUGF("fat_open(%lx), entry %d\n",startcluster,file->direntry);
46 theseven 1668
    return 0;
1669
}
1670
 
1671
int fat_create_file(const char* name,
1672
                    struct fat_file* file,
1673
                    struct fat_dir* dir)
1674
{
1675
    int rc;
1676
 
47 farthen 1677
    DEBUGF("fat_create_file(\"%s\",%lx,%lx)\n",name,(long)file,(long)dir);
46 theseven 1678
    rc = add_dir_entry(dir, file, name, false, false);
1679
    if (!rc) {
1680
        file->firstcluster = 0;
1681
        file->lastcluster = 0;
1682
        file->lastsector = 0;
1683
        file->clusternum = 0;
1684
        file->sectornum = 0;
1685
        file->eof = false;
1686
    }
1687
 
1688
    return rc;
1689
}
1690
 
1691
int fat_create_dir(const char* name,
1692
                   struct fat_dir* newdir,
1693
                   struct fat_dir* dir)
1694
{
1695
#ifdef HAVE_MULTIVOLUME
1696
    struct bpb* fat_bpb = &fat_bpbs[dir->file.volume];
1697
#else
1698
    struct bpb* fat_bpb = &fat_bpbs[0];
1699
#endif
1700
    unsigned char buf[SECTOR_SIZE];
1701
    int i;
1702
    long sector;
1703
    int rc;
1704
    struct fat_file dummyfile;
1705
 
47 farthen 1706
    DEBUGF("fat_create_dir(\"%s\",%lx,%lx)\n",name,(long)newdir,(long)dir);
46 theseven 1707
 
1708
    memset(newdir, 0, sizeof(struct fat_dir));
1709
    memset(&dummyfile, 0, sizeof(struct fat_file));
1710
 
1711
    /* First, add the entry in the parent directory */
1712
    rc = add_dir_entry(dir, &newdir->file, name, true, false);
1713
    if (rc < 0)
1714
        return rc * 10 - 1;
1715
 
1716
    /* Allocate a new cluster for the directory */
1717
    newdir->file.firstcluster = find_free_cluster(IF_MV2(fat_bpb,)
1718
                                                  fat_bpb->fsinfo.nextfree);
1719
    if(newdir->file.firstcluster == 0)
1720
        return -1;
1721
 
1722
    update_fat_entry(IF_MV2(fat_bpb,) newdir->file.firstcluster, FAT_EOF_MARK);
1723
 
1724
    /* Clear the entire cluster */
1725
    memset(buf, 0, sizeof buf);
1726
    sector = cluster2sec(IF_MV2(fat_bpb,) newdir->file.firstcluster);
1727
    for(i = 0;i < (int)fat_bpb->bpb_secperclus;i++) {
1728
        rc = transfer(IF_MV2(fat_bpb,) sector + i, 1, buf, true );
1729
        if (rc < 0)
1730
            return rc * 10 - 2;
1731
    }
1732
 
1733
    /* Then add the "." entry */
1734
    rc = add_dir_entry(newdir, &dummyfile, ".", true, true);
1735
    if (rc < 0)
1736
        return rc * 10 - 3;
1737
    dummyfile.firstcluster = newdir->file.firstcluster;
1738
    update_short_entry(&dummyfile, 0, FAT_ATTR_DIRECTORY);
1739
 
1740
    /* and the ".." entry */
1741
    rc = add_dir_entry(newdir, &dummyfile, "..", true, true);
1742
    if (rc < 0)
1743
        return rc * 10 - 4;
1744
 
1745
    /* The root cluster is cluster 0 in the ".." entry */
1746
    if(dir->file.firstcluster == fat_bpb->bpb_rootclus)
1747
        dummyfile.firstcluster = 0;
1748
    else
1749
        dummyfile.firstcluster = dir->file.firstcluster;
1750
    update_short_entry(&dummyfile, 0, FAT_ATTR_DIRECTORY);
1751
 
1752
    /* Set the firstcluster field in the direntry */
1753
    update_short_entry(&newdir->file, 0, FAT_ATTR_DIRECTORY);
1754
 
1755
    rc = flush_fat(IF_MV(fat_bpb));
1756
    if (rc < 0)
1757
        return rc * 10 - 5;
1758
 
1759
    return rc;
1760
}
1761
 
1762
int fat_truncate(const struct fat_file *file)
1763
{
1764
    /* truncate trailing clusters */
1765
    long next;
1766
    long last = file->lastcluster;
1767
#ifdef HAVE_MULTIVOLUME
1768
    struct bpb* fat_bpb = &fat_bpbs[file->volume];
1769
#endif
1770
 
47 farthen 1771
    DEBUGF("fat_truncate(%lx, %lx)\n", file->firstcluster, last);
46 theseven 1772
 
1773
    for ( last = get_next_cluster(IF_MV2(fat_bpb,) last); last; last = next ) {
1774
        next = get_next_cluster(IF_MV2(fat_bpb,) last);
1775
        update_fat_entry(IF_MV2(fat_bpb,) last,0);
1776
    }
1777
    if (file->lastcluster)
1778
        update_fat_entry(IF_MV2(fat_bpb,) file->lastcluster,FAT_EOF_MARK);
1779
 
1780
    return 0;
1781
}
1782
 
1783
int fat_closewrite(struct fat_file *file, long size, int attr)
1784
{
1785
    int rc;
1786
#ifdef HAVE_MULTIVOLUME
1787
    struct bpb* fat_bpb = &fat_bpbs[file->volume];
1788
#endif
47 farthen 1789
    DEBUGF("fat_closewrite(size=%ld)\n",size);
46 theseven 1790
 
1791
    if (!size) {
1792
        /* empty file */
1793
        if ( file->firstcluster ) {
1794
            update_fat_entry(IF_MV2(fat_bpb,) file->firstcluster, 0);
1795
            file->firstcluster = 0;
1796
        }
1797
    }
1798
 
1799
    if (file->dircluster) {
1800
        rc = update_short_entry(file, size, attr);
1801
        if (rc < 0)
1802
            return rc * 10 - 1;
1803
    }
1804
 
1805
    flush_fat(IF_MV(fat_bpb));
1806
 
1807
#ifdef TEST_FAT
1808
    if ( file->firstcluster ) {
1809
        /* debug */
1810
#ifdef HAVE_MULTIVOLUME
1811
        struct bpb* fat_bpb = &fat_bpbs[file->volume];
1812
#else
1813
        struct bpb* fat_bpb = &fat_bpbs[0];
1814
#endif
1815
        long count = 0;
1816
        long len;
1817
        long next;
1818
        for ( next = file->firstcluster; next;
1819
              next = get_next_cluster(IF_MV2(fat_bpb,) next) ) {
47 farthen 1820
            DEBUGF("cluster %ld: %lx\n", count, next);
46 theseven 1821
            count++;
1822
        }
1823
        len = count * fat_bpb->bpb_secperclus * SECTOR_SIZE;
47 farthen 1824
        DEBUGF("File is %ld clusters (chainlen=%ld, size=%ld)\n",
46 theseven 1825
                count, len, size );
1826
        if ( len > size + fat_bpb->bpb_secperclus * SECTOR_SIZE)
1827
            panicf("Cluster chain is too long\n");
1828
        if ( len < size )
1829
            panicf("Cluster chain is too short\n");
1830
    }
1831
#endif
1832
 
1833
    return 0;
1834
}
1835
 
1836
static int free_direntries(struct fat_file* file)
1837
{
1838
    unsigned char buf[SECTOR_SIZE];
1839
    struct fat_file dir;
1840
    int numentries = file->direntries;
1841
    unsigned int entry = file->direntry - numentries + 1;
1842
    unsigned int sector = entry / DIR_ENTRIES_PER_SECTOR;
1843
    int i;
1844
    int rc;
1845
 
1846
    /* create a temporary file handle for the dir holding this file */
1847
    rc = fat_open(IF_MV2(file->volume,) file->dircluster, &dir, NULL);
1848
    if (rc < 0)
1849
        return rc * 10 - 1;
1850
 
1851
    rc = fat_seek( &dir, sector );
1852
    if (rc < 0)
1853
        return rc * 10 - 2;
1854
 
1855
    rc = fat_readwrite(&dir, 1, buf, false);
1856
    if (rc < 1)
1857
        return rc * 10 - 3;
1858
 
1859
    for (i=0; i < numentries; i++) {
47 farthen 1860
        DEBUGF("Clearing dir entry %d (%d/%d)\n",
46 theseven 1861
                entry, i+1, numentries);
1862
        buf[(entry % DIR_ENTRIES_PER_SECTOR) * DIR_ENTRY_SIZE] = 0xe5;
1863
        entry++;
1864
 
1865
        if ( (entry % DIR_ENTRIES_PER_SECTOR) == 0 ) {
1866
            /* flush this sector */
1867
            rc = fat_seek(&dir, sector);
1868
            if (rc < 0)
1869
                return rc * 10 - 4;
1870
 
1871
            rc = fat_readwrite(&dir, 1, buf, true);
1872
            if (rc < 1)
1873
                return rc * 10 - 5;
1874
 
1875
            if ( i+1 < numentries ) {
1876
                /* read next sector */
1877
                rc = fat_readwrite(&dir, 1, buf, false);
1878
                if (rc < 1)
1879
                    return rc * 10 - 6;
1880
            }
1881
            sector++;
1882
        }
1883
    }
1884
 
1885
    if ( entry % DIR_ENTRIES_PER_SECTOR ) {
1886
        /* flush this sector */
1887
        rc = fat_seek(&dir, sector);
1888
        if (rc < 0)
1889
            return rc * 10 - 7;
1890
 
1891
        rc = fat_readwrite(&dir, 1, buf, true);
1892
        if (rc < 1)
1893
            return rc * 10 - 8;
1894
    }
1895
 
1896
    return 0;
1897
}
1898
 
1899
int fat_remove(struct fat_file* file)
1900
{
1901
    long next, last = file->firstcluster;
1902
    int rc;
1903
#ifdef HAVE_MULTIVOLUME
1904
    struct bpb* fat_bpb = &fat_bpbs[file->volume];
1905
#endif
1906
 
47 farthen 1907
    DEBUGF("fat_remove(%lx)\n",last);
46 theseven 1908
 
1909
    while ( last ) {
1910
        next = get_next_cluster(IF_MV2(fat_bpb,) last);
1911
        update_fat_entry(IF_MV2(fat_bpb,) last,0);
1912
        last = next;
1913
    }
1914
 
1915
    if ( file->dircluster ) {
1916
        rc = free_direntries(file);
1917
        if (rc < 0)
1918
            return rc * 10 - 1;
1919
    }
1920
 
1921
    file->firstcluster = 0;
1922
    file->dircluster = 0;
1923
 
1924
    rc = flush_fat(IF_MV(fat_bpb));
1925
    if (rc < 0)
1926
        return rc * 10 - 2;
1927
 
1928
    return 0;
1929
}
1930
 
1931
int fat_rename(struct fat_file* file, 
1932
                struct fat_dir* dir, 
1933
                const unsigned char* newname,
1934
                long size,
1935
                int attr)
1936
{
1937
    int rc;
1938
    struct fat_dir olddir;
1939
    struct fat_file newfile = *file;
1940
    unsigned char buf[SECTOR_SIZE];
1941
    unsigned char* entry = NULL;
1942
    unsigned short* clusptr = NULL;
1943
    unsigned int parentcluster;
1944
#ifdef HAVE_MULTIVOLUME
1945
    struct bpb* fat_bpb = &fat_bpbs[file->volume];
1946
 
1947
    if (file->volume != dir->file.volume) {
1948
        DEBUGF("No rename across volumes!\n");
1949
        return -1;
1950
    }
1951
#else
1952
    struct bpb* fat_bpb = &fat_bpbs[0];
1953
#endif
1954
 
1955
    if ( !file->dircluster ) {
1956
        DEBUGF("File has no dir cluster!\n");
1957
        return -2;
1958
    }
1959
 
1960
    /* create a temporary file handle */
1961
    rc = fat_opendir(IF_MV2(file->volume,) &olddir, file->dircluster, NULL);
1962
    if (rc < 0)
1963
        return rc * 10 - 1;
1964
 
1965
    /* create new name */
1966
    rc = add_dir_entry(dir, &newfile, newname, false, false);
1967
    if (rc < 0)
1968
        return rc * 10 - 2;
1969
 
1970
    /* write size and cluster link */
1971
    rc = update_short_entry(&newfile, size, attr);
1972
    if (rc < 0)
1973
        return rc * 10 - 3;
1974
 
1975
    /* remove old name */
1976
    rc = free_direntries(file);
1977
    if (rc < 0)
1978
        return rc * 10 - 4;
1979
 
1980
    rc = flush_fat(IF_MV(fat_bpb));
1981
    if (rc < 0)
1982
        return rc * 10 - 5;
1983
 
1984
    /* if renaming a directory, update the .. entry to make sure
1985
       it points to its parent directory (we don't check if it was a move) */
1986
    if(FAT_ATTR_DIRECTORY == attr) {
1987
        /* open the dir that was renamed, we re-use the olddir struct */
1988
        rc = fat_opendir(IF_MV2(file->volume,) &olddir, newfile.firstcluster,
1989
                                                                          NULL);
1990
        if (rc < 0)
1991
            return rc * 10 - 6;
1992
 
1993
        /* get the first sector of the dir */
1994
        rc = fat_seek(&olddir.file, 0);
1995
        if (rc < 0)
1996
            return rc * 10 - 7;
1997
 
1998
        rc = fat_readwrite(&olddir.file, 1, buf, false);
1999
        if (rc < 0)
2000
            return rc * 10 - 8;
2001
 
2002
        /* parent cluster is 0 if parent dir is the root - FAT spec (p.29) */
2003
        if(dir->file.firstcluster == fat_bpb->bpb_rootclus)
2004
            parentcluster = 0;
2005
        else
2006
            parentcluster = dir->file.firstcluster;
2007
 
2008
        entry = buf + DIR_ENTRY_SIZE;
2009
        if(strncmp("..         ", entry, 11))
2010
        {
2011
            /* .. entry must be second entry according to FAT spec (p.29) */
2012
            DEBUGF("Second dir entry is not double-dot!\n");
2013
            return rc * 10 - 9;
2014
        }
2015
        clusptr = (short*)(entry + FATDIR_FSTCLUSHI);
2016
        *clusptr = htole16(parentcluster >> 16);
2017
 
2018
        clusptr = (short*)(entry + FATDIR_FSTCLUSLO);
2019
        *clusptr = htole16(parentcluster & 0xffff);
2020
 
2021
        /* write back this sector */
2022
        rc = fat_seek(&olddir.file, 0);
2023
        if (rc < 0)
2024
            return rc * 10 - 7;
2025
 
2026
        rc = fat_readwrite(&olddir.file, 1, buf, true);
2027
        if (rc < 1)
2028
            return rc * 10 - 8;
2029
    }
2030
 
2031
    return 0;
2032
}
2033
 
2034
static long next_write_cluster(struct fat_file* file,
2035
                              long oldcluster,
2036
                              long* newsector)
2037
{
2038
#ifdef HAVE_MULTIVOLUME
2039
    struct bpb* fat_bpb = &fat_bpbs[file->volume];
2040
#else
2041
    struct bpb* fat_bpb = &fat_bpbs[0];
2042
#endif
2043
    long cluster = 0;
2044
    long sector;
2045
 
47 farthen 2046
    DEBUGF("next_write_cluster(%lx,%lx)\n",file->firstcluster, oldcluster);
46 theseven 2047
 
2048
    if (oldcluster)
2049
        cluster = get_next_cluster(IF_MV2(fat_bpb,) oldcluster);
2050
 
2051
    if (!cluster) {
2052
        if (oldcluster > 0)
2053
            cluster = find_free_cluster(IF_MV2(fat_bpb,) oldcluster+1);
2054
        else if (oldcluster == 0)
2055
            cluster = find_free_cluster(IF_MV2(fat_bpb,)
2056
                                        fat_bpb->fsinfo.nextfree);
2057
#ifdef HAVE_FAT16SUPPORT
2058
        else /* negative, pseudo-cluster of the root dir */
2059
            return 0; /* impossible to append something to the root */
2060
#endif
2061
 
2062
        if (cluster) {
2063
            if (oldcluster)
2064
                update_fat_entry(IF_MV2(fat_bpb,) oldcluster, cluster);
2065
            else
2066
                file->firstcluster = cluster;
2067
            update_fat_entry(IF_MV2(fat_bpb,) cluster, FAT_EOF_MARK);
2068
        }
2069
        else {
2070
#ifdef TEST_FAT
2071
            if (fat_bpb->fsinfo.freecount>0)
2072
                panicf("There is free space, but find_free_cluster() "
2073
                       "didn't find it!\n");
2074
#endif
2075
            DEBUGF("next_write_cluster(): Disk full!\n");
2076
            return 0;
2077
        }
2078
    }
2079
    sector = cluster2sec(IF_MV2(fat_bpb,) cluster);
2080
    if (sector<0)
2081
        return 0;
2082
 
2083
    *newsector = sector;
2084
    return cluster;
2085
}
2086
 
2087
static int transfer(IF_MV2(struct bpb* fat_bpb,) 
2088
                    unsigned long start, long count, char* buf, bool write )
2089
{
2090
#ifndef HAVE_MULTIVOLUME
2091
    struct bpb* fat_bpb = &fat_bpbs[0];
2092
#endif
2093
    int rc;
2094
 
47 farthen 2095
    DEBUGF("transfer(s=%lx, c=%lx, %s)\n",
46 theseven 2096
        start+ fat_bpb->startsector, count, write?"write":"read");
2097
    if (write) {
2098
        unsigned long firstallowed;
2099
#ifdef HAVE_FAT16SUPPORT
2100
        if (fat_bpb->is_fat16)
2101
            firstallowed = fat_bpb->rootdirsector;
2102
        else
2103
#endif
2104
            firstallowed = fat_bpb->firstdatasector;
2105
 
2106
        if (start < firstallowed)
2107
            panicf("Write %ld before data\n", firstallowed - start);
2108
        if (start + count > fat_bpb->totalsectors)
2109
            panicf("Write %ld after data\n",
2110
                start + count - fat_bpb->totalsectors);
2111
        rc = storage_write_sectors(IF_MD2(fat_bpb->drive,)
2112
                               start + fat_bpb->startsector, count, buf);
2113
    }
2114
    else
2115
        rc = storage_read_sectors(IF_MD2(fat_bpb->drive,)
2116
                              start + fat_bpb->startsector, count, buf);
2117
    if (rc < 0) {
2118
        DEBUGF( "transfer() - Couldn't %s sector %lx"
2119
                " (error code %d)\n", 
2120
                write ? "write":"read", start, rc);
2121
        return rc;
2122
    }
2123
    return 0;
2124
}
2125
 
2126
 
2127
long fat_readwrite( struct fat_file *file, long sectorcount,
2128
                   void* buf, bool write )
2129
{
2130
#ifdef HAVE_MULTIVOLUME
2131
    struct bpb* fat_bpb = &fat_bpbs[file->volume];
2132
#else
2133
    struct bpb* fat_bpb = &fat_bpbs[0];
2134
#endif
2135
    long cluster = file->lastcluster;
2136
    long sector = file->lastsector;
2137
    long clusternum = file->clusternum;
2138
    long numsec = file->sectornum;
2139
    bool eof = file->eof;
2140
    long first=0, last=0;
2141
    long i;
2142
    int rc;
2143
 
47 farthen 2144
    DEBUGF( "fat_readwrite(file:%lx,count:0x%lx,buf:%lx,%s)\n",
46 theseven 2145
             file->firstcluster,sectorcount,(long)buf,write?"write":"read");
47 farthen 2146
    DEBUGF( "fat_readwrite: sec=%lx numsec=%ld eof=%d\n",
46 theseven 2147
             sector,numsec, eof?1:0);
2148
 
2149
    if ( eof && !write)
2150
        return 0;
2151
 
2152
    /* find sequential sectors and write them all at once */
2153
    for (i=0; (i < sectorcount) && (sector > -1); i++ ) {
2154
        numsec++;
2155
        if ( numsec > (long)fat_bpb->bpb_secperclus || !cluster ) {
2156
            long oldcluster = cluster;
2157
            long oldsector = sector;
2158
            long oldnumsec = numsec;
2159
            if (write)
2160
                cluster = next_write_cluster(file, cluster, &sector);
2161
            else {
2162
                cluster = get_next_cluster(IF_MV2(fat_bpb,) cluster);
2163
                sector = cluster2sec(IF_MV2(fat_bpb,) cluster);
2164
            }
2165
 
2166
            clusternum++;
2167
            numsec=1;
2168
 
2169
            if (!cluster) {
2170
                eof = true;
2171
                if ( write ) {
2172
                    /* remember last cluster, in case
2173
                       we want to append to the file */
2174
                    sector = oldsector;
2175
                    cluster = oldcluster;
2176
                    numsec = oldnumsec;
2177
                    clusternum--;
2178
                    i = -1; /* Error code */
2179
                    break;
2180
                }
2181
            }
2182
            else
2183
                eof = false;
2184
        }
2185
        else {
2186
            if (sector)
2187
                sector++;
2188
            else {
2189
                /* look up first sector of file */
2190
                sector = cluster2sec(IF_MV2(fat_bpb,) file->firstcluster);
2191
                numsec=1;
2192
#ifdef HAVE_FAT16SUPPORT
2193
                if (file->firstcluster < 0)
2194
                {   /* FAT16 root dir */
2195
                    sector += fat_bpb->rootdiroffset;
2196
                    numsec += fat_bpb->rootdiroffset;
2197
                }
2198
#endif
2199
            }
2200
        }
2201
 
2202
        if (!first)
2203
            first = sector;
2204
 
2205
        if ( ((sector != first) && (sector != last+1)) || /* not sequential */
2206
             (last-first+1 == 256) ) { /* max 256 sectors per ata request */
2207
            long count = last - first + 1;
2208
            rc = transfer(IF_MV2(fat_bpb,) first, count, buf, write );
2209
            if (rc < 0)
2210
                return rc * 10 - 1;
2211
 
2212
            buf = (char *)buf + count * SECTOR_SIZE;
2213
            first = sector;
2214
        }
2215
 
2216
        if ((i == sectorcount-1) && /* last sector requested */
2217
            (!eof))
2218
        {
2219
            long count = sector - first + 1;
2220
            rc = transfer(IF_MV2(fat_bpb,) first, count, buf, write );
2221
            if (rc < 0)
2222
                return rc * 10 - 2;
2223
        }
2224
 
2225
        last = sector;
2226
    }
2227
 
2228
    file->lastcluster = cluster;
2229
    file->lastsector = sector;
2230
    file->clusternum = clusternum;
2231
    file->sectornum = numsec;
2232
    file->eof = eof;
2233
 
2234
    /* if eof, don't report last block as read/written */
2235
    if (eof)
2236
        i--;
2237
 
2238
    DEBUGF("Sectors written: %ld\n", i);
2239
    return i;
2240
}
2241
 
2242
int fat_seek(struct fat_file *file, unsigned long seeksector )
2243
{
2244
#ifdef HAVE_MULTIVOLUME
2245
    struct bpb* fat_bpb = &fat_bpbs[file->volume];
2246
#else
2247
    struct bpb* fat_bpb = &fat_bpbs[0];
2248
#endif
2249
    long clusternum=0, numclusters=0, sectornum=0, sector=0;
2250
    long cluster = file->firstcluster;
2251
    long i;
2252
 
2253
#ifdef HAVE_FAT16SUPPORT
2254
    if (cluster < 0) /* FAT16 root dir */
2255
        seeksector += fat_bpb->rootdiroffset;
2256
#endif
2257
 
2258
    file->eof = false;
2259
    if (seeksector) {
2260
        /* we need to find the sector BEFORE the requested, since
2261
           the file struct stores the last accessed sector */
2262
        seeksector--;
2263
        numclusters = clusternum = seeksector / fat_bpb->bpb_secperclus;
2264
        sectornum = seeksector % fat_bpb->bpb_secperclus;
2265
 
2266
        if (file->clusternum && clusternum >= file->clusternum)
2267
        {
2268
            cluster = file->lastcluster;
2269
            numclusters -= file->clusternum;
2270
        }
2271
 
2272
        for (i=0; i<numclusters; i++) {
2273
            cluster = get_next_cluster(IF_MV2(fat_bpb,) cluster);
2274
            if (!cluster) {
2275
                DEBUGF("Seeking beyond the end of the file! "
2276
                       "(sector %ld, cluster %ld)\n", seeksector, i);
2277
                return -1;
2278
            }
2279
        }
2280
 
2281
        sector = cluster2sec(IF_MV2(fat_bpb,) cluster) + sectornum;
2282
    }
2283
    else {
2284
        sectornum = -1;
2285
    }
2286
 
47 farthen 2287
    DEBUGF("fat_seek(%lx, %lx) == %lx, %lx, %lx\n",
46 theseven 2288
            file->firstcluster, seeksector, cluster, sector, sectornum);
2289
 
2290
    file->lastcluster = cluster;
2291
    file->lastsector = sector;
2292
    file->clusternum = clusternum;
2293
    file->sectornum = sectornum + 1;
2294
    return 0;
2295
}
2296
 
2297
int fat_opendir(IF_MV2(int volume,) 
2298
                struct fat_dir *dir, unsigned long startcluster,
2299
                const struct fat_dir *parent_dir)
2300
{
2301
#ifdef HAVE_MULTIVOLUME
2302
    struct bpb* fat_bpb = &fat_bpbs[volume];
2303
    /* fixme: remove error check when done */
2304
    if (volume >= NUM_VOLUMES || !fat_bpbs[volume].mounted)
2305
    {
47 farthen 2306
        DEBUGF("fat_open() illegal volume %d\n", volume);
46 theseven 2307
        return -1;
2308
    }
2309
#else
2310
    struct bpb* fat_bpb = &fat_bpbs[0];
2311
#endif
2312
    int rc;
2313
 
2314
    if (startcluster == 0)
2315
        startcluster = fat_bpb->bpb_rootclus;
2316
 
2317
    rc = fat_open(IF_MV2(volume,) startcluster, &dir->file, parent_dir);
2318
    if(rc)
2319
    {
2320
        DEBUGF( "fat_opendir() - Couldn't open dir"
2321
                " (error code %d)\n", rc);
2322
        return rc * 10 - 1;
2323
    }
2324
 
2325
    /* assign them after fat_open call so that fat_opendir can be called with the same
2326
     * fat_dir as parent and result */
2327
    dir->entry = 0;
2328
    dir->sector = 0;
2329
 
2330
    return 0;
2331
}
2332
 
2333
int fat_getnext(struct fat_dir *dir, struct fat_direntry *entry)
2334
{
2335
    bool done = false;
2336
    int i, j;
2337
    int rc;
2338
    int order;
2339
    unsigned char firstbyte;
2340
    /* Long file names are stored in special entries. Each entry holds
2341
       up to 13 characters. Names can be max 255 chars (not bytes!) long */
2342
    /* The number of long entries in the long name can be retrieve from the first
2343
     * long entry because there are stored in reverse order and have an ordinal */
2344
    int nb_longs = 0;
2345
    /* The long entries are expected to be in order, so remember the last ordinal */
2346
    int last_long_ord = 0;
2347
 
2348
    dir->entrycount = 0;
2349
 
2350
    while(!done)
2351
    {
2352
        if ( !(dir->entry % DIR_ENTRIES_PER_SECTOR) || !dir->sector )
2353
        {
2354
            rc = fat_readwrite(&dir->file, 1, dir->sectorcache, false);
2355
            if (rc == 0) {
2356
                /* eof */
2357
                entry->name[0] = 0;
2358
                break;
2359
            }
2360
            if (rc < 0) {
2361
                DEBUGF( "fat_getnext() - Couldn't read dir"
2362
                        " (error code %d)\n", rc);
2363
                return rc * 10 - 1;
2364
            }
2365
            dir->sector = dir->file.lastsector;
2366
        }
2367
 
2368
        for (i = dir->entry % DIR_ENTRIES_PER_SECTOR;
2369
             i < DIR_ENTRIES_PER_SECTOR; i++) {
2370
            unsigned int entrypos = i * DIR_ENTRY_SIZE;
2371
 
2372
            firstbyte = dir->sectorcache[entrypos];
2373
            dir->entry++;
2374
 
2375
            if (firstbyte == 0xe5) {
2376
                /* free entry */
2377
                dir->entrycount = 0;
2378
                continue;
2379
            }
2380
 
2381
            if (firstbyte == 0) {
2382
                /* last entry */
2383
                entry->name[0] = 0;
2384
                dir->entrycount = 0;
2385
                return 0;
2386
            }
2387
 
2388
            dir->entrycount++;
2389
 
2390
            /* LFN entry? */
2391
            if ( ( dir->sectorcache[entrypos + FATDIR_ATTR] &
2392
                   FAT_ATTR_LONG_NAME_MASK ) == FAT_ATTR_LONG_NAME ) {
2393
                /* extract ordinal */
2394
                order = dir->sectorcache[entrypos + FATLONG_ORDER] & ~FATLONG_LAST_LONG_ENTRY;
2395
                /* is this entry the first long entry ? (first in order but containing last part) */
2396
                if (dir->sectorcache[entrypos + FATLONG_ORDER] & FATLONG_LAST_LONG_ENTRY) {
2397
                    /* check that order is not too big ! (and non-zero) */
2398
                    if(order <= 0 || order > FATLONG_MAX_ORDER)
2399
                        continue; /* ignore the whole LFN, will trigger lots of warnings */
2400
                    nb_longs = order;
2401
                    last_long_ord = order;
2402
                }
2403
                else {
2404
                    /* check orphan entry */
2405
                    if (nb_longs == 0) {
47 farthen 2406
                        DEBUGF("fat warning: orphan LFN entry");
46 theseven 2407
                        /* ignore */
2408
                        continue;
2409
                    }
2410
 
2411
                    /* check order */
2412
                    if (order != (last_long_ord - 1)) {
47 farthen 2413
                        DEBUGF("fat warning: wrong LFN ordinal");
46 theseven 2414
                        /* ignore the whole LFN, will trigger lots of warnings */
2415
                        nb_longs = 0;
2416
                    }
2417
 
2418
                    last_long_ord = order;
2419
                }
2420
 
2421
                /* copy part, reuse [order] for another purpose :) */
2422
                order = (order - 1) * FATLONG_NAME_BYTES_PER_ENTRY;
2423
                for(j = 0; j < FATLONG_NAME_CHUNKS; j++) {
2424
                    memcpy(dir->longname + order,
2425
                            dir->sectorcache + entrypos + FATLONG_NAME_POS[j],
2426
                            FATLONG_NAME_SIZE[j]);
2427
                    order += FATLONG_NAME_SIZE[j];
2428
                }
2429
            }
2430
            else {
2431
                if ( parse_direntry(entry, dir->sectorcache + entrypos) ) {
2432
 
2433
                    /* don't return volume id entry */
2434
                    if ( (entry->attr &
2435
                          (FAT_ATTR_VOLUME_ID|FAT_ATTR_DIRECTORY))
2436
                         == FAT_ATTR_VOLUME_ID)
2437
                        continue;
2438
 
2439
                    /* replace shortname with longname? */
2440
                    /* check that the long name is complete */
2441
                    if (nb_longs != 0 && last_long_ord == 1) {
2442
                        /* hold a copy of the shortname in case the long one is too long */
2443
                        unsigned char shortname[13]; /* 8+3+dot+\0 */
2444
                        int longname_utf8len = 0;
2445
                        /* One character at a time, add 1 for trailing \0, 4 is the maximum size
2446
                         * of a UTF8 encoded character in rockbox */
2447
                        unsigned char longname_utf8segm[4 + 1];
2448
                        unsigned short ucs;
2449
                        int segm_utf8len;
2450
                        /* Temporarily store short name */
2451
                        strcpy(shortname, entry->name);
2452
                        entry->name[0] = 0;
2453
 
2454
                        /* Convert the FAT name to a utf8-encoded one.
2455
                         * The name is not necessary NUL-terminated ! */
2456
                        for (j = 0; j < nb_longs * FATLONG_NAME_BYTES_PER_ENTRY; j += 2) {
2457
                            ucs = dir->longname[j] | (dir->longname[j + 1] << 8);
2458
                            if(ucs == 0 || ucs == FAT_LONGNAME_PAD_UCS)
2459
                                break;
2460
                            /* utf8encode will return a pointer after the converted
2461
                             * string, subtract the pointer to the start to get the length of it */
2462
                            segm_utf8len = utf8encode(ucs, longname_utf8segm) - longname_utf8segm;
2463
 
2464
                            /* warn the trailing zero ! (FAT_FILENAME_BYTES includes it) */
2465
                            if (longname_utf8len + segm_utf8len >= FAT_FILENAME_BYTES) {
2466
                                /* force use of short name */
2467
                                longname_utf8len = FAT_FILENAME_BYTES + 1;
2468
                                break; /* fallback later */
2469
                            }
2470
                            else {
2471
                                longname_utf8segm[segm_utf8len] = 0;
2472
                                strcat(entry->name + longname_utf8len, longname_utf8segm);
2473
                                longname_utf8len += segm_utf8len;
2474
                            }
2475
                        }
2476
 
2477
                        /* Does the utf8-encoded name fit into the entry? */
2478
                        /* warn the trailing zero ! (FAT_FILENAME_BYTES includes it) */
2479
                        if (longname_utf8len >= FAT_FILENAME_BYTES) {
2480
                            /* Take the short DOS name. Need to utf8-encode it
2481
                               since it may contain chars from the upper half of
2482
                               the OEM code page which wouldn't be a valid utf8.
2483
                               Beware: this file will be shown with strange
2484
                               glyphs in file browser since unicode 0x80 to 0x9F
2485
                               are control characters. */
47 farthen 2486
                            DEBUGF("SN-DOS: %s", shortname);
46 theseven 2487
                            unsigned char *utf8;
2488
                            utf8 = iso_decode(shortname, entry->name, -1,
2489
                                              strlen(shortname));
2490
                            *utf8 = 0;
47 farthen 2491
                            DEBUGF("SN: %s", entry->name);
46 theseven 2492
                        } else {
47 farthen 2493
                            DEBUGF("LN: %s", entry->name);
2494
                            DEBUGF("LNLen: %d", longname_utf8len);
46 theseven 2495
                        }
2496
                    }
2497
                    done = true;
2498
                    i++;
2499
                    break;
2500
                }
2501
            }
2502
        }
2503
    }
2504
    return 0;
2505
}
2506
 
2507
unsigned int fat_get_cluster_size(IF_MV_NONVOID(int volume))
2508
{
2509
#ifndef HAVE_MULTIVOLUME
2510
    const int volume = 0;
2511
#endif
2512
    struct bpb* fat_bpb = &fat_bpbs[volume];
2513
    return fat_bpb->bpb_secperclus * SECTOR_SIZE;
2514
}
2515
 
2516
#ifdef HAVE_MULTIVOLUME
2517
bool fat_ismounted(int volume)
2518
{
2519
    return (volume<NUM_VOLUMES && fat_bpbs[volume].mounted);
2520
}
2521
#endif