summaryrefslogtreecommitdiffstats
path: root/doc/FAT
blob: 9a3a991d14500dd06453685afa04fb9de10781d1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
===============================================================================
		GNU Parted FAT file system documentation
===============================================================================

      by Andrew Clausen <clausen@gnu.org>

      Copyright (C) 2000, 2001 Free Software Foundation, Inc.

      Permission is granted to copy, distribute and/or modify this document
      under the terms of the GNU Free Documentation License, Version 1.3
      or any later version published by the Free Software Foundation;
      with the no Invariant Sections, with the no Front-Cover Texts, and
      with no Back-Cover Texts.  A copy of the license is included in the
      file, COPYING.DOC.


CONTENTS
--------

		PART I - THE FAT FILE SYSTEM

1	Introduction

2	Overview

3	The Boot Sector
3.1	Data Layout
3.2	Descriptions of Fields
3.3	Calculating the ignored fields
3.4	DOS/Windows bootstrap process

4	The Info Sector
4.1	Data Layout
4.2	Descriptions of Fields

5	File Allocation Tables

6	Directory tree
6.1	Directory entries

		PART II - GNU PARTED'S FAT IMPLEMENTATION

7	Resizing "issues"

8	Overview of GNU Parted's Strategy

===============================================================================
			PART I  -  THE FAT FILE SYSTEM
===============================================================================

-------------------------------------------------------------------------------
1	INTRODUCTION
-------------------------------------------------------------------------------

This document describes the FAT filesystem, and GNU Parted's support for it.

Unfortunately, there are no particularly good sources of information on the FAT
filesystem.  The information here was deduced from the source code of about 10
different programs, documentation from about 20 different sources and testing.
There are many cases where documentation for FAT from various sources
(including Microsoft) are misleading, or just plain wrong.  For us,
documentation is correct if it matches the behaviour of Microsoft's
implementation.


-------------------------------------------------------------------------------
2	OVERVIEW
-------------------------------------------------------------------------------

FAT is a filesystem that is mainly used by Microsoft DOS, Windows 95,
Windows 98 and Windows 2000.  FAT also stands for File Allocation Table - a
part of the FAT filesystem.

FAT comes in three flavors: FAT12, FAT16 and FAT32.
FAT12 is used on floppy disks, and REALLY old hard drives <32Mb.  FAT16 is
typically used on small hard drives <500Mb, and is very inefficient for large
hard drives.  FAT32 is used on hard drives >500Mb under Windows 95 OSR2 and
later and Windows 2000.  These three flavors have important differences (not
JUST an increase in the maximum possible number of clusters).  On FAT12 and
FAT16 cluster size directly relates to the filesystem size: the number of
clusters is always between 2041 and 4080 resp. 32761 and 65520.

The FAT filesystem has these parts (on disk, in this order):
  * a bootsector.  This contains all of the information about the filesystem
- whether it's FAT12, FAT16 or FAT32, how big it is, etc.

  * an information sector (FAT32 only).  This contains additional information
that couldn't fit in the boot sector.

  * file allocation tables (FATs).  There are usually two identical copies.
This is used to store the sequence of clusters that make of files.  Essentially,
if you want to know the number of the cluster that comes after cluster X
in a file, you look up the number for X.  If X is a magic number, it means
it's the end of the file.

  * clusters.  The data inside files are stored in clusters.  Most directory
information is stored in clusters (except the root directory in FAT12 and
FAT16).   Clusters may be 1, 2, 4, 8, etc. sectors.  Clusters are numbered,
counting from 2.

  * directory tree.  The FAT filesystem has files and directories (no named
pipes, links, or anything fancy like that), that are stored in clusters.  The
root directory on FAT12 and FAT16 is stored separately.  In FAT32, the root
directory is stored inside a normal cluster, just like everything else.


-------------------------------------------------------------------------------
3	THE BOOT SECTOR
-------------------------------------------------------------------------------

