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.