bug-parted
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 04/10] lib-fs-resize: add wrappers for open, close, resize, get_r


From: Jim Meyering
Subject: [PATCH 04/10] lib-fs-resize: add wrappers for open, close, resize, get_resize_constraint
Date: Fri, 3 Feb 2012 22:46:53 +0100

From: Jim Meyering <address@hidden>

* libparted/fs/r/filesys.c: Implement ped_file_system_resize,
ped_file_system_open, ped_file_system_close and
ped_file_system_get_resize_constraint.
* libparted/fs/r/hfs/hfs.c: Give a few functions global scope,
so we can use them from the above.
* libparted/fs/Makefile.am: Use automake's subdir-objects option.
This avoids conflicts with multiple *.o file names
(e.g., fat.o), now that two directories provide that name.
---
 libparted/fs/Makefile.am |    4 +-
 libparted/fs/r/filesys.c |  229 ++++++++++++++++++++++++++++++++++++++++------
 libparted/fs/r/hfs/hfs.c |   16 ++--
 3 files changed, 210 insertions(+), 39 deletions(-)

diff --git a/libparted/fs/Makefile.am b/libparted/fs/Makefile.am
index 947af0e..ddc8fd9 100644
--- a/libparted/fs/Makefile.am
+++ b/libparted/fs/Makefile.am
@@ -3,9 +3,11 @@
 #
 # This file may be modified and/or distributed without restriction.

+AUTOMAKE_OPTIONS = subdir-objects
+
 partedincludedir = -I$(top_builddir)/include -I$(top_srcdir)/include

-AM_CFLAGS = $(WARN_CFLAGS) $(WERROR_CFLAGS)
+# AM_CFLAGS = $(WARN_CFLAGS) $(WERROR_CFLAGS)

 noinst_LTLIBRARIES    =        libfs.la

diff --git a/libparted/fs/r/filesys.c b/libparted/fs/r/filesys.c
index 5c2d8fb..6463ab5 100644
--- a/libparted/fs/r/filesys.c
+++ b/libparted/fs/r/filesys.c
@@ -37,6 +37,86 @@
 #  define _(String) (String)
 #endif /* ENABLE_NLS */

