home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / UTILITY / FILE / LTARV3.ZIP / LTAR.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-01-28  |  10.5 KB  |  524 lines

  1. #include <ctype.h>
  2. #include <conio.h>
  3. #include <fcntl.h>
  4. #include <dos.h>
  5. #include <dir.h>
  6. #include <errno.h>
  7. #include <io.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <stdarg.h>
  12. #include <sys/stat.h>
  13.  
  14. int tar, memb = -1, memFname = 0, flgExtract = 0, flgVerbose = 0, flgTable = 0 ;
  15. int flgRandFact = 0, flgBuildMap = 0 ;
  16. int dirleng = 8 ;
  17.  
  18. FILE *gMap ;
  19.  
  20. const unsigned secSize = 512 ;
  21. const unsigned nSec = 63 ;
  22. const unsigned bufSize = 32256 ;
  23.  
  24. char *buffer, *tarName ;
  25.  
  26. struct filetime {
  27.     long ft_sec, ft_min, ft_hour, ft_day, ft_month, ft_year ;
  28. } ;
  29.  
  30. typedef struct {
  31.     char name[256] ;
  32.     int x, y, mode, dir ;
  33.     long size, date ;
  34.     struct filetime f ;
  35.     char link[256] ;
  36. } membFilRec ;
  37.  
  38. membFilRec mb ;
  39.  
  40. void error( char *fname, char *cau ) {
  41.  
  42.     fprintf( stderr, "%s error : %s ", cau, fname ) ;
  43.     switch ( errno ) {
  44.         case ENOENT :
  45.             fputs( "path or file not found.\n", stderr ) ;
  46.             break ;
  47.         case EACCES :
  48.             fputs( "permission denied.\n", stderr ) ;
  49.             break ;
  50.         default :
  51.             fprintf( stderr, "error no - %d\n", errno ) ;
  52.     }
  53.     exit( EXIT_FAILURE ) ;
  54. }
  55.  
  56. void
  57. eprintf(
  58.     int i,
  59.     char *s,
  60.     ...
  61. ) {
  62.     va_list v ;
  63.  
  64.     va_start( v, s ) ;
  65.     vfprintf( stderr, s, v ) ;
  66.     va_end( v ) ;
  67.     exit( i ) ;
  68. }
  69.  
  70. long
  71. oct2long(
  72.     char *s,
  73.     int begin,
  74.     int end
  75. ) {
  76.  
  77.     long val = 0L ;
  78.  
  79.     while ( end >= begin ) {
  80.         if ( isdigit( s[begin] ) )
  81.             val = val * 8L + s[begin] - '0' ;
  82.         begin++ ;
  83.     }
  84.  
  85.     return val ;
  86. }
  87.  
  88. oct2int(
  89.     char *s,
  90.     int begin,
  91.     int end
  92. ) {
  93.     int val = 0 ;
  94.  
  95.     while ( end >= begin ) {
  96.         if ( isdigit( s[begin] ) )
  97.             val = val * 8 + s[begin] - '0' ;
  98.         begin++ ;
  99.     }
  100.  
  101.     return val ;
  102. }
  103.  
  104. void
  105. date2ftime( void ) {
  106.  
  107.     static const long monlen[] = {
  108.         31L, 28L, 31L, 30L, 31L, 30L, 31L, 31L, 30L, 31L, 30L, 31L
  109.     } ;
  110.  
  111.     mb.f.ft_sec = mb.date % 60L ;
  112.     mb.date /= 60L ;
  113.     mb.f.ft_min = mb.date % 60L ;
  114.     mb.date /= 60L ;
  115.     mb.f.ft_hour = mb.date % 24L ;
  116.     mb.date /= 24L ;
  117.     mb.f.ft_year = 1970L ;
  118.     while ( mb.date > 0L ) {
  119.         mb.f.ft_year++ ;
  120.         mb.f.ft_day =  mb.f.ft_year % 4L == 0L ? 366L : 365L ;
  121.         mb.date -= mb.f.ft_day ;
  122.     }
  123.     mb.f.ft_year-- ;
  124.     mb.f.ft_day += mb.date + 1L ;
  125.     mb.f.ft_month = 1L ;
  126.     while ( mb.f.ft_day > monlen[( int )mb.f.ft_month - 1] ) {
  127.         mb.f.ft_day -= monlen[( int )mb.f.ft_month - 1] ;
  128.         if ( mb.f.ft_month == 2L && mb.f.ft_year % 4L == 0L )
  129.             mb.f.ft_day-- ;
  130.         mb.f.ft_month++ ;
  131.     }
  132. }
  133.  
  134. void
  135. ftime2tm( char *t ) {
  136.  
  137.     static const char *m[] = {
  138.         "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug",
  139.         "Sep", "Oct", "Nov", "Dec"
  140.     } ;
  141.  
  142.     sprintf( t, "%s %02ld %02ld:%02ld %ld",
  143.         m[( int )mb.f.ft_month - 1], mb.f.ft_day,
  144.         mb.f.ft_hour, mb.f.ft_min, mb.f.ft_year ) ;
  145. }
  146.  
  147. char lastChar( char *s ) { return s[strlen( s ) - 1] ; }
  148.  
  149. void
  150. printMember( void ) {
  151.  
  152.     static char mode[12], tz[80], *modef = "drwxrwxrwx" ;
  153.     static int i, imode ;
  154.  
  155.     if ( flgVerbose ) {
  156.         strcpy( mode, modef ) ;
  157.         if ( !mb.dir )
  158.             *mode = '-' ;
  159.         if ( mb.link[0] )
  160.             *mode = 'l' ;
  161.         for ( imode = mb.mode, i = 1 ; i < 10 ; i++ ) {
  162.             if ( !( imode & 0x0080 ) )
  163.                 mode[i] = '-' ;
  164.             imode <<= 1 ;
  165.         }
  166.         ftime2tm( tz ) ;
  167.         printf(
  168.             "%s %d/%d%8ld %s %s", mode, mb.x, mb.y,
  169.             mb.size, tz, mb.name
  170.         ) ;
  171.         if ( *mode == 'l' )
  172.             printf( " -> %s", mb.link ) ;
  173.     } else if ( flgTable )
  174.         printf( "%s", mb.name ) ;
  175.     else putchar( '.' ) ;
  176. }
  177.  
  178. void
  179. mbInfo( void ) {
  180.  
  181.     mb.name[0] = 0 ;
  182.     strcpy( mb.name, buffer ) ;
  183.     mb.mode = oct2int( buffer, 0x64, 0x6a ) ;
  184.     mb.x = oct2int( buffer, 0x6c, 0x72 ) ;
  185.     mb.y = oct2int( buffer, 0x74, 0x7a ) ;
  186.     mb.size = oct2long( buffer, 0x7c, 0x86 ) ;
  187.     mb.date = oct2long( buffer, 0x88, 0x92 ) ;
  188.     mb.link[0] = 0 ;
  189.     strcpy( mb.link, &buffer[0x9d] ) ;
  190.     date2ftime() ;
  191.     mb.dir = lastChar( mb.name ) == '/' ;
  192. }
  193.  
  194. long
  195. readMemb(
  196.     int op,
  197.     long size,
  198.     unsigned bsize,
  199.     long actSize
  200. ) {
  201.     int iRead, iWrite ;
  202.  
  203.     while ( size >= bsize ) {
  204.         if ( ( iRead = read( tar, buffer, bsize ) ) == -1 )
  205.             error( tarName, "READ" ) ;
  206.  
  207.         if ( iRead != bsize )
  208.             eprintf( EXIT_FAILURE, "\n%s is too short", mb.name ) ;
  209.  
  210.         if ( flgExtract && op && !flgBuildMap ) {
  211.             iWrite = ( int )( actSize < bsize ? actSize : bsize ) ;
  212.             iRead = write( memb, buffer, iWrite ) ;
  213.  
  214.             if ( iRead == -1 )
  215.                 error( tarName, "READ" ) ;
  216.  
  217.             if ( iRead != iWrite )
  218.                 eprintf(
  219.                     EXIT_FAILURE,
  220.                     "\n %s is lost while writing", mb.name
  221.                 ) ;
  222.         }
  223.         size -= bsize ;
  224.         actSize -= bsize ;
  225.     }
  226.     return size ;
  227. }
  228.  
  229. char *
  230. availMembName(
  231.     int l,
  232.     char *s
  233. ) {
  234.     static char name[13], ext[5] ;
  235.     static char *illegal = "*+=|\\[]:;\"'<>,./?" ;
  236.     int fc = 0, nc = 0 ;
  237.     char *p ;
  238.  
  239.     if ( !( strcmp( s, "." ) && strcmp( s, ".." ) ) )
  240.         return s ;
  241.     p = s ;
  242.     while ( *p ) {
  243.         if ( flgRandFact ) {
  244.             srand( fc ) ;
  245.             fc *= random( flgRandFact ) ;
  246.         }
  247.         fc += *p ;
  248.         p++ ;
  249.     }
  250.     p = s ;
  251.     do {
  252.         if ( !strchr( illegal, *p ) ) {
  253.             name[nc] = *p ;
  254.             nc++ ;
  255.         }
  256.     } while ( *++p && nc < l ) ;
  257.     name[nc] = 0 ;
  258.     p = name ;
  259.     sprintf( ext, ".%03X", fc % 0x0fffu ) ;
  260.     strcat( name, ext ) ;
  261.     return name ;
  262. }
  263.  
  264. #define MAXSTR    256
  265.  
  266. int fnSplit(
  267.     char *path,
  268.     char *drive,
  269.     char *dir
  270. ) {
  271.     static char np[MAXSTR] ;
  272.     int r = 0 ;
  273.     char *p, *q, *s ;
  274.  
  275.     strcpy( np, path ) ;
  276.     p = strchr( np, ':' ) ;
  277.     if ( p ) {
  278.         r |= DRIVE ;
  279.         p++ ;
  280.         q = np ;
  281.         while ( q < p ) {
  282.             *drive = *q ;
  283.             *q = 0 ;
  284.             q++ ;
  285.             drive++ ;
  286.         }
  287.         *drive = 0 ;
  288.     } else
  289.         p = np ;
  290.  
  291.     if ( p ) {
  292.         strrev( p ) ;
  293.         q = strpbrk( p, "\\/" ) ;
  294.         if ( q ) {
  295.             s = dir ;
  296.             while ( *q ) {
  297.                 *dir = *q ;
  298.                 q++ ;
  299.                 dir++ ;
  300.             }
  301.             *dir = 0 ;
  302.             r |= DIRECTORY ;
  303.             strrev( s ) ;
  304.         }
  305.     }
  306.     return r ;
  307. }
  308.  
  309. void
  310. openMemb( char *homeDir ) {
  311.  
  312.     static char drive[MAXSTR], dir[MAXSTR] ;
  313.     static char path[MAXSTR], nPath[MAXSTR] ;
  314.     static char linkc[MAXSTR] ;
  315.     static struct ftime ft ;
  316.  
  317.     char *s ;
  318.     int sflag ;
  319.  
  320.     if ( !flgExtract && !flgBuildMap )
  321.         return ;
  322.  
  323.     if ( mb.link[0] ) {
  324.         printf( "LK " ) ;
  325.         strcpy( linkc, mb.link ) ;
  326.     }
  327.  
  328.     strncpy( path, mb.name, MAXSTR ) ;
  329.     setdisk( *homeDir - 'A' ) ;
  330.     chdir( homeDir ) ;
  331.     sflag = fnSplit( path, drive, dir ) ;
  332.     nPath[0] = 0 ;
  333.     printf( "c " ) ;
  334.     if ( sflag & DRIVE ) {
  335.         strcat( nPath, drive ) ;
  336.         if ( !flgBuildMap )
  337.             setdisk( tolower( *drive - 'a' ) ) ;
  338.     }
  339.     if ( sflag & DIRECTORY ) {
  340.         s = dir ;
  341.         if ( *s == '\\' || *s == '/' ) {
  342.             chdir( "\\" ) ;
  343.             s++ ;
  344.             strcat( nPath, "\\" ) ;
  345.         }
  346.         s = strtok( s, "\\/" ) ;
  347.         do {
  348.             s = availMembName( dirleng, s ) ;
  349.             if ( !flgBuildMap )
  350.                 if ( chdir( s ) )
  351.                     if ( mkdir( s ) )
  352.                         error( s, "MKDIR" ) ;
  353.                     else
  354.                         chdir( s ) ;
  355.             strcat( nPath, s ) ;
  356.             strcat( nPath, "\\" ) ;
  357.         } while ( ( s = strtok( NULL, "\\/" ) ) != NULL ) ;
  358.     }
  359.  
  360.     if ( !mb.dir ) {
  361.         s = strtok( strrev( path ), "\\/" ) ;
  362.         s = availMembName( 8, strrev( s ) ) ;
  363.         strcat( nPath, s ) ;
  364.  
  365.         if ( !flgBuildMap ) {
  366.             if ( memb != -1 )
  367.                 close( memb ) ;
  368.  
  369.             memb = open(
  370.                 s, O_CREAT | O_BINARY | O_WRONLY,
  371.                 S_IREAD | S_IWRITE
  372.             ) ;
  373.             if ( mb.link[0] )
  374.                 write( memb, linkc, strlen( linkc ) ) ;
  375.             if ( memb == -1 )
  376.                 error( mb.name, "WRITE" ) ;
  377.             else {
  378.                 ft.ft_tsec = mb.f.ft_sec ;
  379.                 ft.ft_min = mb.f.ft_min ;
  380.                 ft.ft_hour = mb.f.ft_hour ;
  381.                 ft.ft_day = mb.f.ft_day ;
  382.                 ft.ft_month = mb.f.ft_month ;
  383.                 ft.ft_year = mb.f.ft_year - 1980 ;
  384.                 if ( setftime( memb, &ft ) )
  385.                     eprintf(
  386.                         EXIT_FAILURE,
  387.                         "error while set %s's time",
  388.                         mb.name
  389.                     ) ;
  390.             }
  391.         }
  392.     }
  393.  
  394.     fprintf( gMap, "%s %s\n", mb.name, nPath ) ;
  395. }
  396.  
  397. char *banner = "Long Tape Archiver Release 3\n";
  398. char *usage =
  399.     "Usage: ltar [btxv|f filespec|g maptable|l <num>|r <num>]\n"
  400.     "You should supply one of b, t or x options"
  401.     " and include f (filename) option\n"
  402.     "f file    specify the target archive file's name\n"
  403.     "g map    specify the global fname mapping file "
  404.     "(must supply with extract option)\n"
  405.     "l num    num is the most length of directory name\n"
  406.     "r num    num is the random no. factor for converting filename\n"
  407.     "b    build maptable file w/o detar activity\n"
  408.     "t    list a table of content of an archive\n"
  409.     "x    extract files from archive\n"
  410.     "v    verbose the file now process\n"
  411. ;
  412.  
  413. void
  414. main(
  415.     int argc,
  416.     char *argv[]
  417. ) {
  418.     int cargc = 1 ;
  419.     membFilRec dummy_header ;
  420.     long nSize, total = 0L ;
  421.     char *s, *fname = NULL, *gfname = NULL, defDir[MAXPATH] ;
  422.  
  423.     fputs( banner, stderr ) ;
  424.  
  425.     if ( argc < 2 )
  426. usage:
  427.         eprintf( 1, usage ) ;
  428.  
  429.     while ( cargc < argc ) {
  430.         s = argv[cargc] ;
  431.         while ( *s ) {
  432.             if ( *s == 't' )
  433.                 flgTable = 1 ;
  434.             else if ( *s == 'x' )
  435.                 flgExtract = 1 ;
  436.             else if ( *s == 'v' )
  437.                 flgVerbose = 1 ;
  438.             else if ( *s == 'b' )
  439.                 flgBuildMap = 1 ;
  440.             else if ( *s == 'f' ) {
  441.                 cargc++ ;
  442.                 tarName = fname = argv[cargc] ;
  443.                 break ;
  444.             } else if ( *s == 'g' ) {
  445.                 cargc++ ;
  446.                 gfname = argv[cargc] ;
  447.                 break ;
  448.             } else if ( *s == 'l' ) {
  449.                 cargc++ ;
  450.                 s = argv[cargc] ;
  451.                 if ( isdigit( *s ) ) {
  452.                     dirleng = *s - '0' ;
  453.                     if ( dirleng == 0 || dirleng == 9 )
  454.                         dirleng = 8 ;
  455.                 }
  456.                 break ;
  457.             } else if ( *s == 'r' ) {
  458.                 cargc++ ;
  459.                 s = argv[cargc] ;
  460.                 flgRandFact = atoi( s ) ;
  461.                 break ;
  462.             } else
  463.                 fprintf(
  464.                     stderr, "Ignore unknown flag %c\n", *s
  465.                 ) ;
  466.             s++ ;
  467.         }
  468.         cargc++ ;
  469.     }
  470.  
  471.     if ( !( flgBuildMap || flgExtract || flgTable ) || fname == NULL )
  472.         goto usage ;
  473.  
  474.     if ( flgExtract || flgBuildMap )
  475.         if ( gfname == NULL )
  476.             goto usage ;
  477.         else if ( ( gMap = fopen( gfname, "wt" ) ) == NULL )
  478.             error( gfname, "OPEN" ) ;
  479.  
  480.     if ( ( tar = open( fname, O_BINARY | O_RDONLY ) ) == -1 )
  481.         error( fname, "OPEN" ) ;
  482.  
  483.     buffer = ( char * )malloc( bufSize ) ;
  484.     if ( buffer == NULL )
  485.         eprintf( 4, "Not enough memory" ) ;
  486.  
  487.     strcpy( dummy_header.name, "Archive header" ) ;
  488.     getcwd( defDir, MAXPATH ) ;
  489.  
  490.     while ( ! eof( tar ) ) {
  491.         if ( kbhit() ) { getch() ; break ; }
  492.         putchar( '\n' ) ;
  493.         memcpy( &mb, &dummy_header, sizeof ( membFilRec ) ) ;
  494.         readMemb( 0, secSize, secSize, 0 ) ;
  495.         if ( !*buffer )
  496.             break ;
  497.         memcpy( &mb, &dummy_header, sizeof ( membFilRec ) ) ;
  498.         mbInfo() ;
  499.         openMemb( defDir ) ;
  500.         printMember() ;
  501.  
  502.         if ( mb.link[0] )
  503.             continue ;
  504.         total++ ;
  505.  
  506.         if ( mb.size ) {
  507.             nSize = mb.size ;
  508.             nSize = readMemb( 1, nSize, bufSize, nSize ) ;
  509.             nSize = readMemb( 1, nSize, secSize, nSize ) ;
  510.             if ( nSize > 0L )
  511.                 readMemb( 1, secSize, secSize, nSize ) ;
  512.         }
  513.     }
  514.     close( tar ) ;
  515.     if ( flgExtract || flgBuildMap ) {
  516.         fclose( gMap ) ;
  517.         if ( memb != -1 )
  518.             close( memb ) ;
  519.     }
  520.     free( buffer ) ;
  521.     fprintf( stderr, "\nprocessed %ld file(s).\n", total ) ;
  522.     setdisk( *defDir - 'A' ) ;
  523.     chdir( defDir ) ;
  524. }