Annotation of src/usr.bin/rsync/symlinks.c, Revision 1.1
1.1 ! benno 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 <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) {
! 40: if (NULL == (pp = realloc(buf, sz + 1))) {
! 41: ERR(sess, "realloc");
! 42: free(buf);
! 43: return NULL;
! 44: }
! 45: buf = pp;
! 46:
! 47: if (-1 == (nsz = readlink(path, buf, sz))) {
! 48: ERR(sess, "%s: readlink", path);
! 49: free(buf);
! 50: return NULL;
! 51: } else if (0 == nsz) {
! 52: ERRX(sess, "%s: empty link", path);
! 53: free(buf);
! 54: return NULL;
! 55: } else if ((size_t)nsz < sz)
! 56: break;
! 57: }
! 58:
! 59: assert(NULL != buf);
! 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) {
! 79: if (NULL == (pp = realloc(buf, sz + 1))) {
! 80: ERR(sess, "realloc");
! 81: free(buf);
! 82: return NULL;
! 83: }
! 84: buf = pp;
! 85:
! 86: if (-1 == (nsz = readlinkat(fd, path, buf, sz))) {
! 87: ERR(sess, "%s: readlinkat", path);
! 88: free(buf);
! 89: return NULL;
! 90: } else if (0 == nsz) {
! 91: ERRX(sess, "%s: empty link", path);
! 92: free(buf);
! 93: return NULL;
! 94: } else if ((size_t)nsz < sz)
! 95: break;
! 96: }
! 97:
! 98: assert(NULL != buf);
! 99: assert(nsz > 0);
! 100: buf[nsz] = '\0';
! 101: return buf;
! 102: }