home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 7 / FreshFishVol7.bin / bbs / gnu / binutils-1.8.x-src.lha / GNU / src / amiga / binutils-1.8.x / ar.c < prev    next >
C/C++ Source or Header  |  1994-08-21  |  47KB  |  2,003 lines

  1. /* ar.c - Archive modify and extract.
  2.    Copyright (C) 1988 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 1, 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. #include <stdio.h>
  19. #include <ar.h>
  20. #include <errno.h>
  21. #include <sys/types.h>
  22. #include <sys/stat.h>
  23.  
  24. #if !defined(A_OUT) && !defined(MACH_O)
  25. #define A_OUT
  26. #endif
  27.  
  28. #ifdef A_OUT
  29. #ifdef COFF_ENCAPSULATE
  30. #include "a.out.encap.h"
  31. #else
  32. #include <a.out.h>
  33. #endif
  34. #endif
  35.  
  36. #ifdef MACH_O
  37. #ifndef A_OUT
  38. #include <nlist.h>
  39. #endif
  40. #include <sys/loader.h>
  41. #endif
  42.  
  43. #ifdef USG
  44. #include <time.h>
  45. #include <fcntl.h>
  46. #else
  47. #include <sys/file.h>
  48. #include <sys/time.h>
  49. #endif
  50.  
  51. #ifdef    __GNUC__
  52. #define    alloca    __builtin_alloca
  53. #else
  54. # ifdef sparc
  55. #  include <alloca.h>
  56. # else
  57. char *alloca ();
  58. # endif
  59. #endif
  60.  
  61. #ifdef    USG
  62. #define    bcopy(source, dest, size)    memcpy((dest), (source), (size))
  63. #define    bcmp(a, b, size)        memcmp((a), (b), (size))
  64. #define    bzero(s, size)            memset((s), 0, (size))
  65. #endif
  66.  
  67. /* Locking is normally disabled because fcntl hangs on the Sun
  68.    and it isn't supported properly across NFS anyway.  */
  69. #ifdef LOCKS
  70. /* You might need to compile with -I/usr/include/sys if your fcntl.h
  71.    isn't in /usr/include (which is where it should be according to POSIX).  */
  72. #include <fcntl.h>
  73. #endif
  74.  
  75. /* This structure is used internally to represent the info
  76.    on a member of an archive.  This is to make it easier to change format.  */
  77.  
  78. struct member_desc
  79.   {
  80.     /* Name of member.  */
  81.     char *name;
  82.  
  83.     /* The following fields are stored in the member header as decimal or octal
  84.        numerals, but in this structure they are stored as machine numbers.  */
  85.     int mode;        /* Protection mode from member header.  */
  86.     long int date;    /* Last modify date as stored in member header.  */
  87.     unsigned int size;    /* Bytes of member's data, from member header.  */
  88.     int uid, gid;    /* UID and GID fields copied from member header.  */
  89.     unsigned int offset;/* Offset in archive of the header of this member.  */
  90.     unsigned int data_offset;/* Offset of first data byte of the member.  */
  91.  
  92.     /* The next field does not describe where the member was in the
  93.        old archive, but rather where it will be in the modified archive.
  94.        It is set up by write_archive.  */
  95.     unsigned int new_offset;    /* Offset of this member in new archive */
  96.  
  97.     /* Symdef data for member.  Used only for files being inserted.  */
  98.     struct symdef *symdefs;
  99.     unsigned int nsymdefs;    /* Number of entries of symdef data.  */
  100.     unsigned int string_size;    /* Size of strings needed by symdef data.  */
  101.   };
  102.  
  103. /* Each symbol is recorded by something like this.  */
  104.  
  105. struct symdef
  106.   {
  107.     union
  108.       {
  109.     unsigned long int stringoffset;
  110.     char *name;
  111.       } s;
  112.     unsigned long int offset;
  113.   };
  114.  
  115. /* Nonzero means it's the name of an existing member;
  116.    position new or moved files with respect to this one.  */
  117.  
  118. char *posname;
  119.  
  120.  
  121. /* How to use `posname':
  122.    POS_BEFORE means position before that member.
  123.    POS_AFTER means position after that member.
  124.    POS_DEFAULT if position by default; then `posname' should also be zero. */
  125.  
  126. enum { POS_DEFAULT, POS_BEFORE, POS_AFTER } postype;
  127.  
  128. /* Nonzero means describe each action performed.  */
  129.  
  130. int verbose;
  131.  
  132. /* Nonzero means don't warn about creating the archive file if necessary.  */
  133.  
  134. int silent_create;
  135.  
  136. /* Nonzero means don't replace existing members whose
  137.    dates are more recent than the corresponding files.  */
  138.  
  139. int newer_only;
  140.  
  141. /* Nonzero means preserve dates of members when extracting them.  */
  142.  
  143. int preserve_dates;
  144.  
  145. /* Operation to be performed.  */
  146.  
  147. #define DELETE 1
  148. #define REPLACE 2
  149. #define PRINT_TABLE 3
  150. #define PRINT_FILES 4
  151. #define EXTRACT 5
  152. #define MOVE 6
  153. #define QUICK_APPEND 7
  154.  
  155. int operation;
  156.  
  157. /* Name of archive file.  */
  158.  
  159. char *archive;
  160.  
  161. /* Descriptor on which we have locked the original archive file,
  162.    or -1 if this has not been done.  */
  163.  
  164. int lock_indesc;
  165.  
  166. /* Pointer to tail of `argv', at first subfile name argument,
  167.  or zero if no such were specified.  */
  168.  
  169. char **files;
  170.  
  171. /* Nonzero means write a __.SYMDEF member into the modified archive.  */
  172.  
  173. int symdef_flag;
  174.  
  175. /* Nonzero means __.SYMDEF member exists in old archive.  */
  176.  
  177. int symdef_exists;
  178.  
  179. /* Nonzero means don't update __.SYMDEF unless the flag was given.  */
  180.  
  181. int ignore_symdef;
  182.  
  183. /* Total number of symdef entries we will have. */
  184.  
  185. unsigned long int nsymdefs;
  186.  
  187. /* Symdef data from old archive (set up only if we need it) */
  188.  
  189. struct symdef *old_symdefs;
  190.  
  191. /* Number of symdefs in remaining in old_symdefs.  */
  192.  
  193. unsigned int num_old_symdefs;
  194.  
  195. /* Number of symdefs old_symdefs had when it was read in.  */
  196.  
  197. unsigned long int original_num_symdefs;
  198.  
  199. /* String table from old __.SYMDEF member.  */
  200.  
  201. char *old_strings;
  202.  
  203. /* Size of old_strings */
  204.  
  205. unsigned long int old_strings_size;
  206.  
  207. /* String table to be written into __.SYMDEF member.  */
  208.  
  209. char *new_strings;
  210.  
  211. /* Size of new_strings */
  212.  
  213. unsigned long int new_strings_size;
  214.  
  215. /* An archive map is a chain of these structures.
  216.   Each structure describes one member of the archive.
  217.   The chain is in the same order as the members are.  */
  218.  
  219. struct mapelt
  220.   {
  221.     struct member_desc info;
  222.     struct mapelt *next;
  223.   };
  224.  
  225. struct mapelt *maplast;
  226.  
  227. /* If nonzero, this is the map-element for the __.SYMDEF member
  228.    and we should update the time of that member just before finishing.  */
  229.  
  230. struct mapelt *symdef_mapelt;
  231.  
  232. /* Header that we wrote for the __.SYMDEF member.  */
  233.  
  234. struct ar_hdr symdef_header;
  235.  
  236. char *xmalloc (), *xrealloc ();
  237. void free ();
  238.  
  239. void add_to_map (), delete_from_map ();
  240. int insert_in_map ();
  241. void print_descr ();
  242. char *concat ();
  243. void scan ();
  244. void extract_members ();
  245. void extract_member ();
  246. void print_contents ();
  247. void write_symdef_member ();
  248. void read_old_symdefs ();
  249. void two_operations ();
  250. void usage (), fatal (), error (), error_with_file ();
  251. void perror_with_name (), pfatal_with_name ();
  252. void write_archive ();
  253. void touch_symdef_member ();
  254. void update_symdefs ();
  255. void delete_members (), move_members (), replace_members ();
  256. void quick_append ();
  257.  
  258. /* Output BYTES of data at BUF to the descriptor DESC.
  259.    FILE is the name of the file (for error messages).  */
  260.  
  261. void
  262. mywrite (desc, buf, bytes, file)
  263.      int desc;
  264.      char *buf;
  265.      int bytes;
  266.      char *file;
  267. {
  268.   register int val;
  269.  
  270.   while (bytes > 0)
  271.     {
  272.       val = write (desc, buf, bytes);
  273.       if (val <= 0)
  274.     perror_with_name (file);
  275.       buf += val;
  276.       bytes -= val;
  277.     }
  278. }
  279.  
  280. int
  281. main (argc, argv)
  282.      int argc;
  283.      char **argv;
  284. {
  285.   int i;
  286.  
  287.   operation = 0;
  288.   verbose = 0;
  289.   newer_only = 0;
  290.   silent_create = 0;
  291.   posname = 0;
  292.   postype = POS_DEFAULT;
  293.   preserve_dates = 0;
  294.   symdef_flag = 0;
  295.   symdef_exists = 0;
  296.   ignore_symdef = 0;
  297.   symdef_mapelt = 0;
  298.   files = 0;
  299.   lock_indesc = -1;
  300.  
  301.   if (argc < 2)
  302.     usage ("too few command arguments", 0);
  303.  
  304.   {
  305.     char *key = argv[1];
  306.     char *p = key;
  307.     char c;
  308.  
  309.     while (c = *p++)
  310.       {
  311.     switch (c)
  312.       {
  313.       case 'a':
  314.         postype = POS_AFTER;
  315.         break;
  316.  
  317.       case 'b':
  318.         postype = POS_BEFORE;
  319.         break;
  320.  
  321.       case 'c':
  322.         silent_create = 1;
  323.         break;
  324.  
  325.       case 'd':
  326.         if (operation)
  327.           two_operations ();
  328.  
  329.         operation = DELETE;
  330.         break;
  331.  
  332.       case 'i':
  333.         postype = POS_BEFORE;
  334.         break;
  335.  
  336.       case 'l':
  337.         break;
  338.  
  339.       case 'm':
  340.         if (operation)
  341.           two_operations ();
  342.         operation = MOVE;
  343.         break;
  344.  
  345.       case 'o':
  346.         preserve_dates = 1;
  347.         break;
  348.  
  349.       case 'p':
  350.         if (operation)
  351.           two_operations ();
  352.         operation = PRINT_FILES;
  353.         break;
  354.  
  355.       case 'q':
  356.         if (operation)
  357.           two_operations ();
  358.         operation = QUICK_APPEND;
  359.         break;
  360.  
  361.       case 'r':
  362.         if (operation)
  363.