The boot sector contains all of the information about the filesystem
- whether it's FAT12, FAT16 or FAT32, how big it is, etc.  It also contains
the boot loader for the operating system, if there is an operating system
on the file system.  It is always the first thing to appear in the filesystem
- i.e. it's found at sector 0.

A word of warning: while the values inside the boot sector will always be
consistent with the file system, many of these values are not read by
Microsoft's implementation - they are calculated independently.


3.1	The Data Layout
-------------------------------------------------------------------------------

Taken from libparted/fs_fat/bootsector.h:

struct __attribute__ ((packed)) _FatBootSector {
        __u8    boot_jump[3];   /* 00: Boot strap short or near jump */
        __u8    system_id[8];   /* 03: system name */
        __u16   sector_size;    /* 0b: bytes per logical sector */
        __u8    cluster_size;   /* 0d: sectors/cluster */
        __u16   reserved;       /* 0e: reserved sectors */
        __u8    fats;           /* 10: number of FATs */
        __u16   dir_entries;    /* 11: number of root directory entries */
        __u16   sectors;        /* 13: if 0, sector_count supersedes */
        __u8    media;          /* 15: media code */
        __u16   fat_length;     /* 16: sectors/FAT for FAT12/16 */
        __u16   secs_track;     /* 18: sectors per track */
        __u16   heads;          /* 1a: number of heads */
        __u32   hidden;         /* 1c: hidden sectors (partition start) */
        __u32   sector_count;   /* 20: no. of sectors (if sectors == 0) */

        union __attribute__ ((packed)) {
                /* FAT16 fields */
                struct __attribute__ ((packed)) {
                        __u8    drive_num;      /* 24: */
                        __u8    empty_1;        /* 25: */
                        __u8    ext_signature;  /* 26: always 0x29 */
                        __u32   serial_number;  /* 27: */
                        __u8    volume_name [11];       /* 2b: */
                        __u8    fat_name [8];   /* 37: */
                        __u8    boot_code[448]; /* 3f: Boot code (or message) */
                } fat16;
                /* FAT32 fields */
                struct __attribute__ ((packed)) {
                        __u32   fat_length;     /* 24: size of FAT in sectors */
                        __u16   flags;          /* 28: bit8: fat mirroring, low4: active fat */
                        __u16   version;        /* 2a: minor * 256 + major */
                        __u32   root_dir_cluster;       /* 2c: */
                        __u16   info_sector;    /* 30: */
                        __u16   backup_sector;  /* 32: */
                        __u8    empty_1 [12];   /* 34: */
                        __u16   drive_num;      /* 40: */
                        __u8    ext_signature;  /* 42: always 0x29 */
                        __u32   serial_number;  /* 43: */
                        __u8    volume_name [11];       /* 47: */
                        __u8    fat_name [8];   /* 52: */
                        __u8    boot_code[420]; /* 5a: Boot code (or message) */
                } fat32;
        } u;

        __u16   boot_sign;      /* 1fe: always 0xAA55 */
};


3.2	Descriptions of Fields
-------------------------------------------------------------------------------

3.2.1	Fields common to FAT12, FAT16 and FAT32
-----------------------------------------------
        __u8    boot_jump[3];   /* 00: Boot strap short or near jump */
This contains the Intel x86 instruction to "jump" to further down in the
boot sector.  This is necessary, because on PC systems, the first sector of
the disk is loaded and executed.  On hard disks of PC systems, the first
sector of the disk is in fact the Master Boot Record - which contains the
partition table.  The master boot record loads the first sector of the boot
partition, so the end result is the same for floppy's and hard disks.


	__u8    system_id[8];   /* 03: system name */
