1 /*
2 * $Header: /cvsroot/arc/arc/marc.c,v 1.6 2010/08/07 13:06:11 k_reimer Exp $
3 */
4
5 /* MARC - Archive merge utility
6
7 Version 5.21, created on 04/22/87 at 15:05:10
8
9 (C) COPYRIGHT 1985-87 by System Enhancement Associates; ALL RIGHTS RESERVED
10
11 By: Thom Henderson
12
13 Description:
14 This program is used to "merge" archives. That is, to move
15 files from one archive to another with no data conversion.
16 Please refer to the ARC source for a description of archives
17 and archive formats.
18
19 Instructions:
20 Run this program with no arguments for complete instructions.
21
22 Language:
23 Computer Innovations Optimizing C86
24 */
25 #include <stdio.h>
26 #include <string.h>
27 #include "arc.h"
28
29 #if UNIX
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <unistd.h>
33 #include <errno.h>
34 #endif
35
36 #include "proto.h"
37
38 #ifndef __STDC__
39 char *calloc(), *malloc(), *realloc(); /* memory managers */
40 #endif
41 int gethdr(), match(), readhdr();
42 VOID arcdie(), filecopy(), setstamp(), writehdr();
43 static VOID copyfile(), expandlst(), merge();
44
45 FILE *src; /* source archive */
46 char srcname[STRLEN]; /* source archive name */
47 char *pinbuf; /* block input buffer */
48
49 static char **lst; /* files list */
50 static int lnum; /* length of files list */
51
52 int
main(nargs,arg)53 main(nargs,arg) /* system entry point */
54 int nargs; /* number of arguments */
55 char *arg[]; /* pointers to arguments */
56 {
57 char *makefnam();
58 char *envfind();
59 #if !_MTS
60 char *arctemp2; /* temp file stuff */
61 #endif
62 #if GEMDOS
63 VOID exitpause();
64 #endif
65 int n; /* index */
66 #if UNIX
67 struct stat sbuf;
68 #endif
69
70
71 if(nargs<3)
72 { printf("MARC - Archive merger, Version 5.21p, created on 08/07/2010\n");
73 /* printf("(C) COPYRIGHT 1985,86,87 by System Enhancement Associates;");
74 printf(" ALL RIGHTS RESERVED\n\n");
75 printf("Please refer all inquiries to:\n\n");
76 printf(" System Enhancement Associates\n");
77 printf(" 21 New Street, Wayne NJ 07470\n\n");
78 printf("You may copy and distribute this program freely,");
79 printf(" provided that:\n");
80 printf(" 1) No fee is charged for such copying and");
81 printf(" distribution, and\n");
82 printf(" 2) It is distributed ONLY in its original,");
83 printf(" unmodified state.\n\n");
84 printf("If you like this program, and find it of use, then your");
85 printf(" contribution will\n");
86 printf("be appreciated. You may not use this product in a");
87 printf(" commercial environment\n");
88 printf("or a governmental organization without paying a license");
89 printf(" fee of $35. Site\n");
90 printf("licenses and commercial distribution licenses are");
91 printf(" available. A program\n");
92 printf("disk and printed documentation are available for $50.\n");
93 printf("\nIf you fail to abide by the terms of this license, ");
94 printf(" then your conscience\n");
95 printf("will haunt you for the rest of your life.\n\n");
96 */
97 printf("Usage: MARC <tgtarc> <srcarc> [<filename> . . .]\n");
98 printf("Where: <tgtarc> is the archive to add files to,\n");
99 printf(" <srcarc> is the archive to get files from, and\n");
100 printf(" <filename> is zero or more file names to get.\n");
101 printf("\nAdapted from MSDOS by Howard Chu\n");
102 #if GEMDOS
103 exitpause();
104 #endif
105 return 1;
106 }
107
108 /* see where temp files go */
109 #if !_MTS
110 arctemp = calloc(1, STRLEN);
111 if (!(arctemp2 = envfind("ARCTEMP")))
112 arctemp2 = envfind("TMPDIR");
113 if (arctemp2) {
114 strncpy(arctemp, arctemp2, STRLEN - 16);
115 arctemp[STRLEN - 17] = '\0';
116 n = strlen(arctemp);
117 if (arctemp[n - 1] != CUTOFF)
118 arctemp[n] = CUTOFF;
119 }
120 #if UNIX
121 else strcpy(arctemp, "/tmp/");
122 #endif
123 #if !MSDOS
124 {
125 strcat(arctemp, "AXXXXXX");
126 int fd = mkstemp(arctemp);
127 if (fd == -1)
128 {
129 fprintf(stderr, "Unable to create temporary files: %s\n", strerror(errno));
130 exit(235);
131 }
132 close(fd);
133 unlink(arctemp);
134 }
135 #else
136 strcat(arctemp, "$ARCTEMP");
137 #endif
138 #else
139 guinfo("SHFSEP ", gotinf);
140 sepchr[0] = gotinf[0];
141 guinfo("SCRFCHAR", gotinf);
142 tmpchr[0] = gotinf[0];
143 arctemp = "-$$$";
144 arctemp[0] = tmpchr[0];
145 #endif
146
147 for (n = 1; n < nargs; n++)
148 if (strlen(arg[n]) > (STRLEN - 16))
149 {
150 fprintf(stderr, "Too long argument: %s\n", arg[n]);
151 exit(235);
152 }
153
154 #if UNIX
155 if (!stat(arg[1],&sbuf))
156 strcpy(arcname,arg[1]);
157 else
158 makefnam(arg[1],".arc",arcname);
159 if (!stat(arg[2],&sbuf))
160 strcpy(srcname,arg[2]);
161 else
162 makefnam(arg[2],".arc",srcname);
163 #else
164 makefnam(arg[1],".ARC",arcname); /* fix up archive names */
165 makefnam(arg[2],".ARC",srcname);
166 /* makefnam(".$$$",arcname,newname);*/
167 #endif
168 sprintf(newname,"%s.arc",arctemp);
169
170 arc = fopen(arcname,OPEN_R); /* open the archives */
171 if(!(src=fopen(srcname,OPEN_R)))
172 arcdie("Cannot read source archive %s",srcname);
173 if(!(new=tmpopen(newname)))
174 arcdie("Cannot create new archive %s",newname);
175
176 if(!arc)
177 printf("Creating new archive %s\n",arcname);
178
179 /* get the files list set up */
180
181 lnum = nargs-3; /* initial length of list */
182 if(lnum<1) /* phoney for default case */
183 { lnum = 1;
184 lst = (char **) calloc(1,sizeof(char *));
185 lst[0] = "*.*";
186 }
187 else /* else use filenames given */
188 { lst = (char **) calloc(lnum,sizeof(char *));
189 for(n=3; n<nargs; n++)
190 lst[n-3] = arg[n];
191
192 for(n=0; n<lnum; ) /* expand indirect references */
193 { if(*lst[n] == '@')
194 expandlst(n);
195 else n++;
196 }
197 }
198 if (!(pinbuf = malloc(MYBUF)))
199 arcdie("Not enough memory for input buffer.");
200
201 merge(lnum,lst); /* merge desired files */
202
203 if(arc) fclose(arc); /* close the archives */
204 fclose(src);
205 fclose(new);
206
207 if(arc) /* make the switch */
208 if(unlink(arcname))
209 arcdie("Unable to delete old copy of %s",arcname);
210 if(move(newname,arcname))
211 arcdie("Unable to rename %s to %s",newname,arcname);
212
213 setstamp(arcname,arcdate,arctime); /* new arc matches newest file */
214
215 #if GEMDOS
216 exitpause();
217 #endif
218 return nerrs;
219 }
220
221 static VOID
merge(nargs,arg)222 merge(nargs,arg) /* merge two archives */
223 int nargs; /* number of filename templates */
224 char *arg[]; /* pointers to names */
225 {
226 struct heads srch; /* source archive header */
227 struct heads arch; /* target archive header */
228 int gotsrc, gotarc; /* archive entry versions (0=end) */
229 int copy; /* true to copy file from source */
230 int n; /* index */
231
232 gotsrc = gethdr(src,&srch); /* get first source file */
233 gotarc = gethdr(arc,&arch); /* get first target file */
234
235 while(gotsrc || gotarc) /* while more to merge */
236 { if(strcmp(srch.name,arch.name)>0)
237 { copyfile(arc,&arch,gotarc);
238 gotarc = gethdr(arc,&arch);
239 }
240
241 else if(strcmp(srch.name,arch.name)<0)
242 { copy = 0;
243 for(n=0; n<nargs; n++)
244 { if(match(srch.name,arg[n]))
245 { copy = 1;
246 break;
247 }
248 }
249 if(copy) /* select source or target */
250 { printf("Adding file: %s\n",srch.name);
251 copyfile(src,&srch,gotsrc);
252 }
253 else fseek(src,srch.size,1);
254 gotsrc = gethdr(src,&srch);
255 }
256
257 else /* duplicate names */
258 { copy = 0;
259 { if((srch.date>arch.date)
260 || (srch.date==arch.date && srch.time>arch.time))
261 { for(n=0; n<nargs; n++)
262 { if(match(srch.name,arg[n]))
263 { copy = 1;
264 break;
265 }
266 }
267 }
268 }
269 if(copy) /* select source or target */
270 { printf("Updating file: %s\n",srch.name);
271 copyfile(src,&srch,gotsrc);
272 gotsrc = gethdr(src,&srch);
273 if(gotarc)
274 { fseek(arc,arch.size,1);
275 gotarc = gethdr(arc,&arch);
276 }
277 }
278 else
279 { copyfile(arc,&arch,gotarc);
280 gotarc = gethdr(arc,&arch);
281 if(gotsrc)
282 { fseek(src,srch.size,1);
283 gotsrc = gethdr(src,&srch);
284 }
285 }
286 }
287 }
288
289 hdrver = 0; /* end of archive marker */
290 writehdr(&arch,new); /* mark the end of the archive */
291 }
292
gethdr(f,hdr)293 int gethdr(f,hdr) /* special read header for merge */
294 FILE *f; /* file to read from */
295 struct heads *hdr; /* storage for header */
296 {
297 char *i = hdr->name; /* string index */
298 int n; /* index */
299
300 for(n=0; n<FNLEN; n++) /* fill name field */
301 *i++ = 0176; /* impossible high value */
302 *--i = '\0'; /* properly end the name */
303
304 hdrver = 0; /* reset header version */
305 if(readhdr(hdr,f)) /* use normal reading logic */
306 return hdrver; /* return the version */
307 else return 0; /* or fake end of archive */
308 }
309
310 static VOID
copyfile(f,hdr,ver)311 copyfile(f,hdr,ver) /* copy a file from an archive */
312 FILE *f; /* archive to copy from */
313 struct heads *hdr; /* header data for file */
314 int ver; /* header version */
315 {
316 hdrver = ver; /* set header version */
317 writehdr(hdr,new); /* write out the header */
318 filecopy(f,new,hdr->size); /* copy over the data */
319 }
320
321 static VOID
expandlst(n)322 expandlst(n) /* expand an indirect reference */
323 int n; /* number of entry to expand */
324 {
325 FILE *lf, *fopen(); /* list file, opener */
326 char buf[100]; /* input buffer */
327 int x; /* index */
328 char *p = lst[n]+1; /* filename pointer */
329 char *makefnam();
330
331 if(*p) /* use name if one was given */
332 { makefnam(p,".CMD",buf);
333 upper(buf);
334 if(!(lf=fopen(buf,"r")))
335 arcdie("Cannot read list of files in %s",buf);
336 }
337 else lf = stdin; /* else use standard input */
338
339 for(x=n+1; x<lnum; x++) /* drop reference from the list */
340 lst[x-1] = lst[x];
341 lnum--;
342
343 while(fscanf(lf,"%99s",buf)>0) /* read in the list */
344 { if(!(lst=(char **) realloc(lst,(lnum+1)*sizeof(char *))))
345 arcdie("too many file references");
346
347 lst[lnum] = malloc(strlen(buf)+1);
348 strcpy(lst[lnum],buf); /* save the name */
349 lnum++;
350 }
351
352 if(lf!=stdin) /* avoid closing standard input */
353 fclose(lf);
354 }
355