diff options
Diffstat (limited to 'lib/libpathconv/abs2rel.c')
-rw-r--r-- | lib/libpathconv/abs2rel.c | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/lib/libpathconv/abs2rel.c b/lib/libpathconv/abs2rel.c new file mode 100644 index 000000000000..a71009112fb2 --- /dev/null +++ b/lib/libpathconv/abs2rel.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 1997 Shigio Yamaguchi. All rights reserved. + * Copyright (c) 1999 Tama Communications Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include "pathconv.h" /* prototypes */ +/* + * abs2rel: convert an absolute path name into relative. + * + * i) path absolute path + * i) base base directory (must be absolute path) + * o) result result buffer + * i) size size of result buffer + * r) != NULL: relative path + * == NULL: error + */ +char * +abs2rel(const char *path, const char *base, char *result, const size_t size) +{ + const char *pp, *bp, *branch; + /* + * endp points the last position which is safe in the result buffer. + */ + const char *endp = result + size - 1; + char *rp; + + if (*path != '/') { + if (strlen(path) >= size) + goto erange; + strcpy(result, path); + goto finish; + } else if (*base != '/' || !size) { + errno = EINVAL; + return (NULL); + } else if (size == 1) + goto erange; + /* + * seek to branched point. + */ + branch = path; + for (pp = path, bp = base; *pp && *bp && *pp == *bp; pp++, bp++) + if (*pp == '/') + branch = pp; + if ((*pp == 0 || (*pp == '/' && *(pp + 1) == 0)) && + (*bp == 0 || (*bp == '/' && *(bp + 1) == 0))) { + rp = result; + *rp++ = '.'; + if (*pp == '/' || *(pp - 1) == '/') + *rp++ = '/'; + if (rp > endp) + goto erange; + *rp = 0; + goto finish; + } + if ((*pp == 0 && *bp == '/') || (*pp == '/' && *bp == 0)) + branch = pp; + /* + * up to root. + */ + rp = result; + for (bp = base + (branch - path); *bp; bp++) + if (*bp == '/' && *(bp + 1) != 0) { + if (rp + 3 > endp) + goto erange; + *rp++ = '.'; + *rp++ = '.'; + *rp++ = '/'; + } + if (rp > endp) + goto erange; + *rp = 0; + /* + * down to leaf. + */ + if (*branch) { + if (rp + strlen(branch + 1) > endp) + goto erange; + strcpy(rp, branch + 1); + } else + *--rp = 0; +finish: + return result; +erange: + errno = ERANGE; + return (NULL); +} |