1 /* $Id$ */
2 /*
3 * Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17 #include "config.h"
18
19 #include <sys/param.h>
20
21 #include <assert.h>
22 #include <stdint.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25
26 #include "extern.h"
27
28 /*
29 * Allocate space for a readlink(2) invocation.
30 * Returns NULL on failure or a buffer otherwise.
31 * The buffer must be passed to free() by the caller.
32 */
33 char *
symlink_read(const char * path)34 symlink_read(const char *path)
35 {
36 char *buf = NULL;
37 size_t sz;
38 ssize_t nsz = 0;
39 void *pp;
40
41 for (sz = MAXPATHLEN; ; sz *= 2) {
42 if ((pp = realloc(buf, sz + 1)) == NULL) {
43 ERR("realloc");
44 free(buf);
45 return NULL;
46 }
47 buf = pp;
48
49 if ((nsz = readlink(path, buf, sz)) == -1) {
50 ERR("%s: readlink", path);
51 free(buf);
52 return NULL;
53 } else if (nsz == 0) {
54 ERRX("%s: empty link", path);
55 free(buf);
56 return NULL;
57 } else if ((size_t)nsz < sz)
58 break;
59 }
60
61 assert(buf != NULL);
62 assert(nsz > 0);
63 buf[nsz] = '\0';
64 return buf;
65 }
66
67 /*
68 * Allocate space for a readlinkat(2) invocation.
69 * Returns NULL on failure or a buffer otherwise.
70 * The buffer must be passed to free() by the caller.
71 */
72 char *
symlinkat_read(int fd,const char * path)73 symlinkat_read(int fd, const char *path)
74 {
75 char *buf = NULL;
76 size_t sz;
77 ssize_t nsz = 0;
78 void *pp;
79
80 for (sz = MAXPATHLEN; ; sz *= 2) {
81 if ((pp = realloc(buf, sz + 1)) == NULL) {
82 ERR("realloc");
83 free(buf);
84 return NULL;
85 }
86 buf = pp;
87
88 if ((nsz = readlinkat(fd, path, buf, sz)) == -1) {
89 ERR("%s: readlinkat", path);
90 free(buf);
91 return NULL;
92 } else if (nsz == 0) {
93 ERRX("%s: empty link", path);
94 free(buf);
95 return NULL;
96 } else if ((size_t)nsz < sz)
97 break;
98 }
99
100 assert(buf != NULL);
101 assert(nsz > 0);
102 buf[nsz] = '\0';
103 return buf;
104 }
105