bug-parted
[Top][All Lists]
Advanced

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

[patch] canonicalize_file_name


From: Neal H Walfield
Subject: [patch] canonicalize_file_name
Date: Tue, 14 Aug 2001 10:34:55 +0200
User-agent: Mutt/1.3.18i

In libparted/device.c, we were using a home brewed hack to canonicalize
a file name (i.e. expand symbolic links, remove superfuous path
components, etc.).  This is unnecessary as libc already has the
functionality to do this for us.  In a POSIX environment, it is called
realpath.  This function, however, has a few problems, namely, it takes
a buffer but no buffer size.  Glibc has a function called
canonicalize_file_name which does the same thing as read_path, however,
it does not have the problems associated with read_path.

This patch adds a configure test for canonicalize_file_name and if
found, uses that in libparted/device.c.  If, however,
canonicalize_file_name is not found, a wrapper function is present in
libparted/device.c that emulates canonicalize_file_name using
read_path.

As a side node, _POSIX_PATH_MAX should never be used by an application.
POSIX defines this is the minimum accepted value for PATH_MAX.  If you
want to use PATH_MAX, you should do so directly.  However, POSIX does
not guarantee that PATH_MAX is defined; if it is not, there is no limit.
And, in fact, this is the case on GNU/Hurd.

A change log:

2001-08-12  Neal H Walfield  <address@hidden>

        * configure.in: Add check for canonicalize_file_name.
        * config.h (HAVE_CANONICALIZE_FILE_NAME): New marcro.
        * libparted/device.c (_GNU_SOURCE): Enable GNU extensions.
        [!HAVE_CANONICALIZE_FILE_NAME] (canonicalize_file_name):
        Implement it.
        (_readlink): Depreciated and removed in favor of
        canonicalize_file_name.
        (_strcut): Likewise.
        (_remove_doube_slash): Likewise.
        (_remove_dots): Likewise.
        (_normalize_path): Likewise.
        (_ped_device_probe): Use canonicalize_file_name, not
        _normalize_path.
        (ped_device_get): Likewise.

        (devices): Remove superfluous zero initializer.


diff --exclude aclocal.m4 --exclude configure --exclude Makefile.in -urNp 
parted-1.5.4-pre1.orig/configure.in parted-1.5.4-pre1/configure.in
--- parted-1.5.4-pre1.orig/configure.in Sun Aug 12 06:38:14 2001
+++ parted-1.5.4-pre1/configure.in      Mon Aug 13 17:32:20 2001
@@ -307,6 +307,11 @@ if test x$with_readline = xyes; then
        LIBS="$OLD_LIBS"
 fi
 
