1 /* xreadlink.c -- readlink wrapper to return the link name in malloc'd storage
3 Copyright (C) 2001, 2003 Free Software Foundation, Inc.
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 2, or (at your option)
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.
15 You should have received a copy of the GNU General Public License
16 along with this program; see the file COPYING.
17 If not, write to the Free Software Foundation,
18 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20 /* Written by Jim Meyering <jim@meyering.net>
21 and Bruno Haible <bruno@clisp.org>. */
28 #include "xreadlink.h"
38 #include <sys/types.h>
47 # define SIZE_MAX ((size_t) -1)
50 # define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2))
54 # define xmalloc malloc
59 /* Call readlink to get the symbolic link value of FILENAME.
60 Return a pointer to that NUL-terminated string in malloc'd storage.
61 If readlink fails, return NULL (caller may use errno to diagnose).
62 If realloc fails, or if the link value is longer than SIZE_MAX :-),
63 give a diagnostic and exit. */
66 xreadlink (char const *filename
)
68 /* The initial buffer size for the link value. A power of 2
69 detects arithmetic overflow earlier, but is not required. */
70 #define INITIAL_BUF_SIZE 1024
72 /* Allocate the initial buffer on the stack. This way, in the common
73 case of a symlink of small size, we get away with a single small malloc()
74 instead of a big malloc() followed by a shrinking realloc(). */
75 char initial_buf
[INITIAL_BUF_SIZE
];
77 char *buffer
= initial_buf
;
78 size_t buf_size
= sizeof (initial_buf
);
82 /* Attempt to read the link into the current buffer. */
83 ssize_t link_length
= readlink (filename
, buffer
, buf_size
);
87 if (buffer
!= initial_buf
)
89 int saved_errno
= errno
;
96 if ((size_t) link_length
< buf_size
)
98 buffer
[link_length
++] = '\0';
100 /* Return it in a chunk of memory as small as possible. */
101 if (buffer
== initial_buf
)
103 buffer
= (char *) xmalloc (link_length
);
108 memcpy (buffer
, initial_buf
, link_length
);
112 /* Shrink buffer before returning it. */
113 if ((size_t) link_length
< buf_size
)
115 char *smaller_buffer
= (char *) realloc (buffer
, link_length
);
117 if (smaller_buffer
!= NULL
)
118 buffer
= smaller_buffer
;
124 if (buffer
!= initial_buf
)
127 if (SSIZE_MAX
< buf_size
|| (SIZE_MAX
/ 2 < SSIZE_MAX
&& buf_size
== 0))
133 buffer
= (char *) xmalloc (buf_size
);