home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DOS/V Power Report 1998 June
/
Vpr9806a.iso
/
OLS
/
Windows
/
TAR32031
/
tar32031.exe
/
SRC
/
SRC
/
ARCHIO.C
next >
Wrap
C/C++ Source or Header
|
1998-01-15
|
18KB
|
863 lines
#ifndef __DEFCONF_H
#include "defconf.h"
#endif
/*
This file was hacked for kmtar for WIN32
at 1996-05-06.
by tantan SGL00213@niftyserve.or.jp
*/
/*
* archio - archive I/O functions
*
* Written by Koichiro Mori (kmori)
*/
#ifdef RCSID
static char rcsid[] = "$Header: RCS/archio.c 2.9 91/02/19 14:27:33 kmori Exp $";
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <time.h>
#include <dos.h>
#ifdef WIN32
#include <sys/types.h>
#include <io.h>
#endif
#include <sys/stat.h>
#include "defs.h"
#include "tar.h"
#include "main.h"
#include "misc.h"
#include "archio.h"
#include "tapeio.h"
#include "tardir.h"
#if defined(GZIP)
#include "gzip.h"
#endif
#ifdef DLL
#include <wtypes.h>
#include "tar32.h"
#endif
global int Nblocks;
global char *Current_file_name; /* Name of current file */
global long Current_file_size; /* Size of current file */
global int Current_file_mode; /* Size of current file */
global time_t Current_file_mtime; /* Modified time of current file */
global long Current_file_left; /* Left bytes in current file */
static int Withlabel;
static time_t Volume_time; /* Time Stamp */
static int Volno; /* Tape volume No. */
static int Nthdisk; /* Nth disk */
static char Save_file_name[FNAME_BUF];
static long Save_file_size;
static int Save_file_mode;
static time_t Save_file_mtime;
static long Save_file_left;
static char Mode; /* 'r'ead or 'w'rite */
int Afd; /* Archive file descriptor */
static bool Dev; /* Archive file is physical device */
static char *Buff=NULL; /* Archive I/O buffer */
static char *Ptr; /* Pointer to the next rd/wr data */
static int Buffsize; /* Size of Buff */
static int Left; /* Left bytes in Buff */
static int access_method; /* Aechive file access method */
extern HWND api_hwnd;
#define BUFFMARGIN (TBLOCK * 2)
void chk_exist(char *file) /* by tantan */
{
char buf[20];
if (access(file,0) != 0)
return;
fprintf(stderr,"File [%s] already exist. Do you OVER WRITE ? (y/n) ",file);
gets(buf);
strlwr(buf);
if (buf[0] != 'y')
exit(1);
}
/*
* Open device/file
*/
int open_dev(char *file, char mode)
{
extern bool Veflag;
extern char cao_flag;
Dev = NO;
if (*file == ':' || strmatch(file, "/dev/rfd")) {
Dev = YES;
return (open_tape(file, mode));
} else if (strcmp(file, "-") == 0) {
/* set stdio to binary mode */
switch (mode) {
case 'r':
setmode(fileno(stdin),O_BINARY);
return (fileno(stdin));
case 'w':
setmode(fileno(stdout),O_BINARY);
return (fileno(stdout));
case 'a':
errno = EINVAL;
return (-1);
}
} else {
switch (mode) {
case 'r':
return (open(file, O_RDONLY|O_BINARY));
case 'w':
if (Pflag){
return 1;/* stdout file descriptor */
}else{
if (cao_flag)
chk_exist(file);
if (Veflag){
printf("[-- Write verify switch ON --]\n");
return (open(file,O_RDWR | O_CREAT | O_TRUNC | O_BINARY, ~0));
}else
return (creat(file, ~0));
}
case 'a':
if (cao_flag)
chk_exist(file);
return (open(file, O_RDWR | O_CREAT | O_BINARY, ~0));
}
}
}
/*
* Request next volume
*/
void request_volume(int vol, int n, bool go)
{
int m;
if (Dev)
close_tape();
else {
if (Afd == 0 || Afd == 1) /* `tar cf -' or `tar xf -' */
fatal(NULL, "Missing end mark");
close(Afd);
}
for (m = 0; Archives[m]; m++)
;
if (go && m > 1) {
if (Vflag)
fprintf(stderr, "\aVolume %d in %s\n",
vol, Archives[n % m]);
goto noask;
}
for (;;) {
for (;;) {
char message[1000];
sprintf(message,
"Insert volume %d in %s and hit return: ",
vol, Archives[n % m]);
#ifdef DLL
{
int r;
extern HWND api_hwnd;
r=MessageBox(api_hwnd,message,"TAR32.DLL",MB_OKCANCEL);
switch(r){
case IDOK:
goto noask;
break;
case IDCANCEL:
Exitcode=ERROR_USER_CANCEL;
fatal("request_volume","user cancel");
break;
}
}
#else
{
int s;
char line[80];
fputs(message,stderr);
/*fprintf(stderr,
"Insert volume %d in %s and hit return: ",
vol, Archives[n % m]);*/
s = read(0, line, sizeof line);
line[s] = '\0';
switch (line[0]) {
case '!':
system(line + 1);
break;
case 'q':
error(NULL, "aborted");
exit(1);
case '\0':
case '\r':
case '\n':
goto noask;
}
}
#endif
}
noask:
Afd = open_dev(Archives[n % m], Mode);
if (Afd >= 0)
return;
error(Archives[n % m], NULL);
}
}
void set_vol(char *p)
{
struct stat statbuf;
char name[80];
memset(p, 0, TBLOCK);
memset(&statbuf, 0, sizeof statbuf);
statbuf.st_mtime = Volume_time;
sprintf(name, "tar Volume %d", Volno);
encode_dir((HEADER *)p, name, &statbuf, VOLTYPE);
}
int get_volno(char *name)
{
char *s;
s = strstr(name, "Volume");
if (s == NULL)
return (-1);
s += 7;
return (atoi(s));
}
global void check_vol(char *name, struct stat *p)
{
int n;
if ((n = get_volno(name)) < 0) {
error(name, "Bad volume ID");
return;
}
Volno = n;
Volume_time = p->st_mtime;
Withlabel = 1;
}
/*
* Read over multiple volume
*/
global int fill_buff(void)
{
int n, volno;
char name[FNAME_BUF];
struct stat fs;
bool go;
extern bool divi_flag,compress_flag,divi_eof_flag;
extern int read_zZ(int fd,char *Buff,int Buffsize);
Ptr = Buff;
if (Dev)
n = read_tape(Buff, Buffsize);
else
n = read_zZ(Afd, Buff, Buffsize);
if (n > 0 /* || !Mflag */)
return (n);
#if (Miner_V >= 2)
if (wild_flag)
fatal(NULL,"Multi volume not allowed");
#endif
Volno++;
Nthdisk++;
go = Yflag;
again:
#if 0
#ifdef DLL
if(Dev==NO){
Exitcode=ERROR_CANNOT_READ;
fatal("fill_buff","can't read at reading archive");
}
#endif
#endif
request_volume(Volno, Nthdisk, go);
go = NO;
if (Dev)
n = read_tape(Buff, Buffsize);
else
n = read_zZ(Afd, Buff, Buffsize);
if (n <= 0){
Exitcode=ERROR_CANNOT_READ;
fatal(NULL, "can't read");
}
Ptr = Buff;
if (Withlabel) {
if (decode_dir_e(name, &fs, (HEADER *)Buff) != VOLTYPE) {
fprintf(stderr, "No volume header\n");
goto again;
}
#if 0
if (fs.st_mtime != Volume_time) {
fprintf(stderr, "Volume timestamp doesn't match\n");
goto again;
}
#endif
volno = get_volno(name);
if (volno != Volno) {
fprintf(stderr, "Expecting #%d, but #%d\n", Volno, volno);
goto again;
}
Ptr += TBLOCK;
n -= TBLOCK;
}
if (Current_file_left) {
if (decode_dir_e(name, &fs, (HEADER *)Ptr) != MULTYPE ||
strcmp(name, Current_file_name) != 0) {
fprintf(stderr, "%s doesn't continue\n", Current_file_name);
goto again;
}
if (fs.st_size != Current_file_left ||
fs.st_size + strtol(((HEADER *)Ptr)->dbuf.offset, NULL, 8)
!= Current_file_size) {
fprintf(stderr, "%s file size different\n", Current_file_name);
goto again;
}
Ptr += TBLOCK;
return (n - TBLOCK);
}
return (n);
}
/*
* Read [m-n] bytes from archive and set data address to *ptr
*/
global int read_arch(long n, char **ptr)
{
if (Left == 0)
Left = fill_buff();
if (n < 0 || n > Left)
n = Left;
if (ptr)
*ptr = Ptr;
Ptr += n;
Left -= (int)n;
return ((int)n);
}
/*
* Move tape head backward and change 'read' mode to 'write' mode
*/
global int start_write_arch(int n)
{
long rc;
if (Ptr - Buff < n)
return (-1);
if (Dev)
rc = back_tape((int)(Ptr - Buff + Left));
else
rc = lseek(Afd, -(long)(Ptr - Buff + Left), 1);
Left += n;
Ptr -= n;
return (rc < 0 ? -1 : 0);
}
/*
* Write Buff to Ptr
*/
void flush_buff()
{
int size, n;
struct stat fs;
char *p;
extern int write_z(int Afd,char *Buff,int size);
size = Ptr - Buff;
if (Dev)
n = write_tape(Buff, size);
else
n = write_z(Afd, Buff, size);
if (n == size) {
if (Current_file_name != NULL)
strcpy(Save_file_name, Current_file_name);
Save_file_size = Current_file_size;
Save_file_mode = Current_file_mode;
Save_file_mtime = Current_file_mtime;
Save_file_left = Current_file_left;
Ptr = Buff;
return;
}
if (!Mflag)
fatal(NULL, "Out of tape (Use -m)");
Volno++;
Nthdisk++;
#if 0
#ifdef DLL
if(Dev==NO){
Exitcode=ERROR_CANNOT_WRITE;
fatal("flush_buff","can't write at making archive");
}
#endif
#endif
request_volume(Volno, Nthdisk, Yflag);
p = Buff;
if (Save_file_left) {
p -= TBLOCK;
if (size + TBLOCK <= Buffsize)
size += TBLOCK;
fs.st_mode = Save_file_mode;
fs.st_mtime = Save_file_mtime;
fs.st_size = Save_file_left;
memset(p, 0, TBLOCK);
sprintf(((HEADER *)p)->dbuf.offset, "%11lo ",
Save_file_size - Save_file_left);
encode_dir((HEADER *)p, Save_file_name, &fs, MULTYPE);
}
p -= TBLOCK;
if (size + TBLOCK <= Buffsize)
size += TBLOCK;
set_vol(p);
if (Dev)
n = write_tape(p, size);
else
n = write_z(Afd, p, size);
if (n != size)
fatal(NULL, "can't write");
if (p + size < Ptr) {
memcpy(Buff, p + size, (unsigned)(Ptr - (p + size)));
Ptr = Buff + (Ptr - (p + size));
} else
Ptr = Buff;
}
/*
* Return next write-buffer address
*/
global int buff_arch(int n, char **ptr)
{
long left;
left = Buff + Buffsize - Ptr;
if (left <= 0) {
flush_buff();
left = Buff + Buffsize - Ptr;
}
if (n < 0 || n > (int)left)
n = (int)left;
if (ptr)
*ptr = Ptr;
return (n);
}
/*
* Write n bytes
*/
global int write_arch(int n)
{
if (Ptr + n > Buff + Buffsize)
fatal("write_arch", "Can't happen.");
Ptr += n;
return (n);
}
/*
* Open archive file
*/
global int open_arch(char *mode)
{
Nthdisk = 0;
Volno = 1;
Mode = *mode;
Afd = open_dev(Archives[0], Mode);
/* for kmtarsef (SFX) by tsuneo... */
if(Mode=='w' && OPTION_self_extracting){
char *ptr;
char fname[1001];
if(SearchPath(NULL,"kmtarsef.exe",NULL,1000,fname,&ptr)!=0){
FILE *fp;
char buf[OUTBUFSIZ];
long n;
if((fp=fopen(fname,"rb"))!=NULL){
while((n=fread(buf,1,OUTBUFSIZ,fp))>0){
write(Afd,buf,n);
}
fclose(fp);
puts("making self-extracting...");
}else{
char str[1000];
sprintf(str,"can't open [%s]",fname);
MessageBox(api_hwnd,str,"TAR32.DLL",MB_ICONWARNING);
}
}else{
MessageBox(api_hwnd,"can't find kmtarsef.exe.","TAR32.DLL",MB_ICONWARNING);
close(Afd);Afd<0;
}
}
if (Nblocks <= 0)
Nblocks = 20;
Buffsize = Nblocks * TBLOCK;
if (Afd < 0){
Exitcode=ERROR_NOT_FIND_ARC_FILE;
fatal(Archives[0], NULL);
}
init_read_buf(); /* init */
/* printf("buff size = %d\n",BUFFMARGIN + Buffsize);*/
if (Buff == NULL){
Buff = malloc(BUFFMARGIN + Buffsize);
if (Buff == NULL){
Exitcode=ERROR_ENOUGH_MEMORY;
fatal(NULL, "Out of memory");
}
Buff += BUFFMARGIN;
}
Ptr = Buff;
Left = 0;
if (Mflag && Mode == 'w') {
/* Write volume header */
char *p;
Volume_time = time(NULL);
buff_arch(TBLOCK, &p);
set_vol(p);
write_arch(TBLOCK);
}
if (!Dev && Mode != 'w') {
/* check file type */
access_method = get_method(Afd);
if (Mode == 'a' && access_method != 100)
fatal("open_arch","compress file cannot append!");
}
return (Afd);
}
/*
* Close archive file
*/
global int close_arch(char command)
{
extern int gzip_flag;
extern void zip_end(void);
if (Mode != 'r') {
flush_buff();
flush_buff();
}
#if defined(GZIP)
if (command == 'c' && gzip_flag)
zip_end();
#endif
if(Pflag && Afd==1){
return 0;
}else{
return (Dev ? close_tape() : close(Afd));
}
}
global void free_io_buff()
{
if (Buff > (char *)BUFFMARGIN){
free(Buff - BUFFMARGIN);
Buff=NULL;
}else if(Buff!=NULL){
fprintf(stderr,"Not satisfy Buff > BUFFMARGIN or Buff==NULL\n");
exit(1);
}
}
/* for gzip Buffer pointer */
unsigned long innerbuf_len = 0;
char *innerbuf = NULL; /* for unzip */
int inner_file=-1;
/* read_zZの内部静的変数 */
static unsigned long read_zZ_icp; /* innerbuf current read opint */
static read_zZ_read_counter=0;
/*
* raed from compressed file
*/
global int read_zZ(int Afd,char *Buff,int Buffsize)
{
int len=0,ret;
extern int (*work)(void); /* function to call */
// static unsigned long icp; /* innerbuf current read opint */
extern unsigned insize;
#ifdef DYN_ALLOC
extern unsigned char *inbuf;
#else
extern unsigned char inbuf[];
#endif
// static read_counter=0;
if (access_method == 100){ /* normal file */
if (insize){
if ((int)insize >= Buffsize){
memcpy(Buff,inbuf+read_zZ_read_counter,Buffsize);
insize -=Buffsize;
read_zZ_read_counter +=Buffsize;
ret = Buffsize;
}else{
int r;
memcpy(Buff,inbuf+read_zZ_read_counter,insize);
r = read(Afd,Buff+insize,Buffsize-insize);
ret = insize + r;
insize =0;
}
return ret; /* at v3.6 */
}else
return read(Afd,Buff,Buffsize);
}
while(1){
if (innerbuf_len == 0){
if ((ret = (*work)()) != 0) {
return (ret == EOF) ? len : -1;
}
/*
printf("archio:innerbuf_len=%u %Fp \n",innerbuf_len &innerbuf_len);
*/
if (innerbuf_len == 0)
continue;
read_zZ_icp = 0;
}
if ((int)(innerbuf_len - read_zZ_icp) > Buffsize){
memcpy(Buff,innerbuf+read_zZ_icp, Buffsize);
len += Buffsize;
read_zZ_icp += Buffsize;
break;
}else{
memcpy(Buff,innerbuf+read_zZ_icp, innerbuf_len - read_zZ_icp);
len += (int)(innerbuf_len - read_zZ_icp);
Buffsize -= (int)(innerbuf_len - read_zZ_icp);
Buff += (int)(innerbuf_len - read_zZ_icp);
innerbuf_len = 0L;
}
}
return len;
}
#if defined(GZIP)
int write_z(int fh,char *buf,int bufsize)
{
extern int gzip_flag;
extern bool Veflag;
int len;
extern int zip_write(int h,char *buf,int size);
if (!gzip_flag){
len = write(fh,buf,bufsize);
if (Veflag && len > 0){
char buffer[OUTBUFSIZ*2];
if (OUTBUFSIZ*2 < bufsize)
fatal("write_z","Verify inner error");
lseek(fh,-len,SEEK_CUR);
read(fh,buffer,len);
if (memcmp(buffer,buf,len) )
fatal("write","verify error");
}
return len;
}
zip_write(fh,buf,bufsize);
return bufsize;
}
#if P_up_V>=4
/* gzip file */
void gzip_file(char *pack,char *unpack)
{
FILE *fp_unpk;
int fh_pk;
int n;
char buf[OUTBUFSIZ];
if (Vflag){
printf("gzip:packfile is [%s] and unpack file is [%s]\n",pack,unpack);
}
if((fp_unpk=fopen(unpack,"rb"))==NULL){
fatal("gzip_file","can't open unpack file");
}
if((fh_pk=open_arch("w"))<0){
fatal("gzip_file","can't open pack file");
}
while((n=fread(buf,1,OUTBUFSIZ,fp_unpk))>0){
write_z(fh_pk,buf,n);
}
close_arch('c');
fclose(fp_unpk);
}
int get_gunzip_fname(char *unpackfn,char *packfn)
{
int packlen;
packlen=strlen(packfn);
/*
if(packlen>=FNAME_BUF){
return -1;
fatal("archio.c:get_gunzip_fname","Too Long FileName is Specified");
}
*/
strcpy(unpackfn,packfn);
if(packlen>2 && stricmp(packfn+packlen-2,".z")==0){
unpackfn[packlen-2]='\0';
}else if(packlen>3 && stricmp(packfn+packlen-3,".gz")==0){
unpackfn[packlen-3]='\0';
}else if(packlen>4 && stricmp(packfn+packlen-4,".tgz")==0){
strcpy(unpackfn+packlen-4,".tar");
}else if(packlen>4 && stricmp(packfn+packlen-4,".taz")==0){
strcpy(unpackfn+packlen-4,".tar");
}else{
return -1;
/* fatal("main.c:do_x_com()","Can't found gunziped/compressed file name.");*/
}
return 0;
}
/* gunzip or compress -d file */
void gunzip_file(char *pack,char *unpack_tmp)
{
FILE *fp_unpk;
int fh_pk;
int n;
char buf[OUTBUFSIZ];
char unpack[FNAME_BUF];
if(unpack_tmp!=NULL){
if(strlen(unpack_tmp)>=FNAME_BUF){
Exitcode=ERROR_COMMAND_NAME;
fatal("gunzip_file","Too Long Filename.");
}
strcpy(unpack,unpack_tmp);
}else{
if(get_gunzip_fname(unpack,pack)<0){
Exitcode=ERROR_COMMAND_NAME;
fatal("guzip_file","Can't find gunzip/compress -d filename.");
}
}
if(Vflag){
printf("gunzip:packfile is [%s] and unpack file is [%s]\n",pack,unpack);
}
if(Pflag){
fp_unpk=stdout;
}else{
if((fp_unpk=fopen(unpack,"wb"))==NULL){
fatal("gzip_file","can't open pack file");
}
}
if((fh_pk=open_arch("r"))<0){
fatal("gzip_file","can't open unpack file");
}
while((n=read_zZ(fh_pk,buf,OUTBUFSIZ))>0){
fwrite(buf,1,n,fp_unpk);
}
close_arch('x');
if(Pflag && fp_unpk==stdout){
;
}else{
fclose(fp_unpk);
}
}
int get_access_method(void)
{
return access_method;
}
#endif /* P_up_V>=4 */
#endif /* GZIP */
#ifdef DLL
void arch_SetAfd(int fh){
Afd=fh;
}
int arch_GetAfd(void){
return Afd;
}
#endif /*DLL*/
#ifdef DLL
void arch_static_init(void)
{
Nblocks=0;
Current_file_name=NULL; /* Name of current file */
Current_file_size=0; /* Size of current file */
Current_file_mode=0; /* Size of current file */
Current_file_mtime=0; /* Modified time of current file */
Current_file_left=0; /* Left bytes in current file */
Withlabel=0;
Volume_time=0; /* Time Stamp */
Volno=0; /* Tape volume No. */
Nthdisk=0; /* Nth disk */
memset(Save_file_name,0,sizeof(char)*FNAME_BUF);
Save_file_size=0;
Save_file_mode=0;
Save_file_mtime=0;
Save_file_left=0;
Mode=0; /* 'r'ead or 'w'rite */
Afd=0; /* Archive file descriptor */
Dev=0; /* Archive file is physical device */
/*Buff=NULL;*/ /* Archive I/O buffer */
if(Buff!=NULL){
free_io_buff();
}
Ptr=NULL; /* Pointer to the next rd/wr data */
Buffsize=0; /* Size of Buff */
Left=0; /* Left bytes in Buff */
access_method=0; /* Aechive file access method */
/* for gzip Buffer pointer */
innerbuf_len = 0;
innerbuf = NULL; /* for unzip */
inner_file=-1;
/* read_zZの内部静的変数 */
read_zZ_icp=0; /* innerbuf current read opint */
read_zZ_read_counter=0;
}
#endif /* DLL (in arch_static_init)*/