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;
26 reading_filename = hdr->name;
27 writting_filename = temporary_name;
29 if (!fp && generic_format) /* [generic] doesn't need directory
32 header_pos = ftell(nafp);
33 write_header(nafp, hdr);/* DUMMY */
35 if ((hdr->unix_mode & UNIX_FILE_SYMLINK) == UNIX_FILE_SYMLINK) {
36 char buf[256], *b1, *b2;
38 strcpy(buf, hdr->name);
39 b1 = strtok(buf, "|");
40 b2 = strtok(NULL, "|");
41 printf("%s -> %s\t- Symbolic Link\n", b1, b2);
45 if (hdr->original_size == 0) /* empty file or directory */
46 return; /* previous write_header is not DUMMY. (^_^) */
49 data_pos = ftell(nafp);
51 hdr->crc = encode_lzhuf(fp, nafp, hdr->original_size,
52 &v_original_size, &v_packed_size, hdr->name, hdr->method);
54 if (v_packed_size < v_original_size) {
55 next_pos = ftell(nafp);
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);
63 next_pos = ftell(nafp);
65 ftruncate(fileno(nafp), next_pos);
67 bcopy(LZHUFF0_METHOD, hdr->method, METHOD_TYPE_STRAGE);
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);
77 /* ------------------------------------------------------------------------ */
79 append_it(name, oafp, nafp)
90 struct stat stbuf /*, lstbuf*/;
92 boolean directory, symlink;
94 if (GETSTAT(name, &stbuf) < 0) {
95 error("Cannot access", name); /* See cleaning_files, Why? */
99 directory = is_directory(&stbuf);
101 symlink = is_symlink(&stbuf);
105 init_header(name, &stbuf, &hdr);
107 if (!directory && !noexec)
111 fp = xfopen(name, READ_BINARY);
117 old_header = ftell(oafp);
118 if (!get_header(oafp, &ahdr)) {
124 cmp = STRING_COMPARE(ahdr.name, hdr.name);
126 /* for symbolic link. t.okamoto */
127 cmp = strcmp_filename(ahdr.name, hdr.name);
128 if (cmp < 0) { /* SKIP */
129 /* copy old to new */
131 fseek(oafp, old_header, SEEK_SET);
132 copy_old_one(oafp, nafp, &ahdr);
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);
140 } else { /* cmp > 0, INSERT */
141 fseek(oafp, old_header, SEEK_SET);
147 if (update_if_newer) {
148 if (!oafp || /* not in archive */
150 ahdr.unix_last_modified_stamp < /* newer than archive's */
151 hdr.unix_last_modified_stamp) {
153 printf("ADD %s\n", name);
155 add_one(fp, nafp, &hdr);
156 } else { /* cmp == 0 *//* copy old to new */
158 fseek(oafp, old_header, SEEK_SET);
159 copy_old_one(oafp, nafp, &ahdr);
163 if (!oafp || cmp > 0) { /* not in archive or dropped */
165 printf("ADD %s\n", name);
167 add_one(fp, nafp, &hdr);
169 else { /* cmp == 0 */
174 add_one(fp, nafp, &hdr);
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);
193 /* ------------------------------------------------------------------------ */
195 find_update_files(oafp)
196 FILE *oafp; /* old archive */
198 char name[FILENAME_LENGTH];
199 struct string_pool 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);
213 else if ((hdr.unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_DIRECTORY) {
214 strcpy(name, hdr.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);
221 fseek(oafp, hdr.packed_size, SEEK_CUR);
224 fseek(oafp, pos, SEEK_SET);
226 finish_sp(&sp, &cmd_filec, &cmd_filev);
229 /* ------------------------------------------------------------------------ */
236 char lpath[256], *b1, *b2;
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)
247 printf("delete %s -> %s\n", b1, b2);
249 printf("delete %s\n", b1);
253 fseek(oafp, ahdr.packed_size, SEEK_CUR);
256 fseek(oafp, old_header_pos, SEEK_SET);
257 copy_old_one(oafp, nafp, &ahdr);
260 old_header_pos = ftell(oafp);
265 /* ------------------------------------------------------------------------ */
267 /* ------------------------------------------------------------------------ */
269 build_temporary_file()
274 build_temporary_name();
275 signal(SIGINT, interrupt);
277 signal(SIGHUP, interrupt);
280 old_umask = umask(077);
281 afp = xfopen(temporary_name, WRITE_BINARY);
282 remove_temporary_at_error = TRUE;
289 /* ------------------------------------------------------------------------ */
294 build_backup_name(backup_archive_name, archive_name);
296 signal(SIGINT, SIG_IGN);
298 signal(SIGHUP, SIG_IGN);
300 if (rename(archive_name, backup_archive_name) < 0)
301 fatal_error(archive_name);
302 recover_archive_when_interrupt = TRUE;
303 signal(SIGINT, interrupt);
305 signal(SIGHUP, interrupt);
310 /* ------------------------------------------------------------------------ */
312 report_archive_name_if_different()
314 if (!quiet && new_archive_name == new_archive_name_buffer) {
315 /* warning at old archive is SFX */
316 printf("New archive file is \"%s\"\n", new_archive_name);
320 /* ------------------------------------------------------------------------ */
321 #ifdef TMP_FILENAME_TEMPLATE
323 temporary_to_new_archive_file(new_archive_size)
324 long new_archive_size;
328 oafp = xfopen(temporary_name, READ_BINARY);
329 if (!strcmp(new_archive_name, "-")) {
331 writting_filename = "starndard output";
334 nafp = xfopen(new_archive_name, WRITE_BINARY);
335 writting_filename = archive_name;
337 reading_filename = temporary_name;
338 copyfile(oafp, nafp, new_archive_size, 0);
343 recover_archive_when_interrupt = FALSE;
344 unlink(temporary_name);
346 remove_temporary_at_error = FALSE;
349 temporary_to_new_archive_file(new_archive_size)
350 long new_archive_size;
353 p = (char *) strrchr(new_archive_name, '/');
354 p = p ? p + 1 : new_archive_name;
355 unlink(new_archive_name);
356 if (rename(temporary_name, p) < 0) {
357 fprintf(stderr, "Can't rename temporary_name '%s'\n", new_archive_name);
363 /* ------------------------------------------------------------------------ */
365 set_archive_file_mode()
370 if (archive_file_gid < 0) {
371 umask(umask_value = umask(0));
372 archive_file_mode = (~umask_value) & 0666; /* rw-rw-rw- */
373 if (stat(".", &stbuf) >= 0)
374 archive_file_gid = stbuf.st_gid;
376 if (archive_file_gid >= 0)
377 chown(new_archive_name, getuid(), archive_file_gid);
379 chmod(new_archive_name, archive_file_mode);
382 /* ------------------------------------------------------------------------ */
383 /* REMOVE FILE/DIRECTORY */
384 /* ------------------------------------------------------------------------ */
393 if (GETSTAT(name, &stbuf) < 0) {
394 warning("Cannot access", name);
396 else if (is_directory(&stbuf)) {
397 if (find_files(name, &filec, &filev)) {
398 remove_files(filec, filev);
399 free_files(filec, filev);
402 warning("Cannot open directory", name);
405 printf("REMOVE DIRECTORY %s\n", name);
406 else if (rmdir(name) < 0)
407 warning("Cannot remove directory", name);
409 printf("Removed %s.\n", name);
411 else if (is_regularfile(&stbuf)) {
413 printf("REMOVE FILE %s.\n", name);
414 else if (unlink(name) < 0)
415 warning("Cannot remove", name);
417 printf("Removed %s.\n", name);
420 else if (is_symlink(&stbuf)) {
422 printf("REMOVE SYMBOLIC LINK %s.\n", name);
423 else if (unlink(name) < 0)
424 warning("Cannot remove", name);
426 printf("Removed %s.\n", name);
430 error("Cannot remove (not a file or directory)", name);
435 remove_files(filec, filev)
441 for (i = 0; i < filec; i++)
442 remove_one(filev[i]);
445 /* ------------------------------------------------------------------------ */
447 /* ------------------------------------------------------------------------ */
455 boolean old_archive_exist;
456 long new_archive_size;
458 /* exit if no operation */
459 if (!update_if_newer && cmd_filec == 0) {
460 error("No files given in argument, do nothing.", "");
464 /* open old archive if exist */
465 if ((oafp = open_old_archive()) == NULL)
466 old_archive_exist = FALSE;
468 old_archive_exist = TRUE;
470 if (update_if_newer && cmd_filec == 0 && !oafp)
471 fatal_error(archive_name); /* exit if cannot execute
472 * automatic update */
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 nafp = build_temporary_file();
493 /* find needed files when automatic update */
494 if (update_if_newer && cmd_filec == 0)
495 find_update_files(oafp);
497 /* build new archive file */
498 /* cleaning arguments */
499 cleaning_files(&cmd_filec, &cmd_filev);
500 if (cmd_filec == 0) {
508 for (i = 0; i < cmd_filec; i++)
509 oafp = append_it(cmd_filev[i], oafp, nafp);
511 old_header = ftell(oafp);
512 while (get_header(oafp, &ahdr)) {
514 fseek(oafp, ahdr.packed_size, SEEK_CUR);
516 fseek(oafp, old_header, SEEK_SET);
517 copy_old_one(oafp, nafp, &ahdr);
519 old_header = ftell(oafp);
524 write_archive_tail(nafp);
525 new_archive_size = ftell(nafp);
529 /* build backup archive file */
530 if (old_archive_exist)
533 report_archive_name_if_different();
535 /* copy temporary file to new archive file */
536 if (!noexec && (!strcmp(new_archive_name, "-") ||
537 rename(temporary_name, new_archive_name) < 0))
538 temporary_to_new_archive_file(new_archive_size);
540 /* set new archive file mode/group */
541 set_archive_file_mode();
543 /* remove archived files */
544 if (delete_after_append)
545 remove_files(cmd_filec, cmd_filev);
550 /* ------------------------------------------------------------------------ */
555 long new_archive_size;
557 /* open old archive if exist */
558 if ((oafp = open_old_archive()) == NULL)
559 fatal_error(archive_name);
562 /* exit if no operation */
563 if (cmd_filec == 0) {
565 warning("No files given in argument, do nothing.", "");
569 if (archive_is_msdos_sfx1(archive_name)) {
570 skip_msdos_sfx1_code(oafp);
571 build_standard_archive_name(new_archive_name_buffer, archive_name);
572 new_archive_name = new_archive_name_buffer;
575 new_archive_name = archive_name;
578 /* build temporary file */
580 nafp = build_temporary_file();
582 /* build new archive file */
587 write_archive_tail(nafp);
588 new_archive_size = ftell(nafp);
592 /* build backup archive file */
595 /* 1999.5.24 t.oka */
596 if(!noexec && new_archive_size <= 1){
597 unlink(temporary_name);
598 printf("New archive file \"%s\" is not created because it would be empty.\n", new_archive_name);
602 report_archive_name_if_different();
604 /* copy temporary file to new archive file */
605 if (!noexec && rename(temporary_name, new_archive_name) < 0)
606 temporary_to_new_archive_file(new_archive_size);
608 /* set new archive file mode/group */
609 set_archive_file_mode();
614 /* for symbolic link name. t.okamoto 96/2/20 */
615 int strcmp_filename( str1, str2 )
622 while (*p != 0 && *q != 0) {
624 if (*q == 0) return 0;
625 else if (*q != '|') return -1;
626 } else if (*q == '|') {
627 if (*p == 0) return 0;
628 else if (*q != '|') return 1;
629 } else if (*p != *q) break;
632 return (int)*p-(int)*q;
636 /* Local Variables: */
639 /* compile-command:"gcc -c lhadd.c" */