summaryrefslogtreecommitdiff
path: root/libparted
diff options
context:
space:
mode:
Diffstat (limited to 'libparted')
-rw-r--r--libparted/fs/fat/bootsector.c56
-rw-r--r--libparted/fs/fat/fat.c58
-rw-r--r--libparted/fs/fat/fat.h2
3 files changed, 91 insertions, 25 deletions
diff --git a/libparted/fs/fat/bootsector.c b/libparted/fs/fat/bootsector.c
index c8e67b8..cab83be 100644
--- a/libparted/fs/fat/bootsector.c
+++ b/libparted/fs/fat/bootsector.c
@@ -27,21 +27,10 @@
#include <fcntl.h>
#include <errno.h>
-/* Reads in the boot sector (superblock), and does a minimum of sanity
- * checking. The goals are:
- * - to detect fat file systems, even if they are damaged [i.e. not
- * return an error / throw an exception]
- * - to fail detection if there's not enough information for
- * fat_boot_sector_probe_type() to work (or possibly crash on a divide-by-zero)
- */
int
-fat_boot_sector_read (FatBootSector* bs, const PedGeometry *geom)
+fat_boot_sector_is_sane (const FatBootSector* bs)
{
PED_ASSERT (bs != NULL, return 0);
- PED_ASSERT (geom != NULL, return 0);
-
- if (!ped_geometry_read (geom, bs, 0, 1))
- return 0;
if (PED_LE16_TO_CPU (bs->boot_sign) != 0xAA55) {
ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
@@ -88,6 +77,25 @@ fat_boot_sector_read (FatBootSector* bs, const PedGeometry *geom)
return 1;
}
+/* Reads in the boot sector (superblock), and does a minimum of sanity
+ * checking. The goals are:
+ * - to detect fat file systems, even if they are damaged [i.e. not
+ * return an error / throw an exception]
+ * - to fail detection if there's not enough information for
+ * fat_boot_sector_probe_type() to work (or possibly crash on a divide-by-zero)
+ */
+int
+fat_boot_sector_read (FatBootSector* bs, const PedGeometry *geom)
+{
+ PED_ASSERT (bs != NULL, return 0);
+ PED_ASSERT (geom != NULL, return 0);
+
+ if (!ped_geometry_read (geom, bs, 0, 1))
+ return 0;
+
+ return fat_boot_sector_is_sane (bs);
+}
+
/*
Don't trust the FAT12, FAT16 or FAT32 label string.
*/
@@ -383,14 +391,22 @@ fat_boot_sector_write (const FatBootSector* bs, PedFileSystem* fs)
PED_ASSERT (bs != NULL, return 0);
- if (!ped_geometry_write (fs->geom, bs, 0, 1))
- return 0;
- if (fs_info->fat_type == FAT_TYPE_FAT32) {
- if (!ped_geometry_write (fs->geom, bs,
- fs_info->boot_sector_backup_offset, 1))
- return 0;
- }
- return ped_geometry_sync (fs->geom);
+ /* Allocate a sector-sized buffer and copy bs into it
+ at the beginning. Fill any remainder with zeros. */
+ size_t buf_len = fs->geom->dev->sector_size;
+ char *buf = ped_malloc (buf_len);
+ memcpy (buf, bs, sizeof *bs);
+ memset (buf + sizeof *bs, 0, buf_len - sizeof *bs);
+
+ int write_ok
+ = (ped_geometry_write (fs->geom, buf, 0, 1)
+ && (fs_info->fat_type != FAT_TYPE_FAT32
+ || ped_geometry_write (fs->geom, buf,
+ fs_info->boot_sector_backup_offset, 1)));
+ free (buf);
+ if (write_ok)
+ ped_geometry_sync (fs->geom);
+ return write_ok;
}
int
diff --git a/libparted/fs/fat/fat.c b/libparted/fs/fat/fat.c
index ada2d62..94b3981 100644
--- a/libparted/fs/fat/fat.c
+++ b/libparted/fs/fat/fat.c
@@ -109,6 +109,45 @@ fat_set_frag_sectors (PedFileSystem* fs, PedSector frag_sectors)
return 1;
}
+/* FIXME: factor out this function: copied from dos.c
+ Read sector, SECTOR_NUM (which has length DEV->sector_size) into malloc'd
+ storage. If the read fails, free the memory and return zero without
+ modifying *BUF. Otherwise, set *BUF to the new buffer and return 1. */
+static int
+read_sector (const PedDevice *dev, PedSector sector_num, char **buf)
+{
+ char *b = ped_malloc (dev->sector_size);
+ PED_ASSERT (b != NULL, return 0);
+ if (!ped_device_read (dev, b, sector_num, 1)) {
+ free (b);
+ return 0;
+ }
+ *buf = b;
+ return 1;
+}
+
+/* Just like fat_boot_sector_read, but works with sector_size > 512.
+ Upon success, set *SECTOR_BUF to the malloc'd sector_size-byte buffer,
+ and copy the first bytes of that buffer into FBS. Upon success,
+ the caller must free *SECTOR_BUF. */
+static int
+fat_boot_sector_read_2 (FatBootSector* fbs, char **sector_buf,
+ const PedGeometry *geom)
+{
+ char *buf;
+ *sector_buf = NULL;
+ if (!read_sector (geom->dev, 0, &buf))
+ return 0;
+ if (!fat_boot_sector_is_sane (buf)) {
+ free (buf);
+ return 0;
+ }
+ *sector_buf = buf;
+ if (fbs)
+ memcpy (fbs, buf, sizeof *fbs);
+ return 1;
+}
+
PedGeometry*
fat_probe (PedGeometry* geom, FatType* fat_type)
{
@@ -121,7 +160,8 @@ fat_probe (PedGeometry* geom, FatType* fat_type)
goto error;
fs_info = (FatSpecific*) fs->type_specific;
- if (!fat_boot_sector_read (&fs_info->boot_sector, geom))
+ char *s0;
+ if (!fat_boot_sector_read_2 (&fs_info->boot_sector, &s0, geom))
goto error_free_fs;
if (!fat_boot_sector_analyse (&fs_info->boot_sector, fs))
goto error_free_fs;
@@ -131,10 +171,12 @@ fat_probe (PedGeometry* geom, FatType* fat_type)
fs_info->sector_count);
fat_free (fs);
+ free (s0);
return result;
error_free_fs:
fat_free (fs);
+ free (s0);
error:
return NULL;
}
@@ -173,7 +215,9 @@ fat_clobber (PedGeometry* geom)
{
FatBootSector boot_sector;
- if (!fat_boot_sector_read (&boot_sector, geom))
+ // FIXME: remove this comment: ARGH: clobbers stack when sector_size > 512
+ char *s0;
+ if (!fat_boot_sector_read_2 (&boot_sector, &s0, geom))
return 1;
boot_sector.system_id[0] = 0;
@@ -183,7 +227,9 @@ fat_clobber (PedGeometry* geom)
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);
+ int write_ok = ped_geometry_write (geom, s0, 0, 1);
+ free (s0);
+ return write_ok;
}
static int
@@ -220,7 +266,8 @@ fat_open (PedGeometry* geom)
goto error;
fs_info = (FatSpecific*) fs->type_specific;
- if (!fat_boot_sector_read (&fs_info->boot_sector, geom))
+ char *s0;
+ if (!fat_boot_sector_read_2 (&fs_info->boot_sector, &s0, geom))
goto error_free_fs;
if (!fat_boot_sector_analyse (&fs_info->boot_sector, fs))
goto error_free_fs;
@@ -239,6 +286,7 @@ fat_open (PedGeometry* geom)
if (!fat_collect_cluster_info (fs))
goto error_free_buffers;
+ free (s0);
return fs;
error_free_buffers:
@@ -246,6 +294,7 @@ error_free_buffers:
error_free_fat_table:
fat_table_destroy (fs_info->fat);
error_free_fs:
+ free (s0);
fat_free (fs);
error:
return NULL;
@@ -887,4 +936,3 @@ ped_file_system_fat_done ()
ped_file_system_type_unregister (&fat16_type);
ped_file_system_type_unregister (&fat32_type);
}
-
diff --git a/libparted/fs/fat/fat.h b/libparted/fs/fat/fat.h
index d749bc8..1be2979 100644
--- a/libparted/fs/fat/fat.h
+++ b/libparted/fs/fat/fat.h
@@ -155,4 +155,6 @@ extern int fat_resize (PedFileSystem* fs, PedGeometry* geom, PedTimer* timer);
extern int fat_set_frag_sectors (PedFileSystem* fs, PedSector frag_sectors);
+extern int fat_boot_sector_is_sane (const FatBootSector* bs);
+
#endif /* FAT_H_INCLUDED */