1 /*- 2 * Copyright (c) 1990 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Hugh Smith at The University of Guelph. 7 * 8 * %sccs.include.redist.c% 9 */ 10 11 #ifndef lint 12 static char sccsid[] = "@(#)archive.c 5.1 (Berkeley) 01/17/91"; 13 #endif /* not lint */ 14 15 #include <sys/param.h> 16 #include <sys/errno.h> 17 #include <sys/stat.h> 18 #include <fcntl.h> 19 #include <unistd.h> 20 #include <dirent.h> 21 #include <stdio.h> 22 #include <stdlib.h> 23 #include <string.h> 24 #include <ar.h> 25 #include "archive.h" 26 27 extern char *archive; /* archive name */ 28 29 open_archive(mode) 30 int mode; 31 { 32 int created, fd, nr; 33 char buf[SARMAG]; 34 35 created = 0; 36 if (mode & O_CREAT) { 37 mode |= O_EXCL; 38 if ((fd = open(archive, mode, DEFFILEMODE)) >= 0) { 39 /* POSIX.2 puts create message on stderr. */ 40 if (!(options & AR_C)) 41 (void)fprintf(stderr, 42 "ar: creating archive %s.\n", archive); 43 created = 1; 44 goto opened; 45 } 46 if (errno != EEXIST) 47 error(archive); 48 mode &= ~O_EXCL; 49 } 50 if ((fd = open(archive, mode, DEFFILEMODE)) < 0) 51 error(archive); 52 53 /* 54 * Attempt to place a lock on the opened file - if we get an 55 * error then someone is already working on this library. 56 */ 57 opened: if (flock(fd, LOCK_EX|LOCK_NB)) 58 error(archive); 59 60 /* 61 * If not created, O_RDONLY|O_RDWR indicates that it has to be 62 * in archive format. 63 */ 64 if (!created && 65 ((mode & O_ACCMODE) == O_RDONLY || (mode & O_ACCMODE) == O_RDWR)) { 66 if ((nr = read(fd, buf, SARMAG) != SARMAG)) { 67 if (nr >= 0) 68 badfmt(); 69 error(archive); 70 } else if (bcmp(buf, ARMAG, SARMAG)) 71 badfmt(); 72 } else if (write(fd, ARMAG, SARMAG) != SARMAG) 73 error(archive); 74 return(fd); 75 } 76 77 close_archive(fd) 78 int fd; 79 { 80 (void)flock(fd, LOCK_UN); 81 (void)close(fd); 82 } 83 84 /* 85 * copyfile -- 86 * Copy size bytes from one file to another - taking care to handle the 87 * extra byte (for odd size files) when reading archives and tmpfiles 88 * and writing an extra byte if necessary when adding files to archive. 89 * 90 * The padding is really unnecessary, and is almost certainly a remnant 91 * of early archive formats where the header included binary data which 92 * a PDP-11 required to start on an even byte boundary. It should have 93 * been ripped out when the format changed. 94 */ 95 copyfile(cfp, size) 96 CF *cfp; 97 register off_t size; 98 { 99 register int from, nr, nw, off, to; 100 char pad, buf[8*1024]; 101 102 if (!size) 103 return; 104 105 pad = size & 1; 106 from = cfp->rfd; 107 to = cfp->wfd; 108 while (size && 109 (nr = read(from, buf, MIN(size, sizeof(buf)))) > 0) { 110 size -= nr; 111 for (off = 0; off < nr; nr -= off, off += nw) 112 if ((nw = write(to, buf + off, nr)) < 0) 113 error(cfp->wname); 114 } 115 if (size) { 116 if (nr == 0) 117 badfmt(); 118 error(cfp->rname); 119 } 120 121 if (pad) { 122 if (cfp->flags & RPAD && (nr = read(from, buf, 1)) != 1) { 123 if (nr == 0) 124 badfmt(); 125 error(cfp->rname); 126 } 127 if (cfp->flags & WPAD) { 128 pad = '\n'; 129 if (write(to, &pad, 1) != 1) 130 error(cfp->wname); 131 } 132 } 133 } 134