+#define STREQ(a, b) (strcmp (a, b) == 0)
+
+typedef PedFileSystem * (*open_fn_t) (PedGeometry *);
+extern PedFileSystem *hfsplus_open (PedGeometry *);
+extern PedFileSystem *hfs_open (PedGeometry *);
+extern PedFileSystem *fat_open (PedGeometry *);
+
+typedef int (*close_fn_t) (PedFileSystem *);
+extern int hfsplus_close (PedFileSystem *);
+extern int hfs_close (PedFileSystem *);
+extern int fat_close (PedFileSystem *);
+
+typedef int (*resize_fn_t) (PedFileSystem *fs, PedGeometry *geom,
+                           PedTimer *timer);
+extern int hfsplus_resize (PedFileSystem *fs, PedGeometry *geom,
+                          PedTimer *timer);
+extern int hfs_resize (PedFileSystem *fs, PedGeometry *geom,
+                      PedTimer *timer);
+extern int fat_resize (PedFileSystem *fs, PedGeometry *geom,
+                      PedTimer *timer);
+
+typedef PedConstraint * (*resize_constraint_fn_t) (PedFileSystem const *fs);
+extern PedConstraint *hfsplus_get_resize_constraint (PedFileSystem const *fs);
+extern PedConstraint *hfs_get_resize_constraint (PedFileSystem const *fs);
+extern PedConstraint *fat_get_resize_constraint (PedFileSystem const *fs);
+
+static bool
+is_hfs_plus (char const *fs_type_name)
+{
+  return STREQ (fs_type_name, "hfsx") || STREQ (fs_type_name, "hfs+");
+}
+
+static open_fn_t
+open_fn (char const *fs_type_name)
+{
+  if (is_hfs_plus (fs_type_name))
+    return hfsplus_open;
+  if (STREQ (fs_type_name, "hfs"))
+    return hfs_open;
+  if (strncmp (fs_type_name, "fat", 3) == 0)
+    return fat_open;
+  return NULL;
+}
+
+static close_fn_t
+close_fn (char const *fs_type_name)
+{
+  if (is_hfs_plus (fs_type_name))
+    return hfsplus_close;
+  if (STREQ (fs_type_name, "hfs"))
+    return hfs_close;
+  if (strncmp (fs_type_name, "fat", 3) == 0)
+    return fat_close;
+  return NULL;
+}
+
+static resize_fn_t
+resize_fn (char const *fs_type_name)
+{
+  if (is_hfs_plus (fs_type_name))
+    return hfsplus_resize;
+  if (STREQ (fs_type_name, "hfs"))
+    return hfs_resize;
+  if (strncmp (fs_type_name, "fat", 3) == 0)
+    return fat_resize;
+  return NULL;
+}
+
+static resize_constraint_fn_t
+resize_constraint_fn (char const *fs_type_name)
+{
+  if (is_hfs_plus (fs_type_name))
+    return hfsplus_get_resize_constraint;
+  if (STREQ (fs_type_name, "hfs"))
+    return hfs_get_resize_constraint;
+  if (strncmp (fs_type_name, "fat", 3) == 0)
+    return fat_get_resize_constraint;
+  return NULL;
+}
+
 /**
  * This function opens the file system stored on \p geom, if it
  * can find one.
@@ -55,9 +135,6 @@
 PedFileSystem *
 ped_file_system_open (PedGeometry* geom)
 {
-       PedFileSystem*          fs;
-       PedGeometry*            probed_geom;
-
        PED_ASSERT (geom != NULL);

        if (!ped_device_open (geom->dev))
@@ -70,7 +147,15 @@ ped_file_system_open (PedGeometry* geom)
                goto error_close_dev;
        }

-       probed_geom = ped_file_system_probe_specific (type, geom);
+       open_fn_t open_f = open_fn (type->name);
+       if (open_f == NULL) {
+          ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
+                               _("resizing %s file systems is not supported"),
+                               type->name);
+          goto error_close_dev;
+       }
+
+       PedGeometry *probed_geom = ped_file_system_probe_specific (type, geom);
        if (!probed_geom)
                goto error_close_dev;
        if (!ped_geometry_test_inside (geom, probed_geom)) {
@@ -82,19 +167,11 @@ ped_file_system_open (PedGeometry* geom)
                        goto error_destroy_probed_geom;
        }

-       if (!type->ops->open) {
-               ped_exception_throw (PED_EXCEPTION_NO_FEATURE,
-                                    PED_EXCEPTION_CANCEL,
-                                    _("Support for opening %s file systems "
-                                      "is not implemented yet."),
-                                    type->name);
-               goto error_destroy_probed_geom;
-       }
-
-       fs = type->ops->open (probed_geom);
+       PedFileSystem *fs = (*open_f) (probed_geom);
        if (!fs)
                goto error_destroy_probed_geom;
        ped_geometry_destroy (probed_geom);
+       fs->type = type;
        return fs;

 error_destroy_probed_geom:
@@ -113,11 +190,10 @@ error:
 int
 ped_file_system_close (PedFileSystem* fs)
 {
-       PedDevice*      dev = fs->geom->dev;
-
        PED_ASSERT (fs != NULL);
+       PedDevice *dev = fs->geom->dev;

-       if (!fs->type->ops->close (fs))
+       if (!(close_fn (fs->type->name) (fs)))
                goto error_close_dev;
        ped_device_close (dev);
        return 1;
@@ -128,6 +204,77 @@ error_close_dev:
 }

 /**
+ * This function erases all file system signatures that indicate that a
+ * file system occupies a given region described by \p geom.
+ * After this operation ped_file_system_probe() won't detect any file system.
+ *
+ * \note ped_file_system_create() calls this before creating a new file system.
+ *
+ * \return \c 1 on success, \c 0 on failure
+ */
+static int
+ped_file_system_clobber (PedGeometry* geom)
+{
+       PedFileSystemType*      fs_type = NULL;
+
+       PED_ASSERT (geom != NULL);
+
+       if (!ped_device_open (geom->dev))
+               goto error;
+
+       ped_exception_fetch_all ();
+       while ((fs_type = ped_file_system_type_get_next (fs_type))) {
+               PedGeometry*    probed;
+
+               if (!fs_type->ops->clobber)
+                       continue;
+
+               probed = ped_file_system_probe_specific (fs_type, geom);
+               if (!probed) {
+                       ped_exception_catch ();
+                       continue;
+               }
+               ped_geometry_destroy (probed);
+
+               if (fs_type->ops->clobber && !fs_type->ops->clobber (geom)) {
+                       ped_exception_leave_all ();
+                       goto error_close_dev;
+               }
+       }
+       ped_device_close (geom->dev);
+       ped_exception_leave_all ();
+       return 1;
+
+error_close_dev:
+       ped_device_close (geom->dev);
+error:
+       return 0;
+}
+
+/* This function erases all signatures that indicate the presence of
+ * a file system in a particular region, without erasing any data
+ * contained inside the "exclude" region.
+ */
+static int
+ped_file_system_clobber_exclude (PedGeometry* geom,
+                                const PedGeometry* exclude)
+{
+       PedGeometry*    clobber_geom;
+       int             status;
+
+       if (ped_geometry_test_sector_inside (exclude, geom->start))
+               return 1;
+
+       clobber_geom = ped_geometry_duplicate (geom);
+       if (ped_geometry_test_overlap (clobber_geom, exclude))
+               ped_geometry_set_end (clobber_geom, exclude->start - 1);
+
+       status = ped_file_system_clobber (clobber_geom);
+       ped_geometry_destroy (clobber_geom);
+       return status;
+}
+
+/**
  * Resize \p fs to new geometry \p geom.
  *
  * \p geom should satisfy the ped_file_system_get_resize_constraint().
@@ -140,25 +287,47 @@ error_close_dev:
  * \return \c 0 on failure
  */
 int
