summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPino Toscano <[email protected]>2018-12-25 16:44:19 +0100
committerraveit65 <[email protected]>2018-12-30 11:38:27 +0100
commit82108808f13d056b3904c1717658a306a4aba2dd (patch)
treeb9280444bbef3c1c14ef2e7ce2d96edc3afbb337
parent96505c413183f8569fbb45c5d39cfcb7a95598cd (diff)
downloadmate-menus-82108808f13d056b3904c1717658a306a4aba2dd.tar.bz2
mate-menus-82108808f13d056b3904c1717658a306a4aba2dd.tar.xz
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
-rw-r--r--libmenu/Makefile.am2
-rw-r--r--libmenu/canonicalize.c330
-rw-r--r--libmenu/canonicalize.h34
-rw-r--r--libmenu/entry-directories.c4
-rw-r--r--libmenu/matemenu-tree.c10
-rw-r--r--libmenu/menu-layout.c1
6 files changed, 7 insertions, 374 deletions
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 <config.h>
-
-#include "canonicalize.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <limits.h>
-#include <sys/param.h>
-#include <sys/stat.h>
-#include <errno.h>
-#include <stddef.h>
-
-#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 <glib.h>
-
-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 <errno.h>
#include <sys/types.h>
#include <dirent.h>
+#include <stdlib.h>
#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 ? "<yes>" : "<no>");
- 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 <gio/gio.h>
#include <string.h>
#include <errno.h>
+#include <stdlib.h>
#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 <unistd.h>
#include <errno.h>
-#include "canonicalize.h"
#include "entry-directories.h"
#include "menu-util.h"