This contains the name of the program or operatings system that created the
file system.  For FAT32, it seems you must have "MSWIN4.1" here.
If this is "MSDMF3.2" (afaik only the "MSDMF" is checked") the partition
can't be written under Windows 9x, Windows NT and Windows 2000.  This is
how Microsoft realizes read-only installation or distribution floppy disks.


	__u16   sector_size;    /* 0b: bytes per logical sector */
This is bizarre.  Sectors are always 512 bytes.  However, a "logical" sector
is a hack that allows sectors to be bigger (a multiple of 512 bytes).  This
is rarely used, and untested in GNU Parted at the moment.  (Side note: is
it possible to use this to avoid requiring a cluster resize?)


	__u8    cluster_size;   /* 0d: sectors/cluster */
THIS IS IGNORED BY MICROSOFT'S IMPLEMENTATION OF FAT12 AND FAT16!  (See section
3.3)   This contains the size of all clusters, given in sectors.  This value is
"read-only".


	__u16   reserved;       /* 0e: reserved sectors */
The number of sectors before the file allocation tables begin.  i.e. The
number of the first sector of the first file allocation table.


	__u8    fats;           /* 10: number of FATs */
The number of file allocation tables (usually 2).


	__u16   dir_entries;    /* 11: number of root directory entries */
The size of the root directory (FAT12 and FAT16 only), in "directory entries"
(32 bytes).  The root directory is immediately after the FATs (FAT12 and
FAT16 only).  The first cluster (i.e. cluster number 2) starts immediately
after the root directory (or after the FATs for FAT32).


	__u16   sectors;        /* 13: if 0, sector_count supersedes */
THIS IS IGNORED BY MICROSOFT'S IMPLEMENTATION!  The total size of the file
system.  If the file system is bigger than 65536 sectors, this is set to 0,
and a 32 bit field is used instead.  Microsoft's implementation gets this
values from hardware (for floppy disks), or the partition table (for hard
disks), rather than reading it off disk.


	__u8    media;          /* 15: media code */
For hard disks, this should always be 0xf8.


	__u16   fat_length;     /* 16: sectors/FAT for FAT12/16 */
THIS IS IGNORED BY MICROSOFT'S IMPLEMENTATION!  (See section 3.3)  The size in
sectors of each file allocation table (FAT12 and FAT16 only).  A 32-bit field
is used for FAT32.  This value is "read-only".



	__u16   secs_track;     /* 18: sectors per track */
	__u16   heads;          /* 1a: number of heads */
These should match the BIOS geometry.  The GNU Parted README file explains
BIOS geometry.


	__u32   hidden;         /* 1c: hidden sectors (partition start) */
On a hard disk, this should be the number of sectors from the start of the
head (in terms of BIOS geometry) to the start of the partition.  i.e. the
S in the CHS partition start.


	__u32   sector_count;   /* 20: no. of sectors (if sectors == 0) */
The size of the file system in sectors (if sectors is 0).


        __u16   boot_sign;      /* 1fe: always 0xAA55 */
Boot sector signature.  Don't use this exclusively to detect FAT file systems!
It's also the signature for partition table sectors (and it appears in the
same place too!)  Idiots.

3.2.2	Fields in FAT12 and FAT16
---------------------------------

        __u8    drive_num;      /* 24: */
Always 0x80.


        __u8    ext_signature;  /* 26: always 0x29 */
Always 0x29.


        __u32   serial_number;  /* 27: */
Serial number: Used to detect media change on floppy disk and removable drives.


        __u8    volume_name [11];       /* 2b: */
The disk label.


        __u8    fat_name [8];   /* 37: */
"FAT12\0\0\0" or "FAT16\0\0\0".


3.2.3	Fields in FAT32
-----------------------

        __u32   fat_length;     /* 24: size of FAT in sectors */
The size in sectors of each file allocation table.


        __u16   flags;          /* 28: bit8: fat mirroring, low4: active fat */
No idea what these are.


        __u16   version;        /* 2a: minor * 256 + major */
Seems to be 0 (?)


        __u32   root_dir_cluster;       /* 2c: */
The number of the first cluster in the root directory.


        __u16   info_sector;    /* 30: */