+OLD_CFLAGS="$CFLAGS"
+CFLAGS=-D_GNU_SOURCE=1
+AC_CHECK_FUNCS(canonicalize_file_name)
+CFLAGS="$OLD_CFLAGS"
+
 CFLAGS="$CFLAGS -W -Wall -Wno-unused -Wno-switch -Werror"
 
 AC_OUTPUT([
diff --exclude aclocal.m4 --exclude configure --exclude Makefile.in -urNp 
parted-1.5.4-pre1.orig/config.h.in parted-1.5.4-pre1/config.h.in
--- parted-1.5.4-pre1.orig/config.h.in  Sun Jul 15 02:47:02 2001
+++ parted-1.5.4-pre1/config.h.in       Mon Aug 13 17:32:20 2001
@@ -78,6 +78,9 @@
 /* Define if you have the <argz.h> header file. */
 #undef HAVE_ARGZ_H
 
+/* Define if you have the `canonicalize_file_name' function. */
+#undef HAVE_CANONICALIZE_FILE_NAME
+
 /* Define if you have the `dcgettext' function. */
 #undef HAVE_DCGETTEXT
 
diff --exclude aclocal.m4 --exclude configure --exclude Makefile.in -urNp 
parted-1.5.4-pre1.orig/libparted/device.c parted-1.5.4-pre1/libparted/device.c
--- parted-1.5.4-pre1.orig/libparted/device.c   Wed Jul 25 04:11:25 2001
+++ parted-1.5.4-pre1/libparted/device.c        Mon Aug 13 18:58:28 2001
@@ -17,6 +17,8 @@
     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
 
+#define _GNU_SOURCE 1
+
 #include "config.h"
 
 #include <parted/parted.h>
@@ -26,7 +28,38 @@
 #include <stdlib.h>
 #include <unistd.h>
 
-static PedDevice*      devices = NULL;
+static PedDevice*      devices;
+
+#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);
+       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)
@@ -65,102 +98,6 @@ ped_device_get_next (const PedDevice* de
                return devices;
 }
 
-/* wrap around POSIX brain-damage */
-static int
-_readlink (const char* path, char* buf, size_t size)
-{
-       memset (buf, 0, size);
-       return readlink (path, buf, size);
-}
-
-static void
-_strcut (char* str, size_t count)
-{
-       size_t  i;
-
-       for (i = count; str [i]; i++)
-               str [i - count] = str [i];
-       str [i - count] = 0;
-}
-
-static void
-_remove_double_slash (char* path)
-{
-       char*   match;
-
-       while ((match = strstr (path, "//")))
-               _strcut (match, 1);
-}
-
-/* removes ./ and XX/../ from path.  Obviously broken (will remove a./),
- * but who cares?  Expects // to have been removed
- */
-static void
-_remove_dots (char* path)
-{
-       char*   match;
-
-       match = strchr (path, '.');
-       while (match) {
-               if (!strncmp (match, "./", 2)) {
-                       _strcut (match, 2);
-               } else if (!strncmp (match, "../", 3)) {
-                       char*   cut_start;
-
-                       for (cut_start = match - 2;
-                            *cut_start != '/'; cut_start--) {
-                               if (cut_start < path)
-                                       return; /* broken path! */
-                       }
-
-                       _strcut (cut_start, match - cut_start + 2);
-               }
-
-               match = strchr (path, '.');
-       }
-}
-
-/* follows symbolic links.  WTF isn't this in libc?! */
-static char*
-_normalize_path (const char* path)
-{
-       char    normalized [_POSIX_PATH_MAX + 1];
-       int     normalized_len;
-       char    tmp [_POSIX_PATH_MAX + 1];
-
-       strcpy (normalized, path);
-       _remove_double_slash (normalized);
-       _remove_dots (normalized);
-       normalized_len = strlen (path);
-
-       while (_readlink (normalized, tmp, _POSIX_PATH_MAX + 1) > 0) {
-               if (tmp [0] == '/') {
-                       strcpy (normalized, tmp);
-               } else {
-                       char* slash_match = strrchr (normalized, '/');
-                       char* cpy_loc;
-
-                       if (slash_match) {
-                               if (slash_match - normalized + normalized_len
-                                               > _POSIX_PATH_MAX)
-                                       return NULL;
-                               cpy_loc = slash_match + 1;
-                       } else {
-                               cpy_loc = normalized;
-                       }
-
-                       /* check for recursive sym-links */
-                       if (!strcmp (cpy_loc, tmp))
-                               return NULL;
-                       strcpy (cpy_loc, tmp);
-               }
-               _remove_double_slash (normalized);
-               _remove_dots (normalized);
-               normalized_len = strlen (path);
-       }
-       return strdup (normalized);
-}
-
 void
 _ped_device_probe (const char* path)
 {
@@ -168,7 +105,11 @@ _ped_device_probe (const char* path)
        PedDevice*      dev;
 
        PED_ASSERT (path != NULL, return);
-       normalized_path = _normalize_path (path);
+       normalized_path = canonicalize_file_name (path);
+       if (!normalized_path)
+               /* Well, maybe it is just that the file does not exist.
+                * Try it anyway.  */
+               normalized_path = strdup (path);
        if (!normalized_path)
                return;
 
@@ -206,7 +147,11 @@ ped_device_get (const char* path)
        char*           normal_path;
 
        PED_ASSERT (path != NULL, return NULL);
-       normal_path = _normalize_path (path);
+       normal_path = canonicalize_file_name (path);
+       if (!normal_path)
+               /* Well, maybe it is just that the file does not exist.
+                * Try it anyway.  */
+               normal_path = strdup (path);
        if (!normal_path)
                return NULL;
 

Attachment: pgpkcN_I6XJ4b.pgp
Description: PGP signature


reply via email to

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