diff options
author | Pino Toscano <[email protected]> | 2018-12-25 16:44:19 +0100 |
---|---|---|
committer | raveit65 <[email protected]> | 2018-12-30 11:38:27 +0100 |
commit | 82108808f13d056b3904c1717658a306a4aba2dd (patch) | |
tree | b9280444bbef3c1c14ef2e7ce2d96edc3afbb337 /libmenu/canonicalize.c | |
parent | 96505c413183f8569fbb45c5d39cfcb7a95598cd (diff) | |
download | mate-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
Diffstat (limited to 'libmenu/canonicalize.c')
-rw-r--r-- | libmenu/canonicalize.c | 330 |
1 files changed, 0 insertions, 330 deletions
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; -} |