The number of the information sector.


        __u16   backup_sector;  /* 32: */
The number of the backup of the boot sector (i.e. this sector).


        __u16   drive_num;      /* 40: */
Always 0x80.


        __u8    ext_signature;  /* 42: always 0x29 */
Always 0x29.


        __u32   serial_number;  /* 43: */
Serial number (for Echelon, or something)


        __u8    volume_name [11];       /* 47: */
The disk label.


        __u8    fat_name [8];   /* 52: */
"FAT32\0\0\0".


3.3	Calculating the ignored fields
-------------------------------------------------------------------------------
The cluster_size and fat_length fields are ignored by Microsoft's
implementation of FAT12 and FAT16, but NOT FAT32.  That is, they are written out
correctly, but NOT READ IN.  (Note: if FAT32 file system is configured to
have less than 65520 clusters, then Windows assumes it's FAT16)

Since these values don't usually change unless you resize a filesystem, this
causes no problems.  However, if you want to resize the filesystem, you have to
calculate these values to what Microsoft calculates them to, from the size of
the filesystem.  It took me 2 months to figure this out (I want to KILL
somebody...)

Here's the algorithm I came up with that seemed to match all my test data:
(from libparted/fs_fat/calc.c)

FatCluster
fat_max_cluster_count (FatType fat_type) {
        switch (fat_type) {
                case FAT_TYPE_FAT12: return 0xff0;
                case FAT_TYPE_FAT16: return 0xfff0;
                case FAT_TYPE_FAT32: return 0x0ffffff0;
        }
        return 0;
}

FatCluster
fat_min_cluster_count (FatType fat_type) {
        switch (fat_type) {
                case FAT_TYPE_FAT12:
                case FAT_TYPE_FAT16:
                        return fat_max_cluster_count (fat_type) / 2;

                case FAT_TYPE_FAT32: return 0xfff0;
        }
        return 0;
}

static int
calc_sizes (PedGeometry* geom, PedSector align, int cluster_size,
            PedSector root_dir_sectors, FatCluster* out_cluster_count,
            PedSector* out_fat_size, FatType fat_type)
{
        PedSector       data_fat_size;
        PedSector       fat_sectors;
        PedSector       cluster_sectors;
        FatCluster      cluster_count;
        int             i;

        data_fat_size = geom->length - fat_min_reserved_sector_count (fat_type)
                        - align;
        if (fat_type == FAT_TYPE_FAT16)
                data_fat_size -= root_dir_sectors;

        fat_sectors = 0;
        for (i = 0; i < 2; i++) {
                if (fat_type == FAT_TYPE_FAT32)
                        cluster_sectors = data_fat_size - fat_sectors;
                else
                        cluster_sectors = data_fat_size - 2 * fat_sectors;

                cluster_count = cluster_sectors / (cluster_size / 512);
                fat_sectors = div_round_up (cluster_count + 2,
                                            entries_per_sector (fat_type));
        }

        cluster_sectors = data_fat_size - 2 * fat_sectors;
        cluster_count = cluster_sectors / (cluster_size / 512);

        if (cluster_count > fat_max_cluster_count (fat_type)
            || cluster_count < fat_min_cluster_count (fat_type))
                return 0;

        *out_cluster_count = cluster_count;
        *out_fat_size = fat_sectors;

        return 1;
}

FIXME: this is the "trial and error" algorithm.  What happened to my simple,
test one?

If the implications of the above code aren't that clear, here are some of
them:
  * for FAT16, the minimum number of clusters is 32760.
  * the cluster size is completely determined by the size of the file system,
for FAT16.  That means, if a file system is to be resized, it is quite
possible that the cluster size must be changed just to be compatible
with Microsoft's implementation  (Linux, for example, doesn't calculate the
numbers independently, so it would work fine.  So always test your code on
Microsoft as well as Linux)


