home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_200 / 265_01 / ccpio.c < prev    next >
Text File  |  1990-02-15  |  10KB  |  437 lines

  1. /*
  2.  *  CCPIO.C
  3.  *
  4.  *  An Adaption of the UNIX CPIO Archiving Program
  5.  *
  6.  *  Author:  Jon C. Snader
  7.  *
  8.  *
  9.  *  useage: ccpio -a|x|l archive_file [file(s)_to_be archived]
  10.  *      where
  11.  *              -a causes files_to_be_archived to be added to an
  12.  *                 existing archive or put in a new archive
  13.  *
  14.  *              -x extracts all the files from archive_file
  15.  *
  16.  *              -l lists all the files and their sizes in archive_file
  17.  *
  18.  */
  19.  
  20. /* Preprocessor Control */
  21.  
  22. #define MSC5    1        /* Microsoft C ver. 5.0 */
  23. #define MSC4    0        /* Microsoft C ver. 4.0 */
  24. #define LAT3    0        /* Lattice C ver. 3.21 */
  25. #define TURBO    0        /* Turbo C ver. 1.50 */
  26. #define ECOC    0        /* Eco C ver. 3.23 */
  27.  
  28.  
  29. #include <stdio.h>
  30. #include <ctype.h>
  31.  
  32. #if (MSC4 | MSC5 | TURBO)
  33.     #include <stdarg.h>
  34.     #include <io.h>
  35. #endif
  36.  
  37. #if (ECOC)
  38.     #include <varargs.h>
  39.     #define access(x,y)    !fopen (x, "rb")    /* if x file exsits,
  40.                                 return 0 */
  41. #endif
  42.  
  43. #if (ECOC | MSC4 | LAT3)
  44.     #define const
  45. #endif
  46.  
  47. #if (ECOC | LAT3)
  48.     #define SEEK_CUR 1
  49. #endif
  50.  
  51. #if (MSC4 | MSC5 | LAT3 | TURBO)
  52.     #define TRUE ( 1 )
  53.     #define FALSE ( 0 )
  54.     #define phead "%06o%053o%06o%011lo%s%c" /*format string to write a header*/
  55. #else
  56.     #if (ECOC)
  57.         #define phead "%06o%053o%06o%011lo%s"
  58.     #endif
  59. #endif
  60.  
  61. #define NULLFILE ( FILE * )( NULL )
  62. #define EXISTS 0                        /*for access*/
  63. #define N '\0'                          /*a null byte*/
  64. #define MAGIC 070707                    /*magic number indicating cpio arch*/
  65. #define TRAILER_SIZE ( 87L )            /*size of the trailer record*/
  66. #define shead "%6o%*59c%11lo"           /*format string to read a header*/
  67.  
  68.  
  69. typedef int bool;
  70.  
  71. static const char useage[] = "useage: ccpio -a|x|l archive file(s)";
  72. FILE *ar;
  73.  
  74. /*---------------------------------------------------------------------
  75.  *  error  --  output an error message and die
  76.  *---------------------------------------------------------------------
  77.  */
  78.  
  79. #if (MSC4 | MSC5 | TURBO)
  80.  
  81. void error( fmt )
  82.  
  83. char *fmt;
  84.  
  85. {
  86.     va_list args;
  87.  
  88.     va_start( args, fmt );
  89.     vfprintf( stderr, fmt, args );
  90.     exit( 1 );
  91.  
  92. }
  93. #endif
  94.  
  95. #if (LAT3)
  96.  
  97. void error( fmt)
  98.  
  99. char *fmt;
  100.  
  101. {
  102. _pf (fputc, stderr, fmt, (int)(&fmt)+2);
  103. exit(1);
  104. }
  105. #endif
  106.  
  107. #if (ECOC)
  108.  
  109. void error (va_alist)
  110.  
  111. va_dcl
  112.  
  113. {
  114.     char *fmt;
  115.     va_list args;
  116.  
  117.     va_start(args);
  118.     fmt = va_arg (args, char *);
  119.     vfprintf (stderr, fmt, args);
  120.     exit (1);
  121. }
  122. #endif
  123.  
  124.  
  125.  
  126. /*---------------------------------------------------------------------
  127.  *  openRD  --  open the archive file for reading
  128.  *---------------------------------------------------------------------
  129.  */
  130.  
  131. void openRD( archive )
  132.  
  133. char *archive;
  134.  
  135. {
  136.  
  137.     int magicno;
  138.  
  139.     if ( ( ar = fopen( archive, "rb" ) ) == NULLFILE )
  140.         error( "ccpio: can not open %s\n", archive );
  141.  
  142.     if ( fscanf( ar, "%6o", &magicno ) != 1 || magicno != MAGIC )
  143.         error( "ccpio: %s is not an archive file\n", archive );
  144.  
  145. }
  146.  
  147. /*--------------------------------------------------------------------
  148.  *  openWR  --  open the archive file for writing
  149.  *--------------------------------------------------------------------
  150.  */
  151.  
  152. void openWR( archive )
  153.  
  154. char *archive;
  155.  
  156. {
  157.  
  158.     int magicno;
  159.  
  160.     if ( access( archive, EXISTS ) == 0 )
  161.     {
  162.         if ( ( ar = fopen( archive, "r+b" ) ) == NULLFILE )
  163.                error( "ccpio:  Can not open %s\n", archive );
  164.         if ( fscanf( ar, "%6o", &magicno ) != 1 || magicno != MAGIC )
  165.                error( "ccpio: %s is not an archive file\n", archive );
  166.  
  167.         /* position file just before trailer record */
  168.  
  169.         find( "TRAILER!!!" );
  170.           fseek( ar, -TRAILER_SIZE, SEEK_CUR );
  171.     }
  172.     else
  173.     {
  174.            if ( ( ar = fopen( archive, "wb" ) ) == NULLFILE )
  175.             error( "ccpio: can not create %s\n", archive );
  176.     }
  177.  
  178. }
  179.  
  180. /*---------------------------------------------------------------------
  181.  *  fill  --  fill out the file size to an even (512) block
  182.  *---------------------------------------------------------------------
  183.  */
  184.  
  185. void fill()
  186.  
  187. {
  188.  
  189.     /*
  190.      * We need to fill out the last block so that the UNIX cpio can
  191.      * read the archive file without errors.
  192.      *
  193.      */
  194.  
  195.     long size;
  196.     int residue;
  197.  
  198.     fflush( ar );                           /*get the full count*/
  199. #if (ECOC)
  200.     fseek (ar, 0L, 2);        /* go to the end of file */
  201.     size = ftell (ar);
  202.     fseek (ar, 0L, 1);        /* go back to the current pos */
  203. #else
  204.     size = filelength( fileno( ar ) );
  205. #endif
  206.  
  207. printf ("file size : %ld\n",size);
  208.  
  209.     residue = 512 - ( int )( size % 512 );
  210.     if ( residue == 512 )                   /*already at block boundary*/
  211.         return;
  212.     while ( residue-- )
  213.         fputc( '$', ar );
  214.  
  215. }
  216.  
  217. /*---------------------------------------------------------------------
  218.  *  find  --  find a file in the archive
  219.  *---------------------------------------------------------------------
  220.  */
  221.  
  222. bool find( filen )
  223.  
  224. char *filen;
  225.  
  226. {
  227.     char filespec[ 128 ];               /*same as UNIX cpio*/
  228.     long cnt;                           /*size of the file*/
  229.     char *fs;
  230.     int magicno;
  231.  
  232.     rewind( ar );
  233.     for ( ;; )
  234.     {
  235.         /* get the file size and name */
  236.  
  237.         if ( fscanf( ar, shead, &magicno, &cnt ) != 2 || magicno != MAGIC )
  238.             error( "ccpio: corrupted header on archive file\n" );
  239.  
  240.         fs = filespec;
  241.         do
  242.             *fs = getc( ar );
  243.         while ( *fs++ );
  244.  
  245.         if ( strcmp( filespec, filen ) == 0 )
  246.             return TRUE;
  247.  
  248.         /*
  249.          * even if the trailer record is missing, the header check will
  250.          * stop the loop
  251.          *
  252.          */
  253.  
  254.         if ( strcmp( filespec, "TRAILER!!!" ) == 0 )
  255.             return FALSE;
  256.         fseek( ar, cnt, SEEK_CUR );
  257.     }
  258.  
  259. }
  260.  
  261. /*---------------------------------------------------------------------
  262.  *  list --  list the files in the archive
  263.  *---------------------------------------------------------------------
  264.  */
  265.  
  266. void list()
  267.  
  268. {
  269.  
  270.     char filespec[ 128 ];               /*same as UNIX cpio*/
  271.     long cnt;                           /*size of the file*/
  272.     char *fs;
  273.     int magicno;
  274.  
  275.     rewind( ar );
  276.     for ( ;; )
  277.     {
  278.         /* get the file size and name */
  279.  
  280.         if ( fscanf( ar, shead, &magicno, &cnt ) != 2 || magicno != MAGIC )
  281.             error( "ccpio: corrupted header on archive file\n" );
  282.  
  283.         fs = filespec;
  284.         do
  285.             *fs = getc( ar );
  286.         while ( *fs++ );
  287.  
  288.         if ( strcmp( filespec, "TRAILER!!!" ) == 0 )
  289.             break;
  290.  
  291.         fprintf( stderr, "%s (%lu)\n", filespec, cnt );
  292.         fseek( ar, cnt, SEEK_CUR );
  293.     }
  294.  
  295. }
  296.  
  297. /*---------------------------------------------------------------------
  298.  *  archive  --  add a file to the archive
  299.  *---------------------------------------------------------------------
  300.  */
  301.  
  302. void archive( filespec )
  303.  
  304. char *filespec;
  305.  
  306. {
  307.  
  308.     FILE *f;
  309.     int c;
  310.     long size;
  311.  
  312.     if ( ( f = fopen( filespec, "rb" ) ) == NULLFILE )
  313.         error( "ccpio:  Can't open %s\n", filespec );
  314.  
  315.     /*put out the file heading*/
  316.  
  317. #if (ECOC)
  318.     fseek (f, 0L, 2);        /* go to the end of file */
  319.     size = ftell (f);
  320.     fseek (f, 0L, 0);        /* go back to the current pos */
  321. #else
  322.     size = filelength( fileno( f ) );
  323. #endif
  324.  
  325. printf ("file size : %ld\n", size);
  326.  
  327.     fprintf( ar, phead, MAGIC, 0, strlen( filespec ) + 1, size, filespec, N);
  328. #if (ECOC)
  329.     putc (N, ar);
  330. #endif
  331.     /*put out the file*/
  332.  
  333.     while ( ( c = getc( f ) ) != EOF )
  334.         putc( c, ar);
  335.     fclose( f );
  336. }
  337.  
  338. /*---------------------------------------------------------------------
  339.  *  extract  --  extract files from the archive
  340.  *---------------------------------------------------------------------
  341.  */
  342.  
  343. void extract()
  344.  
  345. {
  346.  
  347.     char filespec[ 128 ];               /*same as UNIX cpio*/
  348.     long cnt;                           /*size of the file*/
  349.     char *fs;
  350.     int c;
  351.     int magicno;
  352.     FILE *f;
  353.  
  354.     rewind( ar );
  355.     for ( ;; )
  356.     {
  357.         /* get the file size and name */
  358.  
  359.         if ( fscanf( ar, shead, &magicno, &cnt ) != 2 || magicno != MAGIC )
  360.             error( "ccpio: corrupted header on archive file\n" );
  361.  
  362.         fs = filespec;
  363.         do
  364.             *fs = getc( ar );
  365.         while ( *fs++ );
  366.  
  367.         if ( strcmp( filespec, "TRAILER!!!" ) == 0 )
  368.             break;
  369.  
  370.         fprintf( stderr, "ccpio: extracting %s (%lu)\n", filespec, cnt );
  371.  
  372.         if ( ( f = fopen( filespec, "wb" ) ) == NULLFILE )
  373.             error( "ccpio: can not create %s\n", filespec );
  374.  
  375.         while ( cnt-- && ( c = getc( ar ) ) != EOF  )
  376.              putc( c, f );
  377.  
  378.         fclose( f );
  379.  
  380.         if ( c == EOF )
  381.             error( "ccpio: premature EOF on archive file\n" );
  382.  
  383.     }
  384.  
  385. }
  386.  
  387. /*---------------------------------------------------------------------
  388.  *  main
  389.  *---------------------------------------------------------------------
  390.  */
  391.  
  392. void main( argc, argv )
  393.  
  394. int argc;
  395. char **argv;
  396.  
  397. {
  398.  
  399.     int option;
  400.     unsigned magicno;
  401.  
  402.     if ( **++argv != '-' )
  403.         error( "ccpio: missing option %s\n%s\n", **argv, useage );
  404.     option = ( *argv )[ 1 ];
  405.     argc -= 2;
  406.  
  407.  
  408.  
  409.     switch( toupper( option ) )
  410.     {
  411.         case 'A' :                      /*archive*/
  412.                     openWR( *++argv );
  413.                     while ( --argc )
  414.             archive( *++argv );
  415.             fprintf( ar, phead, MAGIC, 0, 11, 0L, "TRAILER!!!", N );
  416. #if (ECOC)
  417.             putc (N, ar);
  418. #endif
  419.                     fill();
  420.             break;
  421.  
  422.         case 'X' :                      /*extract*/
  423.                     openRD( *++argv );
  424.             extract();
  425.             break;
  426.  
  427.         case 'L' :                      /*list*/
  428.                     openRD( *++argv );
  429.             list();
  430.             break;
  431.  
  432.         default  :
  433.             error( "ccpio: Illegal option %c\n", option );
  434.     }
  435.     fclose( ar );
  436. }
  437.