/* Read symbolic links into a buffer without size limitation, relative to fd.
- Copyright (C) 2001, 2003-2004, 2007, 2009-2011 Free Software Foundation,
+ Copyright (C) 2001, 2003-2004, 2007, 2009-2013 Free Software Foundation,
Inc.
This program is free software: you can redistribute it and/or modify
#include "careadlinkat.h"
-#include "allocator.h"
-
#include <errno.h>
#include <limits.h>
-#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-/* 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)
# 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. */
-ssize_t
-careadlinkatcwd (int fd, char const *filename, char *buffer,
- size_t buffer_size)
-{
- (void) fd;
- return readlink (filename, buffer, buffer_size);
-}
-#endif
+#include "allocator.h"
/* Assuming the current directory is FD, get the symbolic link value
of FILENAME as a null-terminated string and put it into a buffer.
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()
+ <http://pubs.opengroup.org/onlinepubs/9699919799/functions/readlink.html>
+ but can assume that its first argument is the same as FD.
If successful, return the buffer address; otherwise return NULL and
set errno. */
SSIZE_MAX < SIZE_MAX ? (size_t) SSIZE_MAX + 1 : SIZE_MAX;
char stack_buf[1024];
- void *(*pmalloc) (size_t) = malloc;
- void *(*prealloc) (void *, size_t) = realloc;
- void (*pfree) (void *) = free;
- void (*pdie) (void) = NULL;
- if (alloc)
- {
- pmalloc = alloc->malloc;
- prealloc = alloc->realloc;
- pfree = alloc->free;
- pdie = alloc->die;
- }
+ if (! alloc)
+ alloc = &stdlib_allocator;
if (! buffer_size)
{
{
if (buf != buffer)
{
- pfree (buf);
+ alloc->free (buf);
errno = readlinkat_errno;
}
return NULL;
if (buf == stack_buf)
{
- char *b = (char *) pmalloc (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 && prealloc)
+ else if (link_size < buf_size && buf != buffer && alloc->reallocate)
{
/* Shrink BUF before returning it. */
- char *b = (char *) prealloc (buf, link_size);
+ char *b = (char *) alloc->reallocate (buf, link_size);
if (b)
buf = b;
}
}
if (buf != buffer)
- pfree (buf);
+ alloc->free (buf);
if (buf_size <= buf_size_max / 2)
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 *) pmalloc (buf_size);
+ buf = (char *) alloc->allocate (buf_size);
}
while (buf);
- if (pdie)
- pdie ();
+ if (alloc->die)
+ alloc->die (buf_size);
errno = ENOMEM;
return NULL;
}