3.4	DOS/Windows bootstrap process
-------------------------------------------------------------------------------
All of the information that follows is from me reverse-engineering different
versions of Microsoft's boot sectors.  It's pretty weird code (as you can
imagine...), so there might be mistakes here.
	There are many different versions of the boot sector:
* Windows 98/2000/ME FAT12/FAT16 (supports CHS and LBA)
* Windows 98/2000/ME FAT32 (supports CHS and LBA)

(1) The MBR, LILO, or whatever loads in the first sector of the FAT
partition into 0000:7c00, and executes it.

(2) The first sector of the FAT partition (the "boot sector") does:
    (a) loads the Master Boot Record (sector 0 of the disk) using the
    BIOS's CHS calls, and finds the boot partition.  If the boot partition
    has the LBA flag marked, it writes 0xe to [bp+2] (0000:7c02).  The "read
    sectors" function in the boot loader checks for 0xe here, and uses LBA if
    it finds it, and CHS otherwise.

    (b) If it is the FAT32 version of the boot sector, it loads sectors 1
    through 3 of the partition (it finds this from the "hidden" field in the
    FAT boot sector, that was loaded by the MBR/LILO) at address 0000:7e00, and
    continues executing at 0000:8000.  Note: the FAT16 version doesn't require
    any more sectors to be read (they crammed it all in!), and it goes
    directly to step 3.

(3) The code loads IO.SYS (starting at address 0000:0700), off the same
partition, and executes it, beginning execution at 0070:0200.  (Note:
According to the x86 real mode segmentation scheme, 0070:0200 refers to the
same physical memory as 0000:0900)


-------------------------------------------------------------------------------
4	THE INFO SECTOR
-------------------------------------------------------------------------------

The info sector is used in FAT32 to store additional information about the
file system.


4.1	Data Layout
-------------------------------------------------------------------------------

struct __attribute__ ((packed)) _FatInfoSector {
        __u32   signature_1;    /* should be 0x41615252 */
        __u8    unused [480];
        __u32   signature_2;    /* should be 0x61417272 */
        __u32   free_clusters;
        __u32   next_cluster;   /* most recently allocated cluster */
        __u8    unused2 [0xe];
        __u16   signature_3;    /* should be 0xaa55 */
};


4.2	Descriptions of Fields
-------------------------------------------------------------------------------

        __u32   signature_1;    /* should be 0x41615252 */
Always 0x41615252  ("AaRR")


        __u32   signature_2;    /* should be 0x61417272 */
Always 0x61417272  ("aArr")


        __u32   free_clusters;
The number of free clusters.  This could be calculated by going through the
FATs, but this is stored on shutdown to speed things up.


        __u32   next_cluster;   /* most recently allocated cluster */
This contains the number of the last cluster allocated.  This speeds up
cluster allocation, because free clusters usually come in chunks, so you
can scan right for free clusters in the FAT.


        __u16   signature_3;    /* should be 0xaa55 */
Always 0xaa55.


-------------------------------------------------------------------------------
5	FILE ALLOCATION TABLES
-------------------------------------------------------------------------------

File allocation table (FAT) is a strange name, come to think of it.  Perhaps it
should be called cluster allocation table, or something (?).  Essentially,
it is used to represent file chains (i.e. linked lists) for files and
directories.  There are usually two FATs (one is a backup, and should be
identical).

Anyway, a FAT is essentially an array.  In FAT12, each entry is 12 bits,
FAT16 - 16 bits, FAT32 - 32 bits.  Hence the names.

The first byte of each FAT must match the "media" field in the boot sector.
The rest of the first 2 entries are filled with 0xff.

All remaining entries - from 2 onwards - correspond to a cluster.  i.e.
the second entry corresponds to cluster 2.  Clusters are numbered from 2 onwards
(i.e. there is no cluster 1).

