1 /* ------------------------------------------------------------------------ */
3 /* lhadd.c -- LHarc Add Command */
5 /* Copyright (C) MCMLXXXIX Yooichi.Tagawa */
6 /* Modified Nobutaka Watazaki */
8 /* Ver. 1.14 Source All chagned 1995.01.14 N.Watazaki */
9 /* ------------------------------------------------------------------------ */
11 /* ------------------------------------------------------------------------ */
12 static void remove_files();
14 static char new_archive_name_buffer[FILENAME_LENGTH];
15 static char *new_archive_name;
16 /* ------------------------------------------------------------------------ */
18 add_one(fp, nafp, hdr)
22 long header_pos, next_pos, org_pos, data_pos;
23 long v_original_size, v_packed_size;
25 reading_filename = hdr->name;
26 writing_filename = temporary_name;
28 if (!fp && generic_format) /* [generic] doesn't need directory
31 header_pos = ftell(nafp);
32 write_header(nafp, hdr);/* DUMMY */
34 if ((hdr->unix_mode & UNIX_FILE_SYMLINK) == UNIX_FILE_SYMLINK) {
35 char buf[256], *b1, *b2;
37 strcpy(buf, hdr->name);
38 b1 = strtok(buf, "|");
39 b2 = strtok(NULL, "|");
40 printf("%s -> %s\t- Symbolic Link\n", b1, b2);
44 if (hdr->original_size == 0) /* empty file or directory */
45 return; /* previous write_header is not DUMMY. (^_^) */
48 data_pos = ftell(nafp);
50 hdr->crc = encode_lzhuf(fp, nafp, hdr->original_size,
51 &v_original_size, &v_packed_size, hdr->name, hdr->method);
53 if (v_packed_size < v_original_size) {
54 next_pos = ftell(nafp);
56 else { /* retry by stored method */
57 fseek(fp, org_pos, SEEK_SET);
58 fseek(nafp, data_pos, SEEK_SET);
59 hdr->crc = encode_stored_crc(fp, nafp, hdr->original_size,
60 &v_original_size, &v_packed_size);
62 next_pos = ftell(nafp);
64 ftruncate(fileno(nafp), next_pos);
66 memcpy(hdr->method, LZHUFF0_METHOD, METHOD_TYPE_STRAGE);
68 hdr->original_size = v_original_size;
69 hdr->packed_size = v_packed_size;
70 fseek(nafp, header_pos, SEEK_SET);
71 write_header(nafp, hdr);
72 fseek(nafp, next_pos, SEEK_SET);
76 /* ------------------------------------------------------------------------ */
78 append_it(name, oafp, nafp)
89 struct stat stbuf /*, lstbuf*/;
91 boolean directory, symlink;
93 if (GETSTAT(name, &stbuf) < 0) {
94 error("Cannot access file \"%s\"", name); /* See cleaning_files, Why? */
98 directory = is_directory(&stbuf);
100 symlink = is_symlink(&stbuf);
104 init_header(name, &stbuf, &hdr);
106 if (!directory && !noexec)
110 fp = xfopen(name, READ_BINARY);
116 old_header = ftell(oafp);
117 if (!get_header(oafp, &ahdr)) {
122 /* for symbolic link. t.okamoto */
123 cmp = strcmp_filename(ahdr.name, hdr.name);
124 if (cmp < 0) { /* SKIP */
125 /* copy old to new */
127 fseek(oafp, old_header, SEEK_SET);
128 copy_old_one(oafp, nafp, &ahdr);
131 fseek(oafp, ahdr.packed_size, SEEK_CUR);
132 } else if (cmp == 0) { /* REPLACE */
133 /* drop old archive's */
134 fseek(oafp, ahdr.packed_size, SEEK_CUR);
136 } else { /* cmp > 0, INSERT */
137 fseek(oafp, old_header, SEEK_SET);
143 if (update_if_newer) {
144 if (!oafp || /* not in archive */
146 ahdr.unix_last_modified_stamp < /* newer than archive's */
147 hdr.unix_last_modified_stamp) {
149 printf("ADD %s\n", name);
151 add_one(fp, nafp, &hdr);
152 } else { /* cmp == 0 *//* copy old to new */
154 fseek(oafp, old_header, SEEK_SET);
155 copy_old_one(oafp, nafp, &ahdr);
159 if (!oafp || cmp > 0) { /* not in archive or dropped */
161 printf("ADD %s\n", name);
163 add_one(fp, nafp, &hdr);
165 else { /* cmp == 0 */
170 add_one(fp, nafp, &hdr);
179 else { /* recurcive call */
180 if (find_files(name, &filec, &filev)) {
181 for (i = 0; i < filec; i++)
182 oafp = append_it(filev[i], oafp, nafp);
183 free_files(filec, filev);
189 /* ------------------------------------------------------------------------ */
191 find_update_files(oafp)
192 FILE *oafp; /* old archive */
194 char name[FILENAME_LENGTH];
195 struct string_pool sp;
204 while (get_header(oafp, &hdr)) {
205 if ((hdr.unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_REGULAR) {
206 if (stat(hdr.name, &stbuf) >= 0) /* exist ? */
207 add_sp(&sp, hdr.name, strlen(hdr.name) + 1);
209 else if ((hdr.unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_DIRECTORY) {
210 strcpy(name, hdr.name);
212 if (len > 0 && name[len - 1] == '/')
213 name[--len] = '\0'; /* strip tail '/' */
214 if (stat(name, &stbuf) >= 0) /* exist ? */
215 add_sp(&sp, name, len + 1);
217 fseek(oafp, hdr.packed_size, SEEK_CUR);
220 fseek(oafp, pos, SEEK_SET);
222 finish_sp(&sp, &cmd_filec, &cmd_filev);
225 /* ------------------------------------------------------------------------ */
232 char lpath[256], *b1, *b2;
234 old_header_pos = ftell(oafp);
235 while (get_header(oafp, &ahdr)) {
236 strcpy(lpath, ahdr.name);
237 b1 = strtok(lpath, "|");
238 b2 = strtok(NULL, "|");
239 if (need_file(b1)) { /* skip */
240 fseek(oafp, ahdr.packed_size, SEEK_CUR);
241 if (noexec || !quiet)
243 message("delete %s -> %s", b1, b2);
245 message("delete %s", b1);
249 fseek(oafp, ahdr.packed_size, SEEK_CUR);
252 fseek(oafp, old_header_pos, SEEK_SET);
253 copy_old_one(oafp, nafp, &ahdr);
256 old_header_pos = ftell(oafp);
261 /* ------------------------------------------------------------------------ */
263 /* ------------------------------------------------------------------------ */
265 build_temporary_file()
269 signal(SIGINT, interrupt);
271 signal(SIGHUP, interrupt);
274 remove_temporary_at_error = TRUE;
275 temporary_fd = build_temporary_name();
276 if (temporary_fd == -1)
277 fatal_error("Cannot open temporary file \"%s\"", temporary_name);
279 afp = fdopen(temporary_fd, WRITE_BINARY);
281 fatal_error("Cannot open temporary file \"%s\"", temporary_name);
286 /* ------------------------------------------------------------------------ */
291 build_backup_name(backup_archive_name, archive_name);
293 signal(SIGINT, SIG_IGN);
295 signal(SIGHUP, SIG_IGN);
297 if (rename(archive_name, backup_archive_name) < 0) {
299 /* On MinGW, cannot rename when
300 newfile (backup_archive_name) already exists */
301 if (unlink(backup_archive_name) < 0 ||
302 rename(archive_name, backup_archive_name) < 0)
304 fatal_error("Cannot make backup file \"%s\"", archive_name);
306 recover_archive_when_interrupt = TRUE;
307 signal(SIGINT, interrupt);
309 signal(SIGHUP, interrupt);
314 /* ------------------------------------------------------------------------ */
316 report_archive_name_if_different()
318 if (!quiet && new_archive_name == new_archive_name_buffer) {
319 /* warning at old archive is SFX */
320 message("New archive file is \"%s\"", new_archive_name);
324 /* ------------------------------------------------------------------------ */
326 temporary_to_new_archive_file(new_archive_size)
327 long new_archive_size;
331 if (!strcmp(new_archive_name, "-")) {
333 writing_filename = "starndard output";
335 setmode(fileno(stdout), O_BINARY);
339 unlink(new_archive_name);
340 if (rename(temporary_name, new_archive_name) == 0)
342 nafp = xfopen(new_archive_name, WRITE_BINARY);
343 writing_filename = archive_name;
346 oafp = xfopen(temporary_name, READ_BINARY);
347 reading_filename = temporary_name;
348 copyfile(oafp, nafp, new_archive_size, 0);
353 recover_archive_when_interrupt = FALSE;
354 unlink(temporary_name);
356 remove_temporary_at_error = FALSE;
359 /* ------------------------------------------------------------------------ */
361 set_archive_file_mode()
366 if (archive_file_gid < 0) {
367 umask(umask_value = umask(0));
368 archive_file_mode = (~umask_value) & 0666; /* rw-rw-rw- */
369 if (stat(".", &stbuf) >= 0)
370 archive_file_gid = stbuf.st_gid;
372 if (archive_file_gid >= 0)
373 chown(new_archive_name, getuid(), archive_file_gid);
375 chmod(new_archive_name, archive_file_mode);
378 /* ------------------------------------------------------------------------ */
379 /* REMOVE FILE/DIRECTORY */
380 /* ------------------------------------------------------------------------ */
389 if (GETSTAT(name, &stbuf) < 0) {
390 warning("Cannot access \"%s\": %s", name, strerror(errno));
392 else if (is_directory(&stbuf)) {
393 if (find_files(name, &filec, &filev)) {
394 remove_files(filec, filev);
395 free_files(filec, filev);
398 warning("Cannot open directory \"%s\"", name);
401 message("REMOVE DIRECTORY %s", name);
402 else if (rmdir(name) < 0)
403 warning("Cannot remove directory \"%s\"", name);
405 message("Removed %s.", name);
407 else if (is_regularfile(&stbuf)) {
409 message("REMOVE FILE %s.", name);
410 else if (unlink(name) < 0)
411 warning("Cannot remove \"%s\"", name);
413 message("Removed %s.", name);
416 else if (is_symlink(&stbuf)) {
418 printf("REMOVE SYMBOLIC LINK %s.\n", name);
419 else if (unlink(name) < 0)
420 warning("Cannot remove", name);
422 message("Removed %s.", name);
426 error("Cannot remove file \"%s\" (not a file or directory)", name);
431 remove_files(filec, filev)
437 for (i = 0; i < filec; i++)
438 remove_one(filev[i]);
441 /* ------------------------------------------------------------------------ */
443 /* ------------------------------------------------------------------------ */
451 boolean old_archive_exist;
452 long new_archive_size;
454 /* exit if no operation */
455 if (!update_if_newer && cmd_filec == 0) {
456 error("No files given in argument, do nothing.");
460 /* open old archive if exist */
461 if ((oafp = open_old_archive()) == NULL)
462 old_archive_exist = FALSE;
464 old_archive_exist = TRUE;
466 if (update_if_newer && cmd_filec == 0) {
467 warning("No files given in argument");
469 error("archive file \"%s\" does not exists.",
475 if (new_archive && old_archive_exist) {
480 if (oafp && archive_is_msdos_sfx1(archive_name)) {
481 skip_msdos_sfx1_code(oafp);
482 build_standard_archive_name(new_archive_name_buffer, archive_name);
483 new_archive_name = new_archive_name_buffer;
486 new_archive_name = archive_name;
489 /* build temporary file */
491 if (STREQU(new_archive_name, "-")) {
494 setmode(fileno(stdout), O_BINARY);
498 nafp = build_temporary_file();
501 /* find needed files when automatic update */
502 if (update_if_newer && cmd_filec == 0)
503 find_update_files(oafp);
505 /* build new archive file */
506 /* cleaning arguments */
507 cleaning_files(&cmd_filec, &cmd_filev);
508 if (cmd_filec == 0) {
511 if (!noexec && nafp != stdout)
516 for (i = 0; i < cmd_filec; i++) {
517 if (strcmp(cmd_filev[i], archive_name) == 0) {
519 /* exclude target archive */
520 warning("specified file \"%s\" is the generating archive. skip",
522 for (j = i; j < cmd_filec-1; j++)
523 cmd_filev[j] = cmd_filev[j+1];
528 oafp = append_it(cmd_filev[i], oafp, nafp);
532 old_header = ftell(oafp);
533 while (get_header(oafp, &ahdr)) {
535 fseek(oafp, ahdr.packed_size, SEEK_CUR);
537 fseek(oafp, old_header, SEEK_SET);
538 copy_old_one(oafp, nafp, &ahdr);
540 old_header = ftell(oafp);
545 write_archive_tail(nafp);
546 new_archive_size = ftell(nafp);
547 if (nafp != stdout) fclose(nafp);
550 /* build backup archive file */
551 if (old_archive_exist)
554 report_archive_name_if_different();
556 if (nafp != stdout) {
557 /* copy temporary file to new archive file */
558 if (!noexec && rename(temporary_name, new_archive_name) < 0)
559 temporary_to_new_archive_file(new_archive_size);
561 /* set new archive file mode/group */
562 set_archive_file_mode();
564 /* remove archived files */
565 if (delete_after_append)
566 remove_files(cmd_filec, cmd_filev);
571 /* ------------------------------------------------------------------------ */
576 long new_archive_size;
578 /* open old archive if exist */
579 if ((oafp = open_old_archive()) == NULL)
580 fatal_error("Cannot open archive file \"%s\"", archive_name);
582 /* exit if no operation */
583 if (cmd_filec == 0) {
585 warning("No files given in argument, do nothing.");
589 if (archive_is_msdos_sfx1(archive_name)) {
590 skip_msdos_sfx1_code(oafp);
591 build_standard_archive_name(new_archive_name_buffer, archive_name);
592 new_archive_name = new_archive_name_buffer;
595 new_archive_name = archive_name;
598 /* build temporary file */
600 nafp = build_temporary_file();
602 /* build new archive file */
607 write_archive_tail(nafp);
608 new_archive_size = ftell(nafp);
612 /* build backup archive file */
615 /* 1999.5.24 t.oka */
616 if(!noexec && new_archive_size <= 1){
617 unlink(temporary_name);
618 warning("New archive file \"%s\" is not created because it would be empty.", new_archive_name);
622 report_archive_name_if_different();
624 /* copy temporary file to new archive file */
625 if (!noexec && rename(temporary_name, new_archive_name) < 0)
626 temporary_to_new_archive_file(new_archive_size);
628 /* set new archive file mode/group */
629 set_archive_file_mode();
634 /* for symbolic link name. t.okamoto 96/2/20 */
635 int strcmp_filename( str1, str2 )
642 while (*p != 0 && *q != 0) {
644 if (*q == 0) return 0;
645 else if (*q != '|') return -1;
646 } else if (*q == '|') {
647 if (*p == 0) return 0;
648 else if (*q != '|') return 1;
649 } else if (*p != *q) break;
652 return (int)*p-(int)*q;
656 /* Local Variables: */
659 /* compile-command:"gcc -c lhadd.c" */
661 /* vi: set tabstop=4: */