292 lines
4.7 KiB
C
292 lines
4.7 KiB
C
#ident "$Header: /proj/irix6.5.7m/isms/eoe/cmd/xfs/dump/common/RCS/path.c,v 1.4 1994/10/25 23:07:41 tap Exp $"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
|
|
#include "path.h"
|
|
|
|
struct pem {
|
|
char *pem_head;
|
|
char *pem_next;
|
|
};
|
|
|
|
typedef struct pem pem_t;
|
|
|
|
static pem_t * pem_alloc( char *path );
|
|
static void pem_free( pem_t *pemp );
|
|
static char * pem_next( pem_t *pemp );
|
|
|
|
#define PAMAX 1024
|
|
|
|
struct pa {
|
|
char *pa_array[ PAMAX ];
|
|
int pa_cnt;
|
|
};
|
|
|
|
typedef struct pa pa_t;
|
|
|
|
static pa_t * pa_alloc( void );
|
|
static void pa_free( pa_t *pap );
|
|
static void pa_append( pa_t *pap, char *pep );
|
|
static int pa_peel( pa_t *pap );
|
|
static char * pa_gen( pa_t *pap );
|
|
|
|
char *
|
|
path_diff( char *path, char *base )
|
|
{
|
|
char *diff;
|
|
|
|
assert( *base == '/' );
|
|
assert( *path == '/' );
|
|
|
|
if ( ! path_beginswith( path, base )) {
|
|
return 0;
|
|
}
|
|
|
|
for ( ; *base && *path == *base ; path++, base++ )
|
|
;
|
|
|
|
if ( *path == 0 ) {
|
|
return 0;
|
|
}
|
|
|
|
if ( *path == '/' ) {
|
|
path++;
|
|
}
|
|
|
|
diff = ( char * )calloc( 1, strlen( path ) + 1 );
|
|
assert( diff );
|
|
strcpy( diff, path );
|
|
|
|
return diff;
|
|
}
|
|
|
|
int
|
|
path_beginswith( char *path, char *base )
|
|
{
|
|
if ( ! base ) {
|
|
return 0;
|
|
}
|
|
return ! strncmp( base, path, strlen( base ));
|
|
}
|
|
|
|
char *
|
|
path_reltoabs( char *dir, char *basedir )
|
|
{
|
|
char *absdir;
|
|
|
|
/* check if the path starts with a / or
|
|
* is a remote path (i.e. contains machine:/path/name ).
|
|
*/
|
|
if ( ( *dir != '/' ) && ( strchr(dir, ':') == 0 ) ) {
|
|
char *absdir;
|
|
absdir = ( char * )malloc( strlen( basedir )
|
|
+
|
|
1
|
|
+
|
|
strlen( dir )
|
|
+
|
|
1 );
|
|
assert( absdir );
|
|
|
|
( void )sprintf( absdir, "%s/%s", basedir, dir );
|
|
|
|
dir = absdir;
|
|
}
|
|
|
|
if ( strchr(dir, ':') == 0 ) {
|
|
absdir = path_normalize( dir );
|
|
} else {
|
|
absdir = ( char * )malloc( strlen( dir ) + 1);
|
|
( void )sprintf( absdir, "%s", dir);
|
|
}
|
|
|
|
return absdir;
|
|
}
|
|
|
|
char *
|
|
path_normalize( char *path )
|
|
{
|
|
pem_t *pemp = pem_alloc( path );
|
|
pa_t *pap = pa_alloc( );
|
|
char *pep;
|
|
char *npath;
|
|
|
|
assert( path[ 0 ] == '/' );
|
|
|
|
while ( ( pep = pem_next( pemp )) != 0 ) {
|
|
if ( ! strcmp( pep, "" )) {
|
|
free( ( void * )pep );
|
|
continue;
|
|
}
|
|
if ( ! strcmp( pep, "." )) {
|
|
free( ( void * )pep );
|
|
continue;
|
|
}
|
|
if ( ! strcmp( pep, ".." )) {
|
|
int ok;
|
|
free( ( void * )pep );
|
|
ok = pa_peel( pap );
|
|
if ( ! ok ) {
|
|
pa_free( pap );
|
|
pem_free( pemp );
|
|
return 0;
|
|
}
|
|
continue;
|
|
}
|
|
pa_append( pap, pep );
|
|
}
|
|
|
|
npath = pa_gen( pap );
|
|
pa_free( pap );
|
|
pem_free( pemp );
|
|
|
|
return npath;
|
|
}
|
|
|
|
static pem_t *
|
|
pem_alloc( char *path )
|
|
{
|
|
pem_t *pemp = ( pem_t * )calloc( 1, sizeof( pem_t ));
|
|
assert( pemp );
|
|
pemp->pem_head = path;
|
|
pemp->pem_next = pemp->pem_head;
|
|
|
|
return pemp;
|
|
}
|
|
|
|
static void
|
|
pem_free( pem_t *pemp )
|
|
{
|
|
free( ( void * )pemp );
|
|
}
|
|
|
|
static char *
|
|
pem_next( pem_t *pemp )
|
|
{
|
|
char *nextnext;
|
|
size_t len;
|
|
char *p;
|
|
|
|
/* no more left
|
|
*/
|
|
if ( *pemp->pem_next == 0 ) {
|
|
return 0;
|
|
}
|
|
|
|
/* find the following slash
|
|
*/
|
|
nextnext = strchr( pemp->pem_next + 1, '/' );
|
|
|
|
/* if end of string encountered, place next next at end of string
|
|
*/
|
|
if ( ! nextnext ) {
|
|
for ( nextnext = pemp->pem_next ; *nextnext ; nextnext++ )
|
|
;
|
|
}
|
|
|
|
/* determine the length of the path element, sans the leading slash
|
|
*/
|
|
len = ( size_t )( nextnext - pemp->pem_next - 1 );
|
|
|
|
/* allocate buffer to hold the path element, incl null termination
|
|
*/
|
|
p = ( char * )malloc( len + 1 );
|
|
assert( p );
|
|
|
|
/* copy the path element into the buffer
|
|
*/
|
|
strncpy( p, pemp->pem_next + 1, len );
|
|
|
|
/* null-terminate
|
|
*/
|
|
p[ len ] = 0;
|
|
|
|
/* update next
|
|
*/
|
|
pemp->pem_next = nextnext;
|
|
|
|
/* return the allocated buffer to the caller
|
|
*/
|
|
return p;
|
|
}
|
|
|
|
static pa_t *
|
|
pa_alloc( void )
|
|
{
|
|
pa_t *pap = ( pa_t * )calloc( 1, sizeof( pa_t ));
|
|
assert( pap );
|
|
|
|
return pap;
|
|
}
|
|
|
|
static void
|
|
pa_free( pa_t *pap )
|
|
{
|
|
int i;
|
|
|
|
for ( i = 0 ; i < pap->pa_cnt ; i++ ) {
|
|
free( ( void * )pap->pa_array[ i ] );
|
|
}
|
|
|
|
free( ( void * )pap );
|
|
}
|
|
|
|
static void
|
|
pa_append( pa_t *pap, char *pep )
|
|
{
|
|
assert( pap->pa_cnt < PAMAX );
|
|
|
|
pap->pa_array[ pap->pa_cnt ] = pep;
|
|
|
|
pap->pa_cnt++;
|
|
}
|
|
|
|
static int
|
|
pa_peel( pa_t *pap )
|
|
{
|
|
if ( pap->pa_cnt <= 0 ) {
|
|
assert( pap->pa_cnt == 0 );
|
|
return 0;
|
|
}
|
|
|
|
pap->pa_cnt--;
|
|
assert( pap->pa_array[ pap->pa_cnt ] );
|
|
free( ( void * )pap->pa_array[ pap->pa_cnt ] );
|
|
pap->pa_array[ pap->pa_cnt ] = 0;
|
|
|
|
return 1;
|
|
}
|
|
|
|
static char *
|
|
pa_gen( pa_t *pap )
|
|
{
|
|
size_t sz;
|
|
int i;
|
|
char *retp;
|
|
char *p;
|
|
|
|
sz = 0;
|
|
for ( i = 0 ; i < pap->pa_cnt ; i++ ) {
|
|
sz += strlen( pap->pa_array[ i ] ) + 1;
|
|
}
|
|
sz++;
|
|
|
|
retp = ( char * )malloc( sz );
|
|
|
|
if ( pap->pa_cnt <= 0 ) {
|
|
assert( pap->pa_cnt == 0 );
|
|
sprintf( retp, "/" );
|
|
} else {
|
|
p = retp;
|
|
for ( i = 0 ; i < pap->pa_cnt ; i++ ) {
|
|
sprintf( p, "/%s", pap->pa_array[ i ] );
|
|
p += strlen( p );
|
|
}
|
|
}
|
|
|
|
return retp;
|
|
}
|