OSDN Git Service

lib-fs-resize: remove unused probe-related code
[android-x86/external-parted.git] / libparted / fs / r / fat / fat.c
1 /*
2     libparted
3     Copyright (C) 1998-2001, 2007-2012 Free Software Foundation, Inc.
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 3 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include <config.h>
20 #include <string.h>
21 #include <uuid/uuid.h>
22
23 #include "fat.h"
24 #include "calc.h"
25
26 PedFileSystem*
27 fat_alloc (const PedGeometry* geom)
28 {
29         PedFileSystem*          fs;
30
31         fs = (PedFileSystem*) ped_malloc (sizeof (PedFileSystem));
32         if (!fs)
33                 goto error;
34
35         fs->type_specific = (FatSpecific*) ped_malloc (sizeof (FatSpecific));
36         if (!fs->type_specific)
37                 goto error_free_fs;
38
39         fs->geom = ped_geometry_duplicate (geom);
40         if (!fs->geom)
41                 goto error_free_type_specific;
42
43         fs->checked = 0;
44         return fs;
45
46 error_free_type_specific:
47         free (fs->type_specific);
48 error_free_fs:
49         free (fs);
50 error:
51         return NULL;
52 }
53
54 /* Requires the boot sector to be analysed */
55 int
56 fat_alloc_buffers (PedFileSystem* fs)
57 {
58         FatSpecific*    fs_info = FAT_SPECIFIC (fs);
59
60         fs_info->buffer_sectors = BUFFER_SIZE;
61         fs_info->buffer = ped_malloc (fs_info->buffer_sectors * 512);
62         if (!fs_info->buffer)
63                 goto error;
64
65         fs_info->cluster_info = ped_malloc (fs_info->cluster_count + 2);
66         if (!fs_info->cluster_info)
67                 goto error_free_buffer;
68
69         return 1;
70
71 error_free_buffer:
72         free (fs_info->buffer);
73 error:
74         return 0;
75 };
76
77 void
78 fat_free_buffers (PedFileSystem* fs)
79 {
80         FatSpecific*    fs_info = FAT_SPECIFIC (fs);
81
82         free (fs_info->cluster_info);
83         free (fs_info->buffer);
84 }
85
86 void
87 fat_free (PedFileSystem* fs)
88 {
89         ped_geometry_destroy (fs->geom);
90         free (fs->type_specific);
91         free (fs);
92 }
93
94 int
95 fat_set_frag_sectors (PedFileSystem* fs, PedSector frag_sectors)
96 {
97         FatSpecific*    fs_info = FAT_SPECIFIC (fs);
98
99         PED_ASSERT (fs_info->cluster_sectors % frag_sectors == 0
100                         && frag_sectors <= fs_info->cluster_sectors);
101
102         fs_info->frag_size = frag_sectors * 512;
103         fs_info->frag_sectors = frag_sectors;
104         fs_info->buffer_frags = fs_info->buffer_sectors / frag_sectors;
105         fs_info->cluster_frags = fs_info->cluster_sectors / frag_sectors;
106         fs_info->frag_count = fs_info->cluster_count * fs_info->cluster_frags;
107
108         return 1;
109 }
110
111 #ifndef DISCOVER_ONLY
112 int
113 fat_clobber (PedGeometry* geom)
114 {
115         FatBootSector           boot_sector;
116
117         if (!fat_boot_sector_read (&boot_sector, geom))
118                 return 1;
119
120         boot_sector.system_id[0] = 0;
121         boot_sector.boot_sign = 0;
122         if (boot_sector.u.fat16.fat_name[0] == 'F')
123                 boot_sector.u.fat16.fat_name[0] = 0;
124         if (boot_sector.u.fat32.fat_name[0] == 'F')
125                 boot_sector.u.fat32.fat_name[0] = 0;
126
127         return ped_geometry_write (geom, &boot_sector, 0, 1);
128 }
129
130 static int
131 _init_fats (PedFileSystem* fs)
132 {
133         FatSpecific*    fs_info = FAT_SPECIFIC (fs);
134         FatCluster      table_size;
135
136         table_size = fs_info->fat_sectors * 512
137                      / fat_table_entry_size (fs_info->fat_type);
138         fs_info->fat = fat_table_new (fs_info->fat_type, table_size);
139         if (!fs_info->fat)
140                 goto error;
141
142         if (!fat_table_read (fs_info->fat, fs, 0))
143                 goto error_free_fat;
144
145         return 1;
146
147 error_free_fat:
148         fat_table_destroy (fs_info->fat);
149 error:
150         return 0;
151 }
152
153 PedFileSystem*
154 fat_open (PedGeometry* geom)
155 {
156         PedFileSystem*          fs;
157         FatSpecific*            fs_info;
158
159         fs = fat_alloc (geom);
160         if (!fs)
161                 goto error;
162         fs_info = (FatSpecific*) fs->type_specific;
163
164         if (!fat_boot_sector_read (&fs_info->boot_sector, geom))
165                 goto error_free_fs;
166         if (!fat_boot_sector_analyse (&fs_info->boot_sector, fs))
167                 goto error_free_fs;
168         fs->type = (fs_info->fat_type == FAT_TYPE_FAT16)
169                                 ? &fat16_type
170                                 : &fat32_type;
171         if (fs_info->fat_type == FAT_TYPE_FAT32) {
172                 if (!fat_info_sector_read (&fs_info->info_sector, fs))
173                         goto error_free_fs;
174         }
175
176         if (!_init_fats (fs))
177                 goto error_free_fs;
178         if (!fat_alloc_buffers (fs))
179                 goto error_free_fat_table;
180         if (!fat_collect_cluster_info (fs))
181                 goto error_free_buffers;
182
183         return fs;
184
185 error_free_buffers:
186         fat_free_buffers (fs);
187 error_free_fat_table:
188         fat_table_destroy (fs_info->fat);
189 error_free_fs:
190         fat_free (fs);
191 error:
192         return NULL;
193 }
194
195 static int
196 fat_root_dir_clear (PedFileSystem* fs)
197 {
198         FatSpecific*            fs_info = FAT_SPECIFIC (fs);
199         memset (fs_info->buffer, 0, 512 * fs_info->root_dir_sector_count);
200         return ped_geometry_write (fs->geom, fs_info->buffer,
201                                    fs_info->root_dir_offset,
202                                    fs_info->root_dir_sector_count);
203 }
204
205 /* hack: use the ext2 uuid library to generate a reasonably random (hopefully
206  * with /dev/random) number.  Unfortunately, we can only use 4 bytes of it
207  */
208 static uint32_t
209 _gen_new_serial_number (void)
210 {
211         union {
212                 uuid_t uuid;
213                 uint32_t i;
214         } uu32;
215
216         uuid_generate (uu32.uuid);
217         return uu32.i;
218 }
219
220 PedFileSystem*
221 fat_create (PedGeometry* geom, FatType fat_type, PedTimer* timer)
222 {
223         PedFileSystem*          fs;
224         FatSpecific*            fs_info;
225         FatCluster              table_size;
226
227         fs = fat_alloc (geom);
228         if (!fs)
229                 goto error;
230         fs_info = (FatSpecific*) fs->type_specific;
231
232         fs_info->logical_sector_size = 1;
233         fs_info->sectors_per_track = geom->dev->bios_geom.sectors;
234         fs_info->heads = geom->dev->bios_geom.heads;
235         fs_info->sector_count = fs->geom->length;
236         fs_info->fat_table_count = 2;
237 /* some initial values, to be changed later */
238         fs_info->root_dir_sector_count = FAT_ROOT_DIR_ENTRY_COUNT
239                                           / (512 / sizeof (FatDirEntry));
240         fs_info->root_dir_entry_count = FAT_ROOT_DIR_ENTRY_COUNT;
241
242         fs_info->fat_type = fat_type;
243         if (!fat_calc_sizes (fs->geom->length, 0,
244                         fs_info->fat_type,
245                         fs_info->root_dir_sector_count,
246                         &fs_info->cluster_sectors,
247                         &fs_info->cluster_count,
248                         &fs_info->fat_sectors)) {
249                 ped_exception_throw (PED_EXCEPTION_ERROR,
250                         PED_EXCEPTION_CANCEL,
251                         _("Partition too big/small for a %s file system."),
252                         (fat_type == FAT_TYPE_FAT16)
253                                 ? fat16_type.name
254                                 : fat32_type.name);
255                 goto error_free_fs;
256         }
257
258         fs_info->cluster_size = fs_info->cluster_sectors * 512;
259
260         fs_info->fat_offset = fat_min_reserved_sector_count (fs_info->fat_type);
261         fs_info->dir_entries_per_cluster
262                 = fs_info->cluster_size / sizeof (FatDirEntry);
263
264         if (fs_info->fat_type == FAT_TYPE_FAT16) {
265                 /* FAT16 */
266                 fs->type = &fat16_type;
267
268                 if (fs_info->cluster_count
269                         > fat_max_cluster_count (fs_info->fat_type)) {
270                         fs_info->cluster_count
271                                 = fat_max_cluster_count (fs_info->fat_type);
272                 }
273
274                 fs_info->root_dir_sector_count
275                         = FAT_ROOT_DIR_ENTRY_COUNT
276                                 / (512 / sizeof (FatDirEntry));
277                 fs_info->root_dir_entry_count = FAT_ROOT_DIR_ENTRY_COUNT;
278                 fs_info->root_dir_offset
279                         = fs_info->fat_offset
280                         + fs_info->fat_sectors * fs_info->fat_table_count;
281                 fs_info->cluster_offset
282                         = fs_info->root_dir_offset
283                           + fs_info->root_dir_sector_count;
284         } else {
285                 /* FAT32 */
286                 fs->type = &fat32_type;
287
288                 fs_info->info_sector_offset = 1;
289                 fs_info->boot_sector_backup_offset = 6;
290
291                 fs_info->root_dir_sector_count = 0;
292                 fs_info->root_dir_entry_count = 0;
293                 fs_info->root_dir_offset = 0;
294
295                 fs_info->cluster_offset
296                         = fs_info->fat_offset
297                           + fs_info->fat_sectors * fs_info->fat_table_count;
298         }
299
300         table_size = fs_info->fat_sectors * 512
301                      / fat_table_entry_size (fs_info->fat_type);
302         fs_info->fat = fat_table_new (fs_info->fat_type, table_size);
303         if (!fs_info->fat)
304                 goto error_free_fs;
305         fat_table_set_cluster_count (fs_info->fat, fs_info->cluster_count);
306         if (!fat_alloc_buffers (fs))
307                 goto error_free_fat_table;
308
309         if (fs_info->fat_type == FAT_TYPE_FAT32) {
310                 fs_info->root_cluster
311                         = fat_table_alloc_cluster (fs_info->fat);
312                 fat_table_set_eof (fs_info->fat, fs_info->root_cluster);
313                 memset (fs_info->buffer, 0, fs_info->cluster_size);
314                 if (!fat_write_cluster (fs, fs_info->buffer,
315                                         fs_info->root_cluster))
316                         return 0;
317         }
318
319         fs_info->serial_number = _gen_new_serial_number ();
320
321         if (!fat_boot_sector_set_boot_code (&fs_info->boot_sector))
322                 goto error_free_buffers;
323         if (!fat_boot_sector_generate (&fs_info->boot_sector, fs))
324                 goto error_free_buffers;
325         if (!fat_boot_sector_write (&fs_info->boot_sector, fs))
326                 goto error_free_buffers;
327         if (fs_info->fat_type == FAT_TYPE_FAT32) {
328                 if (!fat_info_sector_generate (&fs_info->info_sector, fs))
329                         goto error_free_buffers;
330                 if (!fat_info_sector_write (&fs_info->info_sector, fs))
331                         goto error_free_buffers;
332         }
333
334         if (!fat_table_write_all (fs_info->fat, fs))
335                 goto error_free_buffers;
336
337         if (fs_info->fat_type == FAT_TYPE_FAT16) {
338                 if (!fat_root_dir_clear (fs))
339                         goto error_free_buffers;
340         }
341
342         return fs;
343
344 error_free_buffers:
345         fat_free_buffers (fs);
346 error_free_fat_table:
347         fat_table_destroy (fs_info->fat);
348 error_free_fs:
349         fat_free (fs);
350 error:
351         return NULL;
352 }
353
354 PedFileSystem*
355 fat_create_fat16 (PedGeometry* geom, PedTimer* timer)
356 {
357         return fat_create (geom, FAT_TYPE_FAT16, timer);
358 }
359
360 PedFileSystem*
361 fat_create_fat32 (PedGeometry* geom, PedTimer* timer)
362 {
363         return fat_create (geom, FAT_TYPE_FAT32, timer);
364 }
365
366 int
367 fat_close (PedFileSystem* fs)
368 {
369         FatSpecific*    fs_info = FAT_SPECIFIC (fs);
370
371         fat_free_buffers (fs);
372         fat_table_destroy (fs_info->fat);
373         fat_free (fs);
374         return 1;
375 }
376
377 /* Hack: just resize the file system outside of its boundaries! */
378 PedFileSystem*
379 fat_copy (const PedFileSystem* fs, PedGeometry* geom, PedTimer* timer)
380 {
381         PedFileSystem*          new_fs;
382
383         new_fs = ped_file_system_open (fs->geom);
384         if (!new_fs)
385                 goto error;
386         if (!ped_file_system_resize (new_fs, geom, timer))
387                 goto error_close_new_fs;
388         return new_fs;
389
390 error_close_new_fs:
391         ped_file_system_close (new_fs);
392 error:
393         return 0;
394 }
395
396 static int
397 _compare_fats (PedFileSystem* fs)
398 {
399         FatSpecific*    fs_info = FAT_SPECIFIC (fs);
400         FatTable*       table_copy;
401         FatCluster      table_size;
402         int             i;
403
404         table_size = fs_info->fat_sectors * 512
405                      / fat_table_entry_size (fs_info->fat_type);
406
407         table_copy = fat_table_new (fs_info->fat_type, table_size);
408         if (!table_copy)
409                 goto error;
410
411         for (i = 1; i < fs_info->fat_table_count; i++) {
412                 if (!fat_table_read (table_copy, fs, i))
413                         goto error_free_table_copy;
414                 if (!fat_table_compare (fs_info->fat, table_copy)) {
415                         if (ped_exception_throw (PED_EXCEPTION_ERROR,
416                                 PED_EXCEPTION_IGNORE_CANCEL,
417                                 _("The FATs don't match.  If you don't know "
418                                   "what this means, then select cancel, run "
419                                   "scandisk on the file system, and then come "
420                                   "back."))
421                             != PED_EXCEPTION_IGNORE)
422                                 goto error_free_table_copy;
423                 }
424         }
425
426         fat_table_destroy (table_copy);
427         return 1;
428
429 error_free_table_copy:
430         fat_table_destroy (table_copy);
431 error:
432         return 0;
433 }
434
435 int
436 fat_check (PedFileSystem* fs, PedTimer* timer)
437 {
438         FatSpecific*    fs_info = FAT_SPECIFIC (fs);
439         PedSector       cluster_sectors;
440         FatCluster      cluster_count;
441         PedSector       fat_sectors;
442         PedSector       align_sectors;
443         FatCluster      info_free_clusters;
444
445         align_sectors = fs_info->fat_offset
446                         - fat_min_reserved_sector_count (fs_info->fat_type);
447
448         if (!fat_calc_sizes (fs->geom->length,
449                              align_sectors,
450                              fs_info->fat_type,
451                              fs_info->root_dir_sector_count,
452                              &cluster_sectors,
453                              &cluster_count,
454                              &fat_sectors)) {
455                 if (ped_exception_throw (PED_EXCEPTION_BUG,
456                         PED_EXCEPTION_IGNORE_CANCEL,
457                         _("There are no possible configurations for this FAT "
458                           "type."))
459                                 != PED_EXCEPTION_IGNORE)
460                         goto error;
461         }
462
463         if (fs_info->fat_type == FAT_TYPE_FAT16) {
464                 if (cluster_sectors != fs_info->cluster_sectors
465                     || cluster_count != fs_info->cluster_count
466                     || fat_sectors != fs_info->fat_sectors) {
467                         if (ped_exception_throw (PED_EXCEPTION_WARNING,
468                                 PED_EXCEPTION_IGNORE_CANCEL,
469                                 _("File system doesn't have expected sizes for "
470                                   "Windows to like it.  "
471                                   "Cluster size is %dk (%dk expected); "
472                                   "number of clusters is %d (%d expected); "
473                                   "size of FATs is %d sectors (%d expected)."),
474                                 (int) fs_info->cluster_sectors / 2,
475                                         (int) cluster_sectors / 2,
476                                 (int) fs_info->cluster_count,
477                                         (int) cluster_count,
478                                 (int) fs_info->fat_sectors,
479                                         (int) fat_sectors)
480                                         != PED_EXCEPTION_IGNORE)
481                                 goto error;
482                 }
483         }
484
485         if (fs_info->fat_type == FAT_TYPE_FAT32) {
486                 info_free_clusters
487                         = PED_LE32_TO_CPU (fs_info->info_sector.free_clusters);
488                 if (info_free_clusters != (FatCluster) -1
489                     && info_free_clusters != fs_info->fat->free_cluster_count) {
490                         if (ped_exception_throw (PED_EXCEPTION_WARNING,
491                                 PED_EXCEPTION_IGNORE_CANCEL,
492                                 _("File system is reporting the free space as "
493                                   "%d clusters, not %d clusters."),
494                                 info_free_clusters,
495                                 fs_info->fat->free_cluster_count)
496                                         != PED_EXCEPTION_IGNORE)
497                                 goto error;
498                 }
499         }
500
501         if (!_compare_fats (fs))
502                 goto error;
503
504         fs->checked = 1;
505         return 1;       /* existence of fs implies consistency ;-) */
506
507 error:
508         return 0;
509 }
510
511 /* Calculates how much space there will be in clusters in:
512  *      old_fs intersect the-new-fs
513  */
514 static PedSector
515 _calc_resize_data_size (
516         const PedFileSystem* old_fs,
517         PedSector new_cluster_sectors,
518         FatCluster new_cluster_count,
519         PedSector new_fat_size)
520 {
521         FatSpecific*    old_fs_info = FAT_SPECIFIC (old_fs);
522         PedSector       fat_size_delta;
523
524         fat_size_delta = old_fs_info->fat_sectors - new_fat_size;
525         return new_cluster_sectors * new_cluster_count - fat_size_delta * 2;
526 }
527
528 static int
529 _test_resize_size (const PedFileSystem* fs,
530                    PedSector length, PedSector min_data_size)
531 {
532         FatSpecific*    fs_info = FAT_SPECIFIC (fs);
533         PedGeometry     geom;
534         PedSector       _cluster_sectors;
535         FatCluster      _cluster_count;
536         PedSector       _fat_size;
537
538         ped_geometry_init (&geom, fs->geom->dev, fs->geom->start, length);
539
540         if (fat_calc_resize_sizes (
541                                 &geom,
542                                 fs_info->cluster_sectors,
543                                 FAT_TYPE_FAT16,
544                                 fs_info->root_dir_sector_count,
545                                 fs_info->cluster_sectors,
546                                 &_cluster_sectors,
547                                 &_cluster_count,
548                                 &_fat_size)
549             && _calc_resize_data_size (fs, _cluster_sectors, _cluster_count,
550                                        _fat_size)
551                         >= min_data_size)
552                 return 1;
553
554         if (fat_calc_resize_sizes (
555                                 &geom,
556                                 fs_info->cluster_sectors,
557                                 FAT_TYPE_FAT32,
558                                 0,
559                                 fs_info->cluster_sectors,
560                                 &_cluster_sectors,
561                                 &_cluster_count,
562                                 &_fat_size)
563             && _calc_resize_data_size (fs, _cluster_sectors, _cluster_count,
564                                        _fat_size)
565                         >= min_data_size)
566                 return 1;
567
568         return 0;
569 }
570
571 /* does a binary search (!) for the mininum size.  Too hard to compute directly
572  * (see calc_sizes() for why!)
573  */
574 static PedSector
575 _get_min_resize_size (const PedFileSystem* fs, PedSector min_data_size)
576 {
577         PedSector       min_length = 0;
578         PedSector       max_length = fs->geom->length;
579         PedSector       length;
580
581         while (min_length < max_length - 1) {
582                 length = (min_length + max_length) / 2;
583                 if (_test_resize_size (fs, length, min_data_size))
584                         max_length = length;
585                 else
586                         min_length = length;
587         }
588
589 /* adds a bit of leeway (64 sectors), for resolving extra issues, like root
590  * directory allocation, that aren't covered here.
591  */
592         return max_length + 64;
593 }
594
595 PedConstraint*
596 fat_get_copy_constraint (const PedFileSystem* fs, const PedDevice* dev)
597 {
598         FatSpecific*    fs_info = FAT_SPECIFIC (fs);
599         PedGeometry     full_dev;
600         PedSector       min_cluster_count;
601         FatCluster      used_clusters;
602         PedSector       min_data_size;
603
604         if (!ped_geometry_init (&full_dev, dev, 0, dev->length - 1))
605                 return NULL;
606
607         used_clusters = fs_info->fat->cluster_count
608                         - fs_info->fat->free_cluster_count;
609         min_cluster_count = used_clusters + fs_info->total_dir_clusters;
610         min_data_size = min_cluster_count * fs_info->cluster_sectors;
611
612         return ped_constraint_new (ped_alignment_any, ped_alignment_any,
613                                    &full_dev, &full_dev,
614                                    _get_min_resize_size (fs, min_data_size),
615                                    dev->length);
616 }
617
618 PedConstraint*
619 fat_get_resize_constraint (const PedFileSystem* fs)
620 {
621         return fat_get_copy_constraint (fs, fs->geom->dev);
622 }
623
624 /* FIXME: fat_calc_sizes() needs to say "too big" or "too small", or
625  * something.  This is a really difficult (maths) problem to do
626  * nicely...
627  *      So, this algorithm works if dev->length / 2 is a valid fat_type
628  * size.  (Which is how I got the magic numbers below)
629  */
630 #if 0
631 /* returns: -1 too small, 0 ok, 1 too big */
632 static int
633 _test_create_size (PedSector length, FatType fat_type,
634                    PedSector cluster_sectors, PedSector cluster_count)
635 {
636         PedSector       rootdir_sectors;
637         PedSector       _cluster_sectors;
638         FatCluster      _cluster_count;
639         PedSector       _fat_size;
640
641         rootdir_sectors = (fat_type == FAT_TYPE_FAT16) ? 16 : 0;
642
643         if (!fat_calc_sizes (length, 0, fat_type, rootdir_sectors,
644                              &_cluster_sectors, &_cluster_count, &_fat_size))
645                 return -1; // XXX: doesn't work... can't see a better way!
646
647         if (_cluster_sectors < cluster_sectors)
648                 return -1;
649         if (_cluster_sectors > cluster_sectors)
650                 return 1;
651
652         if (_cluster_count < cluster_count)
653                 return -1;
654         if (_cluster_count > cluster_count)
655                 return 1;
656
657         return 0;
658 }
659
660 static PedSector
661 _get_create_size (PedSector upper_bound, FatType fat_type,
662                   PedSector cluster_sectors, FatCluster cluster_count)
663 {
664         PedSector       min_length = 0;
665         PedSector       max_length = upper_bound;
666         PedSector       length;
667
668         while (1) {
669                 length = (min_length + max_length) / 2;
670                 switch (_test_create_size (length, fat_type, cluster_sectors,
671                                            cluster_count)) {
672                         case -1: min_length = length; break;
673                         case 0: return length;
674                         case 1: max_length = length; break;
675                 }
676                 /* hack... won't always be able to get max cluster count
677                  * with max cluster size, etc. */
678                 if (max_length - min_length == 1)
679                         return min_length;
680         }
681
682         return 0;       /* shut gcc up */
683 }
684 #endif
685
686 PedConstraint*
687 fat_get_create_constraint_fat16 (const PedDevice* dev)
688 {
689         PedGeometry     full_dev;
690         PedSector       min_size;
691         PedSector       max_size;
692
693         if (!ped_geometry_init (&full_dev, dev, 0, dev->length - 1))
694                 return NULL;
695
696 #if 0
697         min_size = _get_create_size (dev->length, FAT_TYPE_FAT16,
698                                      fat_min_cluster_size (FAT_TYPE_FAT16),
699                                      fat_min_cluster_count (FAT_TYPE_FAT16));
700         max_size = _get_create_size (dev->length, FAT_TYPE_FAT16,
701                                      fat_max_cluster_size (FAT_TYPE_FAT16),
702                                      fat_max_cluster_count (FAT_TYPE_FAT16));
703         if (!min_size)
704                 return NULL;
705 #else
706         min_size = 65794;
707         max_size = 2097153;
708 #endif
709
710         return ped_constraint_new (
711                         ped_alignment_any, ped_alignment_any,
712                         &full_dev, &full_dev,
713                         min_size, max_size);
714 }
715
716 PedConstraint*
717 fat_get_create_constraint_fat32 (const PedDevice* dev)
718 {
719         PedGeometry     full_dev;
720         PedSector       min_size;
721
722         if (!ped_geometry_init (&full_dev, dev, 0, dev->length - 1))
723                 return NULL;
724
725 #if 0
726         min_size = _get_create_size (dev->length, FAT_TYPE_FAT32,
727                                      fat_min_cluster_size (FAT_TYPE_FAT32),
728                                      fat_min_cluster_count (FAT_TYPE_FAT32));
729         if (!min_size)
730                 return NULL;
731 #else
732         min_size = 525224;
733 #endif
734
735         return ped_constraint_new (
736                         ped_alignment_any, ped_alignment_any,
737                         &full_dev, &full_dev,
738                         min_size, dev->length);
739 }
740 #endif /* !DISCOVER_ONLY */
741
742 #if 0
743
744 static PedFileSystemOps fat16_ops = {
745         probe:          fat_probe_fat16,
746 #ifndef DISCOVER_ONLY
747         clobber:        fat_clobber,
748         open:           fat_open,
749         create:         fat_create_fat16,
750         close:          fat_close,
751         check:          fat_check,
752         resize:         fat_resize,
753         copy:           fat_copy,
754         get_create_constraint:  fat_get_create_constraint_fat16,
755         get_resize_constraint:  fat_get_resize_constraint,
756         get_copy_constraint:    fat_get_copy_constraint,
757 #else /* !DISCOVER_ONLY */
758         clobber:        NULL,
759         open:           NULL,
760         create:         NULL,
761         close:          NULL,
762         check:          NULL,
763         resize:         NULL,
764         copy:           NULL,
765         get_create_constraint:  NULL,
766         get_resize_constraint:  NULL,
767         get_copy_constraint:    NULL,
768 #endif /* !DISCOVER_ONLY */
769 };
770
771 static PedFileSystemOps fat32_ops = {
772         probe:          fat_probe_fat32,
773 #ifndef DISCOVER_ONLY
774         clobber:        fat_clobber,
775         open:           fat_open,
776         create:         fat_create_fat32,
777         close:          fat_close,
778         check:          fat_check,
779         resize:         fat_resize,
780         copy:           fat_copy,
781         get_create_constraint:  fat_get_create_constraint_fat32,
782         get_resize_constraint:  fat_get_resize_constraint,
783         get_copy_constraint:    fat_get_copy_constraint,
784 #else /* !DISCOVER_ONLY */
785         clobber:        NULL,
786         open:           NULL,
787         create:         NULL,
788         close:          NULL,
789         check:          NULL,
790         resize:         NULL,
791         copy:           NULL,
792         get_create_constraint:  NULL,
793         get_resize_constraint:  NULL,
794         get_copy_constraint:    NULL,
795 #endif /* !DISCOVER_ONLY */
796 };
797
798 #define FAT_BLOCK_SIZES ((int[2]){512, 0})
799
800 PedFileSystemType fat16_type = {
801         next:           NULL,
802         ops:            &fat16_ops,
803         name:           "fat16",
804         block_sizes:    FAT_BLOCK_SIZES
805 };
806
807 PedFileSystemType fat32_type = {
808         next:           NULL,
809         ops:            &fat32_ops,
810         name:           "fat32",
811         block_sizes:    FAT_BLOCK_SIZES
812 };
813
814 void
815 ped_file_system_fat_init ()
816 {
817         if (sizeof (FatBootSector) != 512) {
818                 ped_exception_throw (PED_EXCEPTION_BUG, PED_EXCEPTION_CANCEL,
819                         _("GNU Parted was miscompiled: the FAT boot sector "
820                         "should be 512 bytes.  FAT support will be disabled."));
821         } else {
822                 ped_file_system_type_register (&fat16_type);
823                 ped_file_system_type_register (&fat32_type);
824         }
825 }
826
827 void
828 ped_file_system_fat_done ()
829 {
830         ped_file_system_type_unregister (&fat16_type);
831         ped_file_system_type_unregister (&fat32_type);
832 }
833
834 #endif