This is lhext.c in view mode; [Download] [Up]
/* ------------------------------------------------------------------------ */
/* LHa for UNIX */
/* lhext.c -- LHarc extract */
/* */
/* Copyright (C) MCMLXXXIX Yooichi.Tagawa */
/* Modified Nobutaka Watazaki */
/* */
/* Ver. 0.00 Original 1988.05.23 Y.Tagawa */
/* Ver. 1.00 Fixed 1989.09.22 Y.Tagawa */
/* Ver. 0.03 LHa for UNIX 1991.12.17 M.Oki */
/* Ver. 1.12 LHa for UNIX 1993.10.01 N.Watazaki */
/* Ver. 1.13b Symbolic Link Update Bug Fix 1994.06.21 N.Watazaki */
/* Ver. 1.14 Source All chagned 1995.01.14 N.Watazaki */
/* ------------------------------------------------------------------------ */
#include "lha.h"
/* ------------------------------------------------------------------------ */
static int skip_flg = FALSE; /* FALSE..No Skip , TRUE..Skip */
static char *methods[] =
{
LZHUFF0_METHOD, LZHUFF1_METHOD, LZHUFF2_METHOD, LZHUFF3_METHOD,
LZHUFF4_METHOD, LZHUFF5_METHOD, LZHUFF6_METHOD,
LARC_METHOD, LARC5_METHOD, LARC4_METHOD,
LZHDIRS_METHOD,
NULL
};
/* ------------------------------------------------------------------------ */
static boolean
inquire_extract(name)
char *name;
{
struct stat stbuf;
skip_flg = FALSE;
if (stat(name, &stbuf) >= 0) {
if (!is_regularfile(&stbuf)) {
error("Already exist (not a file)", name);
return FALSE;
}
if (noexec) {
printf("EXTRACT %s but file is exist.\n", name);
return FALSE;
}
else if (!force) {
if (!isatty(0))
return FALSE;
switch (inquire("OverWrite ?(Yes/[No]/All/Skip)", name, "YyNnAaSs\n")) {
case 0:
case 1:/* Y/y */
break;
case 2:
case 3:/* N/n */
case 8:/* Return */
return FALSE;
case 4:
case 5:/* A/a */
force = TRUE;
break;
case 6:
case 7:/* S/s */
skip_flg = TRUE;
break;
}
}
}
if (noexec)
printf("EXTRACT %s\n", name);
return TRUE;
}
/* ------------------------------------------------------------------------ */
static boolean
make_parent_path(name)
char *name;
{
char path[FILENAME_LENGTH];
struct stat stbuf;
register char *p;
/* make parent directory name into PATH for recursive call */
strcpy(path, name);
for (p = path + strlen(path); p > path; p--)
if (p[-1] == '/') {
*--p = '\0';
break;
}
if (p == path) {
message("Why?", "ROOT");
return FALSE; /* no more parent. */
}
if (GETSTAT(path, &stbuf) >= 0) {
if (is_directory(&stbuf))
return TRUE;
error("Not a directory", path);
return FALSE;
}
errno = 0;
if (verbose)
printf("Making directory \"%s\".", path);
if (mkdir(path, 0777) >= 0) /* try */
return TRUE; /* successful done. */
errno = 0;
if (!make_parent_path(path))
return FALSE;
if (mkdir(path, 0777) < 0) { /* try again */
message("Cannot make directory", path);
return FALSE;
}
return TRUE;
}
/* ------------------------------------------------------------------------ */
static FILE *
open_with_make_path(name)
char *name;
{
FILE *fp;
if ((fp = fopen(name, WRITE_BINARY)) == NULL) {
errno = 0;
if (!make_parent_path(name) ||
(fp = fopen(name, WRITE_BINARY)) == NULL)
error("Cannot extract", name);
errno = 0;
}
return fp;
}
/* ------------------------------------------------------------------------ */
static void
adjust_info(name, hdr)
char *name;
LzHeader *hdr;
{
time_t utimebuf[2];
/* adjust file stamp */
utimebuf[0] = utimebuf[1] = hdr->unix_last_modified_stamp;
utime(name, utimebuf);
if (hdr->extend_type == EXTEND_UNIX
|| hdr->extend_type == EXTEND_OS68K
|| hdr->extend_type == EXTEND_XOSK) {
#ifdef NOT_COMPATIBLE_MODE
Please need your modification in this space.
#else
chmod(name, hdr->unix_mode);
#endif
if (!getuid())
chown(name, hdr->unix_uid, hdr->unix_gid);
errno = 0;
}
}
/* ------------------------------------------------------------------------ */
static void
extract_one(afp, hdr)
FILE *afp; /* archive file */
LzHeader *hdr;
{
FILE *fp; /* output file */
struct stat stbuf;
char name[257];
int crc;
int method;
boolean save_quiet, save_verbose, up_flag;
char *q = hdr->name, c;
if (ignore_directory && rindex(hdr->name, '/')) {
q = (char *) rindex(hdr->name, '/') + 1;
}
else {
if (*q == '/') {
q++;
/*
* if OSK then strip device name
*/
if (hdr->extend_type == EXTEND_OS68K
|| hdr->extend_type == EXTEND_XOSK) {
do
c = (*q++);
while (c && c != '/');
if (!c || !*q)
q = "."; /* if device name only */
}
}
}
if (extract_directory)
sprintf(name, "%s/%s", extract_directory, q);
else
strcpy(name, q);
if ((hdr->unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_REGULAR) {
for (method = 0;; method++) {
if (methods[method] == NULL) {
error("Unknown method skiped ...", name);
return;
}
if (bcmp(hdr->method, methods[method], 5) == 0)
break;
}
reading_filename = archive_name;
writting_filename = name;
if (output_to_stdout || verify_mode) {
if (noexec) {
printf("%s %s\n", verify_mode ? "VERIFY" : "EXTRACT", name);
if (afp == stdin) {
int i = hdr->packed_size;
while (i--)
fgetc(afp);
}
return;
}
save_quiet = quiet;
save_verbose = verbose;
if (!quiet && output_to_stdout) {
printf("::::::::\n%s\n::::::::\n", name);
quiet = TRUE;
verbose = FALSE;
}
else if (verify_mode) {
quiet = FALSE;
verbose = TRUE;
}
crc = decode_lzhuf
(afp, stdout, hdr->original_size, hdr->packed_size, name, method);
quiet = save_quiet;
verbose = save_verbose;
}
else {
if (skip_flg == FALSE) {
up_flag = inquire_extract(name);
if (up_flag == FALSE && force == FALSE) {
return;
}
}
if (skip_flg == TRUE) { /* if skip_flg */
if (stat(name, &stbuf) == 0 && force != TRUE) {
if (stbuf.st_mtime >= hdr->unix_last_modified_stamp) {
if (quiet != TRUE)
printf("%s : Skipped...\n", name);
return;
}
}
}
if (noexec) {
if (afp == stdin) {
int i = hdr->packed_size;
while (i--)
fgetc(afp);
}
return;
}
signal(SIGINT, interrupt);
signal(SIGHUP, interrupt);
unlink(name);
errno = 0;
remove_extracting_file_when_interrupt = TRUE;
if ((fp = open_with_make_path(name)) != NULL) {
crc = decode_lzhuf
(afp, fp, hdr->original_size, hdr->packed_size, name, method);
fclose(fp);
}
remove_extracting_file_when_interrupt = FALSE;
signal(SIGINT, SIG_DFL);
signal(SIGHUP, SIG_DFL);
if (!fp)
return;
}
errno = 0;
if (hdr->has_crc && crc != hdr->crc)
error("CRC error", name);
}
else if ((hdr->unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_DIRECTORY ||
(hdr->unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_SYMLINK) {
/* ↑これで、Symblic Link は、大丈夫か? */
if (!ignore_directory && !verify_mode) {
if (noexec) {
if (quiet != TRUE)
printf("EXTRACT %s (directory)\n", name);
return;
}
/* NAME has trailing SLASH '/', (^_^) */
if ((hdr->unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_SYMLINK) {
char buf[256], *bb1, *bb2;
int l_code;
strcpy(buf, name);
bb1 = strtok(buf, "|");
bb2 = strtok(NULL, "|");
#ifdef S_IFLNK
if (skip_flg == FALSE) {
up_flag = inquire_extract(name);
if (up_flag == FALSE && force == FALSE) {
return;
}
}
if (skip_flg == TRUE) { /* if skip_flg */
if (GETSTAT(bb1, &stbuf) == 0 && force != TRUE) {
if (stbuf.st_mtime >= hdr->unix_last_modified_stamp) {
if (quiet != TRUE)
printf("%s : Skipped...\n", bb1);
return;
}
}
}
unlink(bb1);
l_code = symlink(bb2, bb1);
if (l_code < 0)
printf("Cannot make Symbolic Link : ");
if (quiet != TRUE) {
printf("Symbolic Link %s -> %s\n", bb1, bb2);
strcpy(name, bb1); /* Symbolic's name set */
}
#else
sprintf(buf, "%s -> %s", bb1, bb2);
warning("Can't make Symbolic Link", buf);
return;
#endif
}
else {
if (!output_to_stdout && !make_parent_path(name))
return;
}
}
}
else {
error("Unknown information", name);
}
if (!output_to_stdout)
adjust_info(name, hdr);
}
/* ------------------------------------------------------------------------ */
/* EXTRACT COMMAND MAIN */
/* ------------------------------------------------------------------------ */
void
cmd_extract()
{
LzHeader hdr;
long pos;
FILE *afp;
/* open archive file */
if ((afp = open_old_archive()) == NULL)
fatal_error(archive_name);
if (archive_is_msdos_sfx1(archive_name))
skip_msdos_sfx1_code(afp);
/* extract each files */
while (get_header(afp, &hdr)) {
if (need_file(hdr.name)) {
pos = ftell(afp);
extract_one(afp, &hdr);
fseek(afp, pos + hdr.packed_size, SEEK_SET);
}
else {
if (afp != stdin)
fseek(afp, hdr.packed_size, SEEK_CUR);
else {
int i = hdr.packed_size;
while (i--)
fgetc(afp);
}
}
}
/* close archive file */
fclose(afp);
return;
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.