The number in each entry gives the number of the cluster that occurs next in
the file chain (linked list).  However, there are a few magic numbers:

  * unused (0).  Indicates the cluster is unused.
  * end of file (0xff0 for FAT12, 0xfff0 for FAT16, 0x0ffffff0 for FAT32).
Indicates this is the last cluster in the file or directory.  Obviouslly for
FAT32, the number of clusters must be < 0x0ffffff0.  So it should be called
FAT28, perhaps...
  * bad cluster (0xff7 for FAT12, 0xfff7 for FAT16, 0x0ffffff7 for FAT32).
Indicates the disk is physically damaged where the cluster is stored.


-------------------------------------------------------------------------------
6	DIRECTORY TREE
-------------------------------------------------------------------------------

The directory tree is simple: there are files and directories.  Files and
directories are stored in clusters (except the root directory on FAT12 and
FAT16).  Directories are essentially special files that contain directory
entries.

In FAT12 and FAT16, the root directory is stored immediately after the FATs.
In FAT32, the first cluster of the root directory is given in the FAT.  (To
get the second cluster - if there is one - you just look up the FAT)


6.1	Directory Entries
------------------------------------------------------------------------------
Directories are made up of directory entries, each of which represent a file,
a directory or part of a file name (the VFAT extension - YUCK!!!).

Each directory (except the root directory) contains a '.' (this directory) and
'..' (parent directory) entry.

6.1.1	Fields
--------------

From libparted/fs_fat/fat.h:

struct __attribute__ ((packed)) _FatDirEntry {
        __u8            name[8];
        __u8            extension[3];
        __u8            attributes;
        __u8            is_upper_case_name;
        __u8            creation_time_low;      /* milliseconds */
        __u16           creation_time_high;
        __u16           creation_date;
        __u16           access_date;
        __u16           first_cluster_high;     /* for FAT32 */
        __u16           time;
        __u16           date;
        __u16           first_cluster;
        __u32           length;
};

6.1.2	Field Descriptions
--------------------------

        __u8            name[8];
The first part of the file name.  Eg, for a file called README.TXT, this is
README.  Files with names longer than 8 characters use the VFAT extension (not
described here).  When a file is deleted, the first character is set to 0xe5.
If the first character is 0x0, then the entire directory entry is unused.


        __u8            extension[3];
The last part of the file name.  Eg, for a file called README.TXT, this is TXT.
This explains all those .HTM files around the place...


        __u8            attributes;
If this is 0x0f, then this directory entry is a VFAT entry, and stores part
of a file name.  Otherwise, it's treated as various bit fields:

		0x1		read-only
		0x2		hidden
		0x4		system
		0x8		volume label
		0x10		directory
		0x20		archived


        __u8            is_upper_case_name;
A Microsoft cludge: create a file with 8.3 name BUT containing small letters
(like ReadMe.Txt) which is treated as an LFN (long file name) and occupies
three directory entries.  Now when you rename this file to all uppercase
README.TXT,- under Windows NT 4 the then superfluous LFN-VFAT entries are
removed, resulting in a smaller directory, but under Windows 9x the LFN-VFAT
entries are just upd- and this flag is set.  Executing DEFRAG on such entries
MIGHT then remove the superfluous LFN-VFAT entries and shrink the directory.


        __u8            creation_time_low;      /* milliseconds */
        __u16           creation_time_high;
        __u16           creation_date;
Creation time and date.  Not used wih MS-DOS <7.0!


        __u16           access_date;
Last access date.  Not used wih MS-DOS <7.0!


        __u16           first_cluster_high;     /* for FAT32 */
High 32 bits of the first cluster in the file or directory (FAT32 only)


        __u16           time;
        __u16           date;
?


        __u16           first_cluster;
Low 16 bits of first cluster.


        __u32           length;
Length of file in bytes.



===============================================================================
		PART II - GNU PARTED'S FAT IMPLEMENTATION
===============================================================================

-------------------------------------------------------------------------------
7	RESIZING "ISSUES"
-------------------------------------------------------------------------------

