home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / gnu / cpio-2.3-src.lha / src / amiga / cpio-2.3 / main.c < prev    next >
C/C++ Source or Header  |  1993-06-29  |  13KB  |  480 lines

  1. /* main.c - main program and argument processing for cpio.
  2.    Copyright (C) 1990, 1991, 1992 Free Software Foundation, Inc.
  3.  
  4.    This program is free software; you can redistribute it and/or modify
  5.    it under the terms of the GNU General Public License as published by
  6.    the Free Software Foundation; either version 2, or (at your option)
  7.    any later version.
  8.  
  9.    This program is distributed in the hope that it will be useful,
  10.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.    GNU General Public License for more details.
  13.  
  14.    You should have received a copy of the GNU General Public License
  15.    along with this program; if not, write to the Free Software
  16.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  17.  
  18. /* Written by Phil Nelson <phil@cs.wwu.edu>,
  19.    David MacKenzie <djm@gnu.ai.mit.edu>,
  20.    and John Oleynick <juo@klinzhai.rutgers.edu>.  */
  21.  
  22. #include <stdio.h>
  23. #include <getopt.h>
  24. #include <sys/types.h>
  25. #include <sys/stat.h>
  26. #include "filetypes.h"
  27. #include "system.h"
  28. #include "cpiohdr.h"
  29. #include "dstring.h"
  30. #include "extern.h"
  31. #include "rmt.h"
  32.  
  33. struct option long_opts[] =
  34. {
  35.   {"null", 0, 0, '0'},
  36.   {"append", 0, 0, 'A'},
  37.   {"block-size", 1, 0, 130},
  38.   {"create", 0, 0, 'o'},
  39.   {"dereference", 0, 0, 'L'},
  40.   {"dot", 0, 0, 'V'},
  41.   {"extract", 0, 0, 'i'},
  42.   {"file", 1, 0, 'F'},
  43.   {"force-local", 0, &f_force_local, 1},
  44.   {"format", 1, 0, 'H'},
  45.   {"help", 0, 0, 132},
  46.   {"io-size", 1, 0, 'C'},
  47.   {"link", 0, &link_flag, TRUE},
  48.   {"list", 0, &table_flag, TRUE},
  49.   {"make-directories", 0, &create_dir_flag, TRUE},
  50.   {"message", 1, 0, 'M'},
  51.   {"no-preserve-owner", 0, 0, 134},
  52.   {"nonmatching", 0, ©_matching_files, FALSE},
  53.   {"numeric-uid-gid", 0, &numeric_uid, TRUE},
  54.   {"owner", 1, 0, 'R'},
  55.   {"pass-through", 0, 0, 'p'},
  56.   {"pattern-file", 1, 0, 'E'},
  57.   {"preserve-modification-time", 0, &retain_time_flag, TRUE},
  58.   {"rename", 0, &rename_flag, TRUE},
  59.   {"swap", 0, 0, 'b'},
  60.   {"swap-bytes", 0, 0, 's'},
  61.   {"swap-halfwords", 0, 0, 'S'},
  62.   {"reset-access-time", 0, &reset_time_flag, TRUE},
  63.   {"unconditional", 0, &unconditional_flag, TRUE},
  64.   {"verbose", 0, &verbose_flag, TRUE},
  65.   {"version", 0, 0, 131},
  66. #ifdef DEBUG_CPIO
  67.   {"debug", 0, &debug_flag, TRUE},
  68. #endif
  69.   {0, 0, 0, 0}
  70. };
  71.  
  72. /*  Print usage message and exit with error.  */
  73.  
  74. void
  75. usage (fp, status)
  76.   FILE *fp;
  77.   int status;
  78. {
  79.   fprintf (fp, "\
  80. Usage: %s {-o|--create} [-0acvABLV] [-C bytes] [-H format] [-M message]\n\
  81.        [-O [[user@]host:]archive] [-F [[user@]host:]archive]\n\
  82.        [--file=[[user@]host:]archive] [--format=format] [--message=message]\n\
  83.        [--null] [--reset-access-time] [--verbose] [--dot] [--append]\n\
  84.        [--block-size=blocks] [--dereference] [--io-size=bytes]\n\
  85.        [--force-local] [--help] [--version] < name-list [> archive]\n", program_name);
  86.   fprintf (fp, "\
  87.        %s {-i|--extract} [-bcdfmnrtsuvBSV] [-C bytes] [-E file] [-H format]\n\
  88.        [-M message] [-R [user][:.][group]] [-I [[user@]host:]archive]\n\
  89.        [-F [[user@]host:]archive] [--file=[[user@]host:]archive]\n\
  90.        [--make-directories] [--nonmatching] [--preserve-modification-time]\n\
  91.        [--numeric-uid-gid] [--rename] [--list] [--swap-bytes] [--swap] [--dot]\n\
  92.        [--unconditional] [--verbose] [--block-size=blocks] [--swap-halfwords]\n\
  93.        [--io-size=bytes] [--pattern-file=file] [--format=format]\n\
  94.        [--owner=[user][:.][group]] [--no-preserve-owner] [--message=message]\n\
  95.        [--force-local] [--help] [--version] [pattern...] [< archive]\n",
  96.        program_name);
  97.   fprintf (fp, "\
  98.        %s {-p|--pass-through} [-0adlmuvLV] [-R [user][:.][group]]\n\
  99.        [--null] [--reset-access-time] [--make-directories] [--link]\n\
  100.        [--preserve-modification-time] [--unconditional] [--verbose] [--dot]\n\
  101.        [--dereference] [--owner=[user][:.][group]] [--no-preserve-owner]\n\
  102.        [--help] [--version] destination-directory < name-list\n", program_name);
  103.   exit (status);
  104. }
  105.  
  106. /* Process the arguments.  Set all options and set up the copy pass
  107.    directory or the copy in patterns.  */
  108.  
  109. void
  110. process_args (argc, argv)
  111.      int argc;
  112.      char *argv[];
  113. {
  114.   extern char *version_string;
  115.   void (*copy_in) ();        /* Work around for pcc bug.  */
  116.   void (*copy_out) ();
  117.   int c;
  118.   char *input_archive_name = 0;
  119.   char *output_archive_name = 0;
  120.  
  121.   if (argc < 2)
  122.     usage (stderr, 2);
  123.  
  124.   xstat = lstat;
  125.  
  126.   while ((c = getopt_long (argc, argv,
  127.                "0aAbBcC:dfE:F:H:iI:lLmM:noO:prR:sStuvVz",
  128.                long_opts, (int *) 0)) != -1)
  129.     {
  130.       switch (c)
  131.     {
  132.     case 0:            /* A long option that just sets a flag.  */
  133.       break;
  134.  
  135.     case '0':        /* Read null-terminated filenames.  */
  136.       name_end = '\0';
  137.       break;
  138.  
  139.     case 'a':        /* Reset access times.  */
  140.       reset_time_flag = TRUE;
  141.       break;
  142.  
  143.     case 'A':        /* Append to the archive.  */
  144.       append_flag = TRUE;
  145.       break;
  146.  
  147.     case 'b':        /* Swap bytes and halfwords.  */
  148.       swap_bytes_flag = TRUE;
  149.       swap_halfwords_flag = TRUE;
  150.       break;
  151.  
  152.     case 'B':        /* Set block size to 5120.  */
  153.       io_block_size = 5120;
  154.       break;
  155.  
  156.     case 130:        /* --block-size */
  157.       io_block_size = atoi (optarg);
  158.       if (io_block_size < 1)
  159.         error (2, 0, "invalid block size");
  160.       io_block_size *= 512;
  161.       break;
  162.  
  163.     case 'c':        /* Use the old portable ASCII format.  */
  164.       if (archive_format != arf_unknown)
  165.         usage (stderr, 2);
  166. #ifdef SVR4_COMPAT
  167.       archive_format = arf_newascii; /* -H newc.  */
  168. #else
  169.       archive_format = arf_oldascii; /* -H odc.  */
  170. #endif
  171.       break;
  172.  
  173.     case 'C':        /* Block size.  */
  174.       io_block_size = atoi (optarg);
  175.       if (io_block_size < 1)
  176.         error (2, 0, "invalid block size");
  177.       break;
  178.  
  179.     case 'd':        /* Create directories where needed.  */
  180.       create_dir_flag = TRUE;
  181.       break;
  182.  
  183.     case 'f':        /* Only copy files not matching patterns.  */
  184.       copy_matching_files = FALSE;
  185.       break;
  186.  
  187.     case 'E':        /* Pattern file name.  */
  188.       pattern_file_name = optarg;
  189.       break;
  190.  
  191.     case 'F':        /* Archive file name.  */
  192.       archive_name = optarg;
  193.       break;
  194.  
  195.     case 'H':        /* Header format name.  */
  196.       if (archive_format != arf_unknown)
  197.         usage (stderr, 2);
  198.       if (!strcmp (optarg, "crc") || !strcmp (optarg, "CRC"))
  199.         archive_format = arf_crcascii;
  200.       else if (!strcmp (optarg, "newc") || !strcmp (optarg, "NEWC"))
  201.         archive_format = arf_newascii;
  202.       else if (!strcmp (optarg, "odc") || !strcmp (optarg, "ODC"))
  203.         archive_format = arf_oldascii;
  204.       else if (!strcmp (optarg, "bin") || !strcmp (optarg, "BIN"))
  205.         archive_format = arf_binary;
  206.       else if (!strcmp (optarg, "ustar") || !strcmp (optarg, "USTAR"))
  207.         archive_format = arf_ustar;
  208.       else if (!strcmp (optarg, "tar") || !strcmp (optarg, "TAR"))
  209.         archive_format = arf_tar;
  210.       else if (!strcmp (optarg, "hpodc") || !strcmp (optarg, "HPODC"))
  211.         archive_format = arf_hpoldascii;
  212.       else if (!strcmp (optarg, "hpbin") || !strcmp (optarg, "HPBIN"))
  213.         archive_format = arf_hpbinary;
  214.       else
  215.         error (2, 0, "\
  216. invalid archive format `%s'; valid formats are:\n\
  217. crc newc odc bin ustar tar (all-caps also recognized)", optarg);
  218.       break;
  219.  
  220.     case 'i':        /* Copy-in mode.  */
  221.       if (copy_function != 0)
  222.         usage (stderr, 2);
  223.       copy_function = process_copy_in;
  224.       break;
  225.  
  226.     case 'I':        /* Input archive file name.  */
  227.       input_archive_name = optarg;
  228.       break;
  229.  
  230.     case 'k':        /* Handle corrupted archives.  We always handle
  231.                    corrupted archives, but recognize this
  232.                    option for compatability.  */
  233.       break;
  234.  
  235.     case 'l':        /* Link files when possible.  */
  236.       link_flag = TRUE;
  237.       break;
  238.  
  239.     case 'L':        /* Dereference symbolic links.  */
  240.       xstat = stat;
  241.       break;
  242.  
  243.     case 'm':        /* Retain previous file modify times.  */
  244.       retain_time_flag = TRUE;
  245.       break;
  246.  
  247.     case 'M':        /* New media message.  */
  248.       set_new_media_message (optarg);
  249.       break;
  250.  
  251.     case 'n':        /* Long list owner and group as numbers.  */
  252.       numeric_uid = TRUE;
  253.       break;
  254.  
  255.     case 134:        /* --no-preserve-owner */
  256.       if (set_owner_flag || set_group_flag)
  257.         usage (stderr, 2);
  258.       no_chown_flag = TRUE;
  259.       break;
  260.  
  261.     case 'o':        /* Copy-out mode.  */
  262.       if (copy_function != 0)
  263.         usage (stderr, 2);
  264.       copy_function = process_copy_out;
  265.       break;
  266.  
  267.     case 'O':        /* Output archive file name.  */
  268.       output_archive_name = optarg;
  269.       break;
  270.  
  271.     case 'p':        /* Copy-pass mode.  */
  272.       if (copy_function != 0)
  273.         usage (stderr, 2);
  274.       copy_function = process_copy_pass;
  275.       break;
  276.  
  277.     case 'r':        /* Interactively rename.  */
  278.       rename_flag = TRUE;
  279.       break;
  280.  
  281.     case 'R':        /* Set the owner.  */
  282.       if (no_chown_flag)
  283.         usage (stderr, 2);
  284. #ifndef __MSDOS__
  285.       {
  286.         char *e, *u, *g;
  287.  
  288.         e = parse_user_spec (optarg, &set_owner, &set_group, &u, &g);
  289.         if (e)
  290.           error (2, 0, "%s: %s", optarg, e);
  291.         if (u)
  292.           {
  293.         free (u);
  294.         set_owner_flag = TRUE;
  295.           }
  296.         if (g)
  297.           {
  298.         free (g);
  299.         set_group_flag = TRUE;
  300.           }
  301.       }
  302. #endif
  303.       break;
  304.  
  305.     case 's':        /* Swap bytes.  */
  306.       swap_bytes_flag = TRUE;
  307.       break;
  308.  
  309.     case 'S':        /* Swap halfwords.  */
  310.       swap_halfwords_flag = TRUE;
  311.       break;
  312.  
  313.     case 't':        /* Only print a list.  */
  314.       table_flag = TRUE;
  315.       break;
  316.  
  317.     case 'u':        /* Replace all!  Unconditionally!  */
  318.       unconditional_flag = TRUE;
  319.       break;
  320.  
  321.     case 'v':        /* Verbose!  */
  322.       verbose_flag = TRUE;
  323.       break;
  324.  
  325.     case 'V':        /* Print `.' for each file.  */
  326.       dot_flag = TRUE;
  327.       break;
  328.  
  329.     case 131:
  330.       printf ("GNU cpio %s", version_string);
  331.       exit (0);
  332.       break;
  333.  
  334.     case 132:        /* --help */
  335.       usage (stdout, 0);
  336.       break;
  337.  
  338.     default:
  339.       usage (stderr, 2);
  340.     }
  341.     }
  342.  
  343.   /* Do error checking and look at other args.  */
  344.  
  345.   if (copy_function == 0)
  346.     {
  347.       if (table_flag)
  348.     copy_function = process_copy_in;
  349.       else
  350.     usage (stderr, 2);
  351.     }
  352.  
  353.   if ((!table_flag || !verbose_flag) && numeric_uid)
  354.     usage (stderr, 2);
  355.  
  356.   /* Work around for pcc bug.  */
  357.   copy_in = process_copy_in;
  358.   copy_out = process_copy_out;
  359.  
  360.   if (copy_function == copy_in)
  361.     {
  362.       archive_des = 0;
  363.       if (link_flag || reset_time_flag || xstat != lstat || append_flag
  364.       || output_archive_name
  365.       || (archive_name && input_archive_name))
  366.     usage (stderr, 2);
  367.       if (archive_format == arf_crcascii)
  368.     crc_i_flag = TRUE;
  369.       num_patterns = argc - optind;
  370.       save_patterns = &argv[optind];
  371.       if (input_archive_name)
  372.     archive_name = input_archive_name;
  373.     }
  374.   else if (copy_function == copy_out)
  375.     {
  376.       archive_des = 1;
  377.       if (argc != optind || create_dir_flag || rename_flag
  378.       || table_flag || unconditional_flag || link_flag
  379.       || retain_time_flag || no_chown_flag || set_owner_flag
  380.       || set_group_flag || swap_bytes_flag || swap_halfwords_flag
  381.       || (append_flag && !(archive_name || output_archive_name))
  382.       || input_archive_name || (archive_name && output_archive_name))
  383.     usage (stderr, 2);
  384.       if (archive_format == arf_unknown)
  385.     archive_format = arf_binary;
  386.       if (output_archive_name)
  387.     archive_name = output_archive_name;
  388.     }
  389.   else
  390.     {
  391.       /* Copy pass.  */
  392.       archive_des = -1;
  393.       if (argc - 1 != optind || archive_format != arf_unknown
  394.       || swap_bytes_flag || swap_halfwords_flag
  395.       || table_flag || rename_flag || append_flag)
  396.     usage (stderr, 2);
  397.       directory_name = argv[optind];
  398.     }
  399.  
  400.   if (archive_name)
  401.     {
  402.       if (copy_function != copy_in && copy_function != copy_out)
  403.     usage (stderr, 2);
  404.       archive_des = open_archive (archive_name);
  405.       if (archive_des < 0)
  406.     error (1, errno, "%s", archive_name);
  407.     }
  408.  
  409. #ifndef __MSDOS__
  410.   /* Prevent SysV non-root users from giving away files inadvertantly.
  411.      This happens automatically on BSD, where only root can give
  412.      away files.  */
  413.   if (set_owner_flag == FALSE && set_group_flag == FALSE && geteuid ())
  414.     no_chown_flag = TRUE;
  415. #endif
  416. }
  417.  
  418. /* Initialize the input and output buffers to their proper size and
  419.    initialize all variables associated with the input and output
  420.    buffers.  */
  421.  
  422. void
  423. initialize_buffers ()
  424. {
  425.   int buf_size;
  426.  
  427.   /* Make sure buffers can always hold 2 blocks and that they
  428.      are big enough to hold 1 tar record (512 bytes) even if it
  429.      is not aligned on a block boundary.  The extra buffer space
  430.      is needed by process_copyin and peek_in_buf to automatically
  431.      figure out what kind of archive it is reading.  */
  432.  
  433.   if (io_block_size >= 512)
  434.     buf_size = 2 * io_block_size;
  435.   else
  436.     buf_size = 1024;
  437.   input_buffer = (char *) xmalloc (buf_size);
  438.   in_buff = input_buffer;
  439.   input_size = 0;
  440.   input_bytes = 0;
  441.  
  442.   /* Leave space for an `int' sentinel for `empty_output_buffer',
  443.      in case we ever put back sparseness checking.  */
  444.   output_buffer = (char *) xmalloc (buf_size + sizeof (int) * 2);
  445.   out_buff = output_buffer;
  446.   output_size = 0;
  447.   output_bytes = 0;
  448.  
  449.   /* Clear the block of zeros.  */
  450.   bzero (zeros_512, 512);
  451. }
  452.  
  453. void
  454. main (argc, argv)
  455.      int argc;
  456.      char *argv[];
  457. {
  458.   program_name = argv[0];
  459.   umask (0);
  460.  
  461. #ifdef __TURBOC__
  462.   _fmode = O_BINARY;        /* Put stdin and stdout in binary mode.  */
  463. #endif
  464. #ifdef __EMX__            /* gcc on OS/2.  */
  465.   _response (&argc, &argv);
  466.   _wildcard (&argc, &argv);
  467. #endif
  468.  
  469.   process_args (argc, argv);
  470.  
  471.   initialize_buffers ();
  472.  
  473.   (*copy_function) ();
  474.  
  475.   if (archive_des >= 0 && rmtclose (archive_des) == -1)
  476.     error (1, errno, "error closing archive");
  477.  
  478.   exit (0);
  479. }
  480.