Commit | Line | Data |
---|---|---|
c0de20e5 KB |
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 | |
736e2712 | 12 | static char sccsid[] = "@(#)header.c 5.2 (Berkeley) %G%"; |
c0de20e5 KB |
13 | #endif /* not lint */ |
14 | ||
15 | #include <sys/param.h> | |
16 | #include <sys/errno.h> | |
17 | #include <sys/stat.h> | |
18 | #include <dirent.h> | |
19 | #include <stdio.h> | |
20 | #include <ar.h> | |
21 | #include "archive.h" | |
22 | ||
23 | typedef struct ar_hdr HDR; | |
24 | extern CHDR chdr; /* converted header */ | |
25 | static char hb[sizeof(HDR) + 1]; /* real header */ | |
26 | extern char *archive; /* archive name */ | |
27 | ||
28 | /* Convert ar header field to an integer. */ | |
29 | #define AR_ATOI(from, to, len, base) { \ | |
30 | bcopy(from, buf, len); \ | |
31 | buf[len] = '\0'; \ | |
32 | to = strtol(buf, (char **)NULL, base); \ | |
33 | } | |
34 | ||
35 | /* | |
36 | * get_header -- | |
37 | * read the archive header for this member | |
38 | */ | |
39 | get_header(fd) | |
40 | int fd; | |
41 | { | |
42 | struct ar_hdr *hdr; | |
43 | register int len, nr; | |
44 | register char *p, buf[20]; | |
45 | ||
46 | nr = read(fd, hb, sizeof(HDR)); | |
47 | if (nr != sizeof(HDR)) { | |
48 | if (!nr) | |
49 | return(0); | |
50 | if (nr < 0) | |
51 | error(archive); | |
52 | badfmt(); | |
53 | } | |
54 | ||
55 | hdr = (struct ar_hdr *)hb; | |
56 | if (strncmp(hdr->ar_fmag, ARFMAG, sizeof(ARFMAG) - 1)) | |
57 | badfmt(); | |
58 | ||
59 | /* Convert the header into the internal format. */ | |
60 | #define DECIMAL 10 | |
61 | #define OCTAL 8 | |
62 | ||
63 | AR_ATOI(hdr->ar_date, chdr.date, sizeof(hdr->ar_date), DECIMAL); | |
64 | AR_ATOI(hdr->ar_uid, chdr.uid, sizeof(hdr->ar_uid), DECIMAL); | |
65 | AR_ATOI(hdr->ar_gid, chdr.gid, sizeof(hdr->ar_gid), DECIMAL); | |
66 | AR_ATOI(hdr->ar_mode, chdr.mode, sizeof(hdr->ar_mode), OCTAL); | |
67 | AR_ATOI(hdr->ar_size, chdr.size, sizeof(hdr->ar_size), DECIMAL); | |
68 | ||
69 | /* Leading spaces should never happen. */ | |
70 | if (hdr->ar_name[0] == ' ') | |
71 | badfmt(); | |
72 | ||
73 | /* | |
74 | * Long name support. Set the "real" size of the file, and the | |
75 | * long name flag/size. | |
76 | */ | |
77 | if (!bcmp(hdr->ar_name, AR_EFMT1, sizeof(AR_EFMT1) - 1)) { | |
78 | len = atoi(hdr->ar_name + sizeof(AR_EFMT1) - 1); | |
79 | if (len <= 0 || len > MAXNAMLEN) | |
80 | badfmt(); | |
81 | nr = read(fd, chdr.name, len); | |
82 | if (nr != len) { | |
83 | if (nr < 0) | |
84 | error(archive); | |
85 | badfmt(); | |
86 | } | |
736e2712 | 87 | chdr.name[len] = 0; |
c0de20e5 KB |
88 | chdr.size -= (chdr.lname = len); |
89 | } else { | |
90 | bcopy(hdr->ar_name, chdr.name, sizeof(hdr->ar_name)); | |
91 | ||
92 | /* Only strip off trailing spaces. */ | |
93 | for (p = chdr.name + sizeof(hdr->ar_name) - 1; *p == ' '; --p); | |
94 | *++p = '\0'; | |
95 | chdr.lname = 0; | |
96 | } | |
97 | return(1); | |
98 | } | |
99 | ||
100 | /* | |
101 | * put_header -- | |
102 | * Write the archive member header to a file. | |
103 | */ | |
104 | put_header(cfp, sb) | |
105 | CF *cfp; | |
106 | struct stat *sb; | |
107 | { | |
108 | register int lname; | |
109 | register char *name; | |
110 | struct ar_hdr *hdr; | |
111 | char *rname(); | |
112 | ||
113 | /* | |
114 | * If passed an sb structure, reading a file from disk. Get stat(2) | |
115 | * information, build a name and construct a header. (Files are named | |
116 | * by their last component in the archive.) If not, then just write | |
117 | * the last header read. | |
118 | */ | |
119 | if (sb) { | |
120 | name = rname(cfp->rname); | |
121 | (void)fstat(cfp->rfd, sb); | |
122 | ||
123 | if ((lname = strlen(name)) > sizeof(hdr->ar_name) || | |
124 | index(name, ' ')) { | |
125 | (void)sprintf(hb, HDR1, AR_EFMT1, lname, sb->st_mtime, | |
126 | sb->st_uid, sb->st_gid, sb->st_mode, | |
127 | sb->st_size + lname, ARFMAG); | |
128 | } else { | |
129 | lname = 0; | |
130 | (void)sprintf(hb, HDR2, name, sb->st_mtime, sb->st_uid, | |
131 | sb->st_gid, sb->st_mode, sb->st_size, ARFMAG); | |
132 | } | |
133 | } else { | |
134 | lname = chdr.lname; | |
135 | name = chdr.name; | |
136 | } | |
137 | ||
138 | if (write(cfp->wfd, hb, sizeof(HDR)) != sizeof(HDR) || | |
139 | lname && write(cfp->wfd, name, lname) != lname) | |
140 | error(cfp->wname); | |
141 | } |