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

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