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 off_t header_pos, next_pos, org_pos, data_pos;
23 off_t 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 info. */
30 header_pos = ftello(nafp);
31 write_header(nafp, hdr);/* DUMMY */
33 if ((hdr->unix_mode & UNIX_FILE_SYMLINK) == UNIX_FILE_SYMLINK) {
35 printf("%s -> %s\t- Symbolic Link\n", hdr->name, hdr->realname);
38 if (hdr->original_size == 0) { /* empty file, symlink or directory */
39 finish_indicator2(hdr->name, "Frozen", 0);
40 return; /* previous write_header is not DUMMY. (^_^) */
43 data_pos = ftello(nafp);
45 hdr->crc = encode_lzhuf(fp, nafp, hdr->original_size,
46 &v_original_size, &v_packed_size, hdr->name, hdr->method);
48 if (v_packed_size < v_original_size) {
49 next_pos = ftello(nafp);
51 else { /* retry by stored method */
52 fseeko(fp, org_pos, SEEK_SET);
53 fseeko(nafp, data_pos, SEEK_SET);
54 hdr->crc = encode_stored_crc(fp, nafp, hdr->original_size,
55 &v_original_size, &v_packed_size);
57 next_pos = ftello(nafp);
59 if (ftruncate(fileno(nafp), next_pos) == -1)
60 error("cannot truncate archive");
62 if (chsize(fileno(nafp), next_pos) == -1)
63 error("cannot truncate archive");
67 memcpy(hdr->method, LZHUFF0_METHOD, METHOD_TYPE_STORAGE);
69 hdr->original_size = v_original_size;
70 hdr->packed_size = v_packed_size;
71 fseeko(nafp, header_pos, SEEK_SET);
72 write_header(nafp, hdr);
73 fseeko(nafp, next_pos, SEEK_SET);
77 append_it(name, oafp, nafp)
90 boolean directory, symlink;
92 if (GETSTAT(name, &stbuf) < 0) {
93 error("Cannot access file \"%s\"", name); /* See cleaning_files, Why? */
97 directory = is_directory(&stbuf);
99 symlink = is_symlink(&stbuf);
105 if (!directory && !symlink && !noexec) {
106 fp = fopen(name, READ_BINARY);
108 error("Cannot open file \"%s\": %s", name, strerror(errno));
113 init_header(name, &stbuf, &hdr);
115 cmp = 0; /* avoid compiler warnings `uninitialized' */
117 old_header = ftello(oafp);
118 if (!get_header(oafp, &ahdr)) {
119 /* end of archive or error occurred */
125 if (!sort_contents) {
127 fseeko(oafp, old_header, SEEK_SET);
128 copy_old_one(oafp, nafp, &ahdr);
131 fseeko(oafp, ahdr.packed_size, SEEK_CUR);
132 cmp = -1; /* to be -1 always */
136 cmp = strcmp(ahdr.name, hdr.name);
137 if (cmp < 0) { /* SKIP */
138 /* copy old to new */
140 fseeko(oafp, old_header, SEEK_SET);
141 copy_old_one(oafp, nafp, &ahdr);
144 fseeko(oafp, ahdr.packed_size, SEEK_CUR);
145 } else if (cmp == 0) { /* REPLACE */
146 /* drop old archive's */
147 fseeko(oafp, ahdr.packed_size, SEEK_CUR);
149 } else { /* cmp > 0, INSERT */
150 fseeko(oafp, old_header, SEEK_SET);
155 if (!oafp || cmp > 0) { /* not in archive */
157 printf("ADD %s\n", name);
159 add_one(fp, nafp, &hdr);
161 else { /* cmp == 0 */
162 if (!update_if_newer ||
163 ahdr.unix_last_modified_stamp < hdr.unix_last_modified_stamp) {
164 /* newer than archive's */
166 printf("REPLACE %s\n", name);
168 add_one(fp, nafp, &hdr);
170 else { /* copy old to new */
172 fseeko(oafp, old_header, SEEK_SET);
173 copy_old_one(oafp, nafp, &ahdr);
180 if (directory && recursive_archiving) { /* recursive call */
181 if (find_files(name, &filec, &filev)) {
182 for (i = 0; i < filec; i++)
183 oafp = append_it(filev[i], oafp, nafp);
184 free_files(filec, filev);
190 /* ------------------------------------------------------------------------ */
192 find_update_files(oafp)
193 FILE *oafp; /* old archive */
195 char name[FILENAME_LENGTH];
196 struct string_pool sp;
205 while (get_header(oafp, &hdr)) {
206 if ((hdr.unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_REGULAR) {
207 if (stat(hdr.name, &stbuf) >= 0) /* exist ? */
208 add_sp(&sp, hdr.name, strlen(hdr.name) + 1);
210 else if ((hdr.unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_DIRECTORY) {
211 strcpy(name, hdr.name); /* ok */
213 if (len > 0 && name[len - 1] == '/')
214 name[--len] = '\0'; /* strip tail '/' */
215 if (stat(name, &stbuf) >= 0) /* exist ? */
216 add_sp(&sp, name, len + 1);
218 fseeko(oafp, hdr.packed_size, SEEK_CUR);
221 fseeko(oafp, pos, SEEK_SET);
223 finish_sp(&sp, &cmd_filec, &cmd_filev);
226 /* ------------------------------------------------------------------------ */
232 off_t old_header_pos;
234 old_header_pos = ftello(oafp);
235 while (get_header(oafp, &ahdr)) {
236 if (need_file(ahdr.name)) { /* skip */
237 fseeko(oafp, ahdr.packed_size, SEEK_CUR);
238 if (noexec || !quiet) {
239 if ((ahdr.unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_SYMLINK)
240 message("delete %s -> %s", ahdr.name, ahdr.realname);
242 message("delete %s", ahdr.name);
247 fseeko(oafp, ahdr.packed_size, SEEK_CUR);
250 fseeko(oafp, old_header_pos, SEEK_SET);
251 copy_old_one(oafp, nafp, &ahdr);
254 old_header_pos = ftello(oafp);
259 /* ------------------------------------------------------------------------ */
261 /* ------------------------------------------------------------------------ */
263 build_temporary_file()
267 signal(SIGINT, interrupt);
269 signal(SIGHUP, interrupt);
272 temporary_fd = build_temporary_name();
273 if (temporary_fd == -1)
274 fatal_error("Cannot open temporary file \"%s\"", temporary_name);
276 afp = fdopen(temporary_fd, WRITE_BINARY);
278 fatal_error("Cannot open temporary file \"%s\"", temporary_name);
283 /* ------------------------------------------------------------------------ */
288 build_backup_name(backup_archive_name, archive_name,
289 sizeof(backup_archive_name));
291 signal(SIGINT, SIG_IGN);
293 signal(SIGHUP, SIG_IGN);
295 if (rename(archive_name, backup_archive_name) < 0) {
297 /* On MinGW, cannot rename when
298 newfile (backup_archive_name) already exists */
299 if (unlink(backup_archive_name) < 0 ||
300 rename(archive_name, backup_archive_name) < 0)
302 fatal_error("Cannot make backup file \"%s\"", archive_name);
304 recover_archive_when_interrupt = TRUE;
305 signal(SIGINT, interrupt);
307 signal(SIGHUP, interrupt);
312 /* ------------------------------------------------------------------------ */
314 report_archive_name_if_different()
316 if (!quiet && new_archive_name == new_archive_name_buffer) {
317 /* warning at old archive is SFX */
318 message("New archive file is \"%s\"", new_archive_name);
322 /* ------------------------------------------------------------------------ */
324 temporary_to_new_archive_file(new_archive_size)
325 off_t new_archive_size;
329 if (!strcmp(new_archive_name, "-")) {
331 writing_filename = "standard output";
332 #if defined(__MINGW32__) || defined(__DJGPP__)
333 setmode(fileno(stdout), O_BINARY);
337 unlink(new_archive_name);
338 if (rename(temporary_name, new_archive_name) == 0)
340 nafp = xfopen(new_archive_name, WRITE_BINARY);
341 writing_filename = archive_name;
344 oafp = xfopen(temporary_name, READ_BINARY);
345 reading_filename = temporary_name;
346 copyfile(oafp, nafp, new_archive_size, 0, 0);
351 recover_archive_when_interrupt = FALSE;
352 unlink(temporary_name);
355 /* ------------------------------------------------------------------------ */
357 set_archive_file_mode()
362 if (archive_file_gid < 0) {
363 umask(umask_value = umask(0));
364 archive_file_mode = (~umask_value) & 0666; /* rw-rw-rw- */
365 if (stat(".", &stbuf) >= 0)
366 archive_file_gid = stbuf.st_gid;
368 if (archive_file_gid >= 0)
369 chown(new_archive_name, getuid(), archive_file_gid);
371 chmod(new_archive_name, archive_file_mode);
374 /* ------------------------------------------------------------------------ */
375 /* REMOVE FILE/DIRECTORY */
376 /* ------------------------------------------------------------------------ */
385 if (GETSTAT(name, &stbuf) < 0) {
386 warning("Cannot access \"%s\": %s", name, strerror(errno));
388 else if (is_directory(&stbuf)) {
389 if (find_files(name, &filec, &filev)) {
390 remove_files(filec, filev);
391 free_files(filec, filev);
394 warning("Cannot open directory \"%s\"", name);
397 message("REMOVE DIRECTORY %s", name);
398 else if (rmdir(name) < 0)
399 warning("Cannot remove directory \"%s\"", name);
401 message("Removed %s.", name);
403 else if (is_regularfile(&stbuf)) {
405 message("REMOVE FILE %s.", name);
406 else if (unlink(name) < 0)
407 warning("Cannot remove \"%s\"", name);
409 message("Removed %s.", name);
412 else if (is_symlink(&stbuf)) {
414 message("REMOVE SYMBOLIC LINK %s.", name);
415 else if (unlink(name) < 0)
416 warning("Cannot remove", name);
418 message("Removed %s.", name);
422 error("Cannot remove file \"%s\" (not a file or directory)", name);
427 remove_files(filec, filev)
433 for (i = 0; i < filec; i++)
434 remove_one(filev[i]);
437 /* ------------------------------------------------------------------------ */
439 /* ------------------------------------------------------------------------ */
447 boolean old_archive_exist;
448 off_t new_archive_size;
450 /* exit if no operation */
451 if (!update_if_newer && cmd_filec == 0) {
452 error("No files given in argument, do nothing.");
456 /* open old archive if exist */
457 if ((oafp = open_old_archive()) == NULL)
458 old_archive_exist = FALSE;
460 old_archive_exist = TRUE;
462 if (update_if_newer && cmd_filec == 0) {
463 warning("No files given in argument");
465 error("archive file \"%s\" does not exists.",
471 if (new_archive && old_archive_exist) {
476 if (oafp && archive_is_msdos_sfx1(archive_name)) {
477 seek_lha_header(oafp);
478 build_standard_archive_name(new_archive_name_buffer,
480 sizeof(new_archive_name_buffer));
481 new_archive_name = new_archive_name_buffer;
484 new_archive_name = archive_name;
487 /* build temporary file */
488 nafp = NULL; /* avoid compiler warnings `uninitialized' */
490 nafp = build_temporary_file();
492 /* find needed files when automatic update */
493 if (update_if_newer && cmd_filec == 0)
494 find_update_files(oafp);
496 /* build new archive file */
497 /* cleaning arguments */
498 cleaning_files(&cmd_filec, &cmd_filev);
499 if (cmd_filec == 0) {
507 for (i = 0; i < cmd_filec; i++) {
510 if (strcmp(cmd_filev[i], archive_name) == 0) {
511 /* exclude target archive */
512 warning("specified file \"%s\" is the generating archive. skip",
514 for (j = i; j < cmd_filec-1; j++)
515 cmd_filev[j] = cmd_filev[j+1];
521 /* exclude files specified by -x option */
522 for (j = 0; exclude_files && exclude_files[j]; j++) {
523 if (fnmatch(exclude_files[j], basename(cmd_filev[i]),
524 FNM_PATHNAME|FNM_NOESCAPE|FNM_PERIOD) == 0)
528 oafp = append_it(cmd_filev[i], oafp, nafp);
534 old_header = ftello(oafp);
535 while (get_header(oafp, &ahdr)) {
537 fseeko(oafp, ahdr.packed_size, SEEK_CUR);
539 fseeko(oafp, old_header, SEEK_SET);
540 copy_old_one(oafp, nafp, &ahdr);
542 old_header = ftello(oafp);
547 new_archive_size = 0; /* avoid compiler warnings `uninitialized' */
551 write_archive_tail(nafp);
554 warning("ftello(): %s", strerror(errno));
555 new_archive_size = 0;
558 new_archive_size = tmp;
563 /* build backup archive file */
564 if (old_archive_exist && backup_old_archive)
567 report_archive_name_if_different();
569 /* copy temporary file to new archive file */
571 if (strcmp(new_archive_name, "-") == 0 ||
572 rename(temporary_name, new_archive_name) < 0) {
574 temporary_to_new_archive_file(new_archive_size);
578 /* set new archive file mode/group */
579 set_archive_file_mode();
581 /* remove archived files */
582 if (delete_after_append)
583 remove_files(cmd_filec, cmd_filev);
588 /* ------------------------------------------------------------------------ */
593 off_t new_archive_size;
595 /* open old archive if exist */
596 if ((oafp = open_old_archive()) == NULL)
597 fatal_error("Cannot open archive file \"%s\"", archive_name);
599 /* exit if no operation */
600 if (cmd_filec == 0) {
602 warning("No files given in argument, do nothing.");
606 if (archive_is_msdos_sfx1(archive_name)) {
607 seek_lha_header(oafp);
608 build_standard_archive_name(new_archive_name_buffer,
610 sizeof(new_archive_name_buffer));
611 new_archive_name = new_archive_name_buffer;
614 new_archive_name = archive_name;
617 /* build temporary file */
618 nafp = NULL; /* avoid compiler warnings `uninitialized' */
620 nafp = build_temporary_file();
622 /* build new archive file */
626 new_archive_size = 0; /* avoid compiler warnings `uninitialized' */
630 write_archive_tail(nafp);
633 warning("ftello(): %s", strerror(errno));
634 new_archive_size = 0;
637 new_archive_size = tmp;
642 /* build backup archive file */
643 if (backup_old_archive)
646 /* 1999.5.24 t.oka */
647 if(!noexec && new_archive_size <= 1){
648 unlink(temporary_name);
649 if (!backup_old_archive)
650 unlink(archive_name);
651 warning("The archive file \"%s\" was removed because it would be empty.", new_archive_name);
655 report_archive_name_if_different();
657 /* copy temporary file to new archive file */
659 if (rename(temporary_name, new_archive_name) < 0)
660 temporary_to_new_archive_file(new_archive_size);
663 /* set new archive file mode/group */
664 set_archive_file_mode();