blob: ebf023d95ff4c92547eb774648501fa4566fcb4d [file] [log] [blame] [edit]
/*
libparted
Copyright (C) 1998, 1999, 2000, 2001, 2007 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <config.h>
#include <string.h>
#include <uuid/uuid.h>
#include "fat.h"
#include "calc.h"
PedFileSystem*
fat_alloc (const PedGeometry* geom)
{
PedFileSystem* fs;
fs = (PedFileSystem*) ped_malloc (sizeof (PedFileSystem));
if (!fs)
goto error;
fs->type_specific = (FatSpecific*) ped_malloc (sizeof (FatSpecific));
if (!fs->type_specific)
goto error_free_fs;
fs->geom = ped_geometry_duplicate (geom);
if (!fs->geom)
goto error_free_type_specific;
fs->checked = 0;
return fs;
error_free_type_specific:
ped_free (fs->type_specific);
error_free_fs:
ped_free (fs);
error:
return NULL;
}
/* Requires the boot sector to be analysed */
int
fat_alloc_buffers (PedFileSystem* fs)
{
FatSpecific* fs_info = FAT_SPECIFIC (fs);
fs_info->buffer_sectors = BUFFER_SIZE;
fs_info->buffer = ped_malloc (fs_info->buffer_sectors * 512);
if (!fs_info->buffer)
goto error;
fs_info->cluster_info = ped_malloc (fs_info->cluster_count + 2);
if (!fs_info->cluster_info)
goto error_free_buffer;
return 1;
error_free_buffer:
ped_free (fs_info->buffer);
error:
return 0;
};
void
fat_free_buffers (PedFileSystem* fs)
{
FatSpecific* fs_info = FAT_SPECIFIC (fs);
ped_free (fs_info->cluster_info);
ped_free (fs_info->buffer);
}
void
fat_free (PedFileSystem* fs)
{
ped_geometry_destroy (fs->geom);
ped_free (fs->type_specific);
ped_free (fs);
}
int
fat_set_frag_sectors (PedFileSystem* fs, PedSector frag_sectors)
{
FatSpecific* fs_info = FAT_SPECIFIC (fs);
PED_ASSERT (fs_info->cluster_sectors % frag_sectors == 0
&& frag_sectors <= fs_info->cluster_sectors,
return 0);
fs_info->frag_size = frag_sectors * 512;
fs_info->frag_sectors = frag_sectors;
fs_info->buffer_frags = fs_info->buffer_sectors / frag_sectors;
fs_info->cluster_frags = fs_info->cluster_sectors / frag_sectors;
fs_info->frag_count = fs_info->cluster_count * fs_info->cluster_frags;
return 1;
}
PedGeometry*
fat_probe (PedGeometry* geom, FatType* fat_type)
{
PedFileSystem* fs;
FatSpecific* fs_info;
PedGeometry* result;
fs = fat_alloc (geom);
if (!fs)
goto error;
fs_info = (FatSpecific*) fs->type_specific;
if (!fat_boot_sector_read (&fs_info->boot_sector, geom))
goto error_free_fs;
if (!fat_boot_sector_analyse (&fs_info->boot_sector, fs))
goto error_free_fs;
*fat_type = fs_info->fat_type;
result = ped_geometry_new (geom->dev, geom->start,
fs_info->sector_count);
fat_free (fs);
return result;
error_free_fs:
fat_free (fs);
error:
return NULL;
}
PedGeometry*
fat_probe_fat16 (PedGeometry* geom)
{
FatType fat_type;
PedGeometry* probed_geom = fat_probe (geom, &fat_type);
if (probed_geom) {
if (fat_type == FAT_TYPE_FAT16)
return probed_geom;
ped_geometry_destroy (probed_geom);
}
return NULL;
}
PedGeometry*
fat_probe_fat32 (PedGeometry* geom)
{
FatType fat_type;
PedGeometry* probed_geom = fat_probe (geom, &fat_type);
if (probed_geom) {
if (fat_type == FAT_TYPE_FAT32)
return probed_geom;
ped_geometry_destroy (probed_geom);
}
return NULL;
}
#ifndef DISCOVER_ONLY
int
fat_clobber (PedGeometry* geom)
{
FatBootSector boot_sector;
if (!fat_boot_sector_read (&boot_sector, geom))
return 1;
boot_sector.system_id[0] = 0;
boot_sector.boot_sign = 0;
if (boot_sector.u.fat16.fat_name[0] == 'F')
boot_sector.u.fat16.fat_name[0] = 0;
if (boot_sector.u.fat32.fat_name[0] == 'F')
boot_sector.u.fat32.fat_name[0] = 0;
return ped_geometry_write (geom, &boot_sector, 0, 1);
}
static int
_init_fats (PedFileSystem* fs)
{
FatSpecific* fs_info = FAT_SPECIFIC (fs);
FatCluster table_size;
table_size = fs_info->fat_sectors * 512
/ fat_table_entry_size (fs_info->fat_type);
fs_info->fat = fat_table_new (fs_info->fat_type, table_size);
if (!fs_info->fat)
goto error;
if (!fat_table_read (fs_info->fat, fs, 0))
goto error_free_fat;
return 1;
error_free_fat:
fat_table_destroy (fs_info->fat);
error:
return 0;
}
PedFileSystem*
fat_open (PedGeometry* geom)
{
PedFileSystem* fs;
FatSpecific* fs_info;
fs = fat_alloc (geom);
if (!fs)
goto error;
fs_info = (FatSpecific*) fs->type_specific;
if (!fat_boot_sector_read (&fs_info->boot_sector, geom))
goto error_free_fs;
if (!fat_boot_sector_analyse (&fs_info->boot_sector, fs))
goto error_free_fs;
fs->type = (fs_info->fat_type == FAT_TYPE_FAT16)
? &fat16_type
: &fat32_type;
if (fs_info->fat_type == FAT_TYPE_FAT32) {
if (!fat_info_sector_read (&fs_info->info_sector, fs))
goto error_free_fs;
}
if (!_init_fats (fs))
goto error_free_fs;
if (!fat_alloc_buffers (fs))
goto error_free_fat_table;
if (!fat_collect_cluster_info (fs))
goto error_free_buffers;
return fs;
error_free_buffers:
fat_free_buffers (fs);
error_free_fat_table:
fat_table_destroy (fs_info->fat);
error_free_fs:
fat_free (fs);
error:
return NULL;
}
static int
fat_root_dir_clear (PedFileSystem* fs)
{
FatSpecific* fs_info = FAT_SPECIFIC (fs);
memset (fs_info->buffer, 0, 512 * fs_info->root_dir_sector_count);
return ped_geometry_write (fs->geom, fs_info->buffer,
fs_info->root_dir_offset,
fs_info->root_dir_sector_count);
}
/* hack: use the ext2 uuid library to generate a reasonably random (hopefully
* with /dev/random) number. Unfortunately, we can only use 4 bytes of it
*/
static uint32_t
_gen_new_serial_number ()
{
uuid_t uuid;
uuid_generate (uuid);
return * (uint32_t*) &uuid [0];
}
PedFileSystem*
fat_create (PedGeometry* geom, FatType fat_type, PedTimer* timer)
{
PedFileSystem* fs;
FatSpecific* fs_info;
FatCluster table_size;
fs = fat_alloc (geom);
if (!fs)
goto error;
fs_info = (FatSpecific*) fs->type_specific;
fs_info->logical_sector_size = 1;
fs_info->sectors_per_track = geom->dev->bios_geom.sectors;
fs_info->heads = geom->dev->bios_geom.heads;
fs_info->sector_count = fs->geom->length;
fs_info->fat_table_count = 2;
/* some initial values, to be changed later */
fs_info->root_dir_sector_count = FAT_ROOT_DIR_ENTRY_COUNT
/ (512 / sizeof (FatDirEntry));
fs_info->root_dir_entry_count = FAT_ROOT_DIR_ENTRY_COUNT;
fs_info->fat_type = fat_type;
if (!fat_calc_sizes (fs->geom->length, 0,
fs_info->fat_type,
fs_info->root_dir_sector_count,
&fs_info->cluster_sectors,
&fs_info->cluster_count,
&fs_info->fat_sectors)) {
ped_exception_throw (PED_EXCEPTION_ERROR,
PED_EXCEPTION_CANCEL,
_("Partition too big/small for a %s file system."),
(fat_type == FAT_TYPE_FAT16)
? fat16_type.name
: fat32_type.name);
goto error_free_fs;
}
fs_info->cluster_size = fs_info->cluster_sectors * 512;
fs_info->fat_offset = fat_min_reserved_sector_count (fs_info->fat_type);
fs_info->dir_entries_per_cluster
= fs_info->cluster_size / sizeof (FatDirEntry);
if (fs_info->fat_type == FAT_TYPE_FAT16) {
/* FAT16 */
fs->type = &fat16_type;
if (fs_info->cluster_count
> fat_max_cluster_count (fs_info->fat_type)) {
fs_info->cluster_count
= fat_max_cluster_count (fs_info->fat_type);
}
fs_info->root_dir_sector_count
= FAT_ROOT_DIR_ENTRY_COUNT
/ (512 / sizeof (FatDirEntry));
fs_info->root_dir_entry_count = FAT_ROOT_DIR_ENTRY_COUNT;
fs_info->root_dir_offset
= fs_info->fat_offset
+ fs_info->fat_sectors * fs_info->fat_table_count;
fs_info->cluster_offset
= fs_info->root_dir_offset
+ fs_info->root_dir_sector_count;
} else {
/* FAT32 */
fs->type = &fat32_type;
fs_info->info_sector_offset = 1;
fs_info->boot_sector_backup_offset = 6;
fs_info->root_dir_sector_count = 0;
fs_info->root_dir_entry_count = 0;
fs_info->root_dir_offset = 0;
fs_info->cluster_offset
= fs_info->fat_offset
+ fs_info->fat_sectors * fs_info->fat_table_count;
}
table_size = fs_info->fat_sectors * 512
/ fat_table_entry_size (fs_info->fat_type);
fs_info->fat = fat_table_new (fs_info->fat_type, table_size);
if (!fs_info->fat)
goto error_free_fs;
fat_table_set_cluster_count (fs_info->fat, fs_info->cluster_count);
if (!fat_alloc_buffers (fs))
goto error_free_fat_table;
if (fs_info->fat_type == FAT_TYPE_FAT32) {
fs_info->root_cluster
= fat_table_alloc_cluster (fs_info->fat);
fat_table_set_eof (fs_info->fat, fs_info->root_cluster);
memset (fs_info->buffer, 0, fs_info->cluster_size);
if (!fat_write_cluster (fs, fs_info->buffer,
fs_info->root_cluster))
return 0;
}
fs_info->serial_number = _gen_new_serial_number ();
if (!fat_boot_sector_set_boot_code (&fs_info->boot_sector))
goto error_free_buffers;
if (!fat_boot_sector_generate (&fs_info->boot_sector, fs))
goto error_free_buffers;
if (!fat_boot_sector_write (&fs_info->boot_sector, fs))
goto error_free_buffers;
if (fs_info->fat_type == FAT_TYPE_FAT32) {
if (!fat_info_sector_generate (&fs_info->info_sector, fs))
goto error_free_buffers;
if (!fat_info_sector_write (&fs_info->info_sector, fs))
goto error_free_buffers;
}
if (!fat_table_write_all (fs_info->fat, fs))
goto error_free_buffers;
if (fs_info->fat_type == FAT_TYPE_FAT16) {
if (!fat_root_dir_clear (fs))
goto error_free_buffers;
}
return fs;
error_free_buffers:
fat_free_buffers (fs);
error_free_fat_table:
fat_table_destroy (fs_info->fat);
error_free_fs:
fat_free (fs);
error:
return NULL;
}
PedFileSystem*
fat_create_fat16 (PedGeometry* geom, PedTimer* timer)
{
return fat_create (geom, FAT_TYPE_FAT16, timer);
}
PedFileSystem*
fat_create_fat32 (PedGeometry* geom, PedTimer* timer)
{
return fat_create (geom, FAT_TYPE_FAT32, timer);
}
int
fat_close (PedFileSystem* fs)
{
FatSpecific* fs_info = FAT_SPECIFIC (fs);
fat_free_buffers (fs);
fat_table_destroy (fs_info->fat);
fat_free (fs);
return 1;
}
/* Hack: just resize the file system outside of its boundaries! */
PedFileSystem*
fat_copy (const PedFileSystem* fs, PedGeometry* geom, PedTimer* timer)
{
PedFileSystem* new_fs;
new_fs = ped_file_system_open (fs->geom);
if (!new_fs)
goto error;
if (!ped_file_system_resize (new_fs, geom, timer))
goto error_close_new_fs;
return new_fs;
error_close_new_fs:
ped_file_system_close (new_fs);
error:
return 0;
}
static int
_compare_fats (PedFileSystem* fs)
{
FatSpecific* fs_info = FAT_SPECIFIC (fs);
FatTable* table_copy;
FatCluster table_size;
int i;
table_size = fs_info->fat_sectors * 512
/ fat_table_entry_size (fs_info->fat_type);
table_copy = fat_table_new (fs_info->fat_type, table_size);
if (!table_copy)
goto error;
for (i = 1; i < fs_info->fat_table_count; i++) {
if (!fat_table_read (table_copy, fs, i))
goto error_free_table_copy;
if (!fat_table_compare (fs_info->fat, table_copy)) {
if (ped_exception_throw (PED_EXCEPTION_ERROR,
PED_EXCEPTION_IGNORE_CANCEL,
_("The FATs don't match. If you don't know "
"what this means, then select cancel, run "
"scandisk on the file system, and then come "
"back."))
!= PED_EXCEPTION_IGNORE)
goto error_free_table_copy;
}
}
fat_table_destroy (table_copy);
return 1;
error_free_table_copy:
fat_table_destroy (table_copy);
error:
return 0;
}
int
fat_check (PedFileSystem* fs, PedTimer* timer)
{
FatSpecific* fs_info = FAT_SPECIFIC (fs);
PedSector cluster_sectors;
FatCluster cluster_count;
PedSector fat_sectors;
PedSector align_sectors;
FatCluster info_free_clusters;
align_sectors = fs_info->fat_offset
- fat_min_reserved_sector_count (fs_info->fat_type);
if (!fat_calc_sizes (fs->geom->length,
align_sectors,
fs_info->fat_type,
fs_info->root_dir_sector_count,
&cluster_sectors,
&cluster_count,
&fat_sectors)) {
if (ped_exception_throw (PED_EXCEPTION_BUG,
PED_EXCEPTION_IGNORE_CANCEL,
_("There are no possible configurations for this FAT "
"type."))
!= PED_EXCEPTION_IGNORE)
goto error;
}
if (fs_info->fat_type == FAT_TYPE_FAT16) {
if (cluster_sectors != fs_info->cluster_sectors
|| cluster_count != fs_info->cluster_count
|| fat_sectors != fs_info->fat_sectors) {
if (ped_exception_throw (PED_EXCEPTION_WARNING,
PED_EXCEPTION_IGNORE_CANCEL,
_("File system doesn't have expected sizes for "
"Windows to like it. "
"Cluster size is %dk (%dk expected); "
"number of clusters is %d (%d expected); "
"size of FATs is %d sectors (%d expected)."),
(int) fs_info->cluster_sectors / 2,
(int) cluster_sectors / 2,
(int) fs_info->cluster_count,
(int) cluster_count,
(int) fs_info->fat_sectors,
(int) fat_sectors)
!= PED_EXCEPTION_IGNORE)
goto error;
}
}
if (fs_info->fat_type == FAT_TYPE_FAT32) {
info_free_clusters
= PED_LE32_TO_CPU (fs_info->info_sector.free_clusters);
if (info_free_clusters != (FatCluster) -1
&& info_free_clusters != fs_info->fat->free_cluster_count) {
if (ped_exception_throw (PED_EXCEPTION_WARNING,
PED_EXCEPTION_IGNORE_CANCEL,
_("File system is reporting the free space as "
"%d clusters, not %d clusters."),
info_free_clusters,
fs_info->fat->free_cluster_count)
!= PED_EXCEPTION_IGNORE)
goto error;
}
}
if (!_compare_fats (fs))
goto error;
fs->checked = 1;
return 1; /* existence of fs implies consistency ;-) */
error:
return 0;
}
/* Calculates how much space there will be in clusters in:
* old_fs intersect the-new-fs
*/
static PedSector
_calc_resize_data_size (
const PedFileSystem* old_fs,
PedSector new_cluster_sectors,
FatCluster new_cluster_count,
PedSector new_fat_size)
{
FatSpecific* old_fs_info = FAT_SPECIFIC (old_fs);
PedSector fat_size_delta;
fat_size_delta = old_fs_info->fat_sectors - new_fat_size;
return new_cluster_sectors * new_cluster_count - fat_size_delta * 2;
}
static int
_test_resize_size (const PedFileSystem* fs,
PedSector length, PedSector min_data_size)
{
FatSpecific* fs_info = FAT_SPECIFIC (fs);
PedGeometry geom;
PedSector _cluster_sectors;
FatCluster _cluster_count;
PedSector _fat_size;
ped_geometry_init (&geom, fs->geom->dev, fs->geom->start, length);
if (fat_calc_resize_sizes (
&geom,
fs_info->cluster_sectors,
FAT_TYPE_FAT16,
fs_info->root_dir_sector_count,
fs_info->cluster_sectors,
&_cluster_sectors,
&_cluster_count,
&_fat_size)
&& _calc_resize_data_size (fs, _cluster_sectors, _cluster_count,
_fat_size)
>= min_data_size)
return 1;
if (fat_calc_resize_sizes (
&geom,
fs_info->cluster_sectors,
FAT_TYPE_FAT32,
0,
fs_info->cluster_sectors,
&_cluster_sectors,
&_cluster_count,
&_fat_size)
&& _calc_resize_data_size (fs, _cluster_sectors, _cluster_count,
_fat_size)
>= min_data_size)
return 1;
return 0;
}
/* does a binary search (!) for the mininum size. Too hard to compute directly
* (see calc_sizes() for why!)
*/
static PedSector
_get_min_resize_size (const PedFileSystem* fs, PedSector min_data_size)
{
PedSector min_length = 0;
PedSector max_length = fs->geom->length;
PedSector length;
while (min_length < max_length - 1) {
length = (min_length + max_length) / 2;
if (_test_resize_size (fs, length, min_data_size))
max_length = length;
else
min_length = length;
}
/* adds a bit of leeway (64 sectors), for resolving extra issues, like root
* directory allocation, that aren't covered here.
*/
return max_length + 64;
}
PedConstraint*
fat_get_copy_constraint (const PedFileSystem* fs, const PedDevice* dev)
{
FatSpecific* fs_info = FAT_SPECIFIC (fs);
PedGeometry full_dev;
PedSector min_cluster_count;
FatCluster used_clusters;
PedSector min_data_size;
if (!ped_geometry_init (&full_dev, dev, 0, dev->length - 1))
return NULL;
used_clusters = fs_info->fat->cluster_count
- fs_info->fat->free_cluster_count;
min_cluster_count = used_clusters + fs_info->total_dir_clusters;
min_data_size = min_cluster_count * fs_info->cluster_sectors;
return ped_constraint_new (ped_alignment_any, ped_alignment_any,
&full_dev, &full_dev,
_get_min_resize_size (fs, min_data_size),
dev->length);
}
PedConstraint*
fat_get_resize_constraint (const PedFileSystem* fs)
{
return fat_get_copy_constraint (fs, fs->geom->dev);
}
/* FIXME: fat_calc_sizes() needs to say "too big" or "too small", or
* something. This is a really difficult (maths) problem to do
* nicely...
* So, this algorithm works if dev->length / 2 is a valid fat_type
* size. (Which is how I got the magic numbers below)
*/
#if 0
/* returns: -1 too small, 0 ok, 1 too big */
static int
_test_create_size (PedSector length, FatType fat_type,
PedSector cluster_sectors, PedSector cluster_count)
{
PedSector rootdir_sectors;
PedSector _cluster_sectors;
FatCluster _cluster_count;
PedSector _fat_size;
rootdir_sectors = (fat_type == FAT_TYPE_FAT16) ? 16 : 0;
if (!fat_calc_sizes (length, 0, fat_type, rootdir_sectors,
&_cluster_sectors, &_cluster_count, &_fat_size))
return -1; // XXX: doesn't work... can't see a better way!
if (_cluster_sectors < cluster_sectors)
return -1;
if (_cluster_sectors > cluster_sectors)
return 1;
if (_cluster_count < cluster_count)
return -1;
if (_cluster_count > cluster_count)
return 1;
return 0;
}
static PedSector
_get_create_size (PedSector upper_bound, FatType fat_type,
PedSector cluster_sectors, FatCluster cluster_count)
{
PedSector min_length = 0;
PedSector max_length = upper_bound;
PedSector length;
while (1) {
length = (min_length + max_length) / 2;
switch (_test_create_size (length, fat_type, cluster_sectors,
cluster_count)) {
case -1: min_length = length; break;
case 0: return length;
case 1: max_length = length; break;
}
/* hack... won't always be able to get max cluster count
* with max cluster size, etc. */
if (max_length - min_length == 1)
return min_length;
}
return 0; /* shut gcc up */
}
#endif
PedConstraint*
fat_get_create_constraint_fat16 (const PedDevice* dev)
{
PedGeometry full_dev;
PedSector min_size;
PedSector max_size;
if (!ped_geometry_init (&full_dev, dev, 0, dev->length - 1))
return NULL;
#if 0
min_size = _get_create_size (dev->length, FAT_TYPE_FAT16,
fat_min_cluster_size (FAT_TYPE_FAT16),
fat_min_cluster_count (FAT_TYPE_FAT16));
max_size = _get_create_size (dev->length, FAT_TYPE_FAT16,
fat_max_cluster_size (FAT_TYPE_FAT16),
fat_max_cluster_count (FAT_TYPE_FAT16));
if (!min_size)
return NULL;
#else
min_size = 65794;
max_size = 2097153;
#endif
return ped_constraint_new (
ped_alignment_any, ped_alignment_any,
&full_dev, &full_dev,
min_size, max_size);
}
PedConstraint*
fat_get_create_constraint_fat32 (const PedDevice* dev)
{
PedGeometry full_dev;
PedSector min_size;
if (!ped_geometry_init (&full_dev, dev, 0, dev->length - 1))
return NULL;
#if 0
min_size = _get_create_size (dev->length, FAT_TYPE_FAT32,
fat_min_cluster_size (FAT_TYPE_FAT32),
fat_min_cluster_count (FAT_TYPE_FAT32));
if (!min_size)
return NULL;
#else
min_size = 525224;
#endif
return ped_constraint_new (
ped_alignment_any, ped_alignment_any,
&full_dev, &full_dev,
min_size, dev->length);
}
#endif /* !DISCOVER_ONLY */
static PedFileSystemOps fat16_ops = {
probe: fat_probe_fat16,
#ifndef DISCOVER_ONLY
clobber: fat_clobber,
open: fat_open,
create: fat_create_fat16,
close: fat_close,
check: fat_check,
resize: fat_resize,
copy: fat_copy,
get_create_constraint: fat_get_create_constraint_fat16,
get_resize_constraint: fat_get_resize_constraint,
get_copy_constraint: fat_get_copy_constraint,
#else /* !DISCOVER_ONLY */
clobber: NULL,
open: NULL,
create: NULL,
close: NULL,
check: NULL,
resize: NULL,
copy: NULL,
get_create_constraint: NULL,
get_resize_constraint: NULL,
get_copy_constraint: NULL,
#endif /* !DISCOVER_ONLY */
};
static PedFileSystemOps fat32_ops = {
probe: fat_probe_fat32,
#ifndef DISCOVER_ONLY
clobber: fat_clobber,
open: fat_open,
create: fat_create_fat32,
close: fat_close,
check: fat_check,
resize: fat_resize,
copy: fat_copy,
get_create_constraint: fat_get_create_constraint_fat32,
get_resize_constraint: fat_get_resize_constraint,
get_copy_constraint: fat_get_copy_constraint,
#else /* !DISCOVER_ONLY */
clobber: NULL,
open: NULL,
create: NULL,
close: NULL,
check: NULL,
resize: NULL,
copy: NULL,
get_create_constraint: NULL,
get_resize_constraint: NULL,
get_copy_constraint: NULL,
#endif /* !DISCOVER_ONLY */
};
#define FAT_BLOCK_SIZES ((int[2]){512, 0})
PedFileSystemType fat16_type = {
next: NULL,
ops: &fat16_ops,
name: "fat16",
block_sizes: FAT_BLOCK_SIZES
};
PedFileSystemType fat32_type = {
next: NULL,
ops: &fat32_ops,
name: "fat32",
block_sizes: FAT_BLOCK_SIZES
};
void
ped_file_system_fat_init ()
{
if (sizeof (FatBootSector) != 512) {
ped_exception_throw (PED_EXCEPTION_BUG, PED_EXCEPTION_CANCEL,
_("GNU Parted was miscompiled: the FAT boot sector "
"should be 512 bytes. FAT support will be disabled."));
} else {
ped_file_system_type_register (&fat16_type);
ped_file_system_type_register (&fat32_type);
}
}
void
ped_file_system_fat_done ()
{
ped_file_system_type_unregister (&fat16_type);
ped_file_system_type_unregister (&fat32_type);
}