OSDN Git Service

maint: don't hard-code bug-reporting address
[android-x86/external-parted.git] / libparted / device.c
index 483011a..6cbfaaf 100644 (file)
@@ -1,6 +1,6 @@
 /*
     libparted - a library for manipulating disk partitions
-    Copyright (C) 1999 - 2001, 2005, 2007-2008 Free Software Foundation, Inc.
+    Copyright (C) 1999 - 2001, 2005, 2007-2010 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
@@ -42,6 +42,7 @@
 
 #include <limits.h>
 #include <unistd.h>
+#include <stdlib.h>
 #include <errno.h>
 
 #include "architecture.h"
@@ -50,37 +51,6 @@ static PedDevice*    devices; /* legal advice says: initialized to NULL,
                                    under section 6.7.8 part 10
                                    of ISO/EIC 9899:1999 */
 
-#ifndef HAVE_CANONICALIZE_FILE_NAME
-char *
-canonicalize_file_name (const char *name)
-{
-       char *  buf;
-       int     size;
-       char *  result;
-
-#ifdef PATH_MAX
-       size = PATH_MAX;
-#else
-       /* Bigger is better; realpath has no way todo bounds checking.  */
-       size = 4096;
-#endif
-
-       /* Just in case realpath does not NULL terminate the string
-        * or it just fits in SIZE without a NULL terminator.  */
-       buf = calloc (size + 1, sizeof(char));
-       if (! buf) {
-               errno = ENOMEM;
-               return NULL;
-       }
-
-       result = realpath (name, buf);
-       if (! result)
-               free (buf);
-
-       return result;
-}
-#endif /* !HAVE_CANONICALIZE_FILE_NAME */
-
 static void
 _device_register (PedDevice* dev)
 {
@@ -103,6 +73,16 @@ _device_unregister (PedDevice* dev)
                if (walk == dev) break;
        }
 
+       /* This function may be called twice for the same device if a
+          libparted user explictly removes the device from the cache using
+          ped_device_cache_remove(), we get called and it then becomes the
+          user's responsibility to free the PedDevice by calling
+          ped_device_destroy().
+          ped_device_destroy() will then call us a second time, so if the
+          device is not found in the list do nothing. */
+       if (walk == NULL)
+               return;
+
        if (last)
                last->next = dev->next;
        else
@@ -169,10 +149,12 @@ PedDevice*
 ped_device_get (const char* path)
 {
        PedDevice*      walk;
-       char*           normal_path;
+       char*           normal_path = NULL;
 
        PED_ASSERT (path != NULL, return NULL);
-       normal_path = canonicalize_file_name (path);
+       /* Don't canonicalize /dev/mapper paths, see tests/symlink.c */
+       if (strncmp (path, "/dev/mapper/", 12))
+               normal_path = canonicalize_file_name (path);
        if (!normal_path)
                /* Well, maybe it is just that the file does not exist.
                 * Try it anyway.  */
@@ -431,7 +413,7 @@ ped_device_sync_fast (PedDevice* dev)
  *         constraint.
  */
 PedConstraint*
-ped_device_get_constraint (PedDevice* dev)
+ped_device_get_constraint (const PedDevice* dev)
 {
         PedGeometry *s, *e;
         PedConstraint* c = ped_constraint_new (
@@ -445,6 +427,75 @@ ped_device_get_constraint (PedDevice* dev)
         return c;
 }
 
+static PedConstraint*
+_ped_device_get_aligned_constraint(const PedDevice *dev,
+                                   PedAlignment* start_align)
+{
+        PedAlignment *end_align = NULL;
+        PedGeometry *whole_dev_geom = NULL;
+        PedConstraint *c = NULL;
+
+        if (start_align) {
+                end_align = ped_alignment_new(start_align->offset - 1,
+                                              start_align->grain_size);
+                if (!end_align)
+                        goto free_start_align;
+        }
+
+        whole_dev_geom = ped_geometry_new (dev, 0, dev->length);
+
+        if (start_align)
+                c =  ped_constraint_new (start_align, end_align,
+                                         whole_dev_geom, whole_dev_geom,
+                                         1, dev->length);
+        else
+                c =  ped_constraint_new (ped_alignment_any, ped_alignment_any,
+                                         whole_dev_geom, whole_dev_geom,
+                                         1, dev->length);
+
+        free (whole_dev_geom);
+        free (end_align);
+free_start_align:
+        free (start_align);
+        return c;
+}
+
+/**
+ * Get a constraint that represents hardware requirements on geometry and
+ * alignment.
+ *
+ * This function will return a constraint representing the limits imposed
+ * by the size of the disk and the minimal alignment requirements for proper
+ * performance of the disk.
+ *
+ * \return NULL on error, otherwise a pointer to a dynamically allocated
+ *         constraint.
+ */
+PedConstraint*
+ped_device_get_minimal_aligned_constraint(const PedDevice *dev)
+{
+        return _ped_device_get_aligned_constraint(dev,
+                                         ped_device_get_minimum_alignment(dev));
+}
+
+/**
+ * Get a constraint that represents hardware requirements on geometry and
+ * alignment.
+ *
+ * This function will return a constraint representing the limits imposed
+ * by the size of the disk and the alignment requirements for optimal
+ * performance of the disk.
+ *
+ * \return NULL on error, otherwise a pointer to a dynamically allocated
+ *         constraint.
+ */
+PedConstraint*
+ped_device_get_optimal_aligned_constraint(const PedDevice *dev)
+{
+        return _ped_device_get_aligned_constraint(dev,
+                                         ped_device_get_optimum_alignment(dev));
+}
+
 /**
  * Get an alignment that represents minimum hardware requirements on alignment.
  * When for example using media that has a physical sector size that is a
@@ -462,10 +513,16 @@ ped_device_get_constraint (PedDevice* dev)
 PedAlignment*
 ped_device_get_minimum_alignment(const PedDevice *dev)
 {
+        PedAlignment *align = NULL;
+
         if (ped_architecture->dev_ops->get_minimum_alignment)
-                return ped_architecture->dev_ops->get_minimum_alignment(dev);
+                align = ped_architecture->dev_ops->get_minimum_alignment(dev);
 
-        return NULL; /* ped_alignment_none */
+        if (align == NULL)
+                align = ped_alignment_new(0,
+                                dev->phys_sector_size / dev->sector_size);
+
+        return align;
 }
 
 /**
@@ -482,11 +539,27 @@ ped_device_get_minimum_alignment(const PedDevice *dev)
 PedAlignment*
 ped_device_get_optimum_alignment(const PedDevice *dev)
 {
-        if (ped_architecture->dev_ops->get_optimum_alignment)
-                return ped_architecture->dev_ops->get_optimum_alignment(dev);
+        PedAlignment *align = NULL;
 
-        return NULL; /* ped_alignment_none */
+        if (ped_architecture->dev_ops->get_optimum_alignment)
+                align = ped_architecture->dev_ops->get_optimum_alignment(dev);
+
+        /* If the arch specific code could not give as an alignment
+           return a default value based on the type of device. */
+        if (align == NULL) {
+                switch (dev->type) {
+                case PED_DEVICE_DASD:
+                        align = ped_device_get_minimum_alignment(dev);
+                        break;
+                default:
+                        /* Align to a grain of 1MiB (like vista / win7) */
+                        align = ped_alignment_new(0,
+                                                  (PED_DEFAULT_ALIGNMENT
+                                                  / dev->sector_size));
+                }
+        }
+
+        return align;
 }
 
 /** @} */
-