rpm-build/tools/relative.c

172 lines
3.2 KiB
C
Raw Normal View History

2002-03-25 23:37:46 +03:00
/*
2003-02-01 20:48:24 +03:00
Copyright (C) 2001 Dmitry V. Levin <ldv@altlinux.org>
2002-03-25 23:37:46 +03:00
This program 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 of the License, or
(at your option) any later version.
This program 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <error.h>
2002-03-25 23:37:46 +03:00
#include <sys/param.h>
static void *
xmalloc(size_t size)
{
void *r = malloc(size);
if (!r)
error(EXIT_FAILURE, errno, "malloc: allocating %lu bytes",
(unsigned long) size);
return r;
}
static char *
xstrdup(const char *s)
{
size_t len = strlen(s);
char *r = xmalloc(len + 1);
memcpy(r, s, len + 1);
return r;
}
2007-11-18 18:24:55 +03:00
static void __attribute__ ((noreturn))
result(const char *str)
{
puts(str);
exit(0);
}
2002-03-25 23:37:46 +03:00
2007-11-18 18:24:55 +03:00
static const char *
normalize(char *str)
2002-03-25 23:37:46 +03:00
{
2007-11-18 18:24:55 +03:00
char *p;
size_t len;
2002-03-25 23:37:46 +03:00
2007-11-18 18:24:55 +03:00
for (p = strstr(str, "//"); p; p = strstr(str, "//"))
memmove(p, p + 1, strlen(p));
2002-03-25 23:37:46 +03:00
2007-11-18 18:24:55 +03:00
for (p = strstr(str, "/./"); p; p = strstr(str, "/./"))
memmove(p, p + 2, strlen(p + 1));
2002-03-25 23:37:46 +03:00
len = strlen(str);
2007-11-18 18:24:55 +03:00
if ((len >= 2) && ('/' == str[len - 2]) && ('.' == str[len - 1]))
str[len - 1] = '\0';
2002-03-25 23:37:46 +03:00
return str;
}
2007-11-18 18:24:55 +03:00
static void
strip_trailing(char *str, const char sym)
2002-03-25 23:37:46 +03:00
{
2007-11-18 18:24:55 +03:00
char *p;
2002-03-25 23:37:46 +03:00
2007-11-18 18:24:55 +03:00
for (p = strrchr(str, sym); p && (p >= str) && (sym == *p); --p)
2002-03-25 23:37:46 +03:00
*p = '\0';
}
2007-11-18 18:24:55 +03:00
static const char *
base_name(const char *name)
2002-03-25 23:37:46 +03:00
{
2007-11-18 18:24:55 +03:00
const char *p = strrchr(name, '/');
if (p)
2002-03-25 23:37:46 +03:00
return p + 1;
else
return name;
}
2007-11-18 18:24:55 +03:00
static char *
lookup_back(const char *str, const char sym, const char *pos)
2002-03-25 23:37:46 +03:00
{
2007-11-18 18:24:55 +03:00
for (; pos >= str; --pos)
if (sym == *pos)
return (char *) pos;
2002-03-25 23:37:46 +03:00
return 0;
}
2007-11-18 18:24:55 +03:00
int
main(int ac, char *av[])
2002-03-25 23:37:46 +03:00
{
2007-11-18 18:38:34 +03:00
const char *orig_what;
2007-11-18 19:16:28 +03:00
char *what_p, *to_p, *res;
char *what, *to;
2007-11-18 18:38:34 +03:00
2007-11-18 18:24:55 +03:00
if (ac < 3)
2002-03-25 23:37:46 +03:00
{
fprintf(stderr, "Usage: %s <what> <to>\n",
program_invocation_short_name);
2002-03-25 23:37:46 +03:00
return 1;
2007-11-18 18:38:34 +03:00
}
2007-11-18 18:24:55 +03:00
what = xstrdup(av[1]);
to = xstrdup(av[2]);
2007-11-18 18:38:34 +03:00
orig_what = normalize(av[1]);
normalize(av[2]);
2002-03-25 23:37:46 +03:00
what = xstrdup(av[1]);
to = xstrdup(av[2]);
2002-03-25 23:37:46 +03:00
if ('/' != *what)
result(what);
2002-03-25 23:37:46 +03:00
if ('/' != *to)
error(EXIT_FAILURE, 0,
"destination must be absolute filename");
2002-03-25 23:37:46 +03:00
strip_trailing(what, '/');
strip_trailing(to, '/');
2002-03-25 23:37:46 +03:00
for (what_p = what, to_p = to; *what_p && *to_p; ++what_p, ++to_p)
if (*what_p != *to_p)
break;
2002-03-25 23:37:46 +03:00
if (!*what_p && !*to_p)
result(base_name(orig_what));
2002-03-25 23:37:46 +03:00
2007-11-18 19:16:28 +03:00
res = xmalloc(strlen(what) + strlen(to) * 3 / 2 + 3);
2002-03-25 23:37:46 +03:00
2007-11-18 19:16:28 +03:00
if (('/' == *what_p) && !*to_p)
result(orig_what + (++what_p - what));
2002-03-25 23:37:46 +03:00
2007-11-18 19:16:28 +03:00
if ('/' != *to_p || *what_p)
{
what_p = lookup_back(what, '/', what_p - 1);
strcpy(res, "..");
} else
{
res[0] = '\0';
}
for (; *to_p; ++to_p)
{
if ('/' == *to_p)
{
2007-11-18 19:16:28 +03:00
if (*res)
strcat(res, "/..");
else
strcpy(res, "..");
2002-03-25 23:37:46 +03:00
}
}
2007-11-18 19:16:28 +03:00
strcat(res, orig_what + (what_p - what));
result(res);
2002-03-25 23:37:46 +03:00
}