Annotation of src/usr.bin/rsync/symlinks.c, Revision 1.3
1.3 ! deraadt 1: /* $Id: symlinks.c,v 1.2 2019/02/10 23:24:14 benno Exp $ */
1.1 benno 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 <sys/param.h>
18:
19: #include <assert.h>
20: #include <stdint.h>
21: #include <stdlib.h>
22: #include <unistd.h>
23:
24: #include "extern.h"
25:
26: /*
27: * Allocate space for a readlink(2) invocation.
28: * Returns NULL on failure or a buffer otherwise.
29: * The buffer must be passed to free() by the caller.
30: */
31: char *
32: symlink_read(struct sess *sess, const char *path)
33: {
34: char *buf = NULL;
35: size_t sz;
36: ssize_t nsz = 0;
37: void *pp;
38:
39: for (sz = MAXPATHLEN; ; sz *= 2) {
1.3 ! deraadt 40: if ((pp = realloc(buf, sz + 1)) == NULL) {
1.1 benno 41: ERR(sess, "realloc");
42: free(buf);
43: return NULL;
44: }
45: buf = pp;
46:
1.3 ! deraadt 47: if ((nsz = readlink(path, buf, sz)) == -1) {
1.1 benno 48: ERR(sess, "%s: readlink", path);
49: free(buf);
50: return NULL;
1.3 ! deraadt 51: } else if (nsz == 0) {
1.1 benno 52: ERRX(sess, "%s: empty link", path);
53: free(buf);
54: return NULL;
55: } else if ((size_t)nsz < sz)
56: break;
57: }
58:
1.3 ! deraadt 59: assert(buf != NULL);
1.1 benno 60: assert(nsz > 0);
61: buf[nsz] = '\0';
62: return buf;
63: }
64:
65: /*
66: * Allocate space for a readlinkat(2) invocation.
67: * Returns NULL on failure or a buffer otherwise.
68: * The buffer must be passed to free() by the caller.
69: */
70: char *
71: symlinkat_read(struct sess *sess, int fd, const char *path)
72: {
73: char *buf = NULL;
74: size_t sz;
75: ssize_t nsz = 0;
76: void *pp;
77:
78: for (sz = MAXPATHLEN; ; sz *= 2) {
1.3 ! deraadt 79: if ((pp = realloc(buf, sz + 1)) == NULL) {
1.1 benno 80: ERR(sess, "realloc");
81: free(buf);
82: return NULL;
83: }
84: buf = pp;
85:
1.3 ! deraadt 86: if ((nsz = readlinkat(fd, path, buf, sz)) == -1) {
1.1 benno 87: ERR(sess, "%s: readlinkat", path);
88: free(buf);
89: return NULL;
1.3 ! deraadt 90: } else if (nsz == 0) {
1.1 benno 91: ERRX(sess, "%s: empty link", path);
92: free(buf);
93: return NULL;
94: } else if ((size_t)nsz < sz)
95: break;
96: }
97:
1.3 ! deraadt 98: assert(buf != NULL);
1.1 benno 99: assert(nsz > 0);
100: buf[nsz] = '\0';
101: return buf;
102: }