home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
GEMini Atari
/
GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso
/
files
/
archiver
/
rblharc
/
lharc.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-07-08
|
67KB
|
2,420 lines
/*----------------------------------------------------------------------*/
/* LHarc Archiver Driver for UNIX */
/* */
/* Copyright(C) MCMLXXXIX Yooichi.Tagawa */
/* Thanks to H.Yoshizaki. (MS-DOS LHarc) */
/* */
/* V0.00 Original 1988.05.23 Y.Tagawa */
/* V0.01 Alpha Version (for 4.2BSD) 1989.05.28 Y.Tagawa */
/* V0.02 Alpha Version Rel.2 1989.05.29 Y.Tagawa */
/* V0.03 Release #3 Beta Version 1989.07.02 Y.Tagawa */
/* V0.03a Fix few bug 1989.07.03 Y.Tagawa */
/*----------------------------------------------------------------------*/
#include <stdio.h>
#include <ctype.h>
#ifdef atarist
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <unixlib.h>
#include <memory.h>
#include <osbind.h>
#endif
#include <sys/types.h>
#include <sys/file.h>
#include <sys/stat.h>
/* most of System V, define SYSTIME_HAS_NO_TM */
#ifdef SYSTIME_HAS_NO_TM
#include <time.h>
#else
#include <sys/time.h>
#endif
/* #include <strings.h> */
/* #include <string.h> */
/*----------------------------------------------------------------------*/
/* DIRECTORY ACCESS STUFF */
/*----------------------------------------------------------------------*/
#ifndef NODIRECTORY
#ifdef SYSV_SYSTEM_DIR
#include <dirent.h>
#define DIRENTRY struct dirent
#define NAMLEN(p) ((int)strlen (p->d_name))
#else /* not SYSV_SYSTEM_DIR */
#ifdef NONSYSTEM_DIR_LIBRARY
#include "lhdir.h"
#else /* not NONSYSTEM_DIR_LIBRARY */
#include <sys/dir.h>
#endif /* not NONSYSTEM_DIR_LIBRARY */
#define DIRENTRY struct direct
#define NAMLEN(p) p->d_namlen
extern DIR *opendir ();
extern struct direct *readdir ();
#endif /* not SYSV_SYSTEM_DIR */
#endif
/*----------------------------------------------------------------------*/
/* FILE ATTRIBUTES */
/*----------------------------------------------------------------------*/
/* If file mode is not compatible between your Machine/OS and
LHarc standard UNIX file mode.
(See UNIX Manual stat(1), <sys/stat.h>,
and/or below UNIX_* difinitions. ) */
/* #define NOT_COMPATIBLE_MODE */
/*----------------------------------------------------------------------*/
/* MEMORY FUNCTIONS */
/*----------------------------------------------------------------------*/
#ifdef NOBSTRING
#ifdef __ANSI__
#include "mem.h"
#define bcmp(a,b,n) memcmp ((a),(b),(n))
#define bcopy(s,d,n) memmove((d),(s),(n))
#define bzero(d,n) memset((d),0,(n))
#else /* not __ANSI__ */
#include "memory.h"
#define bcmp(a,b,n) memcmp ((a),(b),(n))
#define bcopy(s,d,n) memcpy ((d),(s),(n)) /* movmem((s),(d),(n)) */
#define bzero(d,n) memset((d),0,(n))
#endif /* not __ANSI__ */
#endif /* NOBSTRING */
/*----------------------------------------------------------------------*/
/* YOUR CUSTOMIZIES */
/*----------------------------------------------------------------------*/
/* These difinitions are changable to you like. */
#define ARCHIVENAME_EXTENTION ".lzh"
#ifndef atarist
#define TMP_FILENAME_TEMPLATE "/tmp/lhXXXXXX"
#else
#define TMP_FILENAME_TEMPLATE "lhXXXXXX"
#endif
#define BACKUPNAME_EXTENTION ".bak"
/* #define MULTIBYTE_CHAR */
/* #define USE_PROF */
#define SJC_FIRST_P(c) \
(((unsigned char)(c) >= 0x80) && \
(((unsigned char)(c) < 0xa0) || \
((unsigned char)(c) >= 0xe0) && \
((unsigned char)(c) < 0xfd)))
#define SJC_SECOND_P(c) \
(((unsigned char)(c) >= 0x40) && \
((unsigned char)(c) < 0xfd) && \
((ungigned char)(c) != 0x7f))
#ifdef MULTIBYTE_CHAR
#define MULTIBYTE_FIRST_P SJC_FIRST_P
#define MULTIBYTE_SECOND_P SJC_SECOND_P
#endif MULTIBYTE_CHAR
/*----------------------------------------------------------------------*/
/* OTHER DIFINITIONS */
/*----------------------------------------------------------------------*/
#ifndef SEEK_SET
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
#endif
#ifdef ultrix
#define R_MODE "r"
#define W_MODE "w"
#else
#define R_MODE "rb"
#define W_MODE "wb"
#endif
#ifndef atarist
#define FILENAME_LENGTH 1024
#else
#define FILENAME_LENGTH FILENAME_MAX
#endif
/* non-integral functions */
extern struct tm *localtime ();
extern char *getenv ();
#ifndef atarist
extern char *malloc ();
extern char *realloc ();
#endif
/* external variables */
extern int errno;
#define FALSE 0
#define TRUE 1
typedef int boolean;
/*----------------------------------------------------------------------*/
/* LHarc FILE DIFINITIONS */
/*----------------------------------------------------------------------*/
#define METHOD_TYPE_STRAGE 5
#define LZHUFF0_METHOD "-lh0-"
#define LZHUFF1_METHOD "-lh1-"
#define LARC4_METHOD "-lz4-"
#define LARC5_METHOD "-lz5-"
#define I_HEADER_SIZE 0
#define I_HEADER_CHECKSUM 1
#define I_METHOD 2
#define I_PACKED_SIZE 7
#define I_ORIGINAL_SIZE 11
#define I_LAST_MODIFIED_STAMP 15
#define I_ATTRIBUTE 19
#define I_NAME_LENGTH 21
#define I_NAME 22
#define I_CRC 22 /* + name_length */
#define I_EXTEND_TYPE 24 /* + name_length */
#define I_MINOR_VERSION 25 /* + name_length */
#define I_UNIX_LAST_MODIFIED_STAMP 26 /* + name_length */
#define I_UNIX_MODE 30 /* + name_length */
#define I_UNIX_UID 32 /* + name_length */
#define I_UNIX_GID 34 /* + name_length */
#define I_UNIX_EXTEND_BOTTOM 36 /* + name_length */
#define EXTEND_GENERIC 0
#define EXTEND_UNIX 'U'
#define EXTEND_MSDOS 'M'
#define EXTEND_MACOS 'm'
#define EXTEND_OS9 '9'
#define EXTEND_OS2 '2'
#define EXTEND_OS68K 'K'
#define EXTEND_OS386 '3'
#define EXTEND_HUMAN 'H'
#define EXTEND_CPM 'C'
#define EXTEND_FLEX 'F'
#define GENERIC_ATTRIBUTE 0x20
#define GENERIC_DIRECTORY_ATTRIBUTE 0x10
#define CURRENT_UNIX_MINOR_VERSION 0x00
typedef struct LzHeader {
unsigned char header_size;
char method[METHOD_TYPE_STRAGE];
long packed_size;
long original_size;
long last_modified_stamp;
unsigned short attribute;
char name[256];
unsigned short crc;
boolean has_crc;
unsigned char extend_type;
unsigned char minor_version;
/* extend_type == EXTEND_UNIX and convert from other type. */
time_t unix_last_modified_stamp;
unsigned short unix_mode;
unsigned short unix_uid;
unsigned short unix_gid;
} LzHeader;
#define UNIX_FILE_TYPEMASK 0170000
#define UNIX_FILE_REGULAR 0100000
#define UNIX_FILE_DIRECTORY 0040000
#define UNIX_SETUID 0004000
#define UNIX_SETGID 0002000
#define UNIX_STYCKYBIT 0001000
#define UNIX_OWNER_READ_PERM 0000400
#define UNIX_OWNER_WRITE_PERM 0000200
#define UNIX_OWNER_EXEC_PERM 0000100
#define UNIX_GROUP_READ_PERM 0000040
#define UNIX_GROUP_WRITE_PERM 0000020
#define UNIX_GROUP_EXEC_PERM 0000010
#define UNIX_OTHER_READ_PERM 0000004
#define UNIX_OTHER_WRITE_PERM 0000002
#define UNIX_OTHER_EXEC_PERM 0000001
#define UNIX_RW_RW_RW 0000666
#define LZHEADER_STRAGE 256
#include "proto.h"
static boolean expand_archive_name P((char *dst , char *src ));
static int sort_by_ascii P((char **a , char **b ));
static boolean find_files P((char *name , int *v_filec , char ***v_filev ));
static free_files P((int filec , char **filev ));
static int calc_sum P((char *p , int len ));
static unsigned short get_word P((void ));
static put_word P((unsigned int v ));
static long get_longword P((void ));
static put_longword P((long v ));
static msdos_to_unix_filename P((char *name , int len ));
static generic_to_unix_filename P((char *name , int len ));
static macos_to_unix_filename P((char *name , int len ));
static long gettz P((void ));
static struct tm *msdos_to_unix_stamp_tm P((long a ));
static time_t generic_to_unix_stamp P((long t ));
static long unix_to_generic_stamp P((time_t t ));
static boolean get_header P((FILE *fp , LzHeader *hdr ));
static init_header P((char *name , struct stat *v_stat , LzHeader *hdr ));
static boolean archive_is_msdos_sfx1 P((char *name ));
static boolean skip_msdos_sfx1_code P((FILE *fp ));
static make_standard_archive_name P((char *name , char *orginal ));
static boolean make_parent_path P((char *name ));
static FILE *open_with_make_path P((char *name ));
static copy_old_one P((FILE *oafp , FILE *nafp , LzHeader *hdr ));
static int write_header P((FILE *nafp , LzHeader *hdr ));
static int extract_one P((FILE *fp , LzHeader *hdr ));
static int append_one P((FILE *fp , FILE *nafp , LzHeader *hdr ));
static boolean need_file P((char *name ));
#ifdef atarist
static int st_truncate (FILE *fp, long pos);
static void stexit (int status);
#endif
#undef P
/*----------------------------------------------------------------------*/
/* PROGRAM */
/*----------------------------------------------------------------------*/
#define CMD_UNKNOWN 0
#define CMD_EXTRACT 1
#define CMD_APPEND 2
#define CMD_VIEW 3
static int cmd = CMD_UNKNOWN;
static char **cmd_filev;
static int cmd_filec;
static char *archive_name;
static char expanded_archive_name[FILENAME_LENGTH];
static char temporary_name[FILENAME_LENGTH];
/* options */
boolean quiet = FALSE;
boolean text_mode = FALSE;
/*static boolean verbose = FALSE; */
static boolean noexec = FALSE; /* debugging option */
static boolean force = FALSE;
static boolean prof = FALSE;
static boolean backup = FALSE;
#ifdef atarist
static boolean hold = FALSE;
#endif
/* view flags */
static boolean long_format_listing = FALSE;
/* extract flags */
static boolean output_to_stdout = FALSE;
#ifdef TSTFLG
boolean tstflg = FALSE;
#endif
/* append flags */
static boolean new_archive = FALSE;
static boolean update_if_newer = FALSE;
static boolean update_freshen = FALSE;
static boolean delete_after_append = FALSE;
static boolean delete_from_archive = FALSE;
static boolean remove_temporary_at_error = FALSE;
#ifdef atarist
/* Additional variables for Atari specific chores */
extern char arcshpath[]; /* Path for ARCSHELL */
static boolean arcsh_flg = FALSE; /* Using ARCSHELL ? */
extern char **targv;
extern int targc;
extern char dirbuf[]; /* Original directory when using ARCSHELL */
extern int wildcard;
extern int desktop;
extern int fullpath;
#endif
/*----------------------------------------------------------------------*/
/* NOTES : Text File Format */
/* GENERATOR NewLine */
/* [generic] 0D 0A */
/* [MS-DOS] 0D 0A */
/* [MacOS] 0D */
/* [UNIX] 0A */
/*----------------------------------------------------------------------*/
#ifndef atarist
main (argc, argv)
#else
lzmain(argc, argv)
#endif
int argc;
char *argv[];
{
char *p;
if (argc < 3)
print_tiny_usage_and_exit ();
/* commands */
#ifndef atarist
switch (argv[1][0])
{
#ifdef TSTFLG
case 't':
tstflg = TRUE;
#endif
case 'x':
case 'e':
cmd = CMD_EXTRACT;
break;
case 'p':
output_to_stdout = TRUE;
cmd = CMD_EXTRACT;
break;
case 'c':
new_archive = TRUE;
cmd = CMD_APPEND;
break;
case 'a':
cmd = CMD_APPEND;
break;
case 'd':
delete_from_archive = TRUE;
cmd = CMD_APPEND;
break;
case 'u':
update_if_newer = TRUE;
cmd = CMD_APPEND;
break;
case 'm':
delete_after_append = TRUE;
cmd = CMD_APPEND;
break;
case 'l':
long_format_listing = TRUE;
case 'v':
cmd = CMD_VIEW;
break;
case 'h':
default:
print_tiny_usage_and_exit ();
}
/* options */
p = &argv[1][1];
for (p = &argv[1][1]; *p; )
{
switch (*p++)
{
case 'q': quiet = TRUE; break;
case 'f': force = TRUE; break;
case 'p': prof = TRUE; break;
/* case 'v': verbose = TRUE; break; */
case 't': text_mode = TRUE; break;
case 'n': noexec = TRUE; break;
default:
fprintf (stderr, "unknown option '%c'.\n", p[-1]);
exit (1);
}
}
#else
switch (tolower (argv[1][0])) /* Converts from upper case only < TOS 1.4 */
{
case 't':
tstflg = TRUE;
case 'x':
case 'e':
cmd = CMD_EXTRACT;
break;
case 'p':
output_to_stdout = TRUE;
cmd = CMD_EXTRACT;
break;
case 'c':
new_archive = TRUE;
cmd = CMD_APPEND;
break;
case 'm':
delete_after_append = TRUE;
case 'a':
cmd = CMD_APPEND;
break;
case 'd':
delete_from_archive = TRUE;
fullpath = TRUE;
cmd = CMD_APPEND;
break;
case 'u':
update_if_newer = TRUE;
cmd = CMD_APPEND;
break;
case 'f':
update_if_newer = update_freshen = TRUE;
cmd = CMD_APPEND;
break;
case 'v':
long_format_listing = TRUE;
case 'l':
cmd = CMD_VIEW;
break;
default:
print_tiny_usage_and_exit ();
}
/* options */
p = &argv[1][1];
for (p = &argv[1][1]; *p; )
{
switch (tolower (*p++)) /* Converts from upper case only for < TOS 1.4 */
{
case 'q': quiet = TRUE; break;
case 'f': force = TRUE; break;
case 'z':
if (desktop)
fullpath = TRUE;
else
fullpath = FALSE;
break;
case 's': text_mode = TRUE; break;
case 'n': noexec = TRUE; break;
case 'b': backup = TRUE; break;
case 'h': hold = TRUE; break;
default:
fprintf (stderr, "unknown option '%c'.\n", p[-1]);
stexit (1);
}
}
#endif
/* archive file name */
archive_name = argv[2];
/* target file name */
cmd_filec = argc - 3;
#ifdef ultrix
cmd_filev = &argv[3];
#else
cmd_filev = argv + 3;
#endif
sort_files ();
switch (cmd)
{
case CMD_EXTRACT: cmd_extract (); break;
case CMD_APPEND: cmd_append (); break;
case CMD_VIEW: cmd_view (); break;
}
#ifdef USE_PROF
if (!prof)
exit (0);
#endif
#ifndef atarist
exit (0);
#else
stexit (0);
#endif
}
print_tiny_usage_and_exit ()
{
#ifndef atarist
fprintf (stderr, "\
LHarc for UNIX V0.03 (Beta Version) Copyright(C) 1989 Y.Tagawa\n\
usage: lharc {axevludmcp}[qnft] archive_file [files or directories...]\n\
commands: options: \n\
a Append q quiet \n\
x,e EXtract n no execute \n\
v,l View/List f force (over write at extract) \n\
u Update newer files \n\
d Delete t FILES are TEXT file \n\
m Move \n\
c re-Construct new archive \n\
p Print to STDOUT \n\
t Test the archive only \n\
");
exit (1);
#else
fprintf (stderr,
"LHarc for the Atari ST V1.2 Based on UNIX V0.03 (C) Y. Tagawa\n\
===============================================================12/07/90========\n\
<<< High-performance file-compression program >>>\n\
===============================================================================\n\
usage : xlharc {<command>}[<options>] archive [files or directories]\n\
-------------------------------------------------------------------------------\n\
<command>\n\
a: Add files to archive u: Update files to archive\n\
f: Freshen files in archive m: Move new files into archive\n\
d: Delete files from archive e,x: EXtract files from archive\n\
p: disPlay files in archive l,v: View List of files in archive\n\
c: re-Construct new archive t: Test integrity of archive\n\
<options>\n\
b: keep a Backup h: Hold screen\n\
q: Quiet mode f: Force overwrite at extract\n\
s: files are text files z: %s\n\
===============================================================================\n\
Atari ST version ported by Bill Shroka bjsjr@NCoast.ORG\n\
GEnie: B.Shroka\n",
(desktop) ? "distinguish full pathnames" : "ignore full pathnames");
stexit (1);
#endif
}
message (title, msg)
char *title, *msg;
{
fprintf (stderr, "LHarc: ");
if (errno == 0)
fprintf (stderr, "%s %s\n", title, msg);
else
perror (msg);
}
warning (msg)
char *msg;
{
message ("Warning :", msg);
}
error (msg)
char *msg;
{
message ("Error :", msg);
if (remove_temporary_at_error)
unlink (temporary_name);
#ifndef atarist
exit (1);
#else
stexit (1);
#endif
}
static char *writting_filename;
static char *reading_filename;
write_error ()
{
error (writting_filename);
}
read_error ()
{
error (reading_filename);
}
/*----------------------------------------------------------------------*/
/* */
/*----------------------------------------------------------------------*/
static boolean expand_archive_name (dst, src)
char *dst, *src;
{
register char *p, *dot;
strcpy (dst, src);
for (p = dst, dot = (char*)0; *p; p++)
if (*p == '.')
dot = p;
else if (*p == '/')
dot = (char*)0;
if (dot)
p = dot;
#ifdef ARCHIVENAME_EXTENTION
strcpy (p, ARCHIVENAME_EXTENTION);
#else
strcpy (p, ".lzh");
#endif
return (strcmp (dst, src) != 0);
}
#define STRING_COMPARE(a,b) strcmp((a),(b))
static int sort_by_ascii (a, b)
char **a, **b;
{
return STRING_COMPARE (*a, *b);
}
sort_files ()
{
if(cmd_filec > 0)
qsort (cmd_filev, cmd_filec, sizeof (char*), sort_by_ascii);
}
#ifndef atarist
static char *strdup (string)
char *string;
{
int len = strlen (string) + 1;
char *p = malloc (len);
bcopy (string, p, len);
return p;
}
#endif
#ifdef NODIRECTORY
/* please need your imprementation */
static boolean find_files (name, v_filec, v_filev)
char *name;
int *v_filec;
char ***v_filev;
{
return FALSE; /* DUMMY */
}
#else
#define NUM_ENTRIES 61 /* Added for clarity and ease of change bjsjr */
static boolean find_files (name, v_filec, v_filev)
char *name;
int *v_filec;
char ***v_filev;
{
char newname[FILENAME_LENGTH];
int len, n;
DIR *dirp;
DIRENTRY *dp;
int alloc_size = sizeof (char**) * NUM_ENTRIES; /* any (^_^) */
char **filev;
int filec = 0;
int alloc_counter = 0; /* Counter to notify when it's time to
realloc bjsjr */
strcpy (newname, name);
len = strlen (name);
dirp = opendir (name);
if (dirp)
{
filev = (char**)malloc (alloc_size);
if (!filev)
error ("not enough memory");
for (dp = readdir (dirp); dp != NULL; dp = readdir (dirp))
{
n = NAMLEN (dp);
if ((dp->d_ino != 0) &&
((dp->d_name[0] != '.') ||
((n != 1) &&
((dp->d_name[1] != '.') ||
(n != 2)))) && /* exclude '.' and '..' */
(strcmp (dp->d_name, temporary_name) != 0) &&
(strcmp (dp->d_name, archive_name) != 0))
{
if ((len != 0) && (newname[len-1] != '/'))
{
newname[len] = '/';
strncpy (newname+len+1, dp->d_name, n);
newname[len+n+1] = '\0';
}
else
{
strncpy (newname+len, dp->d_name, n);
newname[len+n] = '\0';
}
filev[filec++] = strdup (newname);
if (++alloc_counter == NUM_ENTRIES) /* If true, time to realloc */
{
alloc_counter = 0; /* Reset counter */
alloc_size *= 2;
filev = (char**)realloc (filev, alloc_size);
}
}
}
closedir (dirp);
}
*v_filev = filev;
*v_filec = filec;
if (dirp)
{
qsort (filev, filec, sizeof (char*), sort_by_ascii);
return TRUE;
}
else
return FALSE;
}
#endif
static free_files (filec, filev)
int filec;
char **filev;
{
int i;
for (i = 0; i < filec; i ++)
free (filev[i]);
free (filev);
}
/*----------------------------------------------------------------------*/
/* */
/*----------------------------------------------------------------------*/
static int calc_sum (p, len)
register char *p;
register int len;
{
register int sum;
for (sum = 0; len; len--)
sum += *p++;
return sum & 0xff;
}
static unsigned char *get_ptr;
#define setup_get(PTR) get_ptr = (unsigned char*)(PTR)
#define get_byte() (*get_ptr++)
#define put_ptr get_ptr
#define setup_put(PTR) put_ptr = (unsigned char*)(PTR)
#define put_byte(c) *put_ptr++ = (unsigned char)(c)
static unsigned short get_word ()
{
int b0, b1;
b0 = get_byte ();
b1 = get_byte ();
return (b1 << 8) + b0;
}
static put_word (v)
unsigned int v;
{
put_byte (v);
put_byte (v >> 8);
}
static long get_longword ()
{
long b0, b1, b2, b3;
b0 = get_byte ();
b1 = get_byte ();
b2 = get_byte ();
b3 = get_byte ();
return (b3 << 24) + (b2 << 16) + (b1 << 8) + b0;
}
static put_longword (v)
long v;
{
put_byte (v);
put_byte (v >> 8);
put_byte (v >> 16);
put_byte (v >> 24);
}
static msdos_to_unix_filename (name, len)
register char *name;
register int len;
{
register int i;
#ifdef MULTIBYTE_CHAR
for (i = 0; i < len; i ++)
{
if (MULTIBYTE_FIRST_P (name[i]) &&
MULTIBYTE_SECOND_P (name[i+1]))
i ++;
else if (name[i] == '\\')
name[i] = '/';
else if (isupper (name[i]))
name[i] = tolower (name[i]);
}
#else
for (i = 0; i < len; i ++)
{
if (name[i] == '\\')
name[i] = '/';
else if (isupper (name[i]))
name[i] = tolower (name[i]);
}
#endif
}
static generic_to_unix_filename (name, len)
register char *name;
register int len;
{
register int i;
boolean lower_case_used = FALSE;
#ifdef MULTIBYTE_CHAR
for (i = 0; i < len; i ++)
{
if (MULTIBYTE_FIRST_P (name[i]) &&
MULTIBYTE_SECOND_P (name[i+1]))
i ++;
else if (islower (name[i]))
{
lower_case_used = TRUE;
break;
}
}
for (i = 0; i < len; i ++)
{
if (MULTIBYTE_FIRST_P (name[i]) &&
MULTIBYTE_SECOND_P (name[i+1]))
i ++;
else if (name[i] == '\\')
name[i] = '/';
else if (!lower_case_used && isupper (name[i]))
name[i] = tolower (name[i]);
}
#else
for (i = 0; i < len; i ++)
if (islower (name[i]))
{
lower_case_used = TRUE;
break;
}
for (i = 0; i < len; i ++)
{
if (name[i] == '\\')
name[i] = '/';
else if (!lower_case_used && isupper (name[i]))
name[i] = tolower (name[i]);
}
#endif
}
static macos_to_unix_filename (name, len)
register char *name;
register int len;
{
register int i;
for (i = 0; i < len; i ++)
{
if (name[i] == ':')
name[i] = '/';
else if (name[i] == '/')
name[i] = ':';
}
}
/*----------------------------------------------------------------------*/
/* */
/* Generic stamp format: */
/* */
/* 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 */
/* |<-------- year ------->|<- month ->|<-- day -->| */
/* */
/* 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 */
/* |<--- hour --->|<---- minute --->|<- second*2 ->| */
/* */
/*----------------------------------------------------------------------*/
#ifdef atarist
long gettz()
{
struct tm *tm;
static char first_time = 1;
static long t;
extern time_t _timezone;
if(first_time)
{
first_time = 0;
t = time ((long *) 0);
tm = localtime (&t);
t = _timezone - tm->tm_isdst*3600;
}
return t;
}
#else
static long gettz ()
{
struct timeval tp;
struct timezone tzp;
gettimeofday (&tp, &tzp); /* specific to 4.3BSD */
/* return (tzp.tz_minuteswest * 60 + (tzp.tz_dsttime != 0 ? 60L * 60L : 0));*/
return (tzp.tz_minuteswest * 60);
}
#endif
#ifdef NOT_USED
static struct tm *msdos_to_unix_stamp_tm (a)
long a;
{
static struct tm t;
t.tm_sec = ( a & 0x1f) * 2;
t.tm_min = (a >> 5) & 0x3f;
t.tm_hour = (a >> 11) & 0x1f;
t.tm_mday = (a >> 16) & 0x1f;
t.tm_mon = (a >> 16+5) & 0x0f - 1;
t.tm_year = ((a >> 16+9) & 0x7f) + 80;
return &t;
}
#endif
static time_t generic_to_unix_stamp (t)
long t;
{
int year, month, day, hour, min, sec;
long longtime;
static unsigned int dsboy[12] = { 0, 31, 59, 90, 120, 151, 181, 212,
243, 273, 304, 334};
unsigned int days;
year = ((int)(t >> 16+9) & 0x7f) + 1980;
month = (int)(t >> 16+5) & 0x0f; /* 1..12 means Jan..Dec */
day = (int)(t >> 16) & 0x1f; /* 1..31 means 1st,...31st */
hour = ((int)t >> 11) & 0x1f;
min = ((int)t >> 5) & 0x3f;
sec = ((int)t & 0x1f) * 2;
/* Calculate days since 1970.01.01 */
days = (365 * (year - 1970) + /* days due to whole years */
(year - 1970 + 1) / 4 + /* days due to leap years */
dsboy[month-1] + /* days since beginning of this year */
day-1); /* days since beginning of month */
if ((year % 4 == 0) &&
(year % 400 != 0) &&
(month >= 3)) /* if this is a leap year and month */
days++; /* is March or later, add a day */
/* Knowing the days, we can find seconds */
/* Added time_t cast -bjsjr */
longtime = ((((time_t)days * 24) + hour) * 60 + min) * 60 + sec;
longtime += gettz (); /* adjust for timezone */
/* special case: if MSDOS format date and time were zero, then we set
time to be zero here too. */
if (t == 0)
longtime = 0;
/* LONGTIME is now the time in seconds, since 1970/01/01 00:00:00. */
return (time_t)longtime;
}
static long unix_to_generic_stamp (t)
time_t t;
{
if(!t) return 0L;
else
{
struct tm *tm = localtime (&t);
return ((((long)(tm->tm_year - 80)) << 25) +
(((long)(tm->tm_mon + 1)) << 21) +
(((long)tm->tm_mday) << 16) +
(long)((tm->tm_hour << 11) +
(tm->tm_min << 5) +
(tm->tm_sec / 2)));
}
}
/*----------------------------------------------------------------------*/
/* */
/*----------------------------------------------------------------------*/
static boolean get_header (fp, hdr)
FILE *fp;
register LzHeader *hdr;
{
int header_size;
int name_length;
char data[LZHEADER_STRAGE];
int checksum;
int i;
bzero (hdr, sizeof (LzHeader));
if (((header_size = getc (fp)) == EOF) || (header_size == 0))
{
return FALSE; /* finish */
}
if (fread (data + I_HEADER_CHECKSUM,
sizeof (char), header_size + 1, fp) < header_size + 1)
{
error ("Invalid header (LHarc file ?)");
return FALSE; /* finish */
}
setup_get (data + I_HEADER_CHECKSUM);
checksum = calc_sum (data + I_METHOD, header_size);
if (get_byte () != checksum)
warning ("Checksum error (LHarc file?)");
hdr->header_size = header_size;
bcopy (data + I_METHOD, hdr->method, METHOD_TYPE_STRAGE);
#ifdef OLD
if ((bcmp (hdr->method, LZHUFF1_METHOD, METHOD_TYPE_STRAGE) != 0) &&
(bcmp (hdr->method, LZHUFF0_METHOD, METHOD_TYPE_STRAGE) != 0) &&
(bcmp (hdr->method, LARC5_METHOD, METHOD_TYPE_STRAGE) != 0) &&
(bcmp (hdr->method, LARC4_METHOD, METHOD_TYPE_STRAGE) != 0))
{
warning ("Unknown method (LHarc file ?)");
return FALSE; /* invalid method */
}
#endif
setup_get (data + I_PACKED_SIZE);
hdr->packed_size = get_longword ();
hdr->original_size = get_longword ();
hdr->last_modified_stamp = get_longword ();
hdr->attribute = get_word ();
name_length = get_byte ();
for (i = 0; i < name_length; i ++)
hdr->name[i] =(char)get_byte ();
hdr->name[name_length] = '\0';
/* defaults for other type */
hdr->unix_mode = UNIX_FILE_REGULAR | UNIX_RW_RW_RW;
hdr->unix_gid = 0;
hdr->unix_uid = 0;
if (header_size - name_length >= 24)
{ /* EXTEND FORMAT */
hdr->crc = get_word ();
hdr->extend_type = get_byte ();
hdr->minor_version = get_byte ();
hdr->has_crc = TRUE;
}
else if (header_size - name_length == 22)
{ /* Generic with CRC */
hdr->crc = get_word ();
hdr->extend_type = EXTEND_GENERIC;
hdr->has_crc = TRUE;
}
else if (header_size - name_length == 20)
{ /* Generic no CRC */
hdr->extend_type = EXTEND_GENERIC;
hdr->has_crc = FALSE;
}
else
{
warning ("Unknown header (LHarc file ?)");
return FALSE;
}
switch (hdr->extend_type)
{
case EXTEND_MSDOS:
msdos_to_unix_filename (hdr->name, name_length);
hdr->unix_last_modified_stamp =
generic_to_unix_stamp (hdr->last_modified_stamp);
break;
case EXTEND_UNIX:
hdr->unix_last_modified_stamp = (time_t)get_longword ();
hdr->unix_mode = get_word ();
hdr->unix_uid = get_word ();
hdr->unix_gid = get_word ();
break;
case EXTEND_MACOS:
macos_to_unix_filename (hdr->name, name_length);
hdr->unix_last_modified_stamp =
generic_to_unix_stamp (hdr->last_modified_stamp);
break;
default:
generic_to_unix_filename (hdr->name, name_length);
hdr->unix_last_modified_stamp =
generic_to_unix_stamp (hdr->last_modified_stamp);
}
return TRUE;
}
static init_header (name, v_stat, hdr)
char *name;
struct stat *v_stat;
LzHeader *hdr;
{
#ifdef atarist
char *temp;
#endif
bcopy (LZHUFF1_METHOD, hdr->method, METHOD_TYPE_STRAGE);
hdr->packed_size = 0;
hdr->original_size = v_stat->st_size;
hdr->last_modified_stamp = unix_to_generic_stamp (v_stat->st_mtime);
hdr->attribute = GENERIC_ATTRIBUTE;
#ifndef atarist
strcpy (hdr->name, name);
#else
if (fullpath || delete_from_archive) {
temp = strchr (name, ':');
strcpy (hdr->name, temp ? (temp + 2) : name);
}
else {
temp = strrchr (name, '\\');
strcpy (hdr->name, temp ? ++temp : name);
}
#endif
hdr->crc = 0x0000;
hdr->extend_type = EXTEND_UNIX;
hdr->unix_last_modified_stamp = v_stat->st_mtime;
/* 00:00:00 since JAN.1.1970 */
#ifdef NOT_COMPATIBLE_MODE
Please need your modification in this space.
#else
hdr->unix_mode = v_stat->st_mode;
#endif
hdr->unix_uid = v_stat->st_uid;
hdr->unix_gid = v_stat->st_gid;
if (!delete_from_archive)
if ((v_stat->st_mode & S_IFMT) == S_IFDIR)
{
bcopy (LZHUFF0_METHOD, hdr->method, METHOD_TYPE_STRAGE);
hdr->attribute = GENERIC_DIRECTORY_ATTRIBUTE;
hdr->original_size = 0;
strcat (hdr->name, "/");
}
}
/* Write only unix extended header. */
static write_header (nafp, hdr)
FILE *nafp;
LzHeader *hdr;
{
int header_size;
int name_length;
char data[LZHEADER_STRAGE];
bzero (data, LZHEADER_STRAGE);
bcopy (hdr->method, data + I_METHOD, METHOD_TYPE_STRAGE);
setup_put (data + I_PACKED_SIZE);
put_longword (hdr->packed_size);
put_longword (hdr->original_size);
put_longword (hdr->last_modified_stamp);
put_word (hdr->attribute);
name_length = strlen (hdr->name);
put_byte (name_length);
bcopy (hdr->name, data + I_NAME, name_length);
setup_put (data + I_NAME + name_length);
put_word (hdr->crc);
put_byte (EXTEND_UNIX);
put_byte (CURRENT_UNIX_MINOR_VERSION);
put_longword ((long)hdr->unix_last_modified_stamp);
put_word (hdr->unix_mode);
put_word (hdr->unix_uid);
put_word (hdr->unix_gid);
header_size = I_UNIX_EXTEND_BOTTOM - 2 + name_length;
data[I_HEADER_SIZE] = header_size;
data[I_HEADER_CHECKSUM] = calc_sum (data + I_METHOD, header_size);
if (fwrite (data, sizeof (char), header_size + 2, nafp) == 0)
error ("cannot write to temporary file");
}
static boolean archive_is_msdos_sfx1 (name)
char *name;
{
int len = strlen (name);
return ((len >= 4) &&
(strcmp (name + len - 4, ".com") == 0 ||
strcmp (name + len - 4, ".exe") == 0 ||
strcmp (name + len - 4, ".ttp") == 0 ||
strcmp (name + len - 4, ".prg") == 0 ||
strcmp (name + len - 4, ".tos") == 0));
}
static boolean skip_msdos_sfx1_code (fp)
FILE *fp;
{
unsigned char buffer[2048];
unsigned char *p, *q;
int n;
n = fread (buffer, sizeof (char), 2048, fp);
for (p = buffer + 2, q = buffer + n - 5; p < q; p ++)
{
/* found "-l??-" keyword (as METHOD type string) */
if (p[0] == '-' && p[1] == 'l' && p[4] == '-')
{
/* size and checksum validate check */
if (p[-2] > 20 && p[-1] == calc_sum (p, p[-2]))
{
fseek (fp, ((p - 2) - buffer) - n, SEEK_CUR);
return TRUE;
}
}
}
fseek (fp, -n, SEEK_CUR);
return FALSE;
}
/*----------------------------------------------------------------------*/
/* */
/*----------------------------------------------------------------------*/
make_tmp_name (original, name)
char *original;
char *name;
{
#ifdef TMP_FILENAME_TEMPLATE
/* "/tmp/lhXXXXXX" etc. */
char *lhtemp;
char c;
extern char *rindex(), *getenv();
if (lhtemp = getenv ("ARCTEMP")) {
strcpy (name, lhtemp);
/*if(lhtemp[(strlen(lhtemp) - 1)] != '/')*/
c = lhtemp[(strlen(lhtemp) - 1)];
if ((c != '/') && (c != '\\'))
strcat (name, "/");
strcat(name, (((lhtemp = rindex(TMP_FILENAME_TEMPLATE, '/')) == NULL)?
TMP_FILENAME_TEMPLATE : &lhtemp[1]));
} else
strcpy (name, TMP_FILENAME_TEMPLATE);
#else
char *p, *s;
strcpy (name, original);
for (p = name, s = (char*)0; *p; p++)
if (*p == '/')
s = p;
strcpy ((s ? s+1 : name), "#..lhXXXXXX");
#endif
mktemp (name);
}
make_backup_name (name, orginal)
char *name;
char *orginal;
{
register char *p, *dot;
strcpy (name, orginal);
for (p = name, dot = (char*)0; *p; p ++)
{
if (*p == '.')
dot = p;
else if (*p == '/')
dot = (char*)0;
}
if (dot)
p = dot;
#ifdef BACKUPNAME_EXTENTION
strcpy (p, BACKUPNAME_EXTENTION) ;
#else
strcpy (p, ".bak");
#endif
}
static make_standard_archive_name (name, orginal)
char *name;
char *orginal;
{
register char *p, *dot;
strcpy (name, orginal);
for (p = name, dot = (char*)0; *p; p ++)
{
if (*p == '.')
dot = p;
else if (*p == '/')
dot = (char*)0;
}
if (dot)
p = dot;
#ifdef ARCHIVENAME_EXTENTION
strcpy (p, ARCHIVENAME_EXTENTION);
#else
strcpy (p, ".lzh");
#endif
}
/*----------------------------------------------------------------------*/
/* */
/*----------------------------------------------------------------------*/
static boolean need_file (name)
char *name;
{
int i;
#ifdef atarist
char *temp;
#endif
if (cmd_filec == 0)
return TRUE;
for (i = 0; i < cmd_filec; i ++)
{
#ifdef atarist
temp = strstr (cmd_filev[i], name);
if ((temp) && (strlen (cmd_filev[i]) != strlen (temp))) {
strncpy (arcshpath, cmd_filev[i], (strlen (cmd_filev[i]) - strlen (temp)) - 1);
chdir (arcshpath);
strcpy (name, temp);
return TRUE;
}
else if (!temp)
return FALSE;
else
if (strcmp (cmd_filev[i], name) == 0)
return TRUE;
}
#else
if (strcmp (cmd_filev[i], name) == 0)
return TRUE;
}
#endif
return FALSE;
}
FILE *xfopen (name, mode)
char *name, *mode;
{
FILE *fp;
if ((fp = fopen (name, mode)) == NULL)
error (name);
return fp;
}
/*----------------------------------------------------------------------*/
/* Listing Stuff */
/*----------------------------------------------------------------------*/
/* need 14 or 22 (when long_format_listing is TRUE) column spaces */
print_size (packed_size, original_size)
long packed_size, original_size;
{
#ifndef atarist
if (long_format_listing)
printf ("%7ld ", packed_size);
#endif
printf ("%7ld ", original_size);
#ifdef atarist
printf (" %7ld ", packed_size);
#endif
if (original_size == 0L)
printf ("******");
else
printf ("%3d.%1d%%",
(int)((packed_size * 100L) / original_size),
(int)((packed_size * 1000L) / original_size) % 10);
}
/* need 12 or 17 (when long_format_listing is TRUE) column spaces */
print_stamp (t)
#ifdef atarist
time_t t;
#else
long t;
#endif
{
static boolean got_now = FALSE;
static time_t now;
static unsigned int threshold;
#ifndef INTERNATIONAL_TIME
static char t_month[12*3+1] = "JanFebMarAprMayJunJulAugSepOctNovDec";
/* fixed DecNov to NovDec bjsjr */
#endif
struct tm *p;
if (t == 0)
{
if (long_format_listing)
printf (" "); /* 17 spaces */
else
printf (" "); /* 12 spaces */
return;
}
if (!got_now)
{
now = time ((time_t*)0);
p = localtime (&now);
threshold = p->tm_year * 12 + p->tm_mon - 6;
got_now = TRUE;
}
p = localtime (&t);
if (long_format_listing)
#ifndef atarist
printf ("%.3s %2d %02d:%02d %04d",
&t_month[p->tm_mon * 3], p->tm_mday,
p->tm_hour, p->tm_min, p->tm_year + 1900);
else
if (p->tm_year * 12 + p->tm_mon > threshold)
printf ("%.3s %2d %02d:%02d",
&t_month[p->tm_mon * 3], p->tm_mday, p->tm_hour,
p->tm_min);
else
printf ("%.3s %2d %04d",
&t_month[p->tm_mon * 3], p->tm_mday, p->tm_year +
1900);
#else
printf ("%04d-%02d-%02d %02d:%02d:%02d",
p->tm_year + 1900, p->tm_mon + 1,
p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec);
else
if (p->tm_year * 12 + p->tm_mon > threshold)
printf ("%02d-%02d %02d:%02d:%02d",
p->tm_mon + 1, p->tm_mday, p->tm_hour, p->tm_min,
p->tm_sec);
else
printf ("%04d-%02d-%02d",
p->tm_year + 1900, p->tm_mon + 1, p->tm_mday);
#endif
}
print_bar ()
{
/* 17+1+(0 or 7+1)+7+1+6+1+(0 or 1+4)+(12 or 17)+1+20 */
/* 12345678901234567_ 1234567_123456 _123456789012 1234 */
#ifndef atarist
if (long_format_listing)
printf ("----------------- ------- ------- ------ ---- ----------------- -------------\n");
else
printf ("----------------- ------- ------ ------------ --------------------\n");
#else
if (long_format_listing)
printf ("-------- ------- ------ ------------------- ----- ---- --------------------\n");
else
printf ("-------- ------- ------ --------------------------------------\n");
#endif
}
/*
view
*/
cmd_view ()
{
FILE *fp;
LzHeader hdr;
register char *p;
long a_packed_size = 0L;
long a_original_size = 0L;
int n_files = 0;
struct stat v_stat;
if ((fp = fopen (archive_name, R_MODE)) == NULL)
if (!expand_archive_name (expanded_archive_name, archive_name))
error (archive_name);
else
{
errno = 0;
fp = xfopen (expanded_archive_name, R_MODE);
archive_name = expanded_archive_name;
}
if (archive_is_msdos_sfx1 (archive_name))
{
skip_msdos_sfx1_code (fp);
}
#ifndef atarist
if (!quiet)
{
/* 12345678901234567_ 1234567_123456 _ 123456789012 1234 */
printf (" PERMSSN UID GID %s SIZE RATIO%s %s STAMP %s NAME\n",
long_format_listing ? " PACKED " : "", /* 8,0 */
long_format_listing ? " CRC" : "", /* 5,0 */
long_format_listing ? " " : "", /* 2,0 */
long_format_listing ? " " : ""); /* 3,0 */
print_bar ();
}
while (get_header (fp, &hdr))
{
if (need_file (hdr.name))
{
if (hdr.extend_type == EXTEND_UNIX)
{
printf ("%c%c%c%c%c%c%c%c%c%4d/%-4d",
((hdr.unix_mode & UNIX_OWNER_READ_PERM) ? 'r' : '-'),
((hdr.unix_mode & UNIX_OWNER_WRITE_PERM) ? 'w' : '-'),
((hdr.unix_mode & UNIX_OWNER_EXEC_PERM) ? 'x' : '-'),
((hdr.unix_mode & UNIX_GROUP_READ_PERM) ? 'r' : '-'),
((hdr.unix_mode & UNIX_GROUP_WRITE_PERM) ? 'w' : '-'),
((hdr.unix_mode & UNIX_GROUP_EXEC_PERM) ? 'x' : '-'),
((hdr.unix_mode & UNIX_OTHER_READ_PERM) ? 'r' : '-'),
((hdr.unix_mode & UNIX_OTHER_WRITE_PERM) ? 'w' : '-'),
((hdr.unix_mode & UNIX_OTHER_EXEC_PERM) ? 'x' : '-'),
hdr.unix_uid, hdr.unix_gid);
}
else
{
switch (hdr.extend_type)
{ /* max 18 characters */
case EXTEND_GENERIC: p = "[generic]"; break;
case EXTEND_CPM: p = "[CP/M]"; break;
/* OS-9 and FLEX's CPU is MC-6809. I like it. :-) */
case EXTEND_FLEX: p = "[FLEX]"; break;
case EXTEND_OS9: p = "[OS-9]"; break;
/* I guessed from this ID. Is this right? */
case EXTEND_OS68K: p = "[OS-9/68K]"; break;
case EXTEND_MSDOS: p = "[MS-DOS]"; break;
/* I have Macintosh. :-) */
case EXTEND_MACOS: p = "[Mac OS]"; break;
case EXTEND_OS2: p = "[OS/2]"; break;
case EXTEND_HUMAN: p = "[Human68K]"; break;
case EXTEND_OS386: p = "[OS-386]"; break;
#ifdef EXTEND_TOWNSOS
/* This ID isn't fixed */
case EXTEND_TOWNSOS: p = "[TownsOS]"; break;
#endif
/* Ouch! Please customize it's ID. */
default: p = "[unknown]"; break;
}
printf ("%-18.18s", p);
}
print_size (hdr.packed_size, hdr.original_size);
if (long_format_listing)
if (hdr.has_crc)
printf (" %04x", hdr.crc);
else
printf (" ****");
printf (" ");
print_stamp (hdr.unix_last_modified_stamp);
printf (" %s\n", hdr.name);
n_files ++;
a_packed_size += hdr.packed_size;
a_original_size += hdr.original_size;
}
fseek (fp, hdr.packed_size, SEEK_CUR);
}
#else
if (!quiet)
{
/* 12345678901234567_ 1234567_123456 _ 123456789012 1234 */
printf("Listing of archive : '%s'\n\n", archive_name);
printf ("Original Packed Ratio %s %s%s Name\n",
long_format_listing ? " Stamp" : "", /* 8,0 */
long_format_listing ? " Methd" : "", /* 5,0 */
long_format_listing ? " CRC" : "", /* 2,0 */
long_format_listing ? " " : ""); /* 3,0 */
print_bar ();
}
while (get_header (fp, &hdr))
{
if (need_file (hdr.name))
{
print_size (hdr.packed_size, hdr.original_size);
if (long_format_listing) {
printf (" ");
print_stamp (hdr.unix_last_modified_stamp);
printf (" %5s", hdr.method);
if (hdr.has_crc)
printf (" %04x", hdr.crc);
else
printf (" ****");
}
printf (" %s\n", hdr.name);
n_files ++;
a_packed_size += hdr.packed_size;
a_original_size += hdr.original_size;
}
fseek (fp, hdr.packed_size, SEEK_CUR);
}
#endif /* atarist */
fclose (fp);
if (!quiet)
{
print_bar ();
#ifndef atarist
printf (" Total %4d file%c ",
n_files, (n_files == 1) ? ' ' : 's');
print_size (a_packed_size, a_original_size);
printf (" ");
if (long_format_listing)
printf (" ");
if (stat (archive_name, &v_stat) < 0)
print_stamp ((time_t)0);
else
print_stamp (v_stat.st_mtime);
printf ("\n");
}
#else
print_size (a_packed_size, a_original_size);
printf (" ");
if (stat (archive_name, &v_stat) < 0)
print_stamp ((time_t)0);
else
print_stamp (v_stat.st_mtime);
printf (" %4d file%c Total\n",
n_files, (n_files == 1) ? ' ' : 's');
}
#endif
return;
}
static boolean make_parent_path (name)
char *name;
{
char path[FILENAME_LENGTH];
struct stat v_stat;
register char *p;
#ifdef TSTFLG
if (tstflg)
return TRUE;
#endif
/* make parent directory name into PATH for recursive call */
strcpy (path, name);
for (p = path + strlen (path); p > path; p --)
if (p[-1] == '/')
{
p[-1] = '\0';
break;
}
if (p == path)
return FALSE; /* no more parent. */
if (stat (path, &v_stat) >= 0)
{
if ((v_stat.st_mode & S_IFMT) != S_IFDIR)
return FALSE; /* already exist. but it isn't directory. */
return TRUE; /* already exist its directory. */
}
errno = 0;
if (!quiet)
message ("Making Directory", path);
#ifdef atarist
if (mkdir (path) >= 0) /* try */
#else
if (mkdir (path, 0777) >= 0) /* try */
#endif
return TRUE; /* successful done. */
errno = 0;
if (!make_parent_path (path))
return FALSE;
#ifdef atarist
if (mkdir (path) < 0) /* try again */
#else
if (mkdir (path, 0777) < 0) /* try again */
#endif
return FALSE;
return TRUE;
}
static FILE *open_with_make_path (name)
char *name;
{
FILE *fp;
struct stat v_stat;
char buffer[1024];
if (stat (name, &v_stat) >= 0)
{
if ((v_stat.st_mode & S_IFMT) != S_IFREG)
return NULL;
if (!force)
{
for (;;)
{
fprintf (stderr, "%s OverWrite ?(Yes/No/All) ", name);
fflush (stderr);
gets (buffer);
if (buffer[0] == 'N' || buffer[0] == 'n')
return NULL;
if (buffer[0] == 'Y' || buffer[0] == 'y')
break;
if (buffer[0] == 'A' || buffer[0] == 'a')
{
force = TRUE;
break;
}
}
}
}
fp = fopen (name, W_MODE);
if (!fp)
{
errno = 0;
if (!make_parent_path (name))
return NULL;
fp = fopen (name, W_MODE);
if (!fp)
message ("Error :", name);
}
return fp;
}
extern int decode_lzhuf (), decode_larc ();
extern int decode_stored_crc (), decode_stored_nocrc ();
static extract_one (fp, hdr)
FILE *fp;
LzHeader *hdr;
{
FILE *ofp; /* output file */
char name[1024];
time_t utimebuf[2];
int crc;
int (*decode_proc)(); /* (ifp,ofp,original_size,name) */
int save_quiet;
#ifdef TSTFLG
char *temp;
#endif
strcpy (name, hdr->name);
#ifdef atarist
if (!fullpath && !tstflg)
if (temp = strrchr (name, '/'))
strcpy (name, ++temp);
#endif
if ((hdr->unix_mode & UNIX_FILE_TYPEMASK) == UNIX_FILE_REGULAR)
{
if (bcmp (hdr->method, LZHUFF1_METHOD, METHOD_TYPE_STRAGE) == 0)
decode_proc = decode_lzhuf;
else if ((bcmp (hdr->method, LZHUFF0_METHOD, METHOD_TYPE_STRAGE) == 0) ||
(bcmp (hdr->method, LARC4_METHOD, METHOD_TYPE_STRAGE) == 0))
decode_proc = (hdr->has_crc) ? decode_stored_crc : decode_stored_nocrc;
else if (bcmp (hdr->method, LARC5_METHOD, METHOD_TYPE_STRAGE) == 0)
decode_proc = decode_larc;
else
message ("Error :", "Sorry, Cannot Extract this method.");
reading_filename = archive_name;
writting_filename = name;
if (output_to_stdout)
{
if (!quiet)
printf ("::::::::\n%s\n::::::::\n", name);
save_quiet = quiet;
quiet = TRUE;
crc = (*decode_proc) (fp, stdout, hdr->original_size, name);
quiet = save_quiet;
}
else
{
#ifdef TSTFLG
if (!tstflg) { /* If we are really EXtracting and not merely Testing */
#endif
if ((ofp = open_with_make_path (name)) == NULL)
return;
else
{
crc = (*decode_proc) (fp, ofp, hdr->original_size, name);
fclose (ofp);
}
#ifdef TSTFLG
}
else /* If we are just Testing */
#ifdef atarist
crc = (*decode_proc) (fp, NULL, hdr->original_size, name);
#else
if ((ofp = fopen("/dev/null", "w")) == NULL)
return;
else
{
crc = (*decode_proc) (fp, ofp, hdr->original_size, name);
fclose (ofp);
}
#endif /*atarist */
#endif /* TSTFLG */
}
if (hdr->has_crc && (crc != hdr->crc))
error ("CRC Error");
}
else
{
#ifdef atarist
if (fullpath || tstflg)
#endif
/* NAME has trailing SLASH '/', (^_^) */
if (!output_to_stdout &&
!make_parent_path (name))
error (name);
}
#ifndef TSTFLG
if (!output_to_stdout)
#else
if (!output_to_stdout && !tstflg)
#endif
{
utimebuf[0] = utimebuf[1] = hdr->unix_last_modified_stamp;
utime (name, utimebuf);
#ifdef NOT_COMPATIBLE_MODE
Please need your modification in this space.
#else
chmod (name, hdr->unix_mode);
#endif
#ifndef atarist
chown (name, hdr->unix_uid, hdr->unix_gid);
#endif
errno = 0;
}
}
/*
extract
*/
cmd_extract ()
{
LzHeader hdr;
long pos;
FILE *fp;
if ((fp = fopen (archive_name, R_MODE)) == NULL)
if (!expand_archive_name (expanded_archive_name, archive_name))
error (archive_name);
else
{
errno = 0;
fp = xfopen (expanded_archive_name, R_MODE);
archive_name = expanded_archive_name;
}
#ifdef TSTFLG
printf ("%s '%s'\n", ((!tstflg) ? "Extract from" : "Testing"), archive_name);
#endif
if (archive_is_msdos_sfx1 (archive_name))
{
skip_msdos_sfx1_code (fp);
}
#ifdef atarist
if (wildcard) {
chdir (arcshpath);
cmd_filec = 0;
}
#endif
while (get_header (fp, &hdr))
{
if (need_file (hdr.name))
{
pos = ftell (fp);
extract_one (fp, &hdr);
fseek (fp, pos + hdr.packed_size, SEEK_SET);
} else {
fseek (fp, hdr.packed_size, SEEK_CUR);
}
}
fclose (fp);
return;
}
/*----------------------------------------------------------------------*/
/* */
/*----------------------------------------------------------------------*/
extern int encode_lzhuf ();
extern int encode_storerd_crc ();
static append_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;
reading_filename = hdr->name;
writting_filename = temporary_name;
org_pos = ftell (fp);
header_pos = ftell (nafp);
write_header (nafp, hdr); /* DUMMY */
if (hdr->original_size == 0)
return; /* previous write_header is not DUMMY. (^_^) */
data_pos = ftell (nafp);
hdr->crc = encode_lzhuf (fp, nafp, hdr->original_size,
&v_original_size, &v_packed_size, hdr->name);
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);
#ifdef atarist
st_truncate (nafp, next_pos);
#else
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);
}
write_tail (nafp)
FILE *nafp;
{
putc (0x00, nafp);
}
static copy_old_one (oafp, nafp, hdr)
FILE *oafp, *nafp;
LzHeader *hdr;
{
if (noexec)
{
fseek (oafp, (long)(hdr->header_size + 2) + hdr->packed_size, SEEK_CUR);
}
else
{
reading_filename = archive_name;
writting_filename = temporary_name;
copy_file (oafp, nafp, (long)(hdr->header_size + 2) + hdr->packed_size);
}
}
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 v_stat;
boolean directory;
#ifdef atarist
char *temp;
#endif
if (!delete_from_archive)
{
if (stat (name, &v_stat) < 0)
{
message ("Error : ", name);
return oafp;
}
}
else
bzero(&v_stat, sizeof(v_stat));
directory = ((v_stat.st_mode & S_IFMT) == S_IFDIR);
#ifndef atarist
init_header (name, &v_stat, &hdr);
#else
if (!fullpath) {
if (!directory)
if (temp = strrchr (name,'/'))
init_header (++temp, &v_stat, &hdr);
else
init_header (name, &v_stat, &hdr);
else
goto nodir;
}
else
init_header (name, &v_stat, &hdr);
#endif
if (!delete_from_archive && !directory)
fp = xfopen (name, R_MODE);
else
fp = NULL;
while (oafp)
{
old_header = ftell (oafp);
if (!get_header (oafp, &ahdr))
{
fclose (oafp);
oafp = NULL;
break;
}
else
{
cmp = STRING_COMPARE (ahdr.name, hdr.name);
if (cmp < 0)
{ /* SKIP */
fseek (oafp, old_header, SEEK_SET);
copy_old_one (oafp, nafp, &ahdr);
}
else if (cmp == 0)
{ /* REPLACE */
fseek (oafp, ahdr.packed_size, SEEK_CUR);
break;
}
else /* cmp > 0, INSERT */
{
fseek (oafp, old_header, SEEK_SET);
break;
}
}
}
if (delete_from_archive)
{
if (noexec)
fprintf (stderr, "DELETE %s\n", name);
else
printf ("%s - Deleted\n", name);
}
else
{
if (!oafp || /* not in archive */
(cmp > 0) || /* // */
!update_if_newer || /* always update */
(ahdr.unix_last_modified_stamp < /* newer than archive's */
hdr.unix_last_modified_stamp))
{
if(fp)
{
if (noexec)
fprintf (stderr, "APPEND %s\n", name);
else
if (!update_freshen || (cmp == 0))
append_one (fp, nafp, &hdr);
}
}
else
{ /* archive has old one */
fseek (oafp, old_header, SEEK_SET);
copy_old_one (oafp, nafp, &ahdr);
}
#ifdef atarist
nodir:
#endif
if (!directory)
{
if (!noexec)
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;
}
}
return oafp;
}
remove_it (name)
char *name;
{
struct stat v_stat;
int i;
char **filev;
int filec;
if (stat (name, &v_stat) < 0)
{
fprintf (stderr, "cannot access \"%s\".\n", name);
return;
}
if ((v_stat.st_mode & S_IFMT) == S_IFDIR)
{
if (!find_files (name, &filec, &filev))
{
fprintf (stderr, "cannot open directory \"%s\".\n", name);
return;
}
for (i = 0; i < filec; i ++)
remove_it (filev[i]);
free_files (filec, filev);
if (noexec)
printf ("REMOVE DIRECTORY \"%s\"\n", name);
else if (rmdir (name) < 0)
fprintf (stderr, "cannot remove directory \"%s\".\n", name);
else if (!quiet)
printf ("Erased \"%s\".\n", name);
}
else
{
if (noexec)
printf ("ERASE \"%s\".\n", name);
else if (unlink (name) < 0)
fprintf (stderr, "cannot remove \"%s\".\n", name);
else if (!quiet)
printf ("Erased \"%s\".\n", name);
}
}
cmd_append ()
{
LzHeader ahdr;
FILE *oafp, *nafp;
char backup_archive_name [ FILENAME_LENGTH ];
char new_archive_name_buffer [ FILENAME_LENGTH ];
char *new_archive_name;
int i;
long old_header;
struct stat v_stat;
boolean old_archive_exist;
if (cmd_filec == 0)
return;
make_tmp_name (archive_name, temporary_name);
if ((oafp = fopen (archive_name, R_MODE)) == NULL)
if (expand_archive_name (expanded_archive_name, archive_name))
{
errno = 0;
oafp = fopen (expanded_archive_name, R_MODE);
archive_name = expanded_archive_name;
}
old_archive_exist = (oafp) ? TRUE : FALSE;
if (new_archive && oafp)
{
fclose (oafp);
oafp = NULL;
}
if (oafp && archive_is_msdos_sfx1 (archive_name))
{
skip_msdos_sfx1_code (oafp);
make_standard_archive_name (new_archive_name_buffer, archive_name);
new_archive_name = new_archive_name_buffer;
}
else
{
new_archive_name = archive_name;
}
errno = 0;
if (!noexec)
{
nafp = xfopen (temporary_name, W_MODE);
remove_temporary_at_error = TRUE;
}
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))
{
fseek (oafp, old_header, SEEK_SET);
copy_old_one (oafp, nafp, &ahdr);
old_header = ftell (oafp);
}
fclose (oafp);
}
if (!noexec)
{
write_tail (nafp);
fclose (nafp);
}
if (backup) {
make_backup_name (backup_archive_name, archive_name);
if (!noexec && old_archive_exist)
if (rename (archive_name, backup_archive_name) < 0)
error (archive_name);
}
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);
}
if (!noexec && rename (temporary_name, new_archive_name) < 0)
{
if (stat (temporary_name, &v_stat) < 0)
error (temporary_name);
oafp = xfopen (temporary_name, R_MODE);
nafp = xfopen (archive_name, W_MODE);
reading_filename = temporary_name;
writting_filename = archive_name;
copy_file (oafp, nafp, (long)v_stat.st_size);
fclose (nafp);
fclose (oafp);
unlink (temporary_name);
}
remove_temporary_at_error = FALSE;
if (delete_after_append)
{
if (!quiet && !noexec)
printf ("Erasing...\n");
for (i = 0; i < cmd_filec; i ++)
remove_it (cmd_filev[i]);
}
return;
}
#ifdef atarist
#include <fcntl.h>
static int st_truncate (fp, pos)
FILE *fp;
long pos;
{
int ifp;
char filename[FILENAME_MAX];
if(fflush(fp))
return -1;
if(fseek(fp, pos, SEEK_SET))
return -1;
ifp = __OPEN_INDEX(fp->_file);
strcpy(filename, __open_stat[ifp].filename);
close(fp->_file);
if((fp->_file = open(filename, O_RDWR)) < 0)
return -1;
fseek(fp, 0L, SEEK_END);
return 0;
}
void stexit (status)
int status;
{
int i;
if (hold) {
fprintf (stderr,"\nHit any key to exit ......");
fflush (stderr);
Bconin (2);
}
chdir (dirbuf);
for (i = 0; i < targc; i++)
free (targv[i]);
free (targv);
exit (status);
}
#endif