diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-06 01:16:24 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-06 01:16:24 +0000 |
commit | 9221dca64f0c8b5de72727491e41cf63e902eaab (patch) | |
tree | d8cbbf520eb4b5c656a54b2e36947008dcb751ad /gl/lib/getcwd-lgpl.c | |
parent | Initial commit. (diff) | |
download | man-db-upstream.tar.xz man-db-upstream.zip |
Adding upstream version 2.8.5.upstream/2.8.5upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'gl/lib/getcwd-lgpl.c')
-rw-r--r-- | gl/lib/getcwd-lgpl.c | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/gl/lib/getcwd-lgpl.c b/gl/lib/getcwd-lgpl.c new file mode 100644 index 0000000..b224cfc --- /dev/null +++ b/gl/lib/getcwd-lgpl.c @@ -0,0 +1,126 @@ +/* Copyright (C) 2011-2019 Free Software Foundation, Inc. + This file is part of gnulib. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +/* Specification */ +#include <unistd.h> + +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +#if GNULIB_GETCWD +/* Favor GPL getcwd.c if both getcwd and getcwd-lgpl modules are in use. */ +typedef int dummy; +#else + +/* Get the name of the current working directory, and put it in SIZE + bytes of BUF. Returns NULL if the directory couldn't be determined + (perhaps because the absolute name was longer than PATH_MAX, or + because of missing read/search permissions on parent directories) + or SIZE was too small. If successful, returns BUF. If BUF is + NULL, an array is allocated with 'malloc'; the array is SIZE bytes + long, unless SIZE == 0, in which case it is as big as + necessary. */ + +# undef getcwd +char * +rpl_getcwd (char *buf, size_t size) +{ + char *ptr; + char *result; + + /* Handle single size operations. */ + if (buf) + { + if (!size) + { + errno = EINVAL; + return NULL; + } + return getcwd (buf, size); + } + + if (size) + { + buf = malloc (size); + if (!buf) + { + errno = ENOMEM; + return NULL; + } + result = getcwd (buf, size); + if (!result) + { + int saved_errno = errno; + free (buf); + errno = saved_errno; + } + return result; + } + + /* Flexible sizing requested. Avoid over-allocation for the common + case of a name that fits within a 4k page, minus some space for + local variables, to be sure we don't skip over a guard page. */ + { + char tmp[4032]; + size = sizeof tmp; + ptr = getcwd (tmp, size); + if (ptr) + { + result = strdup (ptr); + if (!result) + errno = ENOMEM; + return result; + } + if (errno != ERANGE) + return NULL; + } + + /* My what a large directory name we have. */ + do + { + size <<= 1; + ptr = realloc (buf, size); + if (ptr == NULL) + { + free (buf); + errno = ENOMEM; + return NULL; + } + buf = ptr; + result = getcwd (buf, size); + } + while (!result && errno == ERANGE); + + if (!result) + { + int saved_errno = errno; + free (buf); + errno = saved_errno; + } + else + { + /* Trim to fit, if possible. */ + result = realloc (buf, strlen (buf) + 1); + if (!result) + result = buf; + } + return result; +} + +#endif |