summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am1
-rw-r--r--file-utils.c118
-rw-r--r--libnul.h5
3 files changed, 124 insertions, 0 deletions
diff --git a/Makefile.am b/Makefile.am
index 4273d74..530e464 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -9,6 +9,7 @@ libnul_la_SOURCES = \
array.c \
epoll.c \
signal-handler.c \
+ file-utils.c \
libnul.h
clean-local:
diff --git a/file-utils.c b/file-utils.c
new file mode 100644
index 0000000..99806e4
--- /dev/null
+++ b/file-utils.c
@@ -0,0 +1,118 @@
+/* libnul
+ *
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ * Copyright (C) 2009 Soren Sandmann
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <string.h>
+#include "libnul.h"
+
+/* nul_canonicalize_filename cutted and pasted from GIO
+ *
+ * Author: Alexander Larsson
+ */
+char *
+nul_canonicalize_filename (const char *filename)
+{
+ char *canon, *start, *p, *q;
+ char *cwd;
+ int i;
+
+ g_return_val_if_fail (filename != NULL, NULL);
+
+ if (!g_path_is_absolute (filename))
+ {
+ cwd = g_get_current_dir ();
+ canon = g_build_filename (cwd, filename, NULL);
+ g_free (cwd);
+ }
+ else
+ canon = g_strdup (filename);
+
+ start = (char *)g_path_skip_root (canon);
+
+ /* POSIX allows double slashes at the start to
+ * mean something special (as does windows too).
+ * So, "//" != "/", but more than two slashes
+ * is treated as "/".
+ */
+ i = 0;
+ for (p = start - 1;
+ (p >= canon) &&
+ G_IS_DIR_SEPARATOR (*p);
+ p--)
+ i++;
+ if (i > 2)
+ {
+ i -= 1;
+ start -= i;
+ memmove (start, start+i, strlen (start+i)+1);
+ }
+
+ p = start;
+ while (*p != 0)
+ {
+ if (p[0] == '.' && (p[1] == 0 || G_IS_DIR_SEPARATOR (p[1])))
+ {
+ memmove (p, p+1, strlen (p+1)+1);
+ }
+ else if (p[0] == '.' && p[1] == '.' &&
+ (p[2] == 0 || G_IS_DIR_SEPARATOR (p[2])))
+ {
+ q = p + 2;
+ /* Skip previous separator */
+
+ p = p - 2;
+ if (p < start)
+ p = start;
+ while (p > start && !G_IS_DIR_SEPARATOR (*p))
+ p--;
+ if (G_IS_DIR_SEPARATOR (*p))
+ *p++ = G_DIR_SEPARATOR;
+ memmove (p, q, strlen (q)+1);
+ }
+ else
+ {
+ /* Skip until next separator */
+ while (*p != 0 && !G_IS_DIR_SEPARATOR (*p))
+ p++;
+
+ if (*p != 0)
+ {
+ /* Canonicalize one separator */
+ *p++ = G_DIR_SEPARATOR;
+ }
+ }
+
+ /* Remove additional separators */
+ q = p;
+ while (*q && G_IS_DIR_SEPARATOR (*q))
+ q++;
+
+ if (p != q)
+ memmove (p, q, strlen (q)+1);
+ }
+
+ /* Remove trailing slashes */
+ if (p > start && G_IS_DIR_SEPARATOR (*(p-1)))
+ *(p-1) = 0;
+
+ return canon;
+}
+
diff --git a/libnul.h b/libnul.h
index 9fa5764..b3e9955 100644
--- a/libnul.h
+++ b/libnul.h
@@ -245,6 +245,11 @@ void nul_fd_remove_watch (int fd);
gboolean nul_fd_is_watched (int fd);
/*
+ * File utilities
+ */
+char *nul_canonicalize_filename (const char *filename);
+
+/*
* Unix signal handlers
*/
typedef void (* signal_func_t) (int signo, gpointer data);