This is lhadd.c in view mode; [Download] [Up]
/* ------------------------------------------------------------------------ */ /* LHa for UNIX */ /* lhadd.c -- LHarc Add Command */ /* */ /* Copyright (C) MCMLXXXIX Yooichi.Tagawa */ /* Modified Nobutaka Watazaki */ /* */ /* Ver. 1.14 Source All chagned 1995.01.14 N.Watazaki */ /* ------------------------------------------------------------------------ */ #include "lha.h" /* ------------------------------------------------------------------------ */ static void remove_files(); static char new_archive_name_buffer[FILENAME_LENGTH]; static char *new_archive_name; /* ------------------------------------------------------------------------ */ static void add_one(fp, nafp, hdr) FILE *fp, *nafp; LzHeader *hdr; { long header_pos, next_pos, org_pos, data_pos; long v_original_size, v_packed_size; int mode; reading_filename = hdr->name; writting_filename = temporary_name; if (!fp && generic_format) /* [generic] doesn't need directory * info. */ return; header_pos = ftell(nafp); write_header(nafp, hdr);/* DUMMY */ if ((hdr->unix_mode & UNIX_FILE_SYMLINK) == UNIX_FILE_SYMLINK) { char buf[256], *b1, *b2; if (!quiet) { strcpy(buf, hdr->name); b1 = strtok(buf, "|"); b2 = strtok(NULL, "|"); printf("%s -> %s\t- Symbolic Link\n", b1, b2); } /* if quiet .. */ } if (hdr->original_size == 0) /* empty file or directory */ return; /* previous write_header is not DUMMY. (^_^) */ org_pos = ftell(fp); data_pos = ftell(nafp); hdr->crc = encode_lzhuf(fp, nafp, hdr->original_size, &v_original_size, &v_packed_size, hdr->name, hdr->method); if (v_packed_size < v_original_size) { next_pos = ftell(nafp); } else { /* retry by stored method */ fseek(fp, org_pos, SEEK_SET); fseek(nafp, data_pos, SEEK_SET); hdr->crc = encode_stored_crc(fp, nafp, hdr->original_size, &v_original_size, &v_packed_size); fflush(nafp); next_pos = ftell(nafp); #ifndef NOFTRUNCATE ftruncate(fileno(nafp), next_pos); #endif bcopy(LZHUFF0_METHOD, hdr->method, METHOD_TYPE_STRAGE); } hdr->original_size = v_original_size; hdr->packed_size = v_packed_size; fseek(nafp, header_pos, SEEK_SET); write_header(nafp, hdr); fseek(nafp, next_pos, SEEK_SET); } /* ------------------------------------------------------------------------ */ FILE * append_it(name, oafp, nafp) char *name; FILE *oafp, *nafp; { LzHeader ahdr, hdr; FILE *fp; long old_header; int cmp; int filec; char **filev; int i; struct stat stbuf /*, lstbuf*/; boolean directory, symlink; if (GETSTAT(name, &stbuf) < 0) { error("Cannot access", name); /* See cleaning_files, Why? */ return oafp; } directory = is_directory(&stbuf); #ifdef S_IFLNK symlink = is_symlink(&stbuf); #else symlink = 0; #endif init_header(name, &stbuf, &hdr); if (!directory && !noexec) if (symlink) fp = NULL; else fp = xfopen(name, READ_BINARY); else { fp = NULL; } while (oafp) { old_header = ftell(oafp); if (!get_header(oafp, &ahdr)) { fclose(oafp); oafp = NULL; break; } else { #if 0 cmp = STRING_COMPARE(ahdr.name, hdr.name); #endif /* for symbolic link. t.okamoto */ cmp = strcmp_filename(ahdr.name, hdr.name); if (cmp < 0) { /* SKIP */ /* copy old to new */ if (!noexec) { fseek(oafp, old_header, SEEK_SET); copy_old_one(oafp, nafp, &ahdr); } else fseek(oafp, ahdr.packed_size, SEEK_CUR); } else if (cmp == 0) { /* REPLACE */ /* drop old archive's */ fseek(oafp, ahdr.packed_size, SEEK_CUR); break; } else { /* cmp > 0, INSERT */ fseek(oafp, old_header, SEEK_SET); break; } } } if (update_if_newer) { if (!oafp || /* not in archive */ cmp > 0 || /* // */ ahdr.unix_last_modified_stamp < /* newer than archive's */ hdr.unix_last_modified_stamp) { if (noexec) printf("ADD %s\n", name); else add_one(fp, nafp, &hdr); } else { /* cmp == 0 *//* copy old to new */ if (!noexec) { fseek(oafp, old_header, SEEK_SET); copy_old_one(oafp, nafp, &ahdr); } } } else { if (!oafp || cmp > 0) { /* not in archive or dropped */ if (noexec) printf("ADD %s\n", name); else add_one(fp, nafp, &hdr); } else { /* cmp == 0 */ /* replace */ if (noexec) printf("REPLACE\n"); else add_one(fp, nafp, &hdr); } } if (!directory) { if (!noexec) if (!symlink) fclose(fp); } else { /* recurcive call */ if (find_files(name, &filec, &filev)) { for (i = 0; i < filec; i++) oafp = append_it(filev[i], oafp, nafp); free_files(filec, filev); } } return oafp; } /* ------------------------------------------------------------------------ */ static void find_update_files(oafp) FILE *oafp; /* old archive */ { char name[FILENAME_LENGTH]; struct string_pool sp; LzHeader hdr; long pos; struct stat stbuf; int len; pos = ftell(oafp); init_sp(&sp); while (get_header(oafp, &hdr)) { if ((hdr.unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_REGULAR) { if (stat(hdr.name, &stbuf) >= 0) /* exist ? */ add_sp(&sp, hdr.name, strlen(hdr.name) + 1); } else if ((hdr.unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_DIRECTORY) { strcpy(name, hdr.name); len = strlen(name); if (len > 0 && name[len - 1] == '/') name[--len] = '\0'; /* strip tail '/' */ if (stat(name, &stbuf) >= 0) /* exist ? */ add_sp(&sp, name, len + 1); } fseek(oafp, hdr.packed_size, SEEK_CUR); } fseek(oafp, pos, SEEK_SET); finish_sp(&sp, &cmd_filec, &cmd_filev); } /* ------------------------------------------------------------------------ */ static void delete(oafp, nafp) FILE *oafp, *nafp; { LzHeader ahdr; long old_header_pos; char lpath[256], *b1, *b2; old_header_pos = ftell(oafp); while (get_header(oafp, &ahdr)) { strcpy(lpath, ahdr.name); b1 = strtok(lpath, "|"); b2 = strtok(NULL, "|"); if (need_file(b1)) { /* skip */ fseek(oafp, ahdr.packed_size, SEEK_CUR); if (noexec || !quiet) if (b2 != NULL) printf("delete %s -> %s\n", b1, b2); else printf("delete %s\n", b1); } else { /* copy */ if (noexec) { fseek(oafp, ahdr.packed_size, SEEK_CUR); } else { fseek(oafp, old_header_pos, SEEK_SET); copy_old_one(oafp, nafp, &ahdr); } } old_header_pos = ftell(oafp); } return; } /* ------------------------------------------------------------------------ */ /* */ /* ------------------------------------------------------------------------ */ static FILE * build_temporary_file() { int old_umask; FILE *afp; build_temporary_name(); signal(SIGINT, interrupt); signal(SIGHUP, interrupt); old_umask = umask(077); afp = xfopen(temporary_name, WRITE_BINARY); remove_temporary_at_error = TRUE; temporary_fp = afp; umask(old_umask); return afp; } /* ------------------------------------------------------------------------ */ static void build_backup_file() { build_backup_name(backup_archive_name, archive_name); if (!noexec) { signal(SIGINT, SIG_IGN); signal(SIGHUP, SIG_IGN); if (rename(archive_name, backup_archive_name) < 0) fatal_error(archive_name); recover_archive_when_interrupt = TRUE; signal(SIGINT, interrupt); signal(SIGHUP, interrupt); } } /* ------------------------------------------------------------------------ */ static void report_archive_name_if_different() { if (!quiet && new_archive_name == new_archive_name_buffer) { /* warning at old archive is SFX */ printf("New archive file is \"%s\"\n", new_archive_name); } } /* ------------------------------------------------------------------------ */ #ifdef TMP_FILENAME_TEMPLATE void temporary_to_new_archive_file(new_archive_size) long new_archive_size; { FILE *oafp, *nafp; oafp = xfopen(temporary_name, READ_BINARY); if (!strcmp(new_archive_name, "-")) { nafp = stdout; writting_filename = "starndard output"; } else { nafp = xfopen(new_archive_name, WRITE_BINARY); writting_filename = archive_name; } reading_filename = temporary_name; copyfile(oafp, nafp, new_archive_size, 0); if (nafp != stdout) fclose(nafp); fclose(oafp); recover_archive_when_interrupt = FALSE; unlink(temporary_name); remove_temporary_at_error = FALSE; } #else temporary_to_new_archive_file(new_archive_size) long new_archive_size; { char *p; p = (char *) rindex(new_archive_name, '/'); p = p ? p + 1 : new_archive_name; unlink(new_archive_name); if (rename(temporary_name, p) < 0) { fprintf(stderr, "Can't rename temporary_name '%s'\n", new_archive_name); exit(1); } } #endif /* ------------------------------------------------------------------------ */ static void set_archive_file_mode() { int umask_value; struct stat stbuf; if (archive_file_gid < 0) { umask(umask_value = umask(0)); archive_file_mode = (~umask_value) & 0666; /* rw-rw-rw- */ if (stat(".", &stbuf) >= 0) archive_file_gid = stbuf.st_gid; } if (archive_file_gid >= 0) chown(new_archive_name, getuid(), archive_file_gid); chmod(new_archive_name, archive_file_mode); } /* ------------------------------------------------------------------------ */ /* REMOVE FILE/DIRECTORY */ /* ------------------------------------------------------------------------ */ static void remove_one(name) char *name; { struct stat stbuf; int filec; char **filev; if (GETSTAT(name, &stbuf) < 0) { warning("Cannot access", name); } else if (is_directory(&stbuf)) { if (find_files(name, &filec, &filev)) { remove_files(filec, filev); free_files(filec, filev); } else warning("Cannot open directory", name); if (noexec) printf("REMOVE DIRECTORY %s\n", name); else if (rmdir(name) < 0) warning("Cannot remove directory", name); else if (verbose) printf("Removed %s.\n", name); } else if (is_regularfile(&stbuf)) { if (noexec) printf("REMOVE FILE %s.\n", name); else if (unlink(name) < 0) warning("Cannot remove", name); else if (verbose) printf("Removed %s.\n", name); } #ifdef S_IFLNK else if (is_symlink(&stbuf)) { if (noexec) printf("REMOVE SYMBOLIC LINK %s.\n", name); else if (unlink(name) < 0) warning("Cannot remove", name); else if (verbose) printf("Removed %s.\n", name); } #endif else { error("Cannot remove (not a file or directory)", name); } } static void remove_files(filec, filev) int filec; char **filev; { int i; for (i = 0; i < filec; i++) remove_one(filev[i]); } /* ------------------------------------------------------------------------ */ /* */ /* ------------------------------------------------------------------------ */ void cmd_add() { LzHeader ahdr; FILE *oafp, *nafp; int i; long old_header; boolean old_archive_exist; long new_archive_size; /* exit if no operation */ if (!update_if_newer && cmd_filec == 0) { error("No files given in argument, do nothing.", ""); return; } /* open old archive if exist */ if ((oafp = open_old_archive()) == NULL) old_archive_exist = FALSE; else old_archive_exist = TRUE; if (update_if_newer && cmd_filec == 0 && !oafp) fatal_error(archive_name); /* exit if cannot execute * automatic update */ errno = 0; if (new_archive && old_archive_exist) { fclose(oafp); oafp = NULL; } if (oafp && archive_is_msdos_sfx1(archive_name)) { skip_msdos_sfx1_code(oafp); build_standard_archive_name(new_archive_name_buffer, archive_name); new_archive_name = new_archive_name_buffer; } else { new_archive_name = archive_name; } /* build temporary file */ if (!noexec) nafp = build_temporary_file(); /* find needed files when automatic update */ if (update_if_newer && cmd_filec == 0) find_update_files(oafp); /* build new archive file */ /* cleaning arguments */ cleaning_files(&cmd_filec, &cmd_filev); if (cmd_filec == 0) { if (oafp) fclose(oafp); if (!noexec) fclose(nafp); return; } for (i = 0; i < cmd_filec; i++) oafp = append_it(cmd_filev[i], oafp, nafp); if (oafp) { old_header = ftell(oafp); while (get_header(oafp, &ahdr)) { if (noexec) fseek(oafp, ahdr.packed_size, SEEK_CUR); else { fseek(oafp, old_header, SEEK_SET); copy_old_one(oafp, nafp, &ahdr); } old_header = ftell(oafp); } fclose(oafp); } if (!noexec) { write_archive_tail(nafp); new_archive_size = ftell(nafp); fclose(nafp); } /* build backup archive file */ if (old_archive_exist) build_backup_file(); report_archive_name_if_different(); /* copy temporary file to new archive file */ if (!noexec && (!strcmp(new_archive_name, "-") || rename(temporary_name, new_archive_name) < 0)) temporary_to_new_archive_file(new_archive_size); /* set new archive file mode/group */ set_archive_file_mode(); /* remove archived files */ if (delete_after_append) remove_files(cmd_filec, cmd_filev); return; } /* ------------------------------------------------------------------------ */ void cmd_delete() { FILE *oafp, *nafp; long new_archive_size; /* open old archive if exist */ if ((oafp = open_old_archive()) == NULL) fatal_error(archive_name); errno = 0; /* exit if no operation */ if (cmd_filec == 0) { fclose(oafp); warning("No files given in argument, do nothing.", ""); return; } if (archive_is_msdos_sfx1(archive_name)) { skip_msdos_sfx1_code(oafp); build_standard_archive_name(new_archive_name_buffer, archive_name); new_archive_name = new_archive_name_buffer; } else { new_archive_name = archive_name; } /* build temporary file */ if (!noexec) nafp = build_temporary_file(); /* build new archive file */ delete(oafp, nafp); fclose(oafp); if (!noexec) { write_archive_tail(nafp); new_archive_size = ftell(nafp); fclose(nafp); } /* build backup archive file */ build_backup_file(); report_archive_name_if_different(); /* copy temporary file to new archive file */ if (!noexec && rename(temporary_name, new_archive_name) < 0) temporary_to_new_archive_file(new_archive_size); /* set new archive file mode/group */ set_archive_file_mode(); return; } /* for symbolic link name. t.okamoto 96/2/20 */ int strcmp_filename( str1, str2 ) char *str1; char *str2; { char *p, *q; p = str1; q = str2; while (*p != 0 && *q != 0) { if (*p == '|') { if (*q == 0) return 0; else return -1; } else if (*q == '|') { if (*p == 0) return 0; else return 1; } else if (*p != *q) break; p++; q++; } return (int)*p-(int)*q; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.