[BACK]Return to symlinks.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / rsync

Annotation of src/usr.bin/rsync/symlinks.c, Revision 1.2

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: }