"SfR Fresh" - the SfR Freeware/Shareware Archive 
Member "lha-114i/src/lhadd.c" of archive lha-114i.tar.gz:
As a special service "SfR Fresh" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting with prefixed line numbers.
Alternatively you can here view or download the uninterpreted source code file.
That can be also achieved for any archive member file by clicking within an archive contents listing on the first character of the file(path) respectively on the according byte size field.
1 /* ------------------------------------------------------------------------ */
2 /* LHa for UNIX */
3 /* lhadd.c -- LHarc Add Command */
4 /* */
5 /* Copyright (C) MCMLXXXIX Yooichi.Tagawa */
6 /* Modified Nobutaka Watazaki */
7 /* */
8 /* Ver. 1.14 Source All chagned 1995.01.14 N.Watazaki */
9 /* ------------------------------------------------------------------------ */
10 #include "lha.h"
11 /* ------------------------------------------------------------------------ */
12 static void remove_files();
13
14 static char new_archive_name_buffer[FILENAME_LENGTH];
15 static char *new_archive_name;
16 /* ------------------------------------------------------------------------ */
17 static void
18 add_one(fp, nafp, hdr)
19 FILE *fp, *nafp;
20 LzHeader *hdr;
21 {
22 long header_pos, next_pos, org_pos, data_pos;
23 long v_original_size, v_packed_size;
24 int mode;
25
26 reading_filename = hdr->name;
27 writting_filename = temporary_name;
28
29 if (!fp && generic_format) /* [generic] doesn't need directory
30 * info. */
31 return;
32 header_pos = ftell(nafp);
33 write_header(nafp, hdr);/* DUMMY */
34
35 if ((hdr->unix_mode & UNIX_FILE_SYMLINK) == UNIX_FILE_SYMLINK) {
36 char buf[256], *b1, *b2;
37 if (!quiet) {
38 strcpy(buf, hdr->name);
39 b1 = strtok(buf, "|");
40 b2 = strtok(NULL, "|");
41 printf("%s -> %s\t- Symbolic Link\n", b1, b2);
42 } /* if quiet .. */
43 }
44
45 if (hdr->original_size == 0) /* empty file or directory */
46 return; /* previous write_header is not DUMMY. (^_^) */
47
48 org_pos = ftell(fp);
49 data_pos = ftell(nafp);
50
51 hdr->crc = encode_lzhuf(fp, nafp, hdr->original_size,
52 &v_original_size, &v_packed_size, hdr->name, hdr->method);
53
54 if (v_packed_size < v_original_size) {
55 next_pos = ftell(nafp);
56 }
57 else { /* retry by stored method */
58 fseek(fp, org_pos, SEEK_SET);
59 fseek(nafp, data_pos, SEEK_SET);
60 hdr->crc = encode_stored_crc(fp, nafp, hdr->original_size,
61 &v_original_size, &v_packed_size);
62 fflush(nafp);
63 next_pos = ftell(nafp);
64 #ifndef NOFTRUNCATE
65 ftruncate(fileno(nafp), next_pos);
66 #endif
67 bcopy(LZHUFF0_METHOD, hdr->method, METHOD_TYPE_STRAGE);
68 }
69 hdr->original_size = v_original_size;
70 hdr->packed_size = v_packed_size;
71 fseek(nafp, header_pos, SEEK_SET);
72 write_header(nafp, hdr);
73 fseek(nafp, next_pos, SEEK_SET);
74 }
75
76
77 /* ------------------------------------------------------------------------ */
78 FILE *
79 append_it(name, oafp, nafp)
80 char *name;
81 FILE *oafp, *nafp;
82 {
83 LzHeader ahdr, hdr;
84 FILE *fp;
85 long old_header;
86 int cmp;
87 int filec;
88 char **filev;
89 int i;
90 struct stat stbuf /*, lstbuf*/;
91
92 boolean directory, symlink;
93
94 if (GETSTAT(name, &stbuf) < 0) {
95 error("Cannot access", name); /* See cleaning_files, Why? */
96 return oafp;
97 }
98
99 directory = is_directory(&stbuf);
100 #ifdef S_IFLNK
101 symlink = is_symlink(&stbuf);
102 #else
103 symlink = 0;
104 #endif
105 init_header(name, &stbuf, &hdr);
106
107 if (!directory && !noexec)
108 if (symlink)
109 fp = NULL;
110 else
111 fp = xfopen(name, READ_BINARY);
112 else {
113 fp = NULL;
114 }
115
116 while (oafp) {
117 old_header = ftell(oafp);
118 if (!get_header(oafp, &ahdr)) {
119 fclose(oafp);
120 oafp = NULL;
121 break;
122 } else {
123 #if 0
124 cmp = STRING_COMPARE(ahdr.name, hdr.name);
125 #endif
126 /* for symbolic link. t.okamoto */
127 cmp = strcmp_filename(ahdr.name, hdr.name);
128 if (cmp < 0) { /* SKIP */
129 /* copy old to new */
130 if (!noexec) {
131 fseek(oafp, old_header, SEEK_SET);
132 copy_old_one(oafp, nafp, &ahdr);
133 }
134 else
135 fseek(oafp, ahdr.packed_size, SEEK_CUR);
136 } else if (cmp == 0) { /* REPLACE */
137 /* drop old archive's */
138 fseek(oafp, ahdr.packed_size, SEEK_CUR);
139 break;
140 } else { /* cmp > 0, INSERT */
141 fseek(oafp, old_header, SEEK_SET);
142 break;
143 }
144 }
145 }
146
147 if (update_if_newer) {
148 if (!oafp || /* not in archive */
149 cmp > 0 || /* // */
150 ahdr.unix_last_modified_stamp < /* newer than archive's */
151 hdr.unix_last_modified_stamp) {
152 if (noexec)
153 printf("ADD %s\n", name);
154 else
155 add_one(fp, nafp, &hdr);
156 } else { /* cmp == 0 *//* copy old to new */
157 if (!noexec) {
158 fseek(oafp, old_header, SEEK_SET);
159 copy_old_one(oafp, nafp, &ahdr);
160 }
161 }
162 } else {
163 if (!oafp || cmp > 0) { /* not in archive or dropped */
164 if (noexec)
165 printf("ADD %s\n", name);
166 else
167 add_one(fp, nafp, &hdr);
168 }
169 else { /* cmp == 0 */
170 /* replace */
171 if (noexec)
172 printf("REPLACE\n");
173 else
174 add_one(fp, nafp, &hdr);
175 }
176 }
177
178 if (!directory) {
179 if (!noexec)
180 if (!symlink)
181 fclose(fp);
182 }
183 else { /* recurcive call */
184 if (find_files(name, &filec, &filev)) {
185 for (i = 0; i < filec; i++)
186 oafp = append_it(filev[i], oafp, nafp);
187 free_files(filec, filev);
188 }
189 }
190 return oafp;
191 }
192
193 /* ------------------------------------------------------------------------ */
194 static void
195 find_update_files(oafp)
196 FILE *oafp; /* old archive */
197 {
198 char name[FILENAME_LENGTH];
199 struct string_pool sp;
200 LzHeader hdr;
201 long pos;
202 struct stat stbuf;
203 int len;
204
205 pos = ftell(oafp);
206
207 init_sp(&sp);
208 while (get_header(oafp, &hdr)) {
209 if ((hdr.unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_REGULAR) {
210 if (stat(hdr.name, &stbuf) >= 0) /* exist ? */
211 add_sp(&sp, hdr.name, strlen(hdr.name) + 1);
212 }
213 else if ((hdr.unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_DIRECTORY) {
214 strcpy(name, hdr.name);
215 len = strlen(name);
216 if (len > 0 && name[len - 1] == '/')
217 name[--len] = '\0'; /* strip tail '/' */
218 if (stat(name, &stbuf) >= 0) /* exist ? */
219 add_sp(&sp, name, len + 1);
220 }
221 fseek(oafp, hdr.packed_size, SEEK_CUR);
222 }
223
224 fseek(oafp, pos, SEEK_SET);
225
226 finish_sp(&sp, &cmd_filec, &cmd_filev);
227 }
228
229 /* ------------------------------------------------------------------------ */
230 static void
231 delete(oafp, nafp)
232 FILE *oafp, *nafp;
233 {
234 LzHeader ahdr;
235 long old_header_pos;
236 char lpath[256], *b1, *b2;
237
238 old_header_pos = ftell(oafp);
239 while (get_header(oafp, &ahdr)) {
240 strcpy(lpath, ahdr.name);
241 b1 = strtok(lpath, "|");
242 b2 = strtok(NULL, "|");
243 if (need_file(b1)) { /* skip */
244 fseek(oafp, ahdr.packed_size, SEEK_CUR);
245 if (noexec || !quiet)
246 if (b2 != NULL)
247 printf("delete %s -> %s\n", b1, b2);
248 else
249 printf("delete %s\n", b1);
250 }
251 else { /* copy */
252 if (noexec) {
253 fseek(oafp, ahdr.packed_size, SEEK_CUR);
254 }
255 else {
256 fseek(oafp, old_header_pos, SEEK_SET);
257 copy_old_one(oafp, nafp, &ahdr);
258 }
259 }
260 old_header_pos = ftell(oafp);
261 }
262 return;
263 }
264
265 /* ------------------------------------------------------------------------ */
266 /* */
267 /* ------------------------------------------------------------------------ */
268 static FILE *
269 build_temporary_file()
270 {
271 int old_umask;
272 FILE *afp;
273
274 build_temporary_name();
275 signal(SIGINT, interrupt);
276 signal(SIGHUP, interrupt);
277
278 old_umask = umask(077);
279 afp = xfopen(temporary_name, WRITE_BINARY);
280 remove_temporary_at_error = TRUE;
281 temporary_fp = afp;
282 umask(old_umask);
283
284 return afp;
285 }
286
287 /* ------------------------------------------------------------------------ */
288 static void
289 build_backup_file()
290 {
291
292 build_backup_name(backup_archive_name, archive_name);
293 if (!noexec) {
294 signal(SIGINT, SIG_IGN);
295 signal(SIGHUP, SIG_IGN);
296 if (rename(archive_name, backup_archive_name) < 0)
297 fatal_error(archive_name);
298 recover_archive_when_interrupt = TRUE;
299 signal(SIGINT, interrupt);
300 signal(SIGHUP, interrupt);
301 }
302 }
303
304 /* ------------------------------------------------------------------------ */
305 static void
306 report_archive_name_if_different()
307 {
308 if (!quiet && new_archive_name == new_archive_name_buffer) {
309 /* warning at old archive is SFX */
310 printf("New archive file is \"%s\"\n", new_archive_name);
311 }
312 }
313
314 /* ------------------------------------------------------------------------ */
315 #ifdef TMP_FILENAME_TEMPLATE
316 void
317 temporary_to_new_archive_file(new_archive_size)
318 long new_archive_size;
319 {
320 FILE *oafp, *nafp;
321
322 oafp = xfopen(temporary_name, READ_BINARY);
323 if (!strcmp(new_archive_name, "-")) {
324 nafp = stdout;
325 writting_filename = "starndard output";
326 }
327 else {
328 nafp = xfopen(new_archive_name, WRITE_BINARY);
329 writting_filename = archive_name;
330 }
331 reading_filename = temporary_name;
332 copyfile(oafp, nafp, new_archive_size, 0);
333 if (nafp != stdout)
334 fclose(nafp);
335 fclose(oafp);
336
337 recover_archive_when_interrupt = FALSE;
338 unlink(temporary_name);
339
340 remove_temporary_at_error = FALSE;
341 }
342 #else
343 temporary_to_new_archive_file(new_archive_size)
344 long new_archive_size;
345 {
346 char *p;
347 p = (char *) rindex(new_archive_name, '/');
348 p = p ? p + 1 : new_archive_name;
349 unlink(new_archive_name);
350 if (rename(temporary_name, p) < 0) {
351 fprintf(stderr, "Can't rename temporary_name '%s'\n", new_archive_name);
352 exit(1);
353 }
354 }
355 #endif
356
357 /* ------------------------------------------------------------------------ */
358 static void
359 set_archive_file_mode()
360 {
361 int umask_value;
362 struct stat stbuf;
363
364 if (archive_file_gid < 0) {
365 umask(umask_value = umask(0));
366 archive_file_mode = (~umask_value) & 0666; /* rw-rw-rw- */
367 if (stat(".", &stbuf) >= 0)
368 archive_file_gid = stbuf.st_gid;
369 }
370 if (archive_file_gid >= 0)
371 chown(new_archive_name, getuid(), archive_file_gid);
372
373 chmod(new_archive_name, archive_file_mode);
374 }
375
376 /* ------------------------------------------------------------------------ */
377 /* REMOVE FILE/DIRECTORY */
378 /* ------------------------------------------------------------------------ */
379 static void
380 remove_one(name)
381 char *name;
382 {
383 struct stat stbuf;
384 int filec;
385 char **filev;
386
387 if (GETSTAT(name, &stbuf) < 0) {
388 warning("Cannot access", name);
389 }
390 else if (is_directory(&stbuf)) {
391 if (find_files(name, &filec, &filev)) {
392 remove_files(filec, filev);
393 free_files(filec, filev);
394 }
395 else
396 warning("Cannot open directory", name);
397
398 if (noexec)
399 printf("REMOVE DIRECTORY %s\n", name);
400 else if (rmdir(name) < 0)
401 warning("Cannot remove directory", name);
402 else if (verbose)
403 printf("Removed %s.\n", name);
404 }
405 else if (is_regularfile(&stbuf)) {
406 if (noexec)
407 printf("REMOVE FILE %s.\n", name);
408 else if (unlink(name) < 0)
409 warning("Cannot remove", name);
410 else if (verbose)
411 printf("Removed %s.\n", name);
412 }
413 #ifdef S_IFLNK
414 else if (is_symlink(&stbuf)) {
415 if (noexec)
416 printf("REMOVE SYMBOLIC LINK %s.\n", name);
417 else if (unlink(name) < 0)
418 warning("Cannot remove", name);
419 else if (verbose)
420 printf("Removed %s.\n", name);
421 }
422 #endif
423 else {
424 error("Cannot remove (not a file or directory)", name);
425 }
426 }
427
428 static void
429 remove_files(filec, filev)
430 int filec;
431 char **filev;
432 {
433 int i;
434
435 for (i = 0; i < filec; i++)
436 remove_one(filev[i]);
437 }
438
439 /* ------------------------------------------------------------------------ */
440 /* */
441 /* ------------------------------------------------------------------------ */
442 void
443 cmd_add()
444 {
445 LzHeader ahdr;
446 FILE *oafp, *nafp;
447 int i;
448 long old_header;
449 boolean old_archive_exist;
450 long new_archive_size;
451
452 /* exit if no operation */
453 if (!update_if_newer && cmd_filec == 0) {
454 error("No files given in argument, do nothing.", "");
455 return;
456 }
457
458 /* open old archive if exist */
459 if ((oafp = open_old_archive()) == NULL)
460 old_archive_exist = FALSE;
461 else
462 old_archive_exist = TRUE;
463
464 if (update_if_newer && cmd_filec == 0 && !oafp)
465 fatal_error(archive_name); /* exit if cannot execute
466 * automatic update */
467 errno = 0;
468
469 if (new_archive && old_archive_exist) {
470 fclose(oafp);
471 oafp = NULL;
472 }
473
474 if (oafp && archive_is_msdos_sfx1(archive_name)) {
475 skip_msdos_sfx1_code(oafp);
476 build_standard_archive_name(new_archive_name_buffer, archive_name);
477 new_archive_name = new_archive_name_buffer;
478 }
479 else {
480 new_archive_name = archive_name;
481 }
482
483 /* build temporary file */
484 if (!noexec)
485 nafp = build_temporary_file();
486
487 /* find needed files when automatic update */
488 if (update_if_newer && cmd_filec == 0)
489 find_update_files(oafp);
490
491 /* build new archive file */
492 /* cleaning arguments */
493 cleaning_files(&cmd_filec, &cmd_filev);
494 if (cmd_filec == 0) {
495 if (oafp)
496 fclose(oafp);
497 if (!noexec)
498 fclose(nafp);
499 return;
500 }
501
502 for (i = 0; i < cmd_filec; i++)
503 oafp = append_it(cmd_filev[i], oafp, nafp);
504 if (oafp) {
505 old_header = ftell(oafp);
506 while (get_header(oafp, &ahdr)) {
507 if (noexec)
508 fseek(oafp, ahdr.packed_size, SEEK_CUR);
509 else {
510 fseek(oafp, old_header, SEEK_SET);
511 copy_old_one(oafp, nafp, &ahdr);
512 }
513 old_header = ftell(oafp);
514 }
515 fclose(oafp);
516 }
517 if (!noexec) {
518 write_archive_tail(nafp);
519 new_archive_size = ftell(nafp);
520 fclose(nafp);
521 }
522
523 /* build backup archive file */
524 if (old_archive_exist)
525 build_backup_file();
526
527 report_archive_name_if_different();
528
529 /* copy temporary file to new archive file */
530 if (!noexec && (!strcmp(new_archive_name, "-") ||
531 rename(temporary_name, new_archive_name) < 0))
532 temporary_to_new_archive_file(new_archive_size);
533
534 /* set new archive file mode/group */
535 set_archive_file_mode();
536
537 /* remove archived files */
538 if (delete_after_append)
539 remove_files(cmd_filec, cmd_filev);
540
541 return;
542 }
543
544 /* ------------------------------------------------------------------------ */
545 void
546 cmd_delete()
547 {
548 FILE *oafp, *nafp;
549 long new_archive_size;
550
551 /* open old archive if exist */
552 if ((oafp = open_old_archive()) == NULL)
553 fatal_error(archive_name);
554 errno = 0;
555
556 /* exit if no operation */
557 if (cmd_filec == 0) {
558 fclose(oafp);
559 warning("No files given in argument, do nothing.", "");
560 return;
561 }
562
563 if (archive_is_msdos_sfx1(archive_name)) {
564 skip_msdos_sfx1_code(oafp);
565 build_standard_archive_name(new_archive_name_buffer, archive_name);
566 new_archive_name = new_archive_name_buffer;
567 }
568 else {
569 new_archive_name = archive_name;
570 }
571
572 /* build temporary file */
573 if (!noexec)
574 nafp = build_temporary_file();
575
576 /* build new archive file */
577 delete(oafp, nafp);
578 fclose(oafp);
579
580 if (!noexec) {
581 write_archive_tail(nafp);
582 new_archive_size = ftell(nafp);
583 fclose(nafp);
584 }
585
586 /* build backup archive file */
587 build_backup_file();
588
589 /* 1999.5.24 t.oka */
590 if(!noexec && new_archive_size <= 1){
591 unlink(temporary_name);
592 printf("New archive file \"%s\" is not created because it would be empty.\n", new_archive_name);
593 return;
594 }
595
596 report_archive_name_if_different();
597
598 /* copy temporary file to new archive file */
599 if (!noexec && rename(temporary_name, new_archive_name) < 0)
600 temporary_to_new_archive_file(new_archive_size);
601
602 /* set new archive file mode/group */
603 set_archive_file_mode();
604
605 return;
606 }
607
608 /* for symbolic link name. t.okamoto 96/2/20 */
609 int strcmp_filename( str1, str2 )
610 char *str1;
611 char *str2;
612 {
613 char *p, *q;
614
615 p = str1; q = str2;
616 while (*p != 0 && *q != 0) {
617 if (*p == '|') {
618 if (*q == 0) return 0;
619 else if (*q != '|') return -1;
620 } else if (*q == '|') {
621 if (*p == 0) return 0;
622 else if (*q != '|') return 1;
623 } else if (*p != *q) break;
624 p++; q++;
625 }
626 return (int)*p-(int)*q;
627 }
628
629
630 /* Local Variables: */
631 /* mode:c */
632 /* tab-width:4 */
633 /* compile-command:"gcc -c lhadd.c" */
634 /* End: */