[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.4

1.4     ! benno       1: /*     $Id: symlinks.c,v 1.3 2019/02/11 21:41:22 deraadt 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.4     ! benno      41:                        ERR("realloc");
1.1       benno      42:                        free(buf);
                     43:                        return NULL;
                     44:                }
                     45:                buf = pp;
                     46:
1.3       deraadt    47:                if ((nsz = readlink(path, buf, sz)) == -1) {
1.4     ! benno      48:                        ERR("%s: readlink", path);
1.1       benno      49:                        free(buf);
                     50:                        return NULL;
1.3       deraadt    51:                } else if (nsz == 0) {
1.4     ! benno      52:                        ERRX("%s: empty link", path);
1.1       benno      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.4     ! benno      80:                        ERR("realloc");
1.1       benno      81:                        free(buf);
                     82:                        return NULL;
                     83:                }
                     84:                buf = pp;
                     85:
1.3       deraadt    86:                if ((nsz = readlinkat(fd, path, buf, sz)) == -1) {
1.4     ! benno      87:                        ERR("%s: readlinkat", path);
1.1       benno      88:                        free(buf);
                     89:                        return NULL;
1.3       deraadt    90:                } else if (nsz == 0) {
1.4     ! benno      91:                        ERRX("%s: empty link", path);
1.1       benno      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: }