1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
|
/*
* Copyright (c) 1997, 1999 Tama Communications Corporation
*
* This file is part of GNU GLOBAL.
*
* GNU GLOBAL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* GNU GLOBAL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <errno.h>
#ifdef STDC_HEADERS
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#else
#include <strings.h>
#endif
#include "abs2rel.h"
/*
* 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(path, base, result, size)
const char *path;
const char *base;
char *result;
const int 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);
}
|