1 1.1 christos /* Library function for scanning an archive file. 2 1.1 christos Copyright (C) 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 3 1.1 christos 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, 4 1.1 christos Inc. 5 1.1 christos This file is part of GNU Make. 6 1.1 christos 7 1.1 christos GNU Make is free software; you can redistribute it and/or modify it under the 8 1.1 christos terms of the GNU General Public License as published by the Free Software 9 1.1 christos Foundation; either version 2, or (at your option) any later version. 10 1.1 christos 11 1.1 christos GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY 12 1.1 christos WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 1.1 christos A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 1.1 christos 15 1.1 christos You should have received a copy of the GNU General Public License along with 16 1.1 christos GNU Make; see the file COPYING. If not, write to the Free Software 17 1.1 christos Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ 18 1.1 christos 19 1.1 christos #include "make.h" 20 1.1 christos 21 1.1 christos #ifdef HAVE_FCNTL_H 22 1.1 christos #include <fcntl.h> 23 1.1 christos #else 24 1.1 christos #include <sys/file.h> 25 1.1 christos #endif 26 1.1 christos 27 1.1 christos #ifndef NO_ARCHIVES 28 1.1 christos 29 1.1 christos #ifdef VMS 31 1.1 christos #include <lbrdef.h> 32 1.1 christos #include <mhddef.h> 33 1.1 christos #include <credef.h> 34 1.1 christos #include <descrip.h> 35 1.1 christos #include <ctype.h> 36 1.1 christos #if __DECC 37 1.1 christos #include <unixlib.h> 38 1.1 christos #include <lbr$routines.h> 39 1.1 christos #endif 40 1.1 christos 41 1.1 christos static void *VMS_lib_idx; 42 1.1 christos 43 1.1 christos static char *VMS_saved_memname; 44 1.1 christos 45 1.1 christos static time_t VMS_member_date; 46 1.1 christos 47 1.1 christos static long int (*VMS_function) (); 48 1.1 christos 49 1.1 christos static int 50 1.1 christos VMS_get_member_info (struct dsc$descriptor_s *module, unsigned long *rfa) 51 1.1 christos { 52 1.1 christos int status, i; 53 1.1 christos long int fnval; 54 1.1 christos 55 1.1 christos time_t val; 56 1.1 christos 57 1.1 christos static struct dsc$descriptor_s bufdesc = 58 1.1 christos { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL }; 59 1.1 christos 60 1.1 christos struct mhddef *mhd; 61 1.1 christos char filename[128]; 62 1.1 christos 63 1.1 christos bufdesc.dsc$a_pointer = filename; 64 1.1 christos bufdesc.dsc$w_length = sizeof (filename); 65 1.1 christos 66 1.1 christos status = lbr$set_module (&VMS_lib_idx, rfa, &bufdesc, 67 1.1 christos &bufdesc.dsc$w_length, 0); 68 1.1 christos if (! (status & 1)) 69 1.1 christos { 70 1.1 christos error (NILF, _("lbr$set_module failed to extract module info, status = %d"), 71 1.1 christos status); 72 1.1 christos 73 1.1 christos lbr$close (&VMS_lib_idx); 74 1.1 christos 75 1.1 christos return 0; 76 1.1 christos } 77 1.1 christos 78 1.1 christos mhd = (struct mhddef *) filename; 79 1.1 christos 80 1.1 christos #ifdef __DECC 81 1.1 christos /* John Fowler <jfowler (at) nyx.net> writes this is needed in his environment, 82 1.1 christos * but that decc$fix_time() isn't documented to work this way. Let me 83 1.1 christos * know if this causes problems in other VMS environments. 84 1.1 christos */ 85 1.1 christos val = decc$fix_time (&mhd->mhd$l_datim) + timezone - daylight*3600; 86 1.1 christos #endif 87 1.1 christos 88 1.1 christos for (i = 0; i < module->dsc$w_length; i++) 89 1.1 christos filename[i] = _tolower ((unsigned char)module->dsc$a_pointer[i]); 90 1.1 christos 91 1.1 christos filename[i] = '\0'; 92 1.1 christos 93 1.1 christos VMS_member_date = (time_t) -1; 94 1.1 christos 95 1.1 christos fnval = 96 1.1 christos (*VMS_function) (-1, filename, 0, 0, 0, 0, val, 0, 0, 0, 97 1.1 christos VMS_saved_memname); 98 1.1 christos 99 1.1 christos if (fnval) 100 1.1 christos { 101 1.1 christos VMS_member_date = fnval; 102 1.1 christos return 0; 103 1.1 christos } 104 1.1 christos else 105 1.1 christos return 1; 106 1.1 christos } 107 1.1 christos 108 1.1 christos /* Takes three arguments ARCHIVE, FUNCTION and ARG. 109 1.1 christos 110 1.1 christos Open the archive named ARCHIVE, find its members one by one, 111 1.1 christos and for each one call FUNCTION with the following arguments: 112 1.1 christos archive file descriptor for reading the data, 113 1.1 christos member name, 114 1.1 christos member name might be truncated flag, 115 1.1 christos member header position in file, 116 1.1 christos member data position in file, 117 1.1 christos member data size, 118 1.1 christos member date, 119 1.1 christos member uid, 120 1.1 christos member gid, 121 1.1 christos member protection mode, 122 1.1 christos ARG. 123 1.1 christos 124 1.1 christos NOTE: on VMS systems, only name, date, and arg are meaningful! 125 1.1 christos 126 1.1 christos The descriptor is poised to read the data of the member 127 1.1 christos when FUNCTION is called. It does not matter how much 128 1.1 christos data FUNCTION reads. 129 1.1 christos 130 1.1 christos If FUNCTION returns nonzero, we immediately return 131 1.1 christos what FUNCTION returned. 132 1.1 christos 133 1.1 christos Returns -1 if archive does not exist, 134 1.1 christos Returns -2 if archive has invalid format. 135 1.1 christos Returns 0 if have scanned successfully. */ 136 1.1 christos 137 1.4 oster long int 138 1.1 christos ar_scan (char *archive, long int (*function) PARAMS ((int, char *, int, long int, long int, long int, long int, int, int, int, void *)), void *arg) 139 1.1 christos { 140 1.1 christos char *p; 141 1.1 christos 142 1.1 christos static struct dsc$descriptor_s libdesc = 143 1.1 christos { 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL }; 144 1.1 christos 145 1.1 christos unsigned long func = LBR$C_READ; 146 1.1 christos unsigned long type = LBR$C_TYP_UNK; 147 1.1 christos unsigned long index = 1; 148 1.1 christos 149 1.1 christos int status; 150 1.1 christos 151 1.1 christos status = lbr$ini_control (&VMS_lib_idx, &func, &type, 0); 152 1.1 christos 153 1.1 christos if (! (status & 1)) 154 1.1 christos { 155 1.1 christos error (NILF, _("lbr$ini_control failed with status = %d"),status); 156 1.1 christos return -2; 157 1.1 christos } 158 1.1 christos 159 1.1 christos libdesc.dsc$a_pointer = archive; 160 1.1 christos libdesc.dsc$w_length = strlen (archive); 161 1.1 christos 162 1.1 christos status = lbr$open (&VMS_lib_idx, &libdesc, 0, 0, 0, 0, 0); 163 1.1 christos 164 1.1 christos if (! (status & 1)) 165 1.1 christos { 166 1.1 christos error (NILF, _("unable to open library `%s' to lookup member `%s'"), 167 1.1 christos archive, (char *)arg); 168 1.1 christos return -1; 169 1.1 christos } 170 1.1 christos 171 1.1 christos VMS_saved_memname = (char *)arg; 172 1.1 christos 173 1.1 christos /* For comparison, delete .obj from arg name. */ 174 1.1 christos 175 1.1 christos p = strrchr (VMS_saved_memname, '.'); 176 1.1 christos if (p) 177 1.1 christos *p = '\0'; 178 1.1 christos 179 1.1 christos VMS_function = function; 180 1.1 christos 181 1.1 christos VMS_member_date = (time_t) -1; 182 1.1 christos lbr$get_index (&VMS_lib_idx, &index, VMS_get_member_info, 0); 183 1.1 christos 184 1.1 christos /* Undo the damage. */ 185 1.1 christos if (p) 186 1.1 christos *p = '.'; 187 1.1 christos 188 1.1 christos lbr$close (&VMS_lib_idx); 189 1.1 christos 190 1.1 christos return VMS_member_date > 0 ? VMS_member_date : 0; 191 1.1 christos } 192 1.1 christos 193 1.1 christos #else /* !VMS */ 194 1.1 christos 195 1.1 christos /* SCO Unix's compiler defines both of these. */ 196 1.1 christos #ifdef M_UNIX 197 1.1 christos #undef M_XENIX 198 1.1 christos #endif 199 1.1 christos 200 1.1 christos /* On the sun386i and in System V rel 3, ar.h defines two different archive 201 1.1 christos formats depending upon whether you have defined PORTAR (normal) or PORT5AR 202 1.1 christos (System V Release 1). There is no default, one or the other must be defined 203 1.1 christos to have a nonzero value. */ 204 1.1 christos 205 1.1 christos #if (!defined (PORTAR) || PORTAR == 0) && (!defined (PORT5AR) || PORT5AR == 0) 206 1.1 christos #undef PORTAR 207 1.1 christos #ifdef M_XENIX 208 1.1 christos /* According to Jim Sievert <jas1 (at) rsvl.unisys.com>, for SCO XENIX defining 209 1.1 christos PORTAR to 1 gets the wrong archive format, and defining it to 0 gets the 210 1.1 christos right one. */ 211 1.1 christos #define PORTAR 0 212 1.1 christos #else 213 1.1 christos #define PORTAR 1 214 1.1 christos #endif 215 1.1 christos #endif 216 1.1 christos 217 1.1 christos /* On AIX, define these symbols to be sure to get both archive formats. 218 1.1 christos AIX 4.3 introduced the "big" archive format to support 64-bit object 219 1.1 christos files, so on AIX 4.3 systems we need to support both the "normal" and 220 1.1 christos "big" archive formats. An archive's format is indicated in the 221 1.1 christos "fl_magic" field of the "FL_HDR" structure. For a normal archive, 222 1.1 christos this field will be the string defined by the AIAMAG symbol. For a 223 1.1 christos "big" archive, it will be the string defined by the AIAMAGBIG symbol 224 1.1 christos (at least on AIX it works this way). 225 1.1 christos 226 1.1 christos Note: we'll define these symbols regardless of which AIX version 227 1.1 christos we're compiling on, but this is okay since we'll use the new symbols 228 1.1 christos only if they're present. */ 229 1.1 christos #ifdef _AIX 230 1.1 christos # define __AR_SMALL__ 231 1.1 christos # define __AR_BIG__ 232 1.1 christos #endif 233 1.1 christos 234 1.1 christos #ifndef WINDOWS32 235 1.1 christos # ifndef __BEOS__ 236 1.1 christos # include <ar.h> 237 1.1 christos # else 238 1.1 christos /* BeOS 5 doesn't have <ar.h> but has archives in the same format 239 1.1 christos * as many other Unices. This was taken from GNU binutils for BeOS. 240 1.1 christos */ 241 1.1 christos # define ARMAG "!<arch>\n" /* String that begins an archive file. */ 242 1.1 christos # define SARMAG 8 /* Size of that string. */ 243 1.1 christos # define ARFMAG "`\n" /* String in ar_fmag at end of each header. */ 244 1.1 christos struct ar_hdr 245 1.1 christos { 246 1.1 christos char ar_name[16]; /* Member file name, sometimes / terminated. */ 247 1.1 christos char ar_date[12]; /* File date, decimal seconds since Epoch. */ 248 1.1 christos char ar_uid[6], ar_gid[6]; /* User and group IDs, in ASCII decimal. */ 249 1.1 christos char ar_mode[8]; /* File mode, in ASCII octal. */ 250 1.1 christos char ar_size[10]; /* File size, in ASCII decimal. */ 251 1.1 christos char ar_fmag[2]; /* Always contains ARFMAG. */ 252 1.1 christos }; 253 1.1 christos # endif 254 1.1 christos #else 255 1.1 christos /* These should allow us to read Windows (VC++) libraries (according to Frank 256 1.1 christos * Libbrecht <frankl (at) abzx.belgium.hp.com>) 257 1.1 christos */ 258 1.1 christos # include <windows.h> 259 1.1 christos # include <windef.h> 260 1.1 christos # include <io.h> 261 1.1 christos # define ARMAG IMAGE_ARCHIVE_START 262 1.1 christos # define SARMAG IMAGE_ARCHIVE_START_SIZE 263 1.1 christos # define ar_hdr _IMAGE_ARCHIVE_MEMBER_HEADER 264 1.1 christos # define ar_name Name 265 1.1 christos # define ar_mode Mode 266 1.1 christos # define ar_size Size 267 1.1 christos # define ar_date Date 268 1.1 christos # define ar_uid UserID 269 1.1 christos # define ar_gid GroupID 270 1.1 christos #endif 271 1.1 christos 272 1.1 christos /* Cray's <ar.h> apparently defines this. */ 273 1.1 christos #ifndef AR_HDR_SIZE 274 1.1 christos # define AR_HDR_SIZE (sizeof (struct ar_hdr)) 275 1.1 christos #endif 276 1.1 christos 277 1.1 christos /* Takes three arguments ARCHIVE, FUNCTION and ARG. 279 1.1 christos 280 1.1 christos Open the archive named ARCHIVE, find its members one by one, 281 1.1 christos and for each one call FUNCTION with the following arguments: 282 1.1 christos archive file descriptor for reading the data, 283 1.1 christos member name, 284 1.1 christos member name might be truncated flag, 285 1.1 christos member header position in file, 286 1.1 christos member data position in file, 287 1.1 christos member data size, 288 1.1 christos member date, 289 1.1 christos member uid, 290 1.1 christos member gid, 291 1.1 christos member protection mode, 292 1.1 christos ARG. 293 1.1 christos 294 1.1 christos The descriptor is poised to read the data of the member 295 1.1 christos when FUNCTION is called. It does not matter how much 296 1.1 christos data FUNCTION reads. 297 1.1 christos 298 1.1 christos If FUNCTION returns nonzero, we immediately return 299 1.1 christos what FUNCTION returned. 300 1.1 christos 301 1.1 christos Returns -1 if archive does not exist, 302 1.1 christos Returns -2 if archive has invalid format. 303 1.1 christos Returns 0 if have scanned successfully. */ 304 1.4 oster 305 1.1 christos long int 306 1.1 christos ar_scan (char *archive, long int (*function)(int, char *, int, long int, long int, long int, long int, int, int, int, void *), void *arg) 307 1.1 christos { 308 1.1 christos #ifdef AIAMAG 309 1.1 christos FL_HDR fl_header; 310 1.1 christos #ifdef AIAMAGBIG 311 1.1 christos int big_archive = 0; 312 1.1 christos FL_HDR_BIG fl_header_big; 313 1.1 christos #endif 314 1.1 christos #else 315 1.1 christos int long_name = 0; 316 1.1 christos #endif 317 1.1 christos char *namemap = 0; 318 1.1 christos register int desc = open (archive, O_RDONLY, 0); 319 1.1 christos if (desc < 0) 320 1.1 christos return -1; 321 1.1 christos #ifdef SARMAG 322 1.1 christos { 323 1.1 christos char buf[SARMAG]; 324 1.1 christos register int nread = read (desc, buf, SARMAG); 325 1.1 christos if (nread != SARMAG || bcmp (buf, ARMAG, SARMAG)) 326 1.1 christos { 327 1.1 christos (void) close (desc); 328 1.1 christos return -2; 329 1.1 christos } 330 1.1 christos } 331 1.1 christos #else 332 1.1 christos #ifdef AIAMAG 333 1.1 christos { 334 1.1 christos register int nread = read (desc, (char *) &fl_header, FL_HSZ); 335 1.1 christos 336 1.1 christos if (nread != FL_HSZ) 337 1.1 christos { 338 1.1 christos (void) close (desc); 339 1.1 christos return -2; 340 1.1 christos } 341 1.1 christos #ifdef AIAMAGBIG 342 1.1 christos /* If this is a "big" archive, then set the flag and 343 1.1 christos re-read the header into the "big" structure. */ 344 1.1 christos if (!bcmp (fl_header.fl_magic, AIAMAGBIG, SAIAMAG)) 345 1.1 christos { 346 1.1 christos big_archive = 1; 347 1.1 christos 348 1.1 christos /* seek back to beginning of archive */ 349 1.1 christos if (lseek (desc, 0, 0) < 0) 350 1.1 christos { 351 1.1 christos (void) close (desc); 352 1.1 christos return -2; 353 1.1 christos } 354 1.1 christos 355 1.1 christos /* re-read the header into the "big" structure */ 356 1.1 christos nread = read (desc, (char *) &fl_header_big, FL_HSZ_BIG); 357 1.1 christos if (nread != FL_HSZ_BIG) 358 1.1 christos { 359 1.1 christos (void) close (desc); 360 1.1 christos return -2; 361 1.1 christos } 362 1.1 christos } 363 1.1 christos else 364 1.1 christos #endif 365 1.1 christos /* Check to make sure this is a "normal" archive. */ 366 1.1 christos if (bcmp (fl_header.fl_magic, AIAMAG, SAIAMAG)) 367 1.1 christos { 368 1.1 christos (void) close (desc); 369 1.1 christos return -2; 370 1.1 christos } 371 1.1 christos } 372 1.1 christos #else 373 1.1 christos { 374 1.1 christos #ifndef M_XENIX 375 1.1 christos int buf; 376 1.1 christos #else 377 1.1 christos unsigned short int buf; 378 1.1 christos #endif 379 1.1 christos register int nread = read(desc, &buf, sizeof (buf)); 380 1.1 christos if (nread != sizeof (buf) || buf != ARMAG) 381 1.1 christos { 382 1.1 christos (void) close (desc); 383 1.1 christos return -2; 384 1.1 christos } 385 1.1 christos } 386 1.1 christos #endif 387 1.1 christos #endif 388 1.1 christos 389 1.1 christos /* Now find the members one by one. */ 390 1.1 christos { 391 1.1 christos #ifdef SARMAG 392 1.1 christos register long int member_offset = SARMAG; 393 1.1 christos #else 394 1.1 christos #ifdef AIAMAG 395 1.1 christos long int member_offset; 396 1.1 christos long int last_member_offset; 397 1.1 christos 398 1.1 christos #ifdef AIAMAGBIG 399 1.1 christos if ( big_archive ) 400 1.1 christos { 401 1.1 christos sscanf (fl_header_big.fl_fstmoff, "%20ld", &member_offset); 402 1.1 christos sscanf (fl_header_big.fl_lstmoff, "%20ld", &last_member_offset); 403 1.1 christos } 404 1.1 christos else 405 1.1 christos #endif 406 1.1 christos { 407 1.1 christos sscanf (fl_header.fl_fstmoff, "%12ld", &member_offset); 408 1.1 christos sscanf (fl_header.fl_lstmoff, "%12ld", &last_member_offset); 409 1.1 christos } 410 1.1 christos 411 1.1 christos if (member_offset == 0) 412 1.1 christos { 413 1.1 christos /* Empty archive. */ 414 1.1 christos close (desc); 415 1.1 christos return 0; 416 1.1 christos } 417 1.1 christos #else 418 1.1 christos #ifndef M_XENIX 419 1.1 christos register long int member_offset = sizeof (int); 420 1.1 christos #else /* Xenix. */ 421 1.1 christos register long int member_offset = sizeof (unsigned short int); 422 1.1 christos #endif /* Not Xenix. */ 423 1.1 christos #endif 424 1.1 christos #endif 425 1.1 christos 426 1.1 christos while (1) 427 1.1 christos { 428 1.1 christos register int nread; 429 1.1 christos struct ar_hdr member_header; 430 1.1 christos #ifdef AIAMAGBIG 431 1.1 christos struct ar_hdr_big member_header_big; 432 1.1 christos #endif 433 1.1 christos #ifdef AIAMAG 434 1.1 christos char name[256]; 435 1.1 christos int name_len; 436 1.1 christos long int dateval; 437 1.1 christos int uidval, gidval; 438 1.1 christos long int data_offset; 439 1.1 christos #else 440 1.1 christos char namebuf[sizeof member_header.ar_name + 1]; 441 1.1 christos char *name; 442 1.1 christos int is_namemap; /* Nonzero if this entry maps long names. */ 443 1.1 christos #endif 444 1.1 christos long int eltsize; 445 1.1 christos int eltmode; 446 1.1 christos long int fnval; 447 1.1 christos 448 1.1 christos if (lseek (desc, member_offset, 0) < 0) 449 1.1 christos { 450 1.1 christos (void) close (desc); 451 1.1 christos return -2; 452 1.1 christos } 453 1.1 christos 454 1.1 christos #ifdef AIAMAG 455 1.1 christos #define AR_MEMHDR_SZ(x) (sizeof(x) - sizeof (x._ar_name)) 456 1.1 christos 457 1.1 christos #ifdef AIAMAGBIG 458 1.1 christos if (big_archive) 459 1.1 christos { 460 1.1 christos nread = read (desc, (char *) &member_header_big, 461 1.1 christos AR_MEMHDR_SZ(member_header_big) ); 462 1.1 christos 463 1.1 christos if (nread != AR_MEMHDR_SZ(member_header_big)) 464 1.1 christos { 465 1.1 christos (void) close (desc); 466 1.1 christos return -2; 467 1.1 christos } 468 1.1 christos 469 1.1 christos sscanf (member_header_big.ar_namlen, "%4d", &name_len); 470 1.1 christos nread = read (desc, name, name_len); 471 1.1 christos 472 1.1 christos if (nread != name_len) 473 1.1 christos { 474 1.1 christos (void) close (desc); 475 1.1 christos return -2; 476 1.1 christos } 477 1.1 christos 478 1.1 christos name[name_len] = 0; 479 1.1 christos 480 1.1 christos sscanf (member_header_big.ar_date, "%12ld", &dateval); 481 1.1 christos sscanf (member_header_big.ar_uid, "%12d", &uidval); 482 1.1 christos sscanf (member_header_big.ar_gid, "%12d", &gidval); 483 1.1 christos sscanf (member_header_big.ar_mode, "%12o", &eltmode); 484 1.1 christos sscanf (member_header_big.ar_size, "%20ld", &eltsize); 485 1.1 christos 486 1.1 christos data_offset = (member_offset + AR_MEMHDR_SZ(member_header_big) 487 1.1 christos + name_len + 2); 488 1.1 christos } 489 1.1 christos else 490 1.1 christos #endif 491 1.1 christos { 492 1.1 christos nread = read (desc, (char *) &member_header, 493 1.1 christos AR_MEMHDR_SZ(member_header) ); 494 1.1 christos 495 1.1 christos if (nread != AR_MEMHDR_SZ(member_header)) 496 1.1 christos { 497 1.1 christos (void) close (desc); 498 1.1 christos return -2; 499 1.1 christos } 500 1.1 christos 501 1.1 christos sscanf (member_header.ar_namlen, "%4d", &name_len); 502 1.1 christos nread = read (desc, name, name_len); 503 1.1 christos 504 1.1 christos if (nread != name_len) 505 1.1 christos { 506 1.1 christos (void) close (desc); 507 1.1 christos return -2; 508 1.1 christos } 509 1.1 christos 510 1.1 christos name[name_len] = 0; 511 1.1 christos 512 1.1 christos sscanf (member_header.ar_date, "%12ld", &dateval); 513 1.1 christos sscanf (member_header.ar_uid, "%12d", &uidval); 514 1.1 christos sscanf (member_header.ar_gid, "%12d", &gidval); 515 1.1 christos sscanf (member_header.ar_mode, "%12o", &eltmode); 516 1.1 christos sscanf (member_header.ar_size, "%12ld", &eltsize); 517 1.1 christos 518 1.1 christos data_offset = (member_offset + AR_MEMHDR_SZ(member_header) 519 1.1 christos + name_len + 2); 520 1.1 christos } 521 1.1 christos data_offset += data_offset % 2; 522 1.1 christos 523 1.1 christos fnval = 524 1.1 christos (*function) (desc, name, 0, 525 1.1 christos member_offset, data_offset, eltsize, 526 1.1 christos dateval, uidval, gidval, 527 1.1 christos eltmode, arg); 528 1.1 christos 529 1.1 christos #else /* Not AIAMAG. */ 530 1.1 christos nread = read (desc, (char *) &member_header, AR_HDR_SIZE); 531 1.1 christos if (nread == 0) 532 1.1 christos /* No data left means end of file; that is OK. */ 533 1.1 christos break; 534 1.1 christos 535 1.1 christos if (nread != AR_HDR_SIZE 536 1.1 christos #if defined(ARFMAG) || defined(ARFZMAG) 537 1.1 christos || ( 538 1.1 christos # ifdef ARFMAG 539 1.1 christos bcmp (member_header.ar_fmag, ARFMAG, 2) 540 1.1 christos # else 541 1.1 christos 1 542 1.1 christos # endif 543 1.1 christos && 544 1.1 christos # ifdef ARFZMAG 545 1.1 christos bcmp (member_header.ar_fmag, ARFZMAG, 2) 546 1.1 christos # else 547 1.1 christos 1 548 1.1 christos # endif 549 1.1 christos ) 550 1.1 christos #endif 551 1.1 christos ) 552 1.1 christos { 553 1.1 christos (void) close (desc); 554 1.1 christos return -2; 555 1.1 christos } 556 1.1 christos 557 1.1 christos name = namebuf; 558 1.1 christos bcopy (member_header.ar_name, name, sizeof member_header.ar_name); 559 1.1 christos { 560 1.1 christos register char *p = name + sizeof member_header.ar_name; 561 1.1 christos do 562 1.1 christos *p = '\0'; 563 1.1 christos while (p > name && *--p == ' '); 564 1.1 christos 565 1.1 christos #ifndef AIAMAG 566 1.1 christos /* If the member name is "//" or "ARFILENAMES/" this may be 567 1.1 christos a list of file name mappings. The maximum file name 568 1.1 christos length supported by the standard archive format is 14 569 1.1 christos characters. This member will actually always be the 570 1.1 christos first or second entry in the archive, but we don't check 571 1.1 christos that. */ 572 1.1 christos is_namemap = (!strcmp (name, "//") 573 1.1 christos || !strcmp (name, "ARFILENAMES/")); 574 1.1 christos #endif /* Not AIAMAG. */ 575 1.1 christos /* On some systems, there is a slash after each member name. */ 576 1.1 christos if (*p == '/') 577 1.1 christos *p = '\0'; 578 1.1 christos 579 1.1 christos #ifndef AIAMAG 580 1.1 christos /* If the member name starts with a space or a slash, this 581 1.1 christos is an index into the file name mappings (used by GNU ar). 582 1.1 christos Otherwise if the member name looks like #1/NUMBER the 583 1.1 christos real member name appears in the element data (used by 584 1.1 christos 4.4BSD). */ 585 1.1 christos if (! is_namemap 586 1.1 christos && (name[0] == ' ' || name[0] == '/') 587 1.1 christos && namemap != 0) 588 1.1 christos { 589 1.1 christos name = namemap + atoi (name + 1); 590 1.1 christos long_name = 1; 591 1.1 christos } 592 1.1 christos else if (name[0] == '#' 593 1.1 christos && name[1] == '1' 594 1.1 christos && name[2] == '/') 595 1.1 christos { 596 1.1 christos int namesize = atoi (name + 3); 597 1.1 christos 598 1.1 christos name = (char *) alloca (namesize + 1); 599 1.1 christos nread = read (desc, name, namesize); 600 1.1 christos if (nread != namesize) 601 1.1 christos { 602 1.1 christos close (desc); 603 1.1 christos return -2; 604 1.1 christos } 605 1.1 christos name[namesize] = '\0'; 606 1.1 christos 607 1.1 christos long_name = 1; 608 1.1 christos } 609 1.1 christos #endif /* Not AIAMAG. */ 610 1.1 christos } 611 1.1 christos 612 1.1 christos #ifndef M_XENIX 613 1.1 christos sscanf (member_header.ar_mode, "%o", &eltmode); 614 1.1 christos eltsize = atol (member_header.ar_size); 615 1.1 christos #else /* Xenix. */ 616 1.1 christos eltmode = (unsigned short int) member_header.ar_mode; 617 1.1 christos eltsize = member_header.ar_size; 618 1.1 christos #endif /* Not Xenix. */ 619 1.1 christos 620 1.1 christos fnval = 621 1.1 christos (*function) (desc, name, ! long_name, member_offset, 622 1.1 christos member_offset + AR_HDR_SIZE, eltsize, 623 1.1 christos #ifndef M_XENIX 624 1.1 christos atol (member_header.ar_date), 625 1.1 christos atoi (member_header.ar_uid), 626 1.1 christos atoi (member_header.ar_gid), 627 1.1 christos #else /* Xenix. */ 628 1.1 christos member_header.ar_date, 629 1.1 christos member_header.ar_uid, 630 1.1 christos member_header.ar_gid, 631 1.1 christos #endif /* Not Xenix. */ 632 1.1 christos eltmode, arg); 633 1.1 christos 634 1.1 christos #endif /* AIAMAG. */ 635 1.1 christos 636 1.1 christos if (fnval) 637 1.1 christos { 638 1.1 christos (void) close (desc); 639 1.1 christos return fnval; 640 1.1 christos } 641 1.1 christos 642 1.1 christos #ifdef AIAMAG 643 1.1 christos if (member_offset == last_member_offset) 644 1.1 christos /* End of the chain. */ 645 1.1 christos break; 646 1.1 christos 647 1.1 christos #ifdef AIAMAGBIG 648 1.1 christos if (big_archive) 649 1.1 christos sscanf (member_header_big.ar_nxtmem, "%20ld", &member_offset); 650 1.1 christos else 651 1.1 christos #endif 652 1.1 christos sscanf (member_header.ar_nxtmem, "%12ld", &member_offset); 653 1.1 christos 654 1.1 christos if (lseek (desc, member_offset, 0) != member_offset) 655 1.1 christos { 656 1.1 christos (void) close (desc); 657 1.1 christos return -2; 658 1.1 christos } 659 1.1 christos #else 660 1.1 christos 661 1.1 christos /* If this member maps archive names, we must read it in. The 662 1.1 christos name map will always precede any members whose names must 663 1.1 christos be mapped. */ 664 1.1 christos if (is_namemap) 665 1.1 christos { 666 1.1 christos char *clear; 667 1.1 christos char *limit; 668 1.1 christos 669 1.1 christos namemap = (char *) alloca (eltsize); 670 1.1 christos nread = read (desc, namemap, eltsize); 671 1.1 christos if (nread != eltsize) 672 1.1 christos { 673 1.1 christos (void) close (desc); 674 1.1 christos return -2; 675 1.1 christos } 676 1.1 christos 677 1.1 christos /* The names are separated by newlines. Some formats have 678 1.1 christos a trailing slash. Null terminate the strings for 679 1.1 christos convenience. */ 680 1.1 christos limit = namemap + eltsize; 681 1.1 christos for (clear = namemap; clear < limit; clear++) 682 1.1 christos { 683 1.1 christos if (*clear == '\n') 684 1.1 christos { 685 1.1 christos *clear = '\0'; 686 1.1 christos if (clear[-1] == '/') 687 1.1 christos clear[-1] = '\0'; 688 1.1 christos } 689 1.1 christos } 690 1.1 christos 691 1.1 christos is_namemap = 0; 692 1.1 christos } 693 1.1 christos 694 1.1 christos member_offset += AR_HDR_SIZE + eltsize; 695 1.1 christos if (member_offset % 2 != 0) 696 1.1 christos member_offset++; 697 1.1 christos #endif 698 1.1 christos } 699 1.1 christos } 700 1.1 christos 701 1.1 christos close (desc); 702 1.1 christos return 0; 703 1.1 christos } 704 1.1 christos #endif /* !VMS */ 705 1.1 christos 706 1.1 christos /* Return nonzero iff NAME matches MEM. 708 1.1 christos If TRUNCATED is nonzero, MEM may be truncated to 709 1.1 christos sizeof (struct ar_hdr.ar_name) - 1. */ 710 1.1 christos 711 1.1 christos int 712 1.1 christos ar_name_equal (char *name, char *mem, int truncated) 713 1.1 christos { 714 1.1 christos char *p; 715 1.1 christos 716 1.1 christos p = strrchr (name, '/'); 717 1.1 christos if (p != 0) 718 1.1 christos name = p + 1; 719 1.1 christos 720 1.1 christos #ifndef VMS 721 1.1 christos if (truncated) 722 1.1 christos { 723 1.1 christos #ifdef AIAMAG 724 1.1 christos /* TRUNCATED should never be set on this system. */ 725 1.1 christos abort (); 726 1.1 christos #else 727 1.1 christos struct ar_hdr hdr; 728 1.1 christos #if !defined (__hpux) && !defined (cray) 729 1.1 christos return strneq (name, mem, sizeof(hdr.ar_name) - 1); 730 1.1 christos #else 731 1.1 christos return strneq (name, mem, sizeof(hdr.ar_name) - 2); 732 1.1 christos #endif /* !__hpux && !cray */ 733 1.1 christos #endif /* !AIAMAG */ 734 1.1 christos } 735 1.1 christos #endif /* !VMS */ 736 1.1 christos 737 1.1 christos return !strcmp (name, mem); 738 1.1 christos } 739 1.1 christos 740 1.1 christos #ifndef VMS 742 1.1 christos /* ARGSUSED */ 743 1.4 oster static long int 744 1.1 christos ar_member_pos (int desc UNUSED, char *mem, int truncated, 745 1.1 christos long int hdrpos, long int datapos UNUSED, long int size UNUSED, 746 1.1 christos long int date UNUSED, int uid UNUSED, int gid UNUSED, 747 1.1 christos int mode UNUSED, void *name) 748 1.1 christos { 749 1.1 christos if (!ar_name_equal (name, mem, truncated)) 750 1.1 christos return 0; 751 1.1 christos return hdrpos; 752 1.1 christos } 753 1.1 christos 754 1.1 christos /* Set date of member MEMNAME in archive ARNAME to current time. 755 1.1 christos Returns 0 if successful, 756 1.1 christos -1 if file ARNAME does not exist, 757 1.1 christos -2 if not a valid archive, 758 1.1 christos -3 if other random system call error (including file read-only), 759 1.1 christos 1 if valid but member MEMNAME does not exist. */ 760 1.4 oster 761 1.1 christos int 762 1.1 christos ar_member_touch (char *arname, char *memname) 763 1.1 christos { 764 1.1 christos long int pos = ar_scan (arname, ar_member_pos, memname); 765 1.1 christos int fd; 766 1.1 christos struct ar_hdr ar_hdr; 767 1.1 christos int i; 768 1.1 christos unsigned int ui; 769 1.1 christos struct stat statbuf; 770 1.1 christos 771 1.1 christos if (pos < 0) 772 1.1 christos return (int) pos; 773 1.1 christos if (!pos) 774 1.1 christos return 1; 775 1.1 christos 776 1.1 christos fd = open (arname, O_RDWR, 0666); 777 1.1 christos if (fd < 0) 778 1.1 christos return -3; 779 1.1 christos /* Read in this member's header */ 780 1.1 christos if (lseek (fd, pos, 0) < 0) 781 1.1 christos goto lose; 782 1.1 christos if (AR_HDR_SIZE != read (fd, (char *) &ar_hdr, AR_HDR_SIZE)) 783 1.1 christos goto lose; 784 1.1 christos /* Write back the header, thus touching the archive file. */ 785 1.1 christos if (lseek (fd, pos, 0) < 0) 786 1.1 christos goto lose; 787 1.1 christos if (AR_HDR_SIZE != write (fd, (char *) &ar_hdr, AR_HDR_SIZE)) 788 1.1 christos goto lose; 789 1.1 christos /* The file's mtime is the time we we want. */ 790 1.1 christos EINTRLOOP (i, fstat (fd, &statbuf)); 791 1.1 christos if (i < 0) 792 1.1 christos goto lose; 793 1.1 christos #if defined(ARFMAG) || defined(ARFZMAG) || defined(AIAMAG) || defined(WINDOWS32) 794 1.1 christos /* Advance member's time to that time */ 795 1.1 christos for (ui = 0; ui < sizeof ar_hdr.ar_date; ui++) 796 1.1 christos ar_hdr.ar_date[ui] = ' '; 797 1.1 christos sprintf (ar_hdr.ar_date, "%ld", (long int) statbuf.st_mtime); 798 1.1 christos #ifdef AIAMAG 799 1.1 christos ar_hdr.ar_date[strlen(ar_hdr.ar_date)] = ' '; 800 1.1 christos #endif 801 1.1 christos #else 802 1.1 christos ar_hdr.ar_date = statbuf.st_mtime; 803 1.1 christos #endif 804 1.1 christos /* Write back this member's header */ 805 1.1 christos if (lseek (fd, pos, 0) < 0) 806 1.1 christos goto lose; 807 1.1 christos if (AR_HDR_SIZE != write (fd, (char *) &ar_hdr, AR_HDR_SIZE)) 808 1.1 christos goto lose; 809 1.1 christos close (fd); 810 1.1 christos return 0; 811 1.1 christos 812 1.1 christos lose: 813 1.1 christos i = errno; 814 1.1 christos close (fd); 815 1.1 christos errno = i; 816 1.1 christos return -3; 817 1.1 christos } 818 1.1 christos #endif 819 1.1 christos 820 1.1 christos #ifdef TEST 822 1.1 christos 823 1.1 christos long int 824 1.1 christos describe_member (int desc, char *name, int truncated, 825 1.1 christos long int hdrpos, long int datapos, long int size, 826 1.1 christos long int date, int uid, int gid, int mode) 827 1.1 christos { 828 1.1 christos extern char *ctime (); 829 1.1 christos 830 1.1 christos printf (_("Member `%s'%s: %ld bytes at %ld (%ld).\n"), 831 1.1 christos name, truncated ? _(" (name might be truncated)") : "", 832 1.1 christos size, hdrpos, datapos); 833 1.1 christos printf (_(" Date %s"), ctime (&date)); 834 1.1 christos printf (_(" uid = %d, gid = %d, mode = 0%o.\n"), uid, gid, mode); 835 1.1 christos 836 1.1 christos return 0; 837 1.1 christos } 838 1.1 christos 839 1.1 christos int 840 1.1 christos main (int argc, char **argv) 841 1.1 christos { 842 1.1 christos ar_scan (argv[1], describe_member); 843 return 0; 844 } 845 846 #endif /* TEST. */ 847 #endif /* NO_ARCHIVES. */ 848