Home | History | Annotate | Download | only in make-3.81
      1 /* Interface to `ar' archives for GNU Make.
      2 Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
      3 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
      4 Foundation, Inc.
      5 This file is part of GNU Make.
      6 
      7 GNU Make is free software; you can redistribute it and/or modify it under the
      8 terms of the GNU General Public License as published by the Free Software
      9 Foundation; either version 2, or (at your option) any later version.
     10 
     11 GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY
     12 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
     13 A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
     14 
     15 You should have received a copy of the GNU General Public License along with
     16 GNU Make; see the file COPYING.  If not, write to the Free Software
     17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.  */
     18 
     19 #include "make.h"
     20 
     21 #ifndef	NO_ARCHIVES
     22 
     23 #include "filedef.h"
     24 #include "dep.h"
     25 #include <fnmatch.h>
     26 
     27 /* Defined in arscan.c.  */
     28 extern long int ar_scan PARAMS ((char *archive, long int (*function) (), intptr_t arg));
     29 extern int ar_name_equal PARAMS ((char *name, char *mem, int truncated));
     30 #ifndef VMS
     31 extern int ar_member_touch PARAMS ((char *arname, char *memname));
     32 #endif
     33 
     34 /* Return nonzero if NAME is an archive-member reference, zero if not.
     35    An archive-member reference is a name like `lib(member)'.
     36    If a name like `lib((entry))' is used, a fatal error is signaled at
     37    the attempt to use this unsupported feature.  */
     38 
     39 int
     40 ar_name (char *name)
     41 {
     42   char *p = strchr (name, '(');
     43   char *end;
     44 
     45   if (p == 0 || p == name)
     46     return 0;
     47 
     48   end = p + strlen (p) - 1;
     49   if (*end != ')')
     50     return 0;
     51 
     52   if (p[1] == '(' && end[-1] == ')')
     53     fatal (NILF, _("attempt to use unsupported feature: `%s'"), name);
     54 
     55   return 1;
     56 }
     57 
     58 
     59 /* Parse the archive-member reference NAME into the archive and member names.
     60    Put the malloc'd archive name in *ARNAME_P if ARNAME_P is non-nil;
     61    put the malloc'd member name in *MEMNAME_P if MEMNAME_P is non-nil.  */
     62 
     63 void
     64 ar_parse_name (char *name, char **arname_p, char **memname_p)
     65 {
     66   char *p = strchr (name, '('), *end = name + strlen (name) - 1;
     67 
     68   if (arname_p != 0)
     69     *arname_p = savestring (name, p - name);
     70 
     71   if (memname_p != 0)
     72     *memname_p = savestring (p + 1, end - (p + 1));
     73 }
     74 
     75 static long int ar_member_date_1 PARAMS ((int desc, char *mem, int truncated, long int hdrpos,
     77 	long int datapos, long int size, long int date, int uid, int gid, int mode, char *name));
     78 
     79 /* Return the modtime of NAME.  */
     80 
     81 time_t
     82 ar_member_date (char *name)
     83 {
     84   char *arname;
     85   int arname_used = 0;
     86   char *memname;
     87   long int val;
     88 
     89   ar_parse_name (name, &arname, &memname);
     90 
     91   /* Make sure we know the modtime of the archive itself because we are
     92      likely to be called just before commands to remake a member are run,
     93      and they will change the archive itself.
     94 
     95      But we must be careful not to enter_file the archive itself if it does
     96      not exist, because pattern_search assumes that files found in the data
     97      base exist or can be made.  */
     98   {
     99     struct file *arfile;
    100     arfile = lookup_file (arname);
    101     if (arfile == 0 && file_exists_p (arname))
    102       {
    103 	arfile = enter_file (arname);
    104 	arname_used = 1;
    105       }
    106 
    107     if (arfile != 0)
    108       (void) f_mtime (arfile, 0);
    109   }
    110 
    111   val = ar_scan (arname, ar_member_date_1, (intptr_t) memname);
    112 
    113   if (!arname_used)
    114     free (arname);
    115   free (memname);
    116 
    117   return (val <= 0 ? (time_t) -1 : (time_t) val);
    118 }
    119 
    120 /* This function is called by `ar_scan' to find which member to look at.  */
    121 
    122 /* ARGSUSED */
    123 static long int
    124 ar_member_date_1 (int desc UNUSED, char *mem, int truncated,
    125 		  long int hdrpos UNUSED, long int datapos UNUSED,
    126                   long int size UNUSED, long int date,
    127                   int uid UNUSED, int gid UNUSED, int mode UNUSED, char *name)
    128 {
    129   return ar_name_equal (name, mem, truncated) ? date : 0;
    130 }
    131 
    132 /* Set the archive-member NAME's modtime to now.  */
    134 
    135 #ifdef VMS
    136 int
    137 ar_touch (char *name)
    138 {
    139   error (NILF, _("touch archive member is not available on VMS"));
    140   return -1;
    141 }
    142 #else
    143 int
    144 ar_touch (char *name)
    145 {
    146   char *arname, *memname;
    147   int arname_used = 0;
    148   register int val;
    149 
    150   ar_parse_name (name, &arname, &memname);
    151 
    152   /* Make sure we know the modtime of the archive itself before we
    153      touch the member, since this will change the archive itself.  */
    154   {
    155     struct file *arfile;
    156     arfile = lookup_file (arname);
    157     if (arfile == 0)
    158       {
    159 	arfile = enter_file (arname);
    160 	arname_used = 1;
    161       }
    162 
    163     (void) f_mtime (arfile, 0);
    164   }
    165 
    166   val = 1;
    167   switch (ar_member_touch (arname, memname))
    168     {
    169     case -1:
    170       error (NILF, _("touch: Archive `%s' does not exist"), arname);
    171       break;
    172     case -2:
    173       error (NILF, _("touch: `%s' is not a valid archive"), arname);
    174       break;
    175     case -3:
    176       perror_with_name ("touch: ", arname);
    177       break;
    178     case 1:
    179       error (NILF,
    180              _("touch: Member `%s' does not exist in `%s'"), memname, arname);
    181       break;
    182     case 0:
    183       val = 0;
    184       break;
    185     default:
    186       error (NILF,
    187              _("touch: Bad return code from ar_member_touch on `%s'"), name);
    188     }
    189 
    190   if (!arname_used)
    191     free (arname);
    192   free (memname);
    193 
    194   return val;
    195 }
    196 #endif /* !VMS */
    197 
    198 /* State of an `ar_glob' run, passed to `ar_glob_match'.  */
    200 
    201 struct ar_glob_state
    202   {
    203     char *arname;
    204     char *pattern;
    205     unsigned int size;
    206     struct nameseq *chain;
    207     unsigned int n;
    208   };
    209 
    210 /* This function is called by `ar_scan' to match one archive
    211    element against the pattern in STATE.  */
    212 
    213 static long int
    214 ar_glob_match (int desc UNUSED, char *mem, int truncated UNUSED,
    215 	       long int hdrpos UNUSED, long int datapos UNUSED,
    216                long int size UNUSED, long int date UNUSED, int uid UNUSED,
    217                int gid UNUSED, int mode UNUSED, struct ar_glob_state *state)
    218 {
    219   if (fnmatch (state->pattern, mem, FNM_PATHNAME|FNM_PERIOD) == 0)
    220     {
    221       /* We have a match.  Add it to the chain.  */
    222       struct nameseq *new = (struct nameseq *) xmalloc (state->size);
    223       new->name = concat (state->arname, mem, ")");
    224       new->next = state->chain;
    225       state->chain = new;
    226       ++state->n;
    227     }
    228 
    229   return 0L;
    230 }
    231 
    232 /* Return nonzero if PATTERN contains any metacharacters.
    233    Metacharacters can be quoted with backslashes if QUOTE is nonzero.  */
    234 static int
    235 glob_pattern_p (const char *pattern, int quote)
    236 {
    237   const char *p;
    238   int open = 0;
    239 
    240   for (p = pattern; *p != '\0'; ++p)
    241     switch (*p)
    242       {
    243       case '?':
    244       case '*':
    245 	return 1;
    246 
    247       case '\\':
    248 	if (quote)
    249 	  ++p;
    250 	break;
    251 
    252       case '[':
    253 	open = 1;
    254 	break;
    255 
    256       case ']':
    257 	if (open)
    258 	  return 1;
    259 	break;
    260       }
    261 
    262   return 0;
    263 }
    264 
    265 /* Glob for MEMBER_PATTERN in archive ARNAME.
    266    Return a malloc'd chain of matching elements (or nil if none).  */
    267 
    268 struct nameseq *
    269 ar_glob (char *arname, char *member_pattern, unsigned int size)
    270 {
    271   struct ar_glob_state state;
    272   char **names;
    273   struct nameseq *n;
    274   unsigned int i;
    275 
    276   if (! glob_pattern_p (member_pattern, 1))
    277     return 0;
    278 
    279   /* Scan the archive for matches.
    280      ar_glob_match will accumulate them in STATE.chain.  */
    281   i = strlen (arname);
    282   state.arname = (char *) alloca (i + 2);
    283   bcopy (arname, state.arname, i);
    284   state.arname[i] = '(';
    285   state.arname[i + 1] = '\0';
    286   state.pattern = member_pattern;
    287   state.size = size;
    288   state.chain = 0;
    289   state.n = 0;
    290   (void) ar_scan (arname, ar_glob_match, (intptr_t) &state);
    291 
    292   if (state.chain == 0)
    293     return 0;
    294 
    295   /* Now put the names into a vector for sorting.  */
    296   names = (char **) alloca (state.n * sizeof (char *));
    297   i = 0;
    298   for (n = state.chain; n != 0; n = n->next)
    299     names[i++] = n->name;
    300 
    301   /* Sort them alphabetically.  */
    302   qsort ((char *) names, i, sizeof (*names), alpha_compare);
    303 
    304   /* Put them back into the chain in the sorted order.  */
    305   i = 0;
    306   for (n = state.chain; n != 0; n = n->next)
    307     n->name = names[i++];
    308 
    309   return state.chain;
    310 }
    311 
    312 #endif	/* Not NO_ARCHIVES.  */
    313