From 82108808f13d056b3904c1717658a306a4aba2dd Mon Sep 17 00:00:00 2001 From: Pino Toscano Date: Tue, 25 Dec 2018 16:44:19 +0100 Subject: Switch to modern realpath() Assume everywhere that the realpath() implementation has the POSIX.1-2008 behaviour, i.e. allowing NULL as second parameter and thus returning a newly allocated buffer; it is not just a GNU extension, and supported already by modern libc's on other OSes. menu_canonicalize_file_name() is always called with FALSE as second parameter, so it is replaced directly by realpath(); this allows the complete removal of canonicalize.{c,h}. This is a forward-port of the same changes done in gnome-menus, see: https://gitlab.gnome.org/GNOME/gnome-menus/merge_requests/4 --- libmenu/Makefile.am | 2 - libmenu/canonicalize.c | 330 -------------------------------------------- libmenu/canonicalize.h | 34 ----- libmenu/entry-directories.c | 4 +- libmenu/matemenu-tree.c | 10 +- libmenu/menu-layout.c | 1 - 6 files changed, 7 insertions(+), 374 deletions(-) delete mode 100644 libmenu/canonicalize.c delete mode 100644 libmenu/canonicalize.h (limited to 'libmenu') diff --git a/libmenu/Makefile.am b/libmenu/Makefile.am index e6e20e7..34150f2 100644 --- a/libmenu/Makefile.am +++ b/libmenu/Makefile.am @@ -13,7 +13,6 @@ libmate_menu_include_HEADERS = \ matemenu-tree.h libmate_menu_sources = \ - canonicalize.c \ desktop-entries.c \ entry-directories.c \ matemenu-tree.c \ @@ -23,7 +22,6 @@ libmate_menu_sources = \ libmate_menu_la_SOURCES = \ $(libmate_menu_sources) \ - canonicalize.h \ desktop-entries.h \ entry-directories.h \ matemenu-tree.h \ diff --git a/libmenu/canonicalize.c b/libmenu/canonicalize.c deleted file mode 100644 index 1a29ae9..0000000 --- a/libmenu/canonicalize.c +++ /dev/null @@ -1,330 +0,0 @@ -/* Return the canonical absolute name of a given file. - * Copyright (C) 1996-2001, 2002 Free Software Foundation, Inc. - * This file is part of the GNU C Library. - * - * Copyright (C) 2002 Red Hat, Inc. (trivial port to GLib) - * - * The GNU C 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.1 of the License, or (at your option) any later version. - * - * The GNU C 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 the GNU C Library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA. - */ - -#include - -#include "canonicalize.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef MAXSYMLINKS -#define MAXSYMLINKS sysconf(_SC_SYMLOOP_MAX) -#endif - -/* Return the canonical absolute name of file NAME. A canonical name - does not contain any `.', `..' components nor any repeated path - separators ('/') or symlinks. All path components must exist. If - RESOLVED is null, the result is malloc'd; otherwise, if the - canonical name is PATH_MAX chars or more, returns null with `errno' - set to ENAMETOOLONG; if the name fits in fewer than PATH_MAX chars, - returns the name in RESOLVED. If the name cannot be resolved and - RESOLVED is non-NULL, it contains the path of the first component - that cannot be resolved. If the path can be resolved, RESOLVED - holds the same value as the value returned. */ - -static char* menu_realpath(const char* name, char* resolved) -{ - char* rpath = NULL; - char* dest = NULL; - char* extra_buf = NULL; - const char* start; - const char* end; - const char* rpath_limit; - long int path_max; - int num_links = 0; - - if (name == NULL) - { - /* As per Single Unix Specification V2 we must return an error if - * either parameter is a null pointer. We extend this to allow - * the RESOLVED parameter to be NULL in case the we are expected to - * allocate the room for the return value. */ - errno = EINVAL; - return NULL; - } - - if (name[0] == '\0') - { - /* As per Single Unix Specification V2 we must return an error if - * the name argument points to an empty string. */ - errno = ENOENT; - return NULL; - } - - #ifdef PATH_MAX - path_max = PATH_MAX; - #else - path_max = pathconf(name, _PC_PATH_MAX); - - if (path_max <= 0) - { - path_max = 1024; - } - #endif - - rpath = resolved ? g_alloca(path_max) : g_malloc(path_max); - rpath_limit = rpath + path_max; - - if (name[0] != G_DIR_SEPARATOR) - { - if (!getcwd(rpath, path_max)) - { - rpath[0] = '\0'; - goto error; - } - - dest = strchr(rpath, '\0'); - } - else - { - rpath[0] = G_DIR_SEPARATOR; - dest = rpath + 1; - } - - for (start = end = name; *start; start = end) - { - struct stat st; - int n; - - /* Skip sequence of multiple path-separators. */ - while (*start == G_DIR_SEPARATOR) - { - ++start; - } - - /* Find end of path component. */ - for (end = start; *end && *end != G_DIR_SEPARATOR; ++end) - { - /* Nothing. */; - } - - if (end - start == 0) - { - break; - } - else if (end - start == 1 && start[0] == '.') - { - /* nothing */; - } - else if (end - start == 2 && start[0] == '.' && start[1] == '.') - { - /* Back up to previous component, ignore if at root already. */ - if (dest > rpath + 1) - { - while ((--dest)[-1] != G_DIR_SEPARATOR) - { - /* Nothing. */; - } - } - } - else - { - size_t new_size; - - if (dest[-1] != G_DIR_SEPARATOR) - { - *dest++ = G_DIR_SEPARATOR; - } - - if (dest + (end - start) >= rpath_limit) - { - char* new_rpath; - ptrdiff_t dest_offset = dest - rpath; - - if (resolved) - { - #ifdef ENAMETOOLONG - errno = ENAMETOOLONG; - #else - /* Uh... just pick something */ - errno = EINVAL; - #endif - - if (dest > rpath + 1) - { - dest--; - } - - *dest = '\0'; - goto error; - } - - new_size = rpath_limit - rpath; - - if (end - start + 1 > path_max) - { - new_size += end - start + 1; - } - else - { - new_size += path_max; - } - - new_rpath = (char*) realloc(rpath, new_size); - - if (new_rpath == NULL) - { - goto error; - } - - rpath = new_rpath; - rpath_limit = rpath + new_size; - - dest = rpath + dest_offset; - } - - memcpy(dest, start, end - start); - dest = dest + (end - start); - *dest = '\0'; - - if (stat(rpath, &st) < 0) - { - goto error; - } - - if (S_ISLNK(st.st_mode)) - { - char* buf = alloca(path_max); - size_t len; - - if (++num_links > MAXSYMLINKS) - { - errno = ELOOP; - goto error; - } - - n = readlink(rpath, buf, path_max); - - if (n < 0) - { - goto error; - } - - buf[n] = '\0'; - - - - if (!extra_buf) - { - extra_buf = g_alloca(path_max); - } - - len = strlen(end); - - if ((long int) (n + len) >= path_max) - { - #ifdef ENAMETOOLONG - errno = ENAMETOOLONG; - #else - /* Uh... just pick something */ - errno = EINVAL; - #endif - - goto error; - } - - /* Careful here, end may be a pointer into extra_buf... */ - g_memmove(&extra_buf[n], end, len + 1); - name = end = memcpy(extra_buf, buf, n); - - if (buf[0] == G_DIR_SEPARATOR) - { - dest = rpath + 1; /* It's an absolute symlink */ - } - else - { - /* Back up to previous component, ignore if at root already: */ - if (dest > rpath + 1) - { - while ((--dest)[-1] != G_DIR_SEPARATOR) - { - /* Nothing. */; - } - } - } - } - } - } - - if (dest > rpath + 1 && dest[-1] == G_DIR_SEPARATOR) - { - --dest; - } - - *dest = '\0'; - - return resolved ? memcpy(resolved, rpath, dest - rpath + 1) : rpath; - - error: - - if (resolved) - { - strcpy(resolved, rpath); - } - else - { - g_free(rpath); - } - - return NULL; -} - -char* menu_canonicalize_file_name(const char* name, gboolean allow_missing_basename) -{ - char* retval; - - retval = menu_realpath(name, NULL); - - /* We could avoid some system calls by using the second - * argument to realpath() instead of doing realpath - * all over again, but who cares really. we'll see if - * it's ever in a profile. - */ - if (allow_missing_basename && retval == NULL) - { - char* dirname; - char* canonical_dirname; - - dirname = g_path_get_dirname(name); - canonical_dirname = menu_realpath(dirname, NULL); - g_free(dirname); - - if (canonical_dirname) - { - char* basename; - - basename = g_path_get_basename(name); - retval = g_build_filename(canonical_dirname, basename, NULL); - g_free(basename); - g_free(canonical_dirname); - } - } - - return retval; -} diff --git a/libmenu/canonicalize.h b/libmenu/canonicalize.h deleted file mode 100644 index bb291cf..0000000 --- a/libmenu/canonicalize.h +++ /dev/null @@ -1,34 +0,0 @@ -/* Return the canonical absolute name of a given file. - * Copyright (C) 1996-2001, 2002 Free Software Foundation, Inc. - * This file is part of the GNU C Library. - * - * Copyright (C) 2002 Red Hat, Inc. (trivial port to GLib) - * - * The GNU C 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.1 of the License, or (at your option) any later version. - * - * The GNU C 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 the GNU C Library; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA. - */ - -#ifndef MATE_CANONICALIZE_H -#define MATE_CANONICALIZE_H - -#include - -G_BEGIN_DECLS - -char* menu_canonicalize_file_name(const char* name, gboolean allow_missing_basename); - -G_END_DECLS - -#endif /* MATE_CANONICALIZE_H */ diff --git a/libmenu/entry-directories.c b/libmenu/entry-directories.c index 2a21807..33b68eb 100644 --- a/libmenu/entry-directories.c +++ b/libmenu/entry-directories.c @@ -25,10 +25,10 @@ #include #include #include +#include #include "menu-util.h" #include "menu-monitor.h" -#include "canonicalize.h" typedef struct CachedDir CachedDir; typedef struct CachedDirMonitor CachedDirMonitor; @@ -731,7 +731,7 @@ static EntryDirectory* entry_directory_new_full(DesktopEntryType entry_type, con path, is_legacy ? "" : ""); - canonical = menu_canonicalize_file_name (path, FALSE); + canonical = realpath (path, NULL); if (canonical == NULL) { menu_verbose ("Failed to canonicalize \"%s\": %s\n", diff --git a/libmenu/matemenu-tree.c b/libmenu/matemenu-tree.c index 4ce4d55..f65a2be 100644 --- a/libmenu/matemenu-tree.c +++ b/libmenu/matemenu-tree.c @@ -24,11 +24,11 @@ #include #include #include +#include #include "menu-layout.h" #include "menu-monitor.h" #include "menu-util.h" -#include "canonicalize.h" /* private */ typedef struct MateMenuTreeItem MateMenuTreeItem; @@ -333,7 +333,7 @@ static gboolean canonicalize_path (MateMenuTree *tree, const char *path) { - tree->canonical_path = menu_canonicalize_file_name (path, FALSE); + tree->canonical_path = realpath (path, NULL); if (tree->canonical_path) { tree->canonical = TRUE; @@ -1887,7 +1887,7 @@ load_merge_file (MateMenuTree *tree, if (!is_canonical) { - canonical = freeme = menu_canonicalize_file_name (filename, FALSE); + canonical = freeme = realpath (filename, NULL); if (canonical == NULL) { if (add_monitor) @@ -1982,7 +1982,7 @@ compare_basedir_to_config_dir (const char *canonical_basedir, retval = FALSE; - canonical_menus_dir = menu_canonicalize_file_name (dirname, FALSE); + canonical_menus_dir = realpath (dirname, NULL); if (canonical_menus_dir != NULL && strcmp (canonical_basedir, canonical_menus_dir) == 0) { @@ -2056,7 +2056,7 @@ static gboolean load_parent_merge_file(MateMenuTree* tree, GHashTable* loaded_me basedir = menu_layout_node_root_get_basedir(root); menu_name = menu_layout_node_root_get_name(root); - canonical_basedir = menu_canonicalize_file_name(basedir, FALSE); + canonical_basedir = realpath (basedir, NULL); if (canonical_basedir == NULL) { diff --git a/libmenu/menu-layout.c b/libmenu/menu-layout.c index 30d11b3..93ee6db 100644 --- a/libmenu/menu-layout.c +++ b/libmenu/menu-layout.c @@ -29,7 +29,6 @@ #include #include -#include "canonicalize.h" #include "entry-directories.h" #include "menu-util.h" -- cgit v1.2.1