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>
2007-11-18 18:26:46 +03:00
# include <errno.h>
2007-11-18 19:11:58 +03:00
# include <error.h>
2002-03-25 23:37:46 +03:00
# include <sys/param.h>
2007-11-18 18:52:46 +03:00
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 ;
2007-11-18 18:39:22 +03:00
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
2007-11-18 18:39:22 +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 ;
2008-01-17 21:12:07 +03:00
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
{
2007-11-18 18:26: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
2008-01-17 21:12:07 +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
2007-11-18 18:52:46 +03:00
what = xstrdup ( av [ 1 ] ) ;
to = xstrdup ( av [ 2 ] ) ;
2002-03-25 23:37:46 +03:00
2007-11-18 18:52:46 +03:00
if ( ' / ' ! = * what )
result ( what ) ;
2002-03-25 23:37:46 +03:00
2007-11-18 18:52:46 +03:00
if ( ' / ' ! = * to )
error ( EXIT_FAILURE , 0 ,
" destination must be absolute filename " ) ;
2002-03-25 23:37:46 +03:00
2007-11-18 18:52:46 +03:00
strip_trailing ( what , ' / ' ) ;
strip_trailing ( to , ' / ' ) ;
2002-03-25 23:37:46 +03:00
2007-11-18 18:52: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
2007-11-18 18:52: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 18:52:46 +03:00
{
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
}