home *** CD-ROM | disk | FTP | other *** search
- #include <ctype.h>
- #include <conio.h>
- #include <fcntl.h>
- #include <dos.h>
- #include <dir.h>
- #include <errno.h>
- #include <io.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <stdarg.h>
- #include <sys/stat.h>
-
- int tar, memb = -1, memFname = 0, flgExtract = 0, flgVerbose = 0, flgTable = 0 ;
- int flgRandFact = 0, flgBuildMap = 0 ;
- int dirleng = 8 ;
-
- FILE *gMap ;
-
- const unsigned secSize = 512 ;
- const unsigned nSec = 63 ;
- const unsigned bufSize = 32256 ;
-
- char *buffer, *tarName ;
-
- struct filetime {
- long ft_sec, ft_min, ft_hour, ft_day, ft_month, ft_year ;
- } ;
-
- typedef struct {
- char name[256] ;
- int x, y, mode, dir ;
- long size, date ;
- struct filetime f ;
- char link[256] ;
- } membFilRec ;
-
- membFilRec mb ;
-
- void error( char *fname, char *cau ) {
-
- fprintf( stderr, "%s error : %s ", cau, fname ) ;
- switch ( errno ) {
- case ENOENT :
- fputs( "path or file not found.\n", stderr ) ;
- break ;
- case EACCES :
- fputs( "permission denied.\n", stderr ) ;
- break ;
- default :
- fprintf( stderr, "error no - %d\n", errno ) ;
- }
- exit( EXIT_FAILURE ) ;
- }
-
- void
- eprintf(
- int i,
- char *s,
- ...
- ) {
- va_list v ;
-
- va_start( v, s ) ;
- vfprintf( stderr, s, v ) ;
- va_end( v ) ;
- exit( i ) ;
- }
-
- long
- oct2long(
- char *s,
- int begin,
- int end
- ) {
-
- long val = 0L ;
-
- while ( end >= begin ) {
- if ( isdigit( s[begin] ) )
- val = val * 8L + s[begin] - '0' ;
- begin++ ;
- }
-
- return val ;
- }
-
- oct2int(
- char *s,
- int begin,
- int end
- ) {
- int val = 0 ;
-
- while ( end >= begin ) {
- if ( isdigit( s[begin] ) )
- val = val * 8 + s[begin] - '0' ;
- begin++ ;
- }
-
- return val ;
- }
-
- void
- date2ftime( void ) {
-
- static const long monlen[] = {
- 31L, 28L, 31L, 30L, 31L, 30L, 31L, 31L, 30L, 31L, 30L, 31L
- } ;
-
- mb.f.ft_sec = mb.date % 60L ;
- mb.date /= 60L ;
- mb.f.ft_min = mb.date % 60L ;
- mb.date /= 60L ;
- mb.f.ft_hour = mb.date % 24L ;
- mb.date /= 24L ;
- mb.f.ft_year = 1970L ;
- while ( mb.date > 0L ) {
- mb.f.ft_year++ ;
- mb.f.ft_day = mb.f.ft_year % 4L == 0L ? 366L : 365L ;
- mb.date -= mb.f.ft_day ;
- }
- mb.f.ft_year-- ;
- mb.f.ft_day += mb.date + 1L ;
- mb.f.ft_month = 1L ;
- while ( mb.f.ft_day > monlen[( int )mb.f.ft_month - 1] ) {
- mb.f.ft_day -= monlen[( int )mb.f.ft_month - 1] ;
- if ( mb.f.ft_month == 2L && mb.f.ft_year % 4L == 0L )
- mb.f.ft_day-- ;
- mb.f.ft_month++ ;
- }
- }
-
- void
- ftime2tm( char *t ) {
-
- static const char *m[] = {
- "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug",
- "Sep", "Oct", "Nov", "Dec"
- } ;
-
- sprintf( t, "%s %02ld %02ld:%02ld %ld",
- m[( int )mb.f.ft_month - 1], mb.f.ft_day,
- mb.f.ft_hour, mb.f.ft_min, mb.f.ft_year ) ;
- }
-
- char lastChar( char *s ) { return s[strlen( s ) - 1] ; }
-
- void
- printMember( void ) {
-
- static char mode[12], tz[80], *modef = "drwxrwxrwx" ;
- static int i, imode ;
-
- if ( flgVerbose ) {
- strcpy( mode, modef ) ;
- if ( !mb.dir )
- *mode = '-' ;
- if ( mb.link[0] )
- *mode = 'l' ;
- for ( imode = mb.mode, i = 1 ; i < 10 ; i++ ) {
- if ( !( imode & 0x0080 ) )
- mode[i] = '-' ;
- imode <<= 1 ;
- }
- ftime2tm( tz ) ;
- printf(
- "%s %d/%d%8ld %s %s", mode, mb.x, mb.y,
- mb.size, tz, mb.name
- ) ;
- if ( *mode == 'l' )
- printf( " -> %s", mb.link ) ;
- } else if ( flgTable )
- printf( "%s", mb.name ) ;
- else putchar( '.' ) ;
- }
-
- void
- mbInfo( void ) {
-
- mb.name[0] = 0 ;
- strcpy( mb.name, buffer ) ;
- mb.mode = oct2int( buffer, 0x64, 0x6a ) ;
- mb.x = oct2int( buffer, 0x6c, 0x72 ) ;
- mb.y = oct2int( buffer, 0x74, 0x7a ) ;
- mb.size = oct2long( buffer, 0x7c, 0x86 ) ;
- mb.date = oct2long( buffer, 0x88, 0x92 ) ;
- mb.link[0] = 0 ;
- strcpy( mb.link, &buffer[0x9d] ) ;
- date2ftime() ;
- mb.dir = lastChar( mb.name ) == '/' ;
- }
-
- long
- readMemb(
- int op,
- long size,
- unsigned bsize,
- long actSize
- ) {
- int iRead, iWrite ;
-
- while ( size >= bsize ) {
- if ( ( iRead = read( tar, buffer, bsize ) ) == -1 )
- error( tarName, "READ" ) ;
-
- if ( iRead != bsize )
- eprintf( EXIT_FAILURE, "\n%s is too short", mb.name ) ;
-
- if ( flgExtract && op && !flgBuildMap ) {
- iWrite = ( int )( actSize < bsize ? actSize : bsize ) ;
- iRead = write( memb, buffer, iWrite ) ;
-
- if ( iRead == -1 )
- error( tarName, "READ" ) ;
-
- if ( iRead != iWrite )
- eprintf(
- EXIT_FAILURE,
- "\n %s is lost while writing", mb.name
- ) ;
- }
- size -= bsize ;
- actSize -= bsize ;
- }
- return size ;
- }
-
- char *
- availMembName(
- int l,
- char *s
- ) {
- static char name[13], ext[5] ;
- static char *illegal = "*+=|\\[]:;\"'<>,./?" ;
- int fc = 0, nc = 0 ;
- char *p ;
-
- if ( !( strcmp( s, "." ) && strcmp( s, ".." ) ) )
- return s ;
- p = s ;
- while ( *p ) {
- if ( flgRandFact ) {
- srand( fc ) ;
- fc *= random( flgRandFact ) ;
- }
- fc += *p ;
- p++ ;
- }
- p = s ;
- do {
- if ( !strchr( illegal, *p ) ) {
- name[nc] = *p ;
- nc++ ;
- }
- } while ( *++p && nc < l ) ;
- name[nc] = 0 ;
- p = name ;
- sprintf( ext, ".%03X", fc % 0x0fffu ) ;
- strcat( name, ext ) ;
- return name ;
- }
-
- #define MAXSTR 256
-
- int fnSplit(
- char *path,
- char *drive,
- char *dir
- ) {
- static char np[MAXSTR] ;
- int r = 0 ;
- char *p, *q, *s ;
-
- strcpy( np, path ) ;
- p = strchr( np, ':' ) ;
- if ( p ) {
- r |= DRIVE ;
- p++ ;
- q = np ;
- while ( q < p ) {
- *drive = *q ;
- *q = 0 ;
- q++ ;
- drive++ ;
- }
- *drive = 0 ;
- } else
- p = np ;
-
- if ( p ) {
- strrev( p ) ;
- q = strpbrk( p, "\\/" ) ;
- if ( q ) {
- s = dir ;
- while ( *q ) {
- *dir = *q ;
- q++ ;
- dir++ ;
- }
- *dir = 0 ;
- r |= DIRECTORY ;
- strrev( s ) ;
- }
- }
- return r ;
- }
-
- void
- openMemb( char *homeDir ) {
-
- static char drive[MAXSTR], dir[MAXSTR] ;
- static char path[MAXSTR], nPath[MAXSTR] ;
- static char linkc[MAXSTR] ;
- static struct ftime ft ;
-
- char *s ;
- int sflag ;
-
- if ( !flgExtract && !flgBuildMap )
- return ;
-
- if ( mb.link[0] ) {
- printf( "LK " ) ;
- strcpy( linkc, mb.link ) ;
- }
-
- strncpy( path, mb.name, MAXSTR ) ;
- setdisk( *homeDir - 'A' ) ;
- chdir( homeDir ) ;
- sflag = fnSplit( path, drive, dir ) ;
- nPath[0] = 0 ;
- printf( "c " ) ;
- if ( sflag & DRIVE ) {
- strcat( nPath, drive ) ;
- if ( !flgBuildMap )
- setdisk( tolower( *drive - 'a' ) ) ;
- }
- if ( sflag & DIRECTORY ) {
- s = dir ;
- if ( *s == '\\' || *s == '/' ) {
- chdir( "\\" ) ;
- s++ ;
- strcat( nPath, "\\" ) ;
- }
- s = strtok( s, "\\/" ) ;
- do {
- s = availMembName( dirleng, s ) ;
- if ( !flgBuildMap )
- if ( chdir( s ) )
- if ( mkdir( s ) )
- error( s, "MKDIR" ) ;
- else
- chdir( s ) ;
- strcat( nPath, s ) ;
- strcat( nPath, "\\" ) ;
- } while ( ( s = strtok( NULL, "\\/" ) ) != NULL ) ;
- }
-
- if ( !mb.dir ) {
- s = strtok( strrev( path ), "\\/" ) ;
- s = availMembName( 8, strrev( s ) ) ;
- strcat( nPath, s ) ;
-
- if ( !flgBuildMap ) {
- if ( memb != -1 )
- close( memb ) ;
-
- memb = open(
- s, O_CREAT | O_BINARY | O_WRONLY,
- S_IREAD | S_IWRITE
- ) ;
- if ( mb.link[0] )
- write( memb, linkc, strlen( linkc ) ) ;
- if ( memb == -1 )
- error( mb.name, "WRITE" ) ;
- else {
- ft.ft_tsec = mb.f.ft_sec ;
- ft.ft_min = mb.f.ft_min ;
- ft.ft_hour = mb.f.ft_hour ;
- ft.ft_day = mb.f.ft_day ;
- ft.ft_month = mb.f.ft_month ;
- ft.ft_year = mb.f.ft_year - 1980 ;
- if ( setftime( memb, &ft ) )
- eprintf(
- EXIT_FAILURE,
- "error while set %s's time",
- mb.name
- ) ;
- }
- }
- }
-
- fprintf( gMap, "%s %s\n", mb.name, nPath ) ;
- }
-
- char *banner = "Long Tape Archiver Release 3\n";
- char *usage =
- "Usage: ltar [btxv|f filespec|g maptable|l <num>|r <num>]\n"
- "You should supply one of b, t or x options"
- " and include f (filename) option\n"
- "f file specify the target archive file's name\n"
- "g map specify the global fname mapping file "
- "(must supply with extract option)\n"
- "l num num is the most length of directory name\n"
- "r num num is the random no. factor for converting filename\n"
- "b build maptable file w/o detar activity\n"
- "t list a table of content of an archive\n"
- "x extract files from archive\n"
- "v verbose the file now process\n"
- ;
-
- void
- main(
- int argc,
- char *argv[]
- ) {
- int cargc = 1 ;
- membFilRec dummy_header ;
- long nSize, total = 0L ;
- char *s, *fname = NULL, *gfname = NULL, defDir[MAXPATH] ;
-
- fputs( banner, stderr ) ;
-
- if ( argc < 2 )
- usage:
- eprintf( 1, usage ) ;
-
- while ( cargc < argc ) {
- s = argv[cargc] ;
- while ( *s ) {
- if ( *s == 't' )
- flgTable = 1 ;
- else if ( *s == 'x' )
- flgExtract = 1 ;
- else if ( *s == 'v' )
- flgVerbose = 1 ;
- else if ( *s == 'b' )
- flgBuildMap = 1 ;
- else if ( *s == 'f' ) {
- cargc++ ;
- tarName = fname = argv[cargc] ;
- break ;
- } else if ( *s == 'g' ) {
- cargc++ ;
- gfname = argv[cargc] ;
- break ;
- } else if ( *s == 'l' ) {
- cargc++ ;
- s = argv[cargc] ;
- if ( isdigit( *s ) ) {
- dirleng = *s - '0' ;
- if ( dirleng == 0 || dirleng == 9 )
- dirleng = 8 ;
- }
- break ;
- } else if ( *s == 'r' ) {
- cargc++ ;
- s = argv[cargc] ;
- flgRandFact = atoi( s ) ;
- break ;
- } else
- fprintf(
- stderr, "Ignore unknown flag %c\n", *s
- ) ;
- s++ ;
- }
- cargc++ ;
- }
-
- if ( !( flgBuildMap || flgExtract || flgTable ) || fname == NULL )
- goto usage ;
-
- if ( flgExtract || flgBuildMap )
- if ( gfname == NULL )
- goto usage ;
- else if ( ( gMap = fopen( gfname, "wt" ) ) == NULL )
- error( gfname, "OPEN" ) ;
-
- if ( ( tar = open( fname, O_BINARY | O_RDONLY ) ) == -1 )
- error( fname, "OPEN" ) ;
-
- buffer = ( char * )malloc( bufSize ) ;
- if ( buffer == NULL )
- eprintf( 4, "Not enough memory" ) ;
-
- strcpy( dummy_header.name, "Archive header" ) ;
- getcwd( defDir, MAXPATH ) ;
-
- while ( ! eof( tar ) ) {
- if ( kbhit() ) { getch() ; break ; }
- putchar( '\n' ) ;
- memcpy( &mb, &dummy_header, sizeof ( membFilRec ) ) ;
- readMemb( 0, secSize, secSize, 0 ) ;
- if ( !*buffer )
- break ;
- memcpy( &mb, &dummy_header, sizeof ( membFilRec ) ) ;
- mbInfo() ;
- openMemb( defDir ) ;
- printMember() ;
-
- if ( mb.link[0] )
- continue ;
- total++ ;
-
- if ( mb.size ) {
- nSize = mb.size ;
- nSize = readMemb( 1, nSize, bufSize, nSize ) ;
- nSize = readMemb( 1, nSize, secSize, nSize ) ;
- if ( nSize > 0L )
- readMemb( 1, secSize, secSize, nSize ) ;
- }
- }
- close( tar ) ;
- if ( flgExtract || flgBuildMap ) {
- fclose( gMap ) ;
- if ( memb != -1 )
- close( memb ) ;
- }
- free( buffer ) ;
- fprintf( stderr, "\nprocessed %ld file(s).\n", total ) ;
- setdisk( *defDir - 'A' ) ;
- chdir( defDir ) ;
- }