diff options
| author | Daniel Colascione | 2019-06-23 18:19:08 -0700 |
|---|---|---|
| committer | Daniel Colascione | 2019-06-23 18:19:08 -0700 |
| commit | b9ac4f815ebaa1acb0d045fe9583f665efa6f628 (patch) | |
| tree | f2bfcf685bb9f83a67c5f70fe8e4f65ef16d8690 /lib | |
| parent | f3b1b5fb5034de026adc41cf2403cff42f4a0b67 (diff) | |
| download | emacs-b9ac4f815ebaa1acb0d045fe9583f665efa6f628.tar.gz emacs-b9ac4f815ebaa1acb0d045fe9583f665efa6f628.zip | |
Fix locating pdump by symlink
* admin/merge-gnulib (GNULIB_MODULES): Add canonicalize-lgpl module
* build-aux/config.guess, build-aux/gitlog-to-changelog,
build-aux/update-copyright, lib/canonicalize-lgpl.c,
lib/gnulib.mk.in, lib/malloca.c, lib/malloca.h, lib/pathmax.h,
m4/canonicalize.m4, m4/double-slash-root.m4, m4/gnulib-comp.m4,
m4/malloca.m4, my/pathmax.4: copy from GNUlib or regenerate from
update
* src/emacs.c: find dump by canonical path
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/canonicalize-lgpl.c | 428 | ||||
| -rw-r--r-- | lib/gnulib.mk.in | 38 | ||||
| -rw-r--r-- | lib/malloca.c | 105 | ||||
| -rw-r--r-- | lib/malloca.h | 127 | ||||
| -rw-r--r-- | lib/pathmax.h | 83 |
5 files changed, 781 insertions, 0 deletions
diff --git a/lib/canonicalize-lgpl.c b/lib/canonicalize-lgpl.c new file mode 100644 index 00000000000..4d1be6dc24b --- /dev/null +++ b/lib/canonicalize-lgpl.c | |||
| @@ -0,0 +1,428 @@ | |||
| 1 | /* Return the canonical absolute name of a given file. | ||
| 2 | Copyright (C) 1996-2019 Free Software Foundation, Inc. | ||
| 3 | This file is part of the GNU C Library. | ||
| 4 | |||
| 5 | This program is free software: you can redistribute it and/or modify | ||
| 6 | it under the terms of the GNU General Public License as published by | ||
| 7 | the Free Software Foundation; either version 3 of the License, or | ||
| 8 | (at your option) any later version. | ||
| 9 | |||
| 10 | This program is distributed in the hope that it will be useful, | ||
| 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | GNU General Public License for more details. | ||
| 14 | |||
| 15 | You should have received a copy of the GNU General Public License | ||
| 16 | along with this program. If not, see <https://www.gnu.org/licenses/>. */ | ||
| 17 | |||
| 18 | #ifndef _LIBC | ||
| 19 | /* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc | ||
| 20 | optimizes away the name == NULL test below. */ | ||
| 21 | # define _GL_ARG_NONNULL(params) | ||
| 22 | |||
| 23 | # define _GL_USE_STDLIB_ALLOC 1 | ||
| 24 | # include <config.h> | ||
| 25 | #endif | ||
| 26 | |||
| 27 | #if !HAVE_CANONICALIZE_FILE_NAME || !FUNC_REALPATH_WORKS || defined _LIBC | ||
| 28 | |||
| 29 | /* Specification. */ | ||
| 30 | #include <stdlib.h> | ||
| 31 | |||
| 32 | #include <alloca.h> | ||
| 33 | #include <string.h> | ||
| 34 | #include <unistd.h> | ||
| 35 | #include <limits.h> | ||
| 36 | #if HAVE_SYS_PARAM_H || defined _LIBC | ||
| 37 | # include <sys/param.h> | ||
| 38 | #endif | ||
| 39 | #include <sys/stat.h> | ||
| 40 | #include <errno.h> | ||
| 41 | #include <stddef.h> | ||
| 42 | |||
| 43 | #ifdef _LIBC | ||
| 44 | # include <shlib-compat.h> | ||
| 45 | #else | ||
| 46 | # define SHLIB_COMPAT(lib, introduced, obsoleted) 0 | ||
| 47 | # define versioned_symbol(lib, local, symbol, version) extern int dummy | ||
| 48 | # define compat_symbol(lib, local, symbol, version) | ||
| 49 | # define weak_alias(local, symbol) | ||
| 50 | # define __canonicalize_file_name canonicalize_file_name | ||
| 51 | # define __realpath realpath | ||
| 52 | # include "pathmax.h" | ||
| 53 | # include "malloca.h" | ||
| 54 | # include "dosname.h" | ||
| 55 | # if HAVE_GETCWD | ||
| 56 | # if IN_RELOCWRAPPER | ||
| 57 | /* When building the relocatable program wrapper, use the system's getcwd | ||
| 58 | function, not the gnulib override, otherwise we would get a link error. | ||
| 59 | */ | ||
| 60 | # undef getcwd | ||
| 61 | # endif | ||
| 62 | # if defined VMS && !defined getcwd | ||
| 63 | /* We want the directory in Unix syntax, not in VMS syntax. | ||
| 64 | The gnulib override of 'getcwd' takes 2 arguments; the original VMS | ||
| 65 | 'getcwd' takes 3 arguments. */ | ||
| 66 | # define __getcwd(buf, max) getcwd (buf, max, 0) | ||
| 67 | # else | ||
| 68 | # define __getcwd getcwd | ||
| 69 | # endif | ||
| 70 | # else | ||
| 71 | # define __getcwd(buf, max) getwd (buf) | ||
| 72 | # endif | ||
| 73 | # define __readlink readlink | ||
| 74 | # define __set_errno(e) errno = (e) | ||
| 75 | # ifndef MAXSYMLINKS | ||
| 76 | # ifdef SYMLOOP_MAX | ||
| 77 | # define MAXSYMLINKS SYMLOOP_MAX | ||
| 78 | # else | ||
| 79 | # define MAXSYMLINKS 20 | ||
| 80 | # endif | ||
| 81 | # endif | ||
| 82 | #endif | ||
| 83 | |||
| 84 | #ifndef DOUBLE_SLASH_IS_DISTINCT_ROOT | ||
| 85 | # define DOUBLE_SLASH_IS_DISTINCT_ROOT 0 | ||
| 86 | #endif | ||
| 87 | |||
| 88 | /* Define this independently so that stdint.h is not a prerequisite. */ | ||
| 89 | #ifndef SIZE_MAX | ||
| 90 | # define SIZE_MAX ((size_t) -1) | ||
| 91 | #endif | ||
| 92 | |||
| 93 | #if !FUNC_REALPATH_WORKS || defined _LIBC | ||
| 94 | |||
| 95 | static void | ||
| 96 | alloc_failed (void) | ||
| 97 | { | ||
| 98 | #if defined _WIN32 && ! defined __CYGWIN__ | ||
| 99 | /* Avoid errno problem without using the malloc or realloc modules; see: | ||
| 100 | https://lists.gnu.org/r/bug-gnulib/2016-08/msg00025.html */ | ||
| 101 | errno = ENOMEM; | ||
| 102 | #endif | ||
| 103 | } | ||
| 104 | |||
| 105 | /* Return the canonical absolute name of file NAME. A canonical name | ||
| 106 | does not contain any ".", ".." components nor any repeated path | ||
| 107 | separators ('/') or symlinks. All path components must exist. If | ||
| 108 | RESOLVED is null, the result is malloc'd; otherwise, if the | ||
| 109 | canonical name is PATH_MAX chars or more, returns null with 'errno' | ||
| 110 | set to ENAMETOOLONG; if the name fits in fewer than PATH_MAX chars, | ||
| 111 | returns the name in RESOLVED. If the name cannot be resolved and | ||
| 112 | RESOLVED is non-NULL, it contains the path of the first component | ||
| 113 | that cannot be resolved. If the path can be resolved, RESOLVED | ||
| 114 | holds the same value as the value returned. */ | ||
| 115 | |||
| 116 | char * | ||
| 117 | __realpath (const char *name, char *resolved) | ||
| 118 | { | ||
| 119 | char *rpath, *dest, *extra_buf = NULL; | ||
| 120 | const char *start, *end, *rpath_limit; | ||
| 121 | long int path_max; | ||
| 122 | int num_links = 0; | ||
| 123 | size_t prefix_len; | ||
| 124 | |||
| 125 | if (name == NULL) | ||
| 126 | { | ||
| 127 | /* As per Single Unix Specification V2 we must return an error if | ||
| 128 | either parameter is a null pointer. We extend this to allow | ||
| 129 | the RESOLVED parameter to be NULL in case the we are expected to | ||
| 130 | allocate the room for the return value. */ | ||
| 131 | __set_errno (EINVAL); | ||
| 132 | return NULL; | ||
| 133 | } | ||
| 134 | |||
| 135 | if (name[0] == '\0') | ||
| 136 | { | ||
| 137 | /* As per Single Unix Specification V2 we must return an error if | ||
| 138 | the name argument points to an empty string. */ | ||
| 139 | __set_errno (ENOENT); | ||
| 140 | return NULL; | ||
| 141 | } | ||
| 142 | |||
| 143 | #ifdef PATH_MAX | ||
| 144 | path_max = PATH_MAX; | ||
| 145 | #else | ||
| 146 | path_max = pathconf (name, _PC_PATH_MAX); | ||
| 147 | if (path_max <= 0) | ||
| 148 | path_max = 8192; | ||
| 149 | #endif | ||
| 150 | |||
| 151 | if (resolved == NULL) | ||
| 152 | { | ||
| 153 | rpath = malloc (path_max); | ||
| 154 | if (rpath == NULL) | ||
| 155 | { | ||
| 156 | alloc_failed (); | ||
| 157 | return NULL; | ||
| 158 | } | ||
| 159 | } | ||
| 160 | else | ||
| 161 | rpath = resolved; | ||
| 162 | rpath_limit = rpath + path_max; | ||
| 163 | |||
| 164 | /* This is always zero for Posix hosts, but can be 2 for MS-Windows | ||
| 165 | and MS-DOS X:/foo/bar file names. */ | ||
| 166 | prefix_len = FILE_SYSTEM_PREFIX_LEN (name); | ||
| 167 | |||
| 168 | if (!IS_ABSOLUTE_FILE_NAME (name)) | ||
| 169 | { | ||
| 170 | if (!__getcwd (rpath, path_max)) | ||
| 171 | { | ||
| 172 | rpath[0] = '\0'; | ||
| 173 | goto error; | ||
| 174 | } | ||
| 175 | dest = strchr (rpath, '\0'); | ||
| 176 | start = name; | ||
| 177 | prefix_len = FILE_SYSTEM_PREFIX_LEN (rpath); | ||
| 178 | } | ||
| 179 | else | ||
| 180 | { | ||
| 181 | dest = rpath; | ||
| 182 | if (prefix_len) | ||
| 183 | { | ||
| 184 | memcpy (rpath, name, prefix_len); | ||
| 185 | dest += prefix_len; | ||
| 186 | } | ||
| 187 | *dest++ = '/'; | ||
| 188 | if (DOUBLE_SLASH_IS_DISTINCT_ROOT) | ||
| 189 | { | ||
| 190 | if (ISSLASH (name[1]) && !ISSLASH (name[2]) && !prefix_len) | ||
| 191 | *dest++ = '/'; | ||
| 192 | *dest = '\0'; | ||
| 193 | } | ||
| 194 | start = name + prefix_len; | ||
| 195 | } | ||
| 196 | |||
| 197 | for (end = start; *start; start = end) | ||
| 198 | { | ||
| 199 | #ifdef _LIBC | ||
| 200 | struct stat64 st; | ||
| 201 | #else | ||
| 202 | struct stat st; | ||
| 203 | #endif | ||
| 204 | |||
| 205 | /* Skip sequence of multiple path-separators. */ | ||
| 206 | while (ISSLASH (*start)) | ||
| 207 | ++start; | ||
| 208 | |||
| 209 | /* Find end of path component. */ | ||
| 210 | for (end = start; *end && !ISSLASH (*end); ++end) | ||
| 211 | /* Nothing. */; | ||
| 212 | |||
| 213 | if (end - start == 0) | ||
| 214 | break; | ||
| 215 | else if (end - start == 1 && start[0] == '.') | ||
| 216 | /* nothing */; | ||
| 217 | else if (end - start == 2 && start[0] == '.' && start[1] == '.') | ||
| 218 | { | ||
| 219 | /* Back up to previous component, ignore if at root already. */ | ||
| 220 | if (dest > rpath + prefix_len + 1) | ||
| 221 | for (--dest; dest > rpath && !ISSLASH (dest[-1]); --dest) | ||
| 222 | continue; | ||
| 223 | if (DOUBLE_SLASH_IS_DISTINCT_ROOT | ||
| 224 | && dest == rpath + 1 && !prefix_len | ||
| 225 | && ISSLASH (*dest) && !ISSLASH (dest[1])) | ||
| 226 | dest++; | ||
| 227 | } | ||
| 228 | else | ||
| 229 | { | ||
| 230 | size_t new_size; | ||
| 231 | |||
| 232 | if (!ISSLASH (dest[-1])) | ||
| 233 | *dest++ = '/'; | ||
| 234 | |||
| 235 | if (dest + (end - start) >= rpath_limit) | ||
| 236 | { | ||
| 237 | ptrdiff_t dest_offset = dest - rpath; | ||
| 238 | char *new_rpath; | ||
| 239 | |||
| 240 | if (resolved) | ||
| 241 | { | ||
| 242 | __set_errno (ENAMETOOLONG); | ||
| 243 | if (dest > rpath + prefix_len + 1) | ||
| 244 | dest--; | ||
| 245 | *dest = '\0'; | ||
| 246 | goto error; | ||
| 247 | } | ||
| 248 | new_size = rpath_limit - rpath; | ||
| 249 | if (end - start + 1 > path_max) | ||
| 250 | new_size += end - start + 1; | ||
| 251 | else | ||
| 252 | new_size += path_max; | ||
| 253 | new_rpath = (char *) realloc (rpath, new_size); | ||
| 254 | if (new_rpath == NULL) | ||
| 255 | { | ||
| 256 | alloc_failed (); | ||
| 257 | goto error; | ||
| 258 | } | ||
| 259 | rpath = new_rpath; | ||
| 260 | rpath_limit = rpath + new_size; | ||
| 261 | |||
| 262 | dest = rpath + dest_offset; | ||
| 263 | } | ||
| 264 | |||
| 265 | #ifdef _LIBC | ||
| 266 | dest = __mempcpy (dest, start, end - start); | ||
| 267 | #else | ||
| 268 | memcpy (dest, start, end - start); | ||
| 269 | dest += end - start; | ||
| 270 | #endif | ||
| 271 | *dest = '\0'; | ||
| 272 | |||
| 273 | /* FIXME: if lstat fails with errno == EOVERFLOW, | ||
| 274 | the entry exists. */ | ||
| 275 | #ifdef _LIBC | ||
| 276 | if (__lxstat64 (_STAT_VER, rpath, &st) < 0) | ||
| 277 | #else | ||
| 278 | if (lstat (rpath, &st) < 0) | ||
| 279 | #endif | ||
| 280 | goto error; | ||
| 281 | |||
| 282 | if (S_ISLNK (st.st_mode)) | ||
| 283 | { | ||
| 284 | char *buf; | ||
| 285 | size_t len; | ||
| 286 | ssize_t n; | ||
| 287 | |||
| 288 | if (++num_links > MAXSYMLINKS) | ||
| 289 | { | ||
| 290 | __set_errno (ELOOP); | ||
| 291 | goto error; | ||
| 292 | } | ||
| 293 | |||
| 294 | buf = malloca (path_max); | ||
| 295 | if (!buf) | ||
| 296 | { | ||
| 297 | __set_errno (ENOMEM); | ||
| 298 | goto error; | ||
| 299 | } | ||
| 300 | |||
| 301 | n = __readlink (rpath, buf, path_max - 1); | ||
| 302 | if (n < 0) | ||
| 303 | { | ||
| 304 | int saved_errno = errno; | ||
| 305 | freea (buf); | ||
| 306 | __set_errno (saved_errno); | ||
| 307 | goto error; | ||
| 308 | } | ||
| 309 | buf[n] = '\0'; | ||
| 310 | |||
| 311 | if (!extra_buf) | ||
| 312 | { | ||
| 313 | extra_buf = malloca (path_max); | ||
| 314 | if (!extra_buf) | ||
| 315 | { | ||
| 316 | freea (buf); | ||
| 317 | __set_errno (ENOMEM); | ||
| 318 | goto error; | ||
| 319 | } | ||
| 320 | } | ||
| 321 | |||
| 322 | len = strlen (end); | ||
| 323 | /* Check that n + len + 1 doesn't overflow and is <= path_max. */ | ||
| 324 | if (n >= SIZE_MAX - len || n + len >= path_max) | ||
| 325 | { | ||
| 326 | freea (buf); | ||
| 327 | __set_errno (ENAMETOOLONG); | ||
| 328 | goto error; | ||
| 329 | } | ||
| 330 | |||
| 331 | /* Careful here, end may be a pointer into extra_buf... */ | ||
| 332 | memmove (&extra_buf[n], end, len + 1); | ||
| 333 | name = end = memcpy (extra_buf, buf, n); | ||
| 334 | |||
| 335 | if (IS_ABSOLUTE_FILE_NAME (buf)) | ||
| 336 | { | ||
| 337 | size_t pfxlen = FILE_SYSTEM_PREFIX_LEN (buf); | ||
| 338 | |||
| 339 | if (pfxlen) | ||
| 340 | memcpy (rpath, buf, pfxlen); | ||
| 341 | dest = rpath + pfxlen; | ||
| 342 | *dest++ = '/'; /* It's an absolute symlink */ | ||
| 343 | if (DOUBLE_SLASH_IS_DISTINCT_ROOT) | ||
| 344 | { | ||
| 345 | if (ISSLASH (buf[1]) && !ISSLASH (buf[2]) && !pfxlen) | ||
| 346 | *dest++ = '/'; | ||
| 347 | *dest = '\0'; | ||
| 348 | } | ||
| 349 | /* Install the new prefix to be in effect hereafter. */ | ||
| 350 | prefix_len = pfxlen; | ||
| 351 | } | ||
| 352 | else | ||
| 353 | { | ||
| 354 | /* Back up to previous component, ignore if at root | ||
| 355 | already: */ | ||
| 356 | if (dest > rpath + prefix_len + 1) | ||
| 357 | for (--dest; dest > rpath && !ISSLASH (dest[-1]); --dest) | ||
| 358 | continue; | ||
| 359 | if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rpath + 1 | ||
| 360 | && ISSLASH (*dest) && !ISSLASH (dest[1]) && !prefix_len) | ||
| 361 | dest++; | ||
| 362 | } | ||
| 363 | } | ||
| 364 | else if (!S_ISDIR (st.st_mode) && *end != '\0') | ||
| 365 | { | ||
| 366 | __set_errno (ENOTDIR); | ||
| 367 | goto error; | ||
| 368 | } | ||
| 369 | } | ||
| 370 | } | ||
| 371 | if (dest > rpath + prefix_len + 1 && ISSLASH (dest[-1])) | ||
| 372 | --dest; | ||
| 373 | if (DOUBLE_SLASH_IS_DISTINCT_ROOT && dest == rpath + 1 && !prefix_len | ||
| 374 | && ISSLASH (*dest) && !ISSLASH (dest[1])) | ||
| 375 | dest++; | ||
| 376 | *dest = '\0'; | ||
| 377 | |||
| 378 | if (extra_buf) | ||
| 379 | freea (extra_buf); | ||
| 380 | |||
| 381 | return rpath; | ||
| 382 | |||
| 383 | error: | ||
| 384 | { | ||
| 385 | int saved_errno = errno; | ||
| 386 | if (extra_buf) | ||
| 387 | freea (extra_buf); | ||
| 388 | if (resolved == NULL) | ||
| 389 | free (rpath); | ||
| 390 | __set_errno (saved_errno); | ||
| 391 | } | ||
| 392 | return NULL; | ||
| 393 | } | ||
| 394 | versioned_symbol (libc, __realpath, realpath, GLIBC_2_3); | ||
| 395 | #endif /* !FUNC_REALPATH_WORKS || defined _LIBC */ | ||
| 396 | |||
| 397 | |||
| 398 | #if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_3) | ||
| 399 | char * | ||
| 400 | attribute_compat_text_section | ||
| 401 | __old_realpath (const char *name, char *resolved) | ||
| 402 | { | ||
| 403 | if (resolved == NULL) | ||
| 404 | { | ||
| 405 | __set_errno (EINVAL); | ||
| 406 | return NULL; | ||
| 407 | } | ||
| 408 | |||
| 409 | return __realpath (name, resolved); | ||
| 410 | } | ||
| 411 | compat_symbol (libc, __old_realpath, realpath, GLIBC_2_0); | ||
| 412 | #endif | ||
| 413 | |||
| 414 | |||
| 415 | char * | ||
| 416 | __canonicalize_file_name (const char *name) | ||
| 417 | { | ||
| 418 | return __realpath (name, NULL); | ||
| 419 | } | ||
| 420 | weak_alias (__canonicalize_file_name, canonicalize_file_name) | ||
| 421 | |||
| 422 | #else | ||
| 423 | |||
| 424 | /* This declaration is solely to ensure that after preprocessing | ||
| 425 | this file is never empty. */ | ||
| 426 | typedef int dummy; | ||
| 427 | |||
| 428 | #endif | ||
diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in index 6e817fa6897..d0bef0bd5de 100644 --- a/lib/gnulib.mk.in +++ b/lib/gnulib.mk.in | |||
| @@ -72,6 +72,7 @@ | |||
| 72 | # byteswap \ | 72 | # byteswap \ |
| 73 | # c-ctype \ | 73 | # c-ctype \ |
| 74 | # c-strcase \ | 74 | # c-strcase \ |
| 75 | # canonicalize-lgpl \ | ||
| 75 | # careadlinkat \ | 76 | # careadlinkat \ |
| 76 | # close-stream \ | 77 | # close-stream \ |
| 77 | # copy-file-range \ | 78 | # copy-file-range \ |
| @@ -484,6 +485,8 @@ GTK_CFLAGS = @GTK_CFLAGS@ | |||
| 484 | GTK_LIBS = @GTK_LIBS@ | 485 | GTK_LIBS = @GTK_LIBS@ |
| 485 | GTK_OBJ = @GTK_OBJ@ | 486 | GTK_OBJ = @GTK_OBJ@ |
| 486 | GZIP_PROG = @GZIP_PROG@ | 487 | GZIP_PROG = @GZIP_PROG@ |
| 488 | HARFBUZZ_CFLAGS = @HARFBUZZ_CFLAGS@ | ||
| 489 | HARFBUZZ_LIBS = @HARFBUZZ_LIBS@ | ||
| 487 | HAVE_ALLOCA_H = @HAVE_ALLOCA_H@ | 490 | HAVE_ALLOCA_H = @HAVE_ALLOCA_H@ |
| 488 | HAVE_ALPHASORT = @HAVE_ALPHASORT@ | 491 | HAVE_ALPHASORT = @HAVE_ALPHASORT@ |
| 489 | HAVE_ATOLL = @HAVE_ATOLL@ | 492 | HAVE_ATOLL = @HAVE_ATOLL@ |
| @@ -1105,6 +1108,7 @@ pdfdir = @pdfdir@ | |||
| 1105 | prefix = @prefix@ | 1108 | prefix = @prefix@ |
| 1106 | program_transform_name = @program_transform_name@ | 1109 | program_transform_name = @program_transform_name@ |
| 1107 | psdir = @psdir@ | 1110 | psdir = @psdir@ |
| 1111 | runstatedir = @runstatedir@ | ||
| 1108 | sbindir = @sbindir@ | 1112 | sbindir = @sbindir@ |
| 1109 | sharedstatedir = @sharedstatedir@ | 1113 | sharedstatedir = @sharedstatedir@ |
| 1110 | srcdir = @srcdir@ | 1114 | srcdir = @srcdir@ |
| @@ -1243,6 +1247,17 @@ libgnu_a_SOURCES += c-strcase.h c-strcasecmp.c c-strncasecmp.c | |||
| 1243 | endif | 1247 | endif |
| 1244 | ## end gnulib module c-strcase | 1248 | ## end gnulib module c-strcase |
| 1245 | 1249 | ||
| 1250 | ## begin gnulib module canonicalize-lgpl | ||
| 1251 | ifeq (,$(OMIT_GNULIB_MODULE_canonicalize-lgpl)) | ||
| 1252 | |||
| 1253 | |||
| 1254 | EXTRA_DIST += canonicalize-lgpl.c | ||
| 1255 | |||
| 1256 | EXTRA_libgnu_a_SOURCES += canonicalize-lgpl.c | ||
| 1257 | |||
| 1258 | endif | ||
| 1259 | ## end gnulib module canonicalize-lgpl | ||
| 1260 | |||
| 1246 | ## begin gnulib module careadlinkat | 1261 | ## begin gnulib module careadlinkat |
| 1247 | ifeq (,$(OMIT_GNULIB_MODULE_careadlinkat)) | 1262 | ifeq (,$(OMIT_GNULIB_MODULE_careadlinkat)) |
| 1248 | 1263 | ||
| @@ -1980,6 +1995,18 @@ EXTRA_libgnu_a_SOURCES += lstat.c | |||
| 1980 | endif | 1995 | endif |
| 1981 | ## end gnulib module lstat | 1996 | ## end gnulib module lstat |
| 1982 | 1997 | ||
| 1998 | ## begin gnulib module malloca | ||
| 1999 | ifeq (,$(OMIT_GNULIB_MODULE_malloca)) | ||
| 2000 | |||
| 2001 | ifneq (,$(gl_GNULIB_ENABLED_malloca)) | ||
| 2002 | libgnu_a_SOURCES += malloca.c | ||
| 2003 | |||
| 2004 | endif | ||
| 2005 | EXTRA_DIST += malloca.h | ||
| 2006 | |||
| 2007 | endif | ||
| 2008 | ## end gnulib module malloca | ||
| 2009 | |||
| 1983 | ## begin gnulib module memmem-simple | 2010 | ## begin gnulib module memmem-simple |
| 1984 | ifeq (,$(OMIT_GNULIB_MODULE_memmem-simple)) | 2011 | ifeq (,$(OMIT_GNULIB_MODULE_memmem-simple)) |
| 1985 | 2012 | ||
| @@ -2079,6 +2106,17 @@ EXTRA_DIST += openat.h | |||
| 2079 | endif | 2106 | endif |
| 2080 | ## end gnulib module openat-h | 2107 | ## end gnulib module openat-h |
| 2081 | 2108 | ||
| 2109 | ## begin gnulib module pathmax | ||
| 2110 | ifeq (,$(OMIT_GNULIB_MODULE_pathmax)) | ||
| 2111 | |||
| 2112 | ifneq (,$(gl_GNULIB_ENABLED_pathmax)) | ||
| 2113 | |||
| 2114 | endif | ||
| 2115 | EXTRA_DIST += pathmax.h | ||
| 2116 | |||
| 2117 | endif | ||
| 2118 | ## end gnulib module pathmax | ||
| 2119 | |||
| 2082 | ## begin gnulib module pipe2 | 2120 | ## begin gnulib module pipe2 |
| 2083 | ifeq (,$(OMIT_GNULIB_MODULE_pipe2)) | 2121 | ifeq (,$(OMIT_GNULIB_MODULE_pipe2)) |
| 2084 | 2122 | ||
diff --git a/lib/malloca.c b/lib/malloca.c new file mode 100644 index 00000000000..f60c5fb5d93 --- /dev/null +++ b/lib/malloca.c | |||
| @@ -0,0 +1,105 @@ | |||
| 1 | /* Safe automatic memory allocation. | ||
| 2 | Copyright (C) 2003, 2006-2007, 2009-2019 Free Software Foundation, Inc. | ||
| 3 | Written by Bruno Haible <bruno@clisp.org>, 2003, 2018. | ||
| 4 | |||
| 5 | This program is free software; you can redistribute it and/or modify | ||
| 6 | it under the terms of the GNU General Public License as published by | ||
| 7 | the Free Software Foundation; either version 3, or (at your option) | ||
| 8 | any later version. | ||
| 9 | |||
| 10 | This program is distributed in the hope that it will be useful, | ||
| 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | GNU General Public License for more details. | ||
| 14 | |||
| 15 | You should have received a copy of the GNU General Public License | ||
| 16 | along with this program; if not, see <https://www.gnu.org/licenses/>. */ | ||
| 17 | |||
| 18 | #define _GL_USE_STDLIB_ALLOC 1 | ||
| 19 | #include <config.h> | ||
| 20 | |||
| 21 | /* Specification. */ | ||
| 22 | #include "malloca.h" | ||
| 23 | |||
| 24 | #include "verify.h" | ||
| 25 | |||
| 26 | /* The speed critical point in this file is freea() applied to an alloca() | ||
| 27 | result: it must be fast, to match the speed of alloca(). The speed of | ||
| 28 | mmalloca() and freea() in the other case are not critical, because they | ||
| 29 | are only invoked for big memory sizes. | ||
| 30 | Here we use a bit in the address as an indicator, an idea by Ondřej Bílka. | ||
| 31 | malloca() can return three types of pointers: | ||
| 32 | - Pointers ≡ 0 mod 2*sa_alignment_max come from stack allocation. | ||
| 33 | - Pointers ≡ sa_alignment_max mod 2*sa_alignment_max come from heap | ||
| 34 | allocation. | ||
| 35 | - NULL comes from a failed heap allocation. */ | ||
| 36 | |||
| 37 | /* Type for holding very small pointer differences. */ | ||
| 38 | typedef unsigned char small_t; | ||
| 39 | /* Verify that it is wide enough. */ | ||
| 40 | verify (2 * sa_alignment_max - 1 <= (small_t) -1); | ||
| 41 | |||
| 42 | void * | ||
| 43 | mmalloca (size_t n) | ||
| 44 | { | ||
| 45 | #if HAVE_ALLOCA | ||
| 46 | /* Allocate one more word, used to determine the address to pass to freea(), | ||
| 47 | and room for the alignment ≡ sa_alignment_max mod 2*sa_alignment_max. */ | ||
| 48 | size_t nplus = n + sizeof (small_t) + 2 * sa_alignment_max - 1; | ||
| 49 | |||
| 50 | if (nplus >= n) | ||
| 51 | { | ||
| 52 | char *mem = (char *) malloc (nplus); | ||
| 53 | |||
| 54 | if (mem != NULL) | ||
| 55 | { | ||
| 56 | char *p = | ||
| 57 | (char *)((((uintptr_t)mem + sizeof (small_t) + sa_alignment_max - 1) | ||
| 58 | & ~(uintptr_t)(2 * sa_alignment_max - 1)) | ||
| 59 | + sa_alignment_max); | ||
| 60 | /* Here p >= mem + sizeof (small_t), | ||
| 61 | and p <= mem + sizeof (small_t) + 2 * sa_alignment_max - 1 | ||
| 62 | hence p + n <= mem + nplus. | ||
| 63 | So, the memory range [p, p+n) lies in the allocated memory range | ||
| 64 | [mem, mem + nplus). */ | ||
| 65 | ((small_t *) p)[-1] = p - mem; | ||
| 66 | /* p ≡ sa_alignment_max mod 2*sa_alignment_max. */ | ||
| 67 | return p; | ||
| 68 | } | ||
| 69 | } | ||
| 70 | /* Out of memory. */ | ||
| 71 | return NULL; | ||
| 72 | #else | ||
| 73 | # if !MALLOC_0_IS_NONNULL | ||
| 74 | if (n == 0) | ||
| 75 | n = 1; | ||
| 76 | # endif | ||
| 77 | return malloc (n); | ||
| 78 | #endif | ||
| 79 | } | ||
| 80 | |||
| 81 | #if HAVE_ALLOCA | ||
| 82 | void | ||
| 83 | freea (void *p) | ||
| 84 | { | ||
| 85 | /* Check argument. */ | ||
| 86 | if ((uintptr_t) p & (sa_alignment_max - 1)) | ||
| 87 | { | ||
| 88 | /* p was not the result of a malloca() call. Invalid argument. */ | ||
| 89 | abort (); | ||
| 90 | } | ||
| 91 | /* Determine whether p was a non-NULL pointer returned by mmalloca(). */ | ||
| 92 | if ((uintptr_t) p & sa_alignment_max) | ||
| 93 | { | ||
| 94 | void *mem = (char *) p - ((small_t *) p)[-1]; | ||
| 95 | free (mem); | ||
| 96 | } | ||
| 97 | } | ||
| 98 | #endif | ||
| 99 | |||
| 100 | /* | ||
| 101 | * Hey Emacs! | ||
| 102 | * Local Variables: | ||
| 103 | * coding: utf-8 | ||
| 104 | * End: | ||
| 105 | */ | ||
diff --git a/lib/malloca.h b/lib/malloca.h new file mode 100644 index 00000000000..d80c316caa9 --- /dev/null +++ b/lib/malloca.h | |||
| @@ -0,0 +1,127 @@ | |||
| 1 | /* Safe automatic memory allocation. | ||
| 2 | Copyright (C) 2003-2007, 2009-2019 Free Software Foundation, Inc. | ||
| 3 | Written by Bruno Haible <bruno@clisp.org>, 2003. | ||
| 4 | |||
| 5 | This program is free software; you can redistribute it and/or modify | ||
| 6 | it under the terms of the GNU General Public License as published by | ||
| 7 | the Free Software Foundation; either version 3, or (at your option) | ||
| 8 | any later version. | ||
| 9 | |||
| 10 | This program is distributed in the hope that it will be useful, | ||
| 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | GNU General Public License for more details. | ||
| 14 | |||
| 15 | You should have received a copy of the GNU General Public License | ||
| 16 | along with this program; if not, see <https://www.gnu.org/licenses/>. */ | ||
| 17 | |||
| 18 | #ifndef _MALLOCA_H | ||
| 19 | #define _MALLOCA_H | ||
| 20 | |||
| 21 | #include <alloca.h> | ||
| 22 | #include <stddef.h> | ||
| 23 | #include <stdlib.h> | ||
| 24 | #include <stdint.h> | ||
| 25 | |||
| 26 | #include "xalloc-oversized.h" | ||
| 27 | |||
| 28 | |||
| 29 | #ifdef __cplusplus | ||
| 30 | extern "C" { | ||
| 31 | #endif | ||
| 32 | |||
| 33 | |||
| 34 | /* safe_alloca(N) is equivalent to alloca(N) when it is safe to call | ||
| 35 | alloca(N); otherwise it returns NULL. It either returns N bytes of | ||
| 36 | memory allocated on the stack, that lasts until the function returns, | ||
| 37 | or NULL. | ||
| 38 | Use of safe_alloca should be avoided: | ||
| 39 | - inside arguments of function calls - undefined behaviour, | ||
| 40 | - in inline functions - the allocation may actually last until the | ||
| 41 | calling function returns. | ||
| 42 | */ | ||
| 43 | #if HAVE_ALLOCA | ||
| 44 | /* The OS usually guarantees only one guard page at the bottom of the stack, | ||
| 45 | and a page size can be as small as 4096 bytes. So we cannot safely | ||
| 46 | allocate anything larger than 4096 bytes. Also care for the possibility | ||
| 47 | of a few compiler-allocated temporary stack slots. | ||
| 48 | This must be a macro, not a function. */ | ||
| 49 | # define safe_alloca(N) ((N) < 4032 ? alloca (N) : NULL) | ||
| 50 | #else | ||
| 51 | # define safe_alloca(N) ((void) (N), NULL) | ||
| 52 | #endif | ||
| 53 | |||
| 54 | /* malloca(N) is a safe variant of alloca(N). It allocates N bytes of | ||
| 55 | memory allocated on the stack, that must be freed using freea() before | ||
| 56 | the function returns. Upon failure, it returns NULL. */ | ||
| 57 | #if HAVE_ALLOCA | ||
| 58 | # define malloca(N) \ | ||
| 59 | ((N) < 4032 - (2 * sa_alignment_max - 1) \ | ||
| 60 | ? (void *) (((uintptr_t) (char *) alloca ((N) + 2 * sa_alignment_max - 1) \ | ||
| 61 | + (2 * sa_alignment_max - 1)) \ | ||
| 62 | & ~(uintptr_t)(2 * sa_alignment_max - 1)) \ | ||
| 63 | : mmalloca (N)) | ||
| 64 | #else | ||
| 65 | # define malloca(N) \ | ||
| 66 | mmalloca (N) | ||
| 67 | #endif | ||
| 68 | extern void * mmalloca (size_t n); | ||
| 69 | |||
| 70 | /* Free a block of memory allocated through malloca(). */ | ||
| 71 | #if HAVE_ALLOCA | ||
| 72 | extern void freea (void *p); | ||
| 73 | #else | ||
| 74 | # define freea free | ||
| 75 | #endif | ||
| 76 | |||
| 77 | /* nmalloca(N,S) is an overflow-safe variant of malloca (N * S). | ||
| 78 | It allocates an array of N objects, each with S bytes of memory, | ||
| 79 | on the stack. S must be positive and N must be nonnegative. | ||
| 80 | The array must be freed using freea() before the function returns. */ | ||
| 81 | #define nmalloca(n, s) (xalloc_oversized (n, s) ? NULL : malloca ((n) * (s))) | ||
| 82 | |||
| 83 | |||
| 84 | #ifdef __cplusplus | ||
| 85 | } | ||
| 86 | #endif | ||
| 87 | |||
| 88 | |||
| 89 | /* ------------------- Auxiliary, non-public definitions ------------------- */ | ||
| 90 | |||
| 91 | /* Determine the alignment of a type at compile time. */ | ||
| 92 | #if defined __GNUC__ || defined __IBM__ALIGNOF__ | ||
| 93 | # define sa_alignof __alignof__ | ||
| 94 | #elif defined __cplusplus | ||
| 95 | template <class type> struct sa_alignof_helper { char __slot1; type __slot2; }; | ||
| 96 | # define sa_alignof(type) offsetof (sa_alignof_helper<type>, __slot2) | ||
| 97 | #elif defined __hpux | ||
| 98 | /* Work around a HP-UX 10.20 cc bug with enums constants defined as offsetof | ||
| 99 | values. */ | ||
| 100 | # define sa_alignof(type) (sizeof (type) <= 4 ? 4 : 8) | ||
| 101 | #elif defined _AIX | ||
| 102 | /* Work around an AIX 3.2.5 xlc bug with enums constants defined as offsetof | ||
| 103 | values. */ | ||
| 104 | # define sa_alignof(type) (sizeof (type) <= 4 ? 4 : 8) | ||
| 105 | #else | ||
| 106 | # define sa_alignof(type) offsetof (struct { char __slot1; type __slot2; }, __slot2) | ||
| 107 | #endif | ||
| 108 | |||
| 109 | enum | ||
| 110 | { | ||
| 111 | /* The desired alignment of memory allocations is the maximum alignment | ||
| 112 | among all elementary types. */ | ||
| 113 | sa_alignment_long = sa_alignof (long), | ||
| 114 | sa_alignment_double = sa_alignof (double), | ||
| 115 | #if HAVE_LONG_LONG_INT | ||
| 116 | sa_alignment_longlong = sa_alignof (long long), | ||
| 117 | #endif | ||
| 118 | sa_alignment_longdouble = sa_alignof (long double), | ||
| 119 | sa_alignment_max = ((sa_alignment_long - 1) | (sa_alignment_double - 1) | ||
| 120 | #if HAVE_LONG_LONG_INT | ||
| 121 | | (sa_alignment_longlong - 1) | ||
| 122 | #endif | ||
| 123 | | (sa_alignment_longdouble - 1) | ||
| 124 | ) + 1 | ||
| 125 | }; | ||
| 126 | |||
| 127 | #endif /* _MALLOCA_H */ | ||
diff --git a/lib/pathmax.h b/lib/pathmax.h new file mode 100644 index 00000000000..9463a1fb2c6 --- /dev/null +++ b/lib/pathmax.h | |||
| @@ -0,0 +1,83 @@ | |||
| 1 | /* Define PATH_MAX somehow. Requires sys/types.h. | ||
| 2 | Copyright (C) 1992, 1999, 2001, 2003, 2005, 2009-2019 Free Software | ||
| 3 | Foundation, Inc. | ||
| 4 | |||
| 5 | This program is free software; you can redistribute it and/or modify | ||
| 6 | it under the terms of the GNU General Public License as published by | ||
| 7 | the Free Software Foundation; either version 3, or (at your option) | ||
| 8 | any later version. | ||
| 9 | |||
| 10 | This program is distributed in the hope that it will be useful, | ||
| 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | GNU General Public License for more details. | ||
| 14 | |||
| 15 | You should have received a copy of the GNU General Public License | ||
| 16 | along with this program; if not, see <https://www.gnu.org/licenses/>. */ | ||
| 17 | |||
| 18 | #ifndef _PATHMAX_H | ||
| 19 | # define _PATHMAX_H | ||
| 20 | |||
| 21 | /* POSIX:2008 defines PATH_MAX to be the maximum number of bytes in a filename, | ||
| 22 | including the terminating NUL byte. | ||
| 23 | <http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html> | ||
| 24 | PATH_MAX is not defined on systems which have no limit on filename length, | ||
| 25 | such as GNU/Hurd. | ||
| 26 | |||
| 27 | This file does *not* define PATH_MAX always. Programs that use this file | ||
| 28 | can handle the GNU/Hurd case in several ways: | ||
| 29 | - Either with a package-wide handling, or with a per-file handling, | ||
| 30 | - Either through a | ||
| 31 | #ifdef PATH_MAX | ||
| 32 | or through a fallback like | ||
| 33 | #ifndef PATH_MAX | ||
| 34 | # define PATH_MAX 8192 | ||
| 35 | #endif | ||
| 36 | or through a fallback like | ||
| 37 | #ifndef PATH_MAX | ||
| 38 | # define PATH_MAX pathconf ("/", _PC_PATH_MAX) | ||
| 39 | #endif | ||
| 40 | */ | ||
| 41 | |||
| 42 | # include <unistd.h> | ||
| 43 | |||
| 44 | # include <limits.h> | ||
| 45 | |||
| 46 | # ifndef _POSIX_PATH_MAX | ||
| 47 | # define _POSIX_PATH_MAX 256 | ||
| 48 | # endif | ||
| 49 | |||
| 50 | /* Don't include sys/param.h if it already has been. */ | ||
| 51 | # if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN | ||
| 52 | # include <sys/param.h> | ||
| 53 | # endif | ||
| 54 | |||
| 55 | # if !defined PATH_MAX && defined MAXPATHLEN | ||
| 56 | # define PATH_MAX MAXPATHLEN | ||
| 57 | # endif | ||
| 58 | |||
| 59 | # ifdef __hpux | ||
| 60 | /* On HP-UX, PATH_MAX designates the maximum number of bytes in a filename, | ||
| 61 | *not* including the terminating NUL byte, and is set to 1023. | ||
| 62 | Additionally, when _XOPEN_SOURCE is defined to 500 or more, PATH_MAX is | ||
| 63 | not defined at all any more. */ | ||
| 64 | # undef PATH_MAX | ||
| 65 | # define PATH_MAX 1024 | ||
| 66 | # endif | ||
| 67 | |||
| 68 | # if defined _WIN32 && ! defined __CYGWIN__ | ||
| 69 | /* The page "Naming Files, Paths, and Namespaces" on msdn.microsoft.com, | ||
| 70 | section "Maximum Path Length Limitation", | ||
| 71 | <https://docs.microsoft.com/en-us/windows/desktop/FileIO/naming-a-file#maximum-path-length-limitation> | ||
| 72 | explains that the maximum size of a filename, including the terminating | ||
| 73 | NUL byte, is 260 = 3 + 256 + 1. | ||
| 74 | This is the same value as | ||
| 75 | - FILENAME_MAX in <stdio.h>, | ||
| 76 | - _MAX_PATH in <stdlib.h>, | ||
| 77 | - MAX_PATH in <windef.h>. | ||
| 78 | Undefine the original value, because mingw's <limits.h> gets it wrong. */ | ||
| 79 | # undef PATH_MAX | ||
| 80 | # define PATH_MAX 260 | ||
| 81 | # endif | ||
| 82 | |||
| 83 | #endif /* _PATHMAX_H */ | ||