#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 #include #include #include #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; }