Logo Search packages:      
Sourcecode: parted version File versions

fat.c

/*
    libparted
    Copyright (C) 1998, 1999, 2000, 2001 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#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)) {
            *fat_type = fat_boot_sector_probe_type (&fs_info->boot_sector,
                                          geom);
            fat_free (fs);
            return ped_geometry_duplicate (geom);
      }

      *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);
      int         i;
      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 filesystem outside of it's 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 != 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 */
};

PedFileSystemType fat16_type = {
      next: NULL,
      ops:  &fat16_ops,
      name: "fat16"
};

PedFileSystemType fat32_type = {
      next: NULL,
      ops:  &fat32_ops,
      name: "fat32"
};

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);
}


Generated by  Doxygen 1.6.0   Back to index