-ped_file_system_resize (PedFileSystem* fs, PedGeometry* geom, PedTimer* timer)
+ped_file_system_resize (PedFileSystem *fs, PedGeometry *geom, PedTimer *timer)
 {
        PED_ASSERT (fs != NULL);
        PED_ASSERT (geom != NULL);

-       if (!fs->type->ops->resize) {
-               ped_exception_throw (PED_EXCEPTION_NO_FEATURE,
-                                    PED_EXCEPTION_CANCEL,
-                                    _("Support for resizing %s file systems "
-                                      "is not implemented yet."),
-                                    fs->type->name);
-               return 0;
-       }
-       if (!fs->checked && fs->type->ops->check) {
-               if (!ped_file_system_check (fs, timer))
-                       return 0;
+       resize_fn_t resize_f = resize_fn (fs->type->name);
+       if (resize_f == NULL) {
+          ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
+                               _("resizing %s file systems is not supported"),
+                               fs->type->name);
+          return 0;
        }
+
        if (!ped_file_system_clobber_exclude (geom, fs->geom))
                return 0;

-       return fs->type->ops->resize (fs, geom, timer);
+       return resize_f (fs, geom, timer);
+}
+
+/**
+ * Return a constraint that represents all of the possible ways the
+ * file system \p fs can be resized with ped_file_system_resize().
+ * This takes into account the amount of used space on
+ * the filesystem \p fs and the capabilities of the resize algorithm.
+ * Hints:
+ * -# if constraint->start_align->grain_size == 0, or
+ *    constraint->start_geom->length == 1, then the start cannot be moved
+ * -# constraint->min_size is the minimum size you can resize the partition
+ *    to.  You might want to tell the user this ;-).
+ *
+ * \return a PedConstraint on success, \c NULL on failure
+ */
+PedConstraint *
+ped_file_system_get_resize_constraint (const PedFileSystem* fs)
+{
+       PED_ASSERT (fs != NULL);
+
+       resize_constraint_fn_t resize_constraint_f =
+         resize_constraint_fn (fs->type->name);
+       if (resize_constraint_f == NULL)
+         return NULL;
+
+       return resize_constraint_f (fs);
 }
diff --git a/libparted/fs/r/hfs/hfs.c b/libparted/fs/r/hfs/hfs.c
index eb219fb..f7f98f4 100644
--- a/libparted/fs/r/hfs/hfs.c
+++ b/libparted/fs/r/hfs/hfs.c
@@ -79,7 +79,7 @@ hfs_clobber (PedGeometry* geom)
                (!!ped_geometry_sync  (geom));
 }

-static PedFileSystem*
+PedFileSystem *
 hfs_open (PedGeometry* geom)
 {
        uint8_t                 buf[PED_SECTOR_SIZE_DEFAULT];
@@ -149,7 +149,7 @@ ho_fs:      free(fs);
 ho:    return NULL;
 }

-static int
+int
 hfs_close (PedFileSystem *fs)
 {
        HfsPrivateFSData* priv_data = (HfsPrivateFSData*) fs->type_specific;
@@ -166,7 +166,7 @@ hfs_close (PedFileSystem *fs)
        return 1;
 }

-static PedConstraint*
+PedConstraint *
 hfs_get_resize_constraint (const PedFileSystem *fs)
 {
        PedDevice*      dev = fs->geom->dev;
@@ -190,7 +190,7 @@ hfs_get_resize_constraint (const PedFileSystem *fs)
                                   fs->geom->length);
 }

-static int
+int
 hfs_resize (PedFileSystem* fs, PedGeometry* geom, PedTimer* timer)
 {
        uint8_t                 buf[PED_SECTOR_SIZE_DEFAULT];
@@ -375,7 +375,7 @@ hfsplus_clobber (PedGeometry* geom)
        return ( hfs_clobber (geom) && i );
 }

-static int
+int
 hfsplus_close (PedFileSystem *fs)
 {
        HfsPPrivateFSData*      priv_data = (HfsPPrivateFSData*)
@@ -399,7 +399,7 @@ hfsplus_close (PedFileSystem *fs)
        return 1;
 }

-static PedFileSystem*
+PedFileSystem*
 hfsplus_open (PedGeometry* geom)
 {
        uint8_t                 buf[PED_SECTOR_SIZE_DEFAULT];
@@ -569,7 +569,7 @@ hpo_fs: free(fs);
 hpo:   return NULL;
 }

-static PedConstraint*
+PedConstraint *
 hfsplus_get_resize_constraint (const PedFileSystem *fs)
 {
        PedDevice*      dev = fs->geom->dev;
@@ -906,7 +906,7 @@ bb_not_found:
        return 0;
 }

-static int
+int
 hfsplus_resize (PedFileSystem* fs, PedGeometry* geom, PedTimer* timer)
 {
        HfsPPrivateFSData*      priv_data;
-- 
1.7.9.112.gb85f2




reply via email to

[Prev in Thread] Current Thread [Next in Thread]