From 4c560fb4ab6c5d91a2797dfb772be0a6a1cf161c Mon Sep 17 00:00:00 2001 From: Søren Sandmann Pedersen Date: Tue, 14 Apr 2009 07:26:59 -0400 Subject: Add canonicalize_filename() from glib --- Makefile.am | 1 + file-utils.c | 118 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ libnul.h | 5 +++ 3 files changed, 124 insertions(+) create mode 100644 file-utils.c 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 +#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 @@ -244,6 +244,11 @@ void nul_fd_set_poll_handler (int fd, 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 */ -- cgit v1.2.3