X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fcareadlinkat.c;h=751578b9a58fc6f46894cbbef3237d716f1c347b;hb=620ece7758e453efebf7f52a1ab9fc1c49a5020c;hp=15ffe24c0f4cb6fb763e16b08c6fec346cf6dff6;hpb=4266051ac3a82f0a3bdfcf73c7f566e007676a0c;p=gnulib.git diff --git a/lib/careadlinkat.c b/lib/careadlinkat.c index 15ffe24c0..751578b9a 100644 --- a/lib/careadlinkat.c +++ b/lib/careadlinkat.c @@ -22,19 +22,12 @@ #include "careadlinkat.h" -#include "allocator.h" - #include #include #include #include #include -/* Use the system functions, not the gnulib overrides, because this - module does not depend on GNU or POSIX semantics. */ -#undef malloc -#undef realloc - /* Define this independently so that stdint.h is not a prerequisite. */ #ifndef SIZE_MAX # define SIZE_MAX ((size_t) -1) @@ -44,23 +37,21 @@ # define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2)) #endif -#if ! HAVE_READLINKAT -/* Ignore FD. Get the symbolic link value of FILENAME and put it into - BUFFER, with size BUFFER_SIZE. This function acts like readlink - but has readlinkat's signature. */ +#include "allocator.h" + +/* Get the symbolic link value of FILENAME and put it into BUFFER, with + size BUFFER_SIZE. This function acts like readlink but has + readlinkat's signature. */ ssize_t careadlinkatcwd (int fd, char const *filename, char *buffer, size_t buffer_size) { - (void) fd; + /* FD must be AT_FDCWD here, otherwise the caller is using this + function in contexts for which it was not meant for. */ + if (fd != AT_FDCWD) + abort (); return readlink (filename, buffer, buffer_size); } -#endif - -/* A standard allocator. For now, only careadlinkat needs this, but - perhaps it should be moved to the allocator module. */ -static struct allocator const standard_allocator = - { malloc, realloc, free, NULL }; /* Assuming the current directory is FD, get the symbolic link value of FILENAME as a null-terminated string and put it into a buffer. @@ -76,7 +67,10 @@ static struct allocator const standard_allocator = the returned value if it is nonnull and is not BUFFER. A null ALLOC stands for the standard allocator. - The PREADLINKAT function specifies how to read links. + The PREADLINKAT function specifies how to read links. It operates + like POSIX readlinkat() + + but can assume that its first argument is the same as FD. If successful, return the buffer address; otherwise return NULL and set errno. */ @@ -94,7 +88,7 @@ careadlinkat (int fd, char const *filename, char stack_buf[1024]; if (! alloc) - alloc = &standard_allocator; + alloc = &stdlib_allocator; if (! buffer_size) { @@ -138,16 +132,17 @@ careadlinkat (int fd, char const *filename, if (buf == stack_buf) { - char *b = (char *) alloc->malloc (link_size); + char *b = (char *) alloc->allocate (link_size); + buf_size = link_size; if (! b) break; memcpy (b, buf, link_size); buf = b; } - else if (link_size < buf_size && buf != buffer && alloc->realloc) + else if (link_size < buf_size && buf != buffer && alloc->reallocate) { /* Shrink BUF before returning it. */ - char *b = (char *) alloc->realloc (buf, link_size); + char *b = (char *) alloc->reallocate (buf, link_size); if (b) buf = b; } @@ -162,14 +157,19 @@ careadlinkat (int fd, char const *filename, buf_size *= 2; else if (buf_size < buf_size_max) buf_size = buf_size_max; + else if (buf_size_max < SIZE_MAX) + { + errno = ENAMETOOLONG; + return NULL; + } else break; - buf = (char *) alloc->malloc (buf_size); + buf = (char *) alloc->allocate (buf_size); } while (buf); if (alloc->die) - alloc->die (); + alloc->die (buf_size); errno = ENOMEM; return NULL; }