146003Sbostic /*- 246003Sbostic * Copyright (c) 1990 The Regents of the University of California. 346003Sbostic * All rights reserved. 446003Sbostic * 546003Sbostic * This code is derived from software contributed to Berkeley by 646003Sbostic * Hugh Smith at The University of Guelph. 746003Sbostic * 846003Sbostic * %sccs.include.redist.c% 946003Sbostic */ 1046003Sbostic 1146003Sbostic #ifndef lint 12*47233Sbostic static char sccsid[] = "@(#)replace.c 5.6 (Berkeley) 03/11/91"; 1346003Sbostic #endif /* not lint */ 1446003Sbostic 1546003Sbostic #include <sys/param.h> 1646003Sbostic #include <sys/stat.h> 1746003Sbostic #include <fcntl.h> 1847205Sbostic #include <dirent.h> 1947205Sbostic #include <errno.h> 2046003Sbostic #include <unistd.h> 2146003Sbostic #include <ar.h> 2246003Sbostic #include <stdio.h> 23*47233Sbostic #include <string.h> 2446003Sbostic #include "archive.h" 25*47233Sbostic #include "extern.h" 2646003Sbostic 2746003Sbostic extern CHDR chdr; /* converted header */ 2846003Sbostic extern char *archive; /* archive name */ 2946003Sbostic extern char *tname; /* temporary file "name" */ 3046003Sbostic 3146003Sbostic /* 3246003Sbostic * replace -- 3346003Sbostic * Replace or add named members to archive. Entries already in the 3446003Sbostic * archive are swapped in place. Others are added before or after 3546003Sbostic * the key entry, based on the a, b and i options. If the u option 3646003Sbostic * is specified, modification dates select for replacement. 3746003Sbostic */ 3846003Sbostic replace(argv) 3946003Sbostic char **argv; 4046003Sbostic { 4147214Sbostic extern char *posarg, *posname; /* positioning file name */ 4246003Sbostic register char *file; 4346003Sbostic register int afd, curfd, mods, sfd; 4446003Sbostic struct stat sb; 4546003Sbostic CF cf; 4646003Sbostic off_t size, tsize; 4746003Sbostic int err, exists, tfd1, tfd2; 4846003Sbostic char *rname(); 4946003Sbostic 5046003Sbostic /* 5146003Sbostic * If doesn't exist, simply append to the archive. There's 5246003Sbostic * a race here, but it's pretty short, and not worth fixing. 5346003Sbostic */ 5446003Sbostic exists = !stat(archive, &sb); 5546003Sbostic afd = open_archive(O_CREAT|O_RDWR); 5646003Sbostic 5746003Sbostic if (!exists) { 5846003Sbostic tfd1 = -1; 5946003Sbostic tfd2 = tmp(); 6046003Sbostic goto append; 6146003Sbostic } 6246003Sbostic 6346003Sbostic tfd1 = tmp(); /* Files before key file. */ 6446003Sbostic tfd2 = tmp(); /* Files after key file. */ 6546003Sbostic 6646003Sbostic /* 6746003Sbostic * Break archive into two parts -- entries before and after the key 6846003Sbostic * entry. If positioning before the key, place the key at the 6946003Sbostic * beginning of the after key entries and if positioning after the 7046003Sbostic * key, place the key at the end of the before key entries. Put it 7146003Sbostic * all back together at the end. 7246003Sbostic */ 7346009Sbostic mods = (options & (AR_A|AR_B)); 7446003Sbostic for (err = 0, curfd = tfd1; get_header(afd);) { 75*47233Sbostic if (*argv && (file = files(argv))) { 7646003Sbostic if ((sfd = open(file, O_RDONLY)) < 0) { 7746003Sbostic err = 1; 7846003Sbostic (void)fprintf(stderr, "ar: %s: %s.\n", 7946003Sbostic file, strerror(errno)); 8046003Sbostic goto useold; 8146003Sbostic } 8246003Sbostic (void)fstat(sfd, &sb); 8346003Sbostic if (options & AR_U && sb.st_mtime <= chdr.date) 8446003Sbostic goto useold; 8546003Sbostic 8646003Sbostic if (options & AR_V) 8747214Sbostic (void)printf("r - %s\n", file); 8846003Sbostic 8947205Sbostic /* Read from disk, write to an archive; pad on write */ 9046003Sbostic SETCF(sfd, file, curfd, tname, WPAD); 9147205Sbostic put_object(&cf, &sb); 9246003Sbostic (void)close(sfd); 9347205Sbostic skipobj(afd); 9446003Sbostic continue; 9546003Sbostic } 9646003Sbostic 9746003Sbostic if (mods && compare(posname)) { 9846003Sbostic mods = 0; 9946003Sbostic if (options & AR_B) 10046003Sbostic curfd = tfd2; 10147205Sbostic /* Read and write to an archive; pad on both. */ 10246003Sbostic SETCF(afd, archive, curfd, tname, RPAD|WPAD); 10347205Sbostic put_object(&cf, (struct stat *)NULL); 10446003Sbostic if (options & AR_A) 10546003Sbostic curfd = tfd2; 10646003Sbostic } else { 10747205Sbostic /* Read and write to an archive; pad on both. */ 10846003Sbostic useold: SETCF(afd, archive, curfd, tname, RPAD|WPAD); 10947205Sbostic put_object(&cf, (struct stat *)NULL); 11046003Sbostic } 11146003Sbostic } 11246003Sbostic 11346003Sbostic if (mods) { 11446003Sbostic (void)fprintf(stderr, "ar: %s: archive member not found.\n", 11547214Sbostic posarg); 11646003Sbostic close_archive(afd); 11746003Sbostic return(1); 11846003Sbostic } 11946003Sbostic 12046003Sbostic /* Append any left-over arguments to the end of the after file. */ 12146003Sbostic append: while (file = *argv++) { 12246003Sbostic if (options & AR_V) 12347214Sbostic (void)printf("a - %s\n", file); 12446003Sbostic if ((sfd = open(file, O_RDONLY)) < 0) { 12546003Sbostic err = 1; 12646003Sbostic (void)fprintf(stderr, "ar: %s: %s.\n", 12746003Sbostic file, strerror(errno)); 12846003Sbostic continue; 12946003Sbostic } 13046003Sbostic (void)fstat(sfd, &sb); 13147205Sbostic /* Read from disk, write to an archive; pad on write. */ 13246009Sbostic SETCF(sfd, file, 13346009Sbostic options & (AR_A|AR_B) ? tfd1 : tfd2, tname, WPAD); 13447205Sbostic put_object(&cf, &sb); 13546003Sbostic (void)close(sfd); 13646003Sbostic } 13746003Sbostic 13846003Sbostic (void)lseek(afd, (off_t)SARMAG, SEEK_SET); 13946003Sbostic 14047205Sbostic SETCF(tfd1, tname, afd, archive, NOPAD); 14146003Sbostic if (tfd1 != -1) { 14246003Sbostic tsize = size = lseek(tfd1, (off_t)0, SEEK_CUR); 14346003Sbostic (void)lseek(tfd1, (off_t)0, SEEK_SET); 14446003Sbostic copyfile(&cf, size); 14546003Sbostic } else 14646003Sbostic tsize = 0; 14746003Sbostic 14846003Sbostic tsize += size = lseek(tfd2, (off_t)0, SEEK_CUR); 14946003Sbostic (void)lseek(tfd2, (off_t)0, SEEK_SET); 15046003Sbostic cf.rfd = tfd2; 15146003Sbostic copyfile(&cf, size); 15246003Sbostic 15346003Sbostic (void)ftruncate(afd, tsize + SARMAG); 15446003Sbostic close_archive(afd); 15546003Sbostic return(err); 15646003Sbostic } 157