add orphans function; files() bug fix -- return the argv matched.
[unix-history] / usr / src / usr.bin / ar / header.c
CommitLineData
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 12static 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
23typedef struct ar_hdr HDR;
24extern CHDR chdr; /* converted header */
25static char hb[sizeof(HDR) + 1]; /* real header */
26extern 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 */
39get_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 */
104put_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}