To resize a FAT file system, a program must:
  * copy all used clusters that lie outside of the new partition onto free
space on that partition.  The directory tree and FATs must be updated to
reflect this.
  * grow or shrink the file allocation table(s) to the size corresponding
to the size of the partition.
  * convert between FAT16 and FAT32 if necessary.  This involves:
    - changing the form of the root directory (FAT16 has it's before the
      clusters whereas FAT32 stores it in normal clusters).
    - creating space for the backup boot sector and info sector.
    - updating the directory tree to use 32 bit first cluster entries.
  * align the start of the clusters (using the "reserved" field in the
boot sector), so that the clusters that are common to the old and new
partition can be preserved.
  * re-number clusters.  e.g. if you chop out some clusters from the beginning
(i.e. move the start forward), then the first cluster (i.e. number 2) will
be refer to a different cluster on the disk.  The directory tree and FATs must
be updated to reflect this.
  * create a new boot sector (and the info sector and backup boot sector for
FAT32)


-------------------------------------------------------------------------------
8	OVERVIEW OF GNU PARTED'S STRATEGY
-------------------------------------------------------------------------------

GNU Parted copies all clusters that are not accessible from the new file system
(either because it lies outside the file system, or file system meta-data must
reside there instead) to an accessible place.

Since all clusters must be renumbered (in most cases), the entire directory
tree must be updated.  However converting the directory tree from one numbering
system to another would break the file system if it was interrupted halfway
through.  Instead, GNU Parted duplicates the directory tree (except the root
directory for FAT16) along with clusters that need to be copied because they
lie outside the new file system.  The directory tree is duplicated at the same
time as inaccessible clusters are.  The relevant function,
needs_duplicating() in libparted/fs_fat/clstdup.c is:

	static int
	needs_duplicating (FatOpContext* ctx, FatCluster cluster)
	{
		FatSpecific*    fs_info = FAT_SPECIFIC (ctx->old_fs);

		return (fs_info->fat_flag_map [cluster] == FAT_FLAG_FILE
			&& !fat_op_context_map_static_cluster (ctx, cluster))
			|| fs_info->fat_flag_map [cluster]
				== FAT_FLAG_DIRECTORY;
	}



A good overview of this implementation is in the fat_resize() function, in
libparted/fs_fat/resize.c (slightly edited):

	int
	fat_resize (PedFileSystem* fs, PedGeometry* geom)
	{
		FatSpecific*	fs_info = FAT_SPECIFIC (fs);
		FatSpecific*	new_fs_info;
		FatOpContext*	ctx;
		PedFileSystem*	new_fs;

		ctx = create_resize_context (fs, geom);
		if (!ctx)
			return 0;
		new_fs = ctx->new_fs;
		new_fs_info = FAT_SPECIFIC (new_fs);

		if (!fat_duplicate_clusters (ctx))
			return 0;
		if (fs_info->fat_type == FAT_TYPE_FAT16
				&& new_fs_info->fat_type == FAT_TYPE_FAT32) {
			if (!alloc_root_dir (ctx))
				return 0;
		}
		if (!fat_construct_new_fat (ctx))
			return 0;
		if (!fat_construct_dir_tree (ctx))
			return 0;
		if (!fat_table_write_all (new_fs_info->fat, new_fs))
			return 0;

		if (!fat_boot_sector_generate (&new_fs_info->boot_sector,
					       new_fs))
			return 0;
		if (!fat_boot_sector_write (&new_fs_info->boot_sector, new_fs))
			return 0;
		if (new_fs_info->fat_type == FAT_TYPE_FAT32) {
			if (!fat_info_sector_generate (
					&new_fs_info->info_sector, new_fs))
				return 0;
			if (!fat_info_sector_write (&new_fs_info->info_sector,
						    new_fs))
				return 0;
		}

		if (!resize_context_assimilate (ctx))
			return 0;

		return 1;
	}