areadlink.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. /* areadlink.c -- readlink wrapper to return the link name in malloc'd storage
  2. Unlike xreadlink and xreadlink_with_size, don't ever call exit.
  3. Copyright (C) 2001, 2003-2007 Free Software Foundation, Inc.
  4. This program is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  14. /* Written by Jim Meyering <jim@meyering.net>
  15. and Bruno Haible <bruno@clisp.org>. */
  16. #include <config.h>
  17. /* Specification. */
  18. #include "areadlink.h"
  19. #include <string.h>
  20. #include <errno.h>
  21. #include <limits.h>
  22. #include <sys/types.h>
  23. #include <stdlib.h>
  24. #include <unistd.h>
  25. #ifndef SIZE_MAX
  26. # define SIZE_MAX ((size_t) -1)
  27. #endif
  28. #ifndef SSIZE_MAX
  29. # define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2))
  30. #endif
  31. /* Call readlink to get the symbolic link value of FILENAME.
  32. Return a pointer to that NUL-terminated string in malloc'd storage.
  33. If readlink fails, return NULL and set errno.
  34. If realloc fails, or if the link value is longer than SIZE_MAX :-),
  35. return NULL and set errno to ENOMEM. */
  36. char *
  37. areadlink (char const *filename)
  38. {
  39. /* The initial buffer size for the link value. A power of 2
  40. detects arithmetic overflow earlier, but is not required. */
  41. #define INITIAL_BUF_SIZE 1024
  42. /* Allocate the initial buffer on the stack. This way, in the common
  43. case of a symlink of small size, we get away with a single small malloc()
  44. instead of a big malloc() followed by a shrinking realloc(). */
  45. char initial_buf[INITIAL_BUF_SIZE];
  46. char *buffer = initial_buf;
  47. size_t buf_size = sizeof (initial_buf);
  48. while (1)
  49. {
  50. /* Attempt to read the link into the current buffer. */
  51. ssize_t link_length = readlink (filename, buffer, buf_size);
  52. /* On AIX 5L v5.3 and HP-UX 11i v2 04/09, readlink returns -1
  53. with errno == ERANGE if the buffer is too small. */
  54. if (link_length < 0 && errno != ERANGE)
  55. {
  56. if (buffer != initial_buf)
  57. {
  58. int saved_errno = errno;
  59. free (buffer);
  60. errno = saved_errno;
  61. }
  62. return NULL;
  63. }
  64. if ((size_t) link_length < buf_size)
  65. {
  66. buffer[link_length++] = '\0';
  67. /* Return it in a chunk of memory as small as possible. */
  68. if (buffer == initial_buf)
  69. {
  70. buffer = (char *) malloc (link_length);
  71. if (buffer == NULL)
  72. /* errno is ENOMEM. */
  73. return NULL;
  74. memcpy (buffer, initial_buf, link_length);
  75. }
  76. else
  77. {
  78. /* Shrink buffer before returning it. */
  79. if ((size_t) link_length < buf_size)
  80. {
  81. char *smaller_buffer = (char *) realloc (buffer, link_length);
  82. if (smaller_buffer != NULL)
  83. buffer = smaller_buffer;
  84. }
  85. }
  86. return buffer;
  87. }
  88. if (buffer != initial_buf)
  89. free (buffer);
  90. buf_size *= 2;
  91. if (SSIZE_MAX < buf_size || (SIZE_MAX / 2 < SSIZE_MAX && buf_size == 0))
  92. {
  93. errno = ENOMEM;
  94. return NULL;
  95. }
  96. buffer = (char *) malloc (buf_size);
  97. if (buffer == NULL)
  98. /* errno is ENOMEM. */
  99. return NULL;
  100. }
  101. }