diff options
| author | Paul Eggert | 2011-04-05 22:19:39 -0700 |
|---|---|---|
| committer | Paul Eggert | 2011-04-05 22:19:39 -0700 |
| commit | 41cf7d1aec986e1b92ca14231ac4ec242c233d45 (patch) | |
| tree | 7360e455dc2e0043a31fda1d29cc6323aa213104 /lib | |
| parent | 1e3cdd8228651f226beb6ac75453968a6c64feff (diff) | |
| parent | b69769da408705e40929b793d79d3bfe6a3a5a48 (diff) | |
| download | emacs-41cf7d1aec986e1b92ca14231ac4ec242c233d45.tar.gz emacs-41cf7d1aec986e1b92ca14231ac4ec242c233d45.zip | |
Fix more problems found by GCC 4.6.0's static checks.
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/allocator.h | 53 | ||||
| -rw-r--r-- | lib/careadlinkat.c | 175 | ||||
| -rw-r--r-- | lib/careadlinkat.h | 67 | ||||
| -rw-r--r-- | lib/gnulib.mk | 10 |
4 files changed, 304 insertions, 1 deletions
diff --git a/lib/allocator.h b/lib/allocator.h new file mode 100644 index 00000000000..4ac863b224c --- /dev/null +++ b/lib/allocator.h | |||
| @@ -0,0 +1,53 @@ | |||
| 1 | /* Memory allocators such as malloc+free. | ||
| 2 | |||
| 3 | Copyright (C) 2011 Free Software 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 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 <http://www.gnu.org/licenses/>. */ | ||
| 17 | |||
| 18 | /* Written by Paul Eggert. */ | ||
| 19 | |||
| 20 | #ifndef _GL_ALLOCATOR_H | ||
| 21 | |||
| 22 | #include <stddef.h> | ||
| 23 | |||
| 24 | /* An object describing a memory allocator family. */ | ||
| 25 | |||
| 26 | struct allocator | ||
| 27 | { | ||
| 28 | /* Do not use GCC attributes such as __attribute__ ((malloc)) with | ||
| 29 | the function types pointed at by these members, because these | ||
| 30 | attributes do not work with pointers to functions. See | ||
| 31 | <http://lists.gnu.org/archive/html/bug-gnulib/2011-04/msg00007.html>. */ | ||
| 32 | |||
| 33 | /* Call MALLOC to allocate memory, like 'malloc'. On failure MALLOC | ||
| 34 | should return NULL, though not necessarily set errno. When given | ||
| 35 | a zero size it may return NULL even if successful. */ | ||
| 36 | void *(*malloc) (size_t); | ||
| 37 | |||
| 38 | /* If nonnull, call REALLOC to reallocate memory, like 'realloc'. | ||
| 39 | On failure REALLOC should return NULL, though not necessarily set | ||
| 40 | errno. When given a zero size it may return NULL even if | ||
| 41 | successful. */ | ||
| 42 | void *(*realloc) (void *, size_t); | ||
| 43 | |||
| 44 | /* Call FREE to free memory, like 'free'. */ | ||
| 45 | void (*free) (void *); | ||
| 46 | |||
| 47 | /* If nonnull, call DIE if MALLOC or REALLOC fails. DIE should not | ||
| 48 | return. DIE can be used by code that detects memory overflow | ||
| 49 | while calculating sizes to be passed to MALLOC or REALLOC. */ | ||
| 50 | void (*die) (void); | ||
| 51 | }; | ||
| 52 | |||
| 53 | #endif | ||
diff --git a/lib/careadlinkat.c b/lib/careadlinkat.c new file mode 100644 index 00000000000..15ffe24c0f4 --- /dev/null +++ b/lib/careadlinkat.c | |||
| @@ -0,0 +1,175 @@ | |||
| 1 | /* Read symbolic links into a buffer without size limitation, relative to fd. | ||
| 2 | |||
| 3 | Copyright (C) 2001, 2003-2004, 2007, 2009-2011 Free Software Foundation, | ||
| 4 | Inc. | ||
| 5 | |||
| 6 | This program is free software: you can redistribute it and/or modify | ||
| 7 | it under the terms of the GNU General Public License as published by | ||
| 8 | the Free Software Foundation; either version 3 of the License, or | ||
| 9 | (at your option) any later version. | ||
| 10 | |||
| 11 | This program is distributed in the hope that it will be useful, | ||
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | GNU General Public License for more details. | ||
| 15 | |||
| 16 | You should have received a copy of the GNU General Public License | ||
| 17 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ | ||
| 18 | |||
| 19 | /* Written by Paul Eggert, Bruno Haible, and Jim Meyering. */ | ||
| 20 | |||
| 21 | #include <config.h> | ||
| 22 | |||
| 23 | #include "careadlinkat.h" | ||
| 24 | |||
| 25 | #include "allocator.h" | ||
| 26 | |||
| 27 | #include <errno.h> | ||
| 28 | #include <limits.h> | ||
| 29 | #include <stdlib.h> | ||
| 30 | #include <string.h> | ||
| 31 | #include <unistd.h> | ||
| 32 | |||
| 33 | /* Use the system functions, not the gnulib overrides, because this | ||
| 34 | module does not depend on GNU or POSIX semantics. */ | ||
| 35 | #undef malloc | ||
| 36 | #undef realloc | ||
| 37 | |||
| 38 | /* Define this independently so that stdint.h is not a prerequisite. */ | ||
| 39 | #ifndef SIZE_MAX | ||
| 40 | # define SIZE_MAX ((size_t) -1) | ||
| 41 | #endif | ||
| 42 | |||
| 43 | #ifndef SSIZE_MAX | ||
| 44 | # define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2)) | ||
| 45 | #endif | ||
| 46 | |||
| 47 | #if ! HAVE_READLINKAT | ||
| 48 | /* Ignore FD. Get the symbolic link value of FILENAME and put it into | ||
| 49 | BUFFER, with size BUFFER_SIZE. This function acts like readlink | ||
| 50 | but has readlinkat's signature. */ | ||
| 51 | ssize_t | ||
| 52 | careadlinkatcwd (int fd, char const *filename, char *buffer, | ||
| 53 | size_t buffer_size) | ||
| 54 | { | ||
| 55 | (void) fd; | ||
| 56 | return readlink (filename, buffer, buffer_size); | ||
| 57 | } | ||
| 58 | #endif | ||
| 59 | |||
| 60 | /* A standard allocator. For now, only careadlinkat needs this, but | ||
| 61 | perhaps it should be moved to the allocator module. */ | ||
| 62 | static struct allocator const standard_allocator = | ||
| 63 | { malloc, realloc, free, NULL }; | ||
| 64 | |||
| 65 | /* Assuming the current directory is FD, get the symbolic link value | ||
| 66 | of FILENAME as a null-terminated string and put it into a buffer. | ||
| 67 | If FD is AT_FDCWD, FILENAME is interpreted relative to the current | ||
| 68 | working directory, as in openat. | ||
| 69 | |||
| 70 | If the link is small enough to fit into BUFFER put it there. | ||
| 71 | BUFFER's size is BUFFER_SIZE, and BUFFER can be null | ||
| 72 | if BUFFER_SIZE is zero. | ||
| 73 | |||
| 74 | If the link is not small, put it into a dynamically allocated | ||
| 75 | buffer managed by ALLOC. It is the caller's responsibility to free | ||
| 76 | the returned value if it is nonnull and is not BUFFER. A null | ||
| 77 | ALLOC stands for the standard allocator. | ||
| 78 | |||
| 79 | The PREADLINKAT function specifies how to read links. | ||
| 80 | |||
| 81 | If successful, return the buffer address; otherwise return NULL and | ||
| 82 | set errno. */ | ||
| 83 | |||
| 84 | char * | ||
| 85 | careadlinkat (int fd, char const *filename, | ||
| 86 | char *buffer, size_t buffer_size, | ||
| 87 | struct allocator const *alloc, | ||
| 88 | ssize_t (*preadlinkat) (int, char const *, char *, size_t)) | ||
| 89 | { | ||
| 90 | char *buf; | ||
| 91 | size_t buf_size; | ||
| 92 | size_t buf_size_max = | ||
| 93 | SSIZE_MAX < SIZE_MAX ? (size_t) SSIZE_MAX + 1 : SIZE_MAX; | ||
| 94 | char stack_buf[1024]; | ||
| 95 | |||
| 96 | if (! alloc) | ||
| 97 | alloc = &standard_allocator; | ||
| 98 | |||
| 99 | if (! buffer_size) | ||
| 100 | { | ||
| 101 | /* Allocate the initial buffer on the stack. This way, in the | ||
| 102 | common case of a symlink of small size, we get away with a | ||
| 103 | single small malloc() instead of a big malloc() followed by a | ||
| 104 | shrinking realloc(). */ | ||
| 105 | buffer = stack_buf; | ||
| 106 | buffer_size = sizeof stack_buf; | ||
| 107 | } | ||
| 108 | |||
| 109 | buf = buffer; | ||
| 110 | buf_size = buffer_size; | ||
| 111 | |||
| 112 | do | ||
| 113 | { | ||
| 114 | /* Attempt to read the link into the current buffer. */ | ||
| 115 | ssize_t link_length = preadlinkat (fd, filename, buf, buf_size); | ||
| 116 | size_t link_size; | ||
| 117 | if (link_length < 0) | ||
| 118 | { | ||
| 119 | /* On AIX 5L v5.3 and HP-UX 11i v2 04/09, readlink returns -1 | ||
| 120 | with errno == ERANGE if the buffer is too small. */ | ||
| 121 | int readlinkat_errno = errno; | ||
| 122 | if (readlinkat_errno != ERANGE) | ||
| 123 | { | ||
| 124 | if (buf != buffer) | ||
| 125 | { | ||
| 126 | alloc->free (buf); | ||
| 127 | errno = readlinkat_errno; | ||
| 128 | } | ||
| 129 | return NULL; | ||
| 130 | } | ||
| 131 | } | ||
| 132 | |||
| 133 | link_size = link_length; | ||
| 134 | |||
| 135 | if (link_size < buf_size) | ||
| 136 | { | ||
| 137 | buf[link_size++] = '\0'; | ||
| 138 | |||
| 139 | if (buf == stack_buf) | ||
| 140 | { | ||
| 141 | char *b = (char *) alloc->malloc (link_size); | ||
| 142 | if (! b) | ||
| 143 | break; | ||
| 144 | memcpy (b, buf, link_size); | ||
| 145 | buf = b; | ||
| 146 | } | ||
| 147 | else if (link_size < buf_size && buf != buffer && alloc->realloc) | ||
| 148 | { | ||
| 149 | /* Shrink BUF before returning it. */ | ||
| 150 | char *b = (char *) alloc->realloc (buf, link_size); | ||
| 151 | if (b) | ||
| 152 | buf = b; | ||
| 153 | } | ||
| 154 | |||
| 155 | return buf; | ||
| 156 | } | ||
| 157 | |||
| 158 | if (buf != buffer) | ||
| 159 | alloc->free (buf); | ||
| 160 | |||
| 161 | if (buf_size <= buf_size_max / 2) | ||
| 162 | buf_size *= 2; | ||
| 163 | else if (buf_size < buf_size_max) | ||
| 164 | buf_size = buf_size_max; | ||
| 165 | else | ||
| 166 | break; | ||
| 167 | buf = (char *) alloc->malloc (buf_size); | ||
| 168 | } | ||
| 169 | while (buf); | ||
| 170 | |||
| 171 | if (alloc->die) | ||
| 172 | alloc->die (); | ||
| 173 | errno = ENOMEM; | ||
| 174 | return NULL; | ||
| 175 | } | ||
diff --git a/lib/careadlinkat.h b/lib/careadlinkat.h new file mode 100644 index 00000000000..c5e4bcfc15f --- /dev/null +++ b/lib/careadlinkat.h | |||
| @@ -0,0 +1,67 @@ | |||
| 1 | /* Read symbolic links into a buffer without size limitation, relative to fd. | ||
| 2 | |||
| 3 | Copyright (C) 2011 Free Software 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 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 <http://www.gnu.org/licenses/>. */ | ||
| 17 | |||
| 18 | /* Written by Paul Eggert, Bruno Haible, and Jim Meyering. */ | ||
| 19 | |||
| 20 | #ifndef _GL_CAREADLINKAT_H | ||
| 21 | |||
| 22 | #include <fcntl.h> | ||
| 23 | #include <unistd.h> | ||
| 24 | |||
| 25 | struct allocator; | ||
| 26 | |||
| 27 | /* Assuming the current directory is FD, get the symbolic link value | ||
| 28 | of FILENAME as a null-terminated string and put it into a buffer. | ||
| 29 | If FD is AT_FDCWD, FILENAME is interpreted relative to the current | ||
| 30 | working directory, as in openat. | ||
| 31 | |||
| 32 | If the link is small enough to fit into BUFFER put it there. | ||
| 33 | BUFFER's size is BUFFER_SIZE, and BUFFER can be null | ||
| 34 | if BUFFER_SIZE is zero. | ||
| 35 | |||
| 36 | If the link is not small, put it into a dynamically allocated | ||
| 37 | buffer managed by ALLOC. It is the caller's responsibility to free | ||
| 38 | the returned value if it is nonnull and is not BUFFER. | ||
| 39 | |||
| 40 | The PREADLINKAT function specifies how to read links. | ||
| 41 | |||
| 42 | If successful, return the buffer address; otherwise return NULL and | ||
| 43 | set errno. */ | ||
| 44 | |||
| 45 | char *careadlinkat (int fd, char const *filename, | ||
| 46 | char *buffer, size_t buffer_size, | ||
| 47 | struct allocator const *alloc, | ||
| 48 | ssize_t (*preadlinkat) (int, char const *, | ||
| 49 | char *, size_t)); | ||
| 50 | |||
| 51 | /* Suitable values for careadlinkat's FD and PREADLINKAT arguments, | ||
| 52 | when doing a plain readlink. */ | ||
| 53 | #if HAVE_READLINKAT | ||
| 54 | # define careadlinkatcwd readlinkat | ||
| 55 | #else | ||
| 56 | /* Define AT_FDCWD independently, so that the careadlinkat module does | ||
| 57 | not depend on the fcntl-h module. The value does not matter, since | ||
| 58 | careadlinkatcwd ignores it, but we might as well use the same value | ||
| 59 | as fcntl-h. */ | ||
| 60 | # ifndef AT_FDCWD | ||
| 61 | # define AT_FDCWD (-3041965) | ||
| 62 | # endif | ||
| 63 | ssize_t careadlinkatcwd (int fd, char const *filename, | ||
| 64 | char *buffer, size_t buffer_size); | ||
| 65 | #endif | ||
| 66 | |||
| 67 | #endif /* _GL_CAREADLINKAT_H */ | ||
diff --git a/lib/gnulib.mk b/lib/gnulib.mk index 030f95b7a68..bb5bdcf852e 100644 --- a/lib/gnulib.mk +++ b/lib/gnulib.mk | |||
| @@ -9,7 +9,7 @@ | |||
| 9 | # the same distribution terms as the rest of that program. | 9 | # the same distribution terms as the rest of that program. |
| 10 | # | 10 | # |
| 11 | # Generated by gnulib-tool. | 11 | # Generated by gnulib-tool. |
| 12 | # Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=. --makefile-name=gnulib.mk --no-libtool --macro-prefix=gl --no-vc-files crypto/md5 dtoastr filemode getloadavg getopt-gnu ignore-value intprops lstat mktime readlink socklen stdio strftime symlink sys_stat | 12 | # Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=. --makefile-name=gnulib.mk --no-libtool --macro-prefix=gl --no-vc-files careadlinkat crypto/md5 dtoastr filemode getloadavg getopt-gnu ignore-value intprops lstat mktime readlink socklen stdio strftime symlink sys_stat |
| 13 | 13 | ||
| 14 | 14 | ||
| 15 | MOSTLYCLEANFILES += core *.stackdump | 15 | MOSTLYCLEANFILES += core *.stackdump |
| @@ -69,6 +69,14 @@ EXTRA_DIST += $(top_srcdir)/./c++defs.h | |||
| 69 | 69 | ||
| 70 | ## end gnulib module c++defs | 70 | ## end gnulib module c++defs |
| 71 | 71 | ||
| 72 | ## begin gnulib module careadlinkat | ||
| 73 | |||
| 74 | libgnu_a_SOURCES += careadlinkat.c | ||
| 75 | |||
| 76 | EXTRA_DIST += allocator.h careadlinkat.h | ||
| 77 | |||
| 78 | ## end gnulib module careadlinkat | ||
| 79 | |||
| 72 | ## begin gnulib module crypto/md5 | 80 | ## begin gnulib module crypto/md5 |
| 73 | 81 | ||
| 74 | 82 | ||