home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume44
/
unzip
/
part03
< prev
next >
Wrap
Internet Message Format
|
1994-09-19
|
72KB
From: zip-bugs@wkuvx1.wku.edu (Info-ZIP group)
Newsgroups: comp.sources.misc
Subject: v44i068: unzip - Info-ZIP portable UnZip, version 5.12, Part03/20
Date: 18 Sep 1994 23:14:25 -0500
Organization: Sterling Software
Sender: kent@sparky.sterling.com
Approved: kent@sparky.sterling.com
Message-ID: <35j371$qls@sparky.sterling.com>
X-Md4-Signature: 21f88c198c6b8f5182408c7bb827ba4d
Submitted-by: zip-bugs@wkuvx1.wku.edu (Info-ZIP group)
Posting-number: Volume 44, Issue 68
Archive-name: unzip/part03
Environment: UNIX, VMS, OS/2, MS-DOS, MACINTOSH, WIN-NT, LINUX, MINIX, COHERENT, AMIGA?, ATARI TOS, SGI, DEC, Cray, Convex, Amdahl, Sun
Supersedes: unzip50: Volume 31, Issue 104-117
#! /bin/sh
# This is a shell archive. Remove anything before this line, then feed it
# into a shell via "sh file" or similar. To overwrite existing files,
# type "sh file -c".
# Contents: unzip-5.12/version.h unzip-5.12/vms/vms.c
# Wrapped by kent@sparky on Sat Sep 17 23:33:36 1994
PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin:$PATH ; export PATH
echo If this archive is complete, you will see the following message:
echo ' "shar: End of archive 3 (of 20)."'
if test -f 'unzip-5.12/version.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'unzip-5.12/version.h'\"
else
echo shar: Extracting \"'unzip-5.12/version.h'\" \(855 characters\)
sed "s/^X//" >'unzip-5.12/version.h' <<'END_OF_FILE'
X/*
X version.h (for UnZip) by Info-ZIP.
X
X This header file is not copyrighted and may be distributed without
X restriction. (That's a little geek humor, heh heh.)
X */
X
X#ifndef __version_h /* don't include more than once */
X#define __version_h
X
X#ifdef BETA
X# define BETALEVEL "e"
X# define UZ_VERSION "5.12e BETA of 25 Aug 94" /* internal beta level */
X# define ZI_VERSION "2.02e BETA of 25 Aug 94"
X# define D2_VERSION "0.0 BETA of xx Xxx 94"
X#else
X# define BETALEVEL ""
X# define UZ_VERSION "5.12 of 28 August 1994" /* official release version */
X# define ZI_VERSION "2.02 of 28 August 1994"
X# define D2_VERSION "0.0 of x Xxxxxx 1994" /* (DLL for OS/2) */
X# define RELEASE
X#endif
X
X#define UZ_MAJORVER 5
X#define UZ_MINORVER 1
X
X#define ZI_MAJORVER 2
X#define ZI_MINORVER 0
X
X#define PATCHLEVEL 2
X
X#endif /* !__version_h */
END_OF_FILE
if test 855 -ne `wc -c <'unzip-5.12/version.h'`; then
echo shar: \"'unzip-5.12/version.h'\" unpacked with wrong size!
fi
# end of 'unzip-5.12/version.h'
fi
if test -f 'unzip-5.12/vms/vms.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'unzip-5.12/vms/vms.c'\"
else
echo shar: Extracting \"'unzip-5.12/vms/vms.c'\" \(66172 characters\)
sed "s/^X//" >'unzip-5.12/vms/vms.c' <<'END_OF_FILE'
X/*---------------------------------------------------------------------------
X
X vms.c Igor Mandrichenko and others
X
X This file contains routines to extract VMS file attributes from a zipfile
X extra field and create a file with these attributes. The code was almost
X entirely written by Igor, with a couple of routines by CN.
X
X ---------------------------------------------------------------------------
X
X Copyright (C) 1992-93 Igor Mandrichenko.
X Permission is granted to any individual or institution to use, copy,
X or redistribute this software so long as all of the original files
X are included unmodified and that this copyright notice is retained.
X
X Revision history:
X
X 1.x [moved to History.510 for brevity]
X 2.0 Mandrichenko 7-apr-1993
X Implement PKWARE style VMS file attributes
X 2.0-1 Mandrichenko 10-apr-1993
X ACL handling code added.
X 2.1 Mandrichenko 24-aug-1993
X Get both PKWARE and new INFO-ZIP signatures as equivalent
X Use vmsmunch.h instead of fatdef.h
X 2.2 Cave Newt 3-oct-1993
X Merged GRR 5.1e changes with latest Igor version: open_outfile,
X close_outfile, check_for_newer, UpdateCRC, flush, no ZIPINFO,
X ctype.h, pInfo->textmode, etc. Also merged new do_wild/mapname/
X checkdir routines from Igor and moved VMSmunch.h into vms.h.
X 2.2-1 Mandrichenko 14-dec-1993
X Bug fixes in mapname/checkdir stuff.
X _flush_stream() rewritten to fix some bugs.
X 2.2-2 Goathunter 3 Jan 94
X Fixes for Alpha-VMS.
X 2.2-3 Cave Newt 11 Jan 94
X Disabled version-check by default; enable with CHECK_VERSIONS.
X Installed Igor's ctrl-Z patch.
X 2.2-4 Mandrichenko 18 Jan 94
X Fixed auto-appending of ".zip" and inability to create second
X level of directory structure.
X 2.2-5 Cave Newt, Mike Freeman 28 Jan 94
X Changed close_outfile() to return void for compatibility;
X fixed declaration of second parameter to flush() (ulg size);
X changed str[n]icmp() to STR[N]ICMP().
X 2.2-6 Christian Spieler 9 Apr 94
X Numerous bug fixes/improvements.
X 2.2-7 Cave Newt 11 Apr 94
X Fixed version-number/semicolon bug.
X 2.3 Cave Newt 21 Jun 94
X Added prototype version() routine.
X 2.3-1 Cave Newt 1 Jul 94
X *Really* fixed version-number/semicolon bug.
X 2.3-2 Rodney Brown 10 Jul 94
X Added VMS status/severity level (define RETURN_SEVERITY)
X 2.3-3 Charles Bailey 10 Aug 94
X Fixed severity levels.
X 2.3-4 CN, CS, IM, RB 16 Aug 94
X Further severity tweaks; do_wild() bugfix (CS)
X 2.3-5 CS, CN, IM, GH 18 Aug 94
X Further do_wild() modifications and fixes.
X 2.3-6 Christian Spieler 23 Aug 94
X Added lots of typecasts and fixed some initializations for DEC C.
X
X ---------------------------------------------------------------------------*/
X
X#ifdef VMS /* VMS only ! */
X
X#include "unzip.h"
X#include "vms.h" /* now includes VMSmunch.h */
X
X#define BUFS512 8192*2 /* Must be a multiple of 512 */
X
X#define OK(s) ((s)&1) /* VMS success or warning status */
X#define STRICMP(s1,s2) STRNICMP(s1,s2,2147483647)
X
X/*
X* Local static storage
X*/
Xstatic struct FAB fileblk;
Xstatic struct XABDAT dattim;
Xstatic struct XABRDT rdt;
Xstatic struct RAB rab;
Xstatic struct NAM nam;
X
Xstatic struct FAB *outfab = 0;
Xstatic struct RAB *outrab = 0;
Xstatic struct XABFHC *xabfhc = 0;
Xstatic struct XABDAT *xabdat = 0;
Xstatic struct XABRDT *xabrdt = 0;
Xstatic struct XABPRO *xabpro = 0;
Xstatic struct XABKEY *xabkey = 0;
Xstatic struct XABALL *xaball = 0;
Xstruct XAB *first_xab = 0L, *last_xab = 0L;
X
Xstatic char query = 0;
Xstatic int text_output = 0,
X raw_input,
X hostnum;
X
Xstatic uch rfm;
X
Xstatic uch locbuf[BUFS512];
Xstatic int loccnt = 0;
Xstatic uch *locptr;
Xstatic char got_eol = 0;
X
Xstatic int _flush_blocks(),
X _flush_stream(),
X _flush_varlen(),
X _flush_qio(),
X _close_qio(),
X _close_rms(),
X WriteRecord(),
X WriteBuffer(),
X find_eol();
X
Xstatic int (*_flush_routine)(),
X (*_close_routine)();
X
Xstatic int get_vms_version();
Xstatic int replace();
Xstatic uch *extract_block();
Xstatic void init_buf_ring();
Xstatic void decompress_bits();
Xstatic void UpdateCRC();
Xstatic void message();
Xstatic void free_up();
X
Xstruct bufdsc
X{
X struct bufdsc *next;
X uch *buf;
X int bufcnt;
X};
X
Xstatic struct bufdsc b1, b2, *curbuf;
Xstatic uch buf1[BUFS512];
X
Xint check_format()
X{
X int rtype;
X struct FAB fab;
X
X fab = cc$rms_fab;
X fab.fab$l_fna = zipfn;
X fab.fab$b_fns = strlen(zipfn);
X
X sys$open(&fab);
X rtype = fab.fab$b_rfm;
X sys$close(&fab);
X
X if (rtype == FAB$C_VAR || rtype == FAB$C_VFC)
X {
X fprintf(stderr,
X "\n Error: zipfile is in variable-length record format. Please\n\
X run \"bilf l %s\" to convert the zipfile to stream-LF\n\
X record format. (bilf.c and make_bilf.com are included in the\n\
X VMS UnZip source distribution.)\n\n", zipfn);
X return PK_ERR;
X }
X
X return PK_COOL;
X}
X
X
X
X#define PRINTABLE_FORMAT(x) ( (x) == FAB$C_VAR \
X || (x) == FAB$C_STMLF \
X || (x) == FAB$C_STMCR \
X || (x) == FAB$C_STM )
X
X/* VMS extra field types */
X#define VAT_NONE 0
X#define VAT_IZ 1 /* Old INFO-ZIP format */
X#define VAT_PK 2 /* PKWARE format */
X
Xstatic int vet;
X
Xstatic int create_default_output(),
X create_rms_output(),
X create_qio_output();
X
X/*
X * open_outfile() assignments:
X *
X * VMS attributes ? create_xxx _flush_xxx
X * ---------------- ---------- ----------
X * not found 'default' text mode ?
X * yes -> 'stream'
X * no -> 'block'
X *
X * yes, in IZ format 'rms' text mode ?
X * yes -> switch(fab.rfm)
X * VAR -> 'varlen'
X * STM* -> 'stream'
X * default -> 'block'
X * no -> 'block'
X *
X * yes, in PK format 'qio' 'qio'
X *
X * "text mode" == pInfo -> text || cflag
X */
X
Xint open_outfile()
X{
X switch(vet = find_vms_attrs())
X { case VAT_NONE:
X default:
X return create_default_output();
X case VAT_IZ:
X return create_rms_output();
X case VAT_PK:
X return create_qio_output();
X }
X}
X
Xstatic void init_buf_ring()
X{
X locptr = &locbuf[0];
X loccnt = 0;
X
X b1.buf = &locbuf[0];
X b1.bufcnt = 0;
X b1.next = &b2;
X b2.buf = &buf1[0];
X b2.bufcnt = 0;
X b2.next = &b1;
X curbuf = &b1;
X}
X
X
X
Xstatic int create_default_output()
X{
X int ierr, yr, mo, dy, hh, mm, ss;
X char timbuf[24]; /* length = first entry in "stupid" + 1 */
X int attr_given; /* =1 if VMS attributes are present in
X * extra_field */
X
X rab = cc$rms_rab; /* fill FAB & RAB with default values */
X fileblk = cc$rms_fab;
X
X text_output = pInfo->textmode || cflag; /* extract the file in text
X * (variable-length) format */
X hostnum = pInfo -> hostnum;
X
X outfab = &fileblk;
X outfab->fab$l_xab = 0L;
X rfm = FAB$C_STMLF; /* Default, stream-LF format from VMS
X * or UNIX */
X if (text_output)
X { /* Default format for output text file */
X
X outfab->fab$b_rfm = FAB$C_VAR; /* variable length records */
X outfab->fab$b_rat = FAB$M_CR; /* carriage-return carriage ctrl */
X }
X else
X { /* Default format for output binary file */
X
X outfab->fab$b_rfm = FAB$C_STMLF; /* stream-LF record format */
X outfab->fab$b_rat = FAB$M_CR; /* carriage-return carriage ctrl */
X }
X
X if (!cflag) /* Redirect output */
X outfab->fab$l_fna = filename;
X else
X outfab->fab$l_fna = "sys$output:";
X
X outfab->fab$b_fns = strlen(outfab->fab$l_fna);
X
X {
X static char *month[] =
X {"JAN", "FEB", "MAR", "APR", "MAY", "JUN",
X "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"};
X
X /* fixed-length string descriptor: */
X struct dsc$descriptor stupid =
X {23, DSC$K_DTYPE_T, DSC$K_CLASS_S, timbuf};
X
X yr = ((lrec.last_mod_file_date >> 9) & 0x7f) + 1980;
X mo = ((lrec.last_mod_file_date >> 5) & 0x0f) - 1;
X dy = (lrec.last_mod_file_date & 0x1f);
X hh = (lrec.last_mod_file_time >> 11) & 0x1f;
X mm = (lrec.last_mod_file_time >> 5) & 0x3f;
X ss = (lrec.last_mod_file_time & 0x1f) * 2;
X
X dattim = cc$rms_xabdat; /* fill XABs with default values */
X rdt = cc$rms_xabrdt;
X sprintf(timbuf, "%02d-%3s-%04d %02d:%02d:%02d.00", dy, month[mo], yr,
X hh, mm, ss);
X sys$bintim(&stupid, &dattim.xab$q_cdt);
X memcpy(&rdt.xab$q_rdt, &dattim.xab$q_cdt, sizeof(rdt.xab$q_rdt));
X
X dattim.xab$l_nxt = outfab->fab$l_xab;
X outfab->fab$l_xab = (void *) &dattim;
X }
X
X outfab->fab$w_ifi = 0; /* Clear IFI. It may be nonzero after ZIP */
X
X ierr = sys$create(outfab);
X if (ierr == RMS$_FEX)
X ierr = replace();
X
X if (ierr == 0) /* Canceled */
X return free_up(), 1;
X
X if (ERR(ierr))
X {
X char buf[256];
X
X sprintf(buf, "[ Cannot create output file %s ]\n", filename);
X message(buf, ierr);
X message("", outfab->fab$l_stv);
X free_up();
X return PK_WARN;
X }
X
X if (!text_output) /* Do not reopen text files and stdout
X * Just open them in right mode */
X {
X /*
X * Reopen file for Block I/O with no XABs.
X */
X if ((ierr = sys$close(outfab)) != RMS$_NORMAL)
X {
X#ifdef DEBUG
X message("[ create_output_file: sys$close failed ]\n", ierr);
X message("", outfab->fab$l_stv);
X#endif
X fprintf(stderr, "Can't create output file: %s\n", filename);
X free_up();
X return PK_WARN;
X }
X
X
X outfab->fab$b_fac = FAB$M_BIO | FAB$M_PUT; /* Get ready for block
X * output */
X outfab->fab$l_xab = 0L; /* Unlink all XABs */
X
X if ((ierr = sys$open(outfab)) != RMS$_NORMAL)
X {
X char buf[256];
X
X sprintf(buf, "[ Cannot open output file %s ]\n", filename);
X message(buf, ierr);
X message("", outfab->fab$l_stv);
X free_up();
X return PK_WARN;
X }
X }
X
X outrab = &rab;
X rab.rab$l_fab = outfab;
X if (!text_output)
X { rab.rab$l_rop |= RAB$M_BIO;
X rab.rab$l_rop |= RAB$M_ASY;
X }
X rab.rab$b_rac = RAB$C_SEQ;
X
X if ((ierr = sys$connect(outrab)) != RMS$_NORMAL)
X {
X#ifdef DEBUG
X message("create_output_file: sys$connect failed.\n", ierr);
X message("", outfab->fab$l_stv);
X#endif
X fprintf(stderr, "Can't create output file: %s\n", filename);
X free_up();
X return PK_WARN;
X }
X
X init_buf_ring();
X
X _flush_routine = text_output? got_eol=0,_flush_stream : _flush_blocks;
X _close_routine = _close_rms;
X return PK_COOL;
X}
X
X
X
Xstatic int create_rms_output()
X{
X int ierr, yr, mo, dy, hh, mm, ss;
X char timbuf[24]; /* length = first entry in "stupid" + 1 */
X
X rab = cc$rms_rab; /* fill FAB & RAB with default values */
X fileblk = cc$rms_fab;
X
X text_output = cflag; /* extract the file in text (variable-length)
X * format; ignore -a when attributes saved */
X hostnum = pInfo -> hostnum;
X
X if (cflag)
X {
X if(!PRINTABLE_FORMAT(rfm=outfab->fab$b_rfm))
X { printf("[ File %s has illegal record format to put to screen ]\n",
X filename);
X free_up();
X return PK_DISK;
X }
X }
X
X if (!cflag) /* Redirect output */
X outfab->fab$l_fna = filename;
X else
X outfab->fab$l_fna = "sys$output:";
X
X outfab->fab$b_fns = strlen(outfab->fab$l_fna);
X
X if (!(xabdat && xabrdt)) /* Use date/time info
X * from zipfile if
X * no attributes given
X */
X {
X static char *month[] =
X {"JAN", "FEB", "MAR", "APR", "MAY", "JUN",
X "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"};
X
X /* fixed-length string descriptor: */
X struct dsc$descriptor stupid =
X {23, DSC$K_DTYPE_T, DSC$K_CLASS_S, timbuf};
X
X yr = ((lrec.last_mod_file_date >> 9) & 0x7f) + 1980;
X mo = ((lrec.last_mod_file_date >> 5) & 0x0f) - 1;
X dy = (lrec.last_mod_file_date & 0x1f);
X hh = (lrec.last_mod_file_time >> 11) & 0x1f;
X mm = (lrec.last_mod_file_time >> 5) & 0x3f;
X ss = (lrec.last_mod_file_time & 0x1f) * 2;
X
X dattim = cc$rms_xabdat; /* fill XABs with default values */
X rdt = cc$rms_xabrdt;
X sprintf(timbuf, "%02d-%3s-%04d %02d:%02d:%02d.00", dy, month[mo], yr,
X hh, mm, ss);
X sys$bintim(&stupid, &dattim.xab$q_cdt);
X memcpy(&rdt.xab$q_rdt, &dattim.xab$q_cdt, sizeof(rdt.xab$q_rdt));
X
X if (xabdat == 0L)
X {
X dattim.xab$l_nxt = outfab->fab$l_xab;
X outfab->fab$l_xab = (void *) &dattim;
X }
X }
X
X outfab->fab$w_ifi = 0; /* Clear IFI. It may be nonzero after ZIP */
X
X ierr = sys$create(outfab);
X if (ierr == RMS$_FEX)
X ierr = replace();
X
X if (ierr == 0) /* Canceled */
X return free_up(), 1;
X
X if (ERR(ierr))
X {
X char buf[256];
X
X sprintf(buf, "[ Cannot create output file %s ]\n", filename);
X message(buf, ierr);
X message("", outfab->fab$l_stv);
X free_up();
X return PK_WARN;
X }
X
X if (!text_output) /* Do not reopen text files and stdout
X * Just open them in right mode */
X {
X /*
X * Reopen file for Block I/O with no XABs.
X */
X if ((ierr = sys$close(outfab)) != RMS$_NORMAL)
X {
X#ifdef DEBUG
X message("[ create_output_file: sys$close failed ]\n", ierr);
X message("", outfab->fab$l_stv);
X#endif
X fprintf(stderr, "Can't create output file: %s\n", filename);
X free_up();
X return PK_WARN;
X }
X
X
X outfab->fab$b_fac = FAB$M_BIO | FAB$M_PUT; /* Get ready for block
X * output */
X outfab->fab$l_xab = 0L; /* Unlink all XABs */
X
X if ((ierr = sys$open(outfab)) != RMS$_NORMAL)
X {
X char buf[256];
X
X sprintf(buf, "[ Cannot open output file %s ]\n", filename);
X message(buf, ierr);
X message("", outfab->fab$l_stv);
X free_up();
X return PK_WARN;
X }
X }
X
X outrab = &rab;
X rab.rab$l_fab = outfab;
X if (!text_output)
X { rab.rab$l_rop |= RAB$M_BIO;
X rab.rab$l_rop |= RAB$M_ASY;
X }
X rab.rab$b_rac = RAB$C_SEQ;
X
X if ((ierr = sys$connect(outrab)) != RMS$_NORMAL)
X {
X#ifdef DEBUG
X message("create_output_file: sys$connect failed.\n", ierr);
X message("", outfab->fab$l_stv);
X#endif
X fprintf(stderr, "Can't create output file: %s\n", filename);
X free_up();
X return PK_WARN;
X }
X
X init_buf_ring();
X
X if( text_output )
X switch(rfm)
X {
X case FAB$C_VAR:
X _flush_routine = _flush_varlen;
X break;
X case FAB$C_STM:
X case FAB$C_STMCR:
X case FAB$C_STMLF:
X _flush_routine = _flush_stream;
X got_eol = 0;
X break;
X default:
X _flush_routine = _flush_blocks;
X break;
X }
X else
X _flush_routine = _flush_blocks;
X _close_routine = _close_rms;
X return PK_COOL;
X}
X
X
X
Xstatic int pka_devchn;
Xstatic int pka_vbn;
X
Xstatic struct
X{ short status;
X long count;
X short dummy;
X} pka_io_sb;
X
Xstatic struct
X{ short status;
X short dummy;
X void *addr;
X} pka_acp_sb;
X
Xstatic struct fibdef pka_fib;
Xstatic struct atrdef pka_atr[VMS_MAX_ATRCNT];
Xstatic int pka_idx;
Xstatic ulg pka_uchar;
Xstatic struct fatdef pka_rattr;
X
Xstatic struct dsc$descriptor pka_fibdsc =
X{ sizeof(pka_fib), DSC$K_DTYPE_Z, DSC$K_CLASS_S, (void *) &pka_fib };
X
Xstatic struct dsc$descriptor_s pka_devdsc =
X{ 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, &nam.nam$t_dvi[1] };
X
Xstatic struct dsc$descriptor_s pka_fnam =
X{ 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0 };
X
X
X
Xstatic int create_qio_output()
X{ int status;
X static char exp_nam[NAM$C_MAXRSS];
X static char res_nam[NAM$C_MAXRSS];
X int i;
X
X if( cflag )
X { fprintf(stderr,"[ Cannot put to screen ]\n");
X return PK_DISK;
X }
X
X fileblk = cc$rms_fab;
X fileblk.fab$l_fna = filename;
X fileblk.fab$b_fns = strlen(filename);
X
X nam = cc$rms_nam;
X fileblk.fab$l_nam = &nam;
X nam.nam$l_esa = exp_nam;
X nam.nam$b_ess = sizeof(exp_nam);
X nam.nam$l_rsa = res_nam;
X nam.nam$b_rss = sizeof(res_nam);
X
X if( ERR(status = sys$parse(&fileblk)) )
X { message("create_output_file: sys$parse failed.\n", status);
X return PK_DISK;
X }
X
X pka_devdsc.dsc$w_length = (unsigned short)nam.nam$t_dvi[0];
X
X if( ERR(status = sys$assign(&pka_devdsc,&pka_devchn,0,0)) )
X { message("sys$assign failed.\n",status);
X return PK_DISK;
X }
X
X pka_fnam.dsc$a_pointer = nam.nam$l_name;
X pka_fnam.dsc$w_length = nam.nam$b_name + nam.nam$b_type;
X if( V_flag /* keep versions */ )
X pka_fnam.dsc$w_length += nam.nam$b_ver;
X
X for (i=0;i<3;i++)
X { pka_fib.FIB$W_DID[i]=nam.nam$w_did[i];
X pka_fib.FIB$W_FID[i]=0;
X }
X
X pka_fib.FIB$L_ACCTL = FIB$M_WRITE;
X /* Allocate space for the file */
X pka_fib.FIB$W_EXCTL = FIB$M_EXTEND;
X if( pka_uchar & FCH$M_CONTIG )
X pka_fib.FIB$W_EXCTL |= FIB$M_ALCON | FIB$M_FILCON;
X if( pka_uchar & FCH$M_CONTIGB )
X pka_fib.FIB$W_EXCTL |= FIB$M_ALCONB;
X
X#define SWAPW(x) ( (((x)>>16)&0xFFFF) + ((x)<<16) )
X
X pka_fib.fib$l_exsz = SWAPW(pka_rattr.fat$r_hiblk_overlay.fat$l_hiblk);
X
X status = sys$qiow(0, pka_devchn, IO$_CREATE|IO$M_CREATE|IO$M_ACCESS,
X &pka_acp_sb, 0, 0,
X &pka_fibdsc, &pka_fnam, 0, 0, &pka_atr, 0);
X
X if( !ERR(status) )
X status = pka_acp_sb.status;
X
X if( ERR(status) )
X { message("[ Create file QIO failed.\n",status);
X return PK_DISK;
X sys$dassgn(pka_devchn);
X }
X
X pka_vbn = 1;
X _flush_routine = _flush_qio;
X _close_routine = _close_qio;
X return PK_COOL;
X}
X
X
X
Xstatic int replace()
X{ /*
X * File exists. Inquire user about further action.
X */
X char answ[10];
X struct NAM nam;
X int ierr;
X
X if (query == 0)
X {
X do
X {
X fprintf(stderr,
X "%s exists: [o]verwrite, new [v]ersion or [n]o extract?\n\
X (uppercase response [O,V,N] = do same for all files): ",
X filename);
X fflush(stderr);
X } while (fgets(answ, 9, stderr) == NULL && !isalpha(answ[0])
X && tolower(answ[0]) != 'o'
X && tolower(answ[0]) != 'v'
X && tolower(answ[0]) != 'n');
X
X if (isupper(answ[0]))
X query = answ[0] = tolower(answ[0]);
X }
X else
X answ[0] = query;
X
X switch (answ[0])
X {
X case 'n':
X ierr = 0;
X break;
X case 'v':
X nam = cc$rms_nam;
X nam.nam$l_rsa = filename;
X nam.nam$b_rss = FILNAMSIZ - 1;
X
X outfab->fab$l_fop |= FAB$M_MXV;
X outfab->fab$l_nam = &nam;
X
X ierr = sys$create(outfab);
X if (!ERR(ierr))
X {
X outfab->fab$l_nam = 0L;
X filename[outfab->fab$b_fns = nam.nam$b_rsl] = 0;
X }
X break;
X case 'o':
X outfab->fab$l_fop |= FAB$M_SUP;
X ierr = sys$create(outfab);
X break;
X }
X return ierr;
X}
X
X
X
X#define W(p) (*(unsigned short*)(p))
X#define L(p) (*(unsigned long*)(p))
X#define EQL_L(a,b) ( L(a) == L(b) )
X#define EQL_W(a,b) ( W(a) == W(b) )
X
X/****************************************************************
X * Function find_vms_attrs scans ZIP entry extra field if any *
X * and looks for VMS attribute records. Returns 0 if either no *
X * attributes found or no fab given. *
X ****************************************************************/
Xint find_vms_attrs()
X{
X uch *scan = extra_field;
X struct EB_header *hdr;
X int len;
X int type=VAT_NONE;
X
X outfab = NULL;
X xabfhc = NULL;
X xabdat = NULL;
X xabrdt = NULL;
X xabpro = NULL;
X first_xab = last_xab = NULL;
X
X if (scan == NULL)
X return PK_COOL;
X len = lrec.extra_field_length;
X
X#define LINK(p) { /* Link xaballs and xabkeys into chain */ \
X if( first_xab == 0L ) \
X first_xab = (void *) p; \
X if( last_xab != 0L ) \
X last_xab -> xab$l_nxt = (void *) p; \
X last_xab = (void *) p; \
X p -> xab$l_nxt = 0; \
X }
X /* End of macro LINK */
X
X while (len > 0)
X {
X hdr = (struct EB_header *) scan;
X if (EQL_W(&hdr->tag, IZ_SIGNATURE))
X {
X /*
X * INFO-ZIP style extra block decoding
X */
X struct IZ_block *blk;
X uch *block_id;
X
X type = VAT_IZ;
X
X blk = (struct IZ_block *)hdr;
X block_id = (uch *) &blk->bid;
X if (EQL_L(block_id, FABSIG))
X {
X outfab = (struct FAB *) extract_block(blk, 0,
X &cc$rms_fab, FABL);
X }
X else if (EQL_L(block_id, XALLSIG))
X {
X xaball = (struct XABALL *) extract_block(blk, 0,
X &cc$rms_xaball, XALLL);
X LINK(xaball);
X }
X else if (EQL_L(block_id, XKEYSIG))
X {
X xabkey = (struct XABKEY *) extract_block(blk, 0,
X &cc$rms_xabkey, XKEYL);
X LINK(xabkey);
X }
X else if (EQL_L(block_id, XFHCSIG))
X {
X xabfhc = (struct XABFHC *) extract_block(blk, 0,
X &cc$rms_xabfhc, XFHCL);
X }
X else if (EQL_L(block_id, XDATSIG))
X {
X xabdat = (struct XABDAT *) extract_block(blk, 0,
X &cc$rms_xabdat, XDATL);
X }
X else if (EQL_L(block_id, XRDTSIG))
X {
X xabrdt = (struct XABRDT *) extract_block(blk, 0,
X &cc$rms_xabrdt, XRDTL);
X }
X else if (EQL_L(block_id, XPROSIG))
X {
X xabpro = (struct XABPRO *) extract_block(blk, 0,
X &cc$rms_xabpro, XPROL);
X }
X else if (EQL_L(block_id, VERSIG))
X {
X#ifdef CHECK_VERSIONS
X char verbuf[80];
X int verlen = 0;
X uch *vers;
X char *m;
X
X get_vms_version(verbuf, 80);
X vers = extract_block(blk, &verlen, 0, 0);
X if ((m = strrchr((char *) vers, '-')) != NULL)
X *m = 0; /* Cut out release number */
X if (strcmp(verbuf, (char *) vers) && qflag < 2)
X {
X printf("[ Warning: VMS version mismatch.");
X
X printf(" This version %s --", verbuf);
X strncpy(verbuf, (char *) vers, verlen);
X verbuf[verlen] = 0;
X printf(" version made by %s ]\n", verbuf);
X }
X free(vers);
X#endif
X }
X else
X fprintf(stderr, "[ Warning: Unknown block signature %s ]\n",
X block_id);
X }
X else if (hdr->tag == PK_SIGNATURE || hdr->tag == IZ_NEW_SIGNATURE)
X {
X /*
X * PKWARE style extra block decoding
X */
X struct PK_header *blk;
X register byte *scn;
X register int len;
X
X type = VAT_PK;
X
X blk = (struct PK_header *)hdr;
X len = blk -> size;
X scn = (byte *)(&blk->data);
X pka_idx = 0;
X
X while(len > PK_FLDHDR_SIZE)
X { register struct PK_field *fld;
X int skip=0;
X
X fld = (struct PK_field *)scn;
X switch(fld->tag)
X { case ATR$C_UCHAR:
X pka_uchar = L(&fld->value);
X break;
X case ATR$C_RECATTR:
X pka_rattr = *(struct fatdef *)(&fld->value);
X break;
X case ATR$C_UIC:
X case ATR$C_ADDACLENT:
X skip = !secinf;
X break;
X }
X
X if( !skip )
X { pka_atr[pka_idx].atr$w_size = fld->size;
X pka_atr[pka_idx].atr$w_type = fld->tag;
X pka_atr[pka_idx].atr$l_addr = &fld->value;
X ++pka_idx;
X }
X len -= fld->size + PK_FLDHDR_SIZE;
X scn += fld->size + PK_FLDHDR_SIZE;
X }
X pka_atr[pka_idx].atr$w_size = 0; /* End of list */
X pka_atr[pka_idx].atr$w_type = 0;
X pka_atr[pka_idx].atr$l_addr = 0L;
X }
X len -= hdr->size + 4;
X scan += hdr->size + 4;
X }
X
X
X if( type == VAT_IZ )
X { if (outfab != 0)
X { /* Do not link XABPRO,XABRDT now. Leave them for sys$close() */
X
X outfab->fab$l_xab = 0L;
X if (xabfhc != 0L)
X {
X xabfhc->xab$l_nxt = outfab->fab$l_xab;
X outfab->fab$l_xab = (void *) xabfhc;
X }
X if (xabdat != 0L)
X {
X xabdat->xab$l_nxt = outfab->fab$l_xab;
X outfab->fab$l_xab = (void *) xabdat;
X }
X if (first_xab != 0L) /* Link xaball,xabkey subchain */
X {
X last_xab->xab$l_nxt = outfab->fab$l_xab;
X outfab->fab$l_xab = (void *) first_xab;
X }
X }
X else
X type = VAT_NONE;
X }
X return type;
X}
X
X
X
Xstatic void free_up()
X{ /*
X * Free up all allocated xabs
X */
X if (xabdat != 0L) free(xabdat);
X if (xabpro != 0L) free(xabpro);
X if (xabrdt != 0L) free(xabrdt);
X if (xabfhc != 0L) free(xabfhc);
X while (first_xab != 0L)
X {
X struct XAB *x;
X
X x = (struct XAB *) first_xab->xab$l_nxt;
X free(first_xab);
X first_xab = x;
X }
X if (outfab != 0L && outfab != &fileblk)
X free(outfab);
X}
X
X
X
X#ifdef CHECK_VERSIONS
X
Xstatic int get_vms_version(verbuf, len)
X char *verbuf;
X int len;
X{
X int i = SYI$_VERSION;
X int verlen = 0;
X struct dsc$descriptor version;
X char *m;
X
X version.dsc$a_pointer = verbuf;
X version.dsc$w_length = len - 1;
X version.dsc$b_dtype = DSC$K_DTYPE_B;
X version.dsc$b_class = DSC$K_CLASS_S;
X
X if (ERR(lib$getsyi(&i, 0, &version, &verlen, 0, 0)) || verlen == 0)
X return 0;
X
X /* Cut out trailing spaces "V5.4-3 " -> "V5.4-3" */
X for (m = verbuf + verlen, i = verlen - 1; i > 0 && verbuf[i] == ' '; --i)
X --m;
X *m = 0;
X
X /* Cut out release number "V5.4-3" -> "V5.4" */
X if ((m = strrchr(verbuf, '-')) != NULL)
X *m = 0;
X return strlen(verbuf) + 1; /* Transmit ending 0 too */
X}
X
X#endif /* CHECK_VERSIONS */
X
X
X
X/*
X * Extracts block from p. If resulting length is less then needed, fill
X * extra space with corresponding bytes from 'init'.
X * Currently understands 3 formats of block compression:
X * - Simple storing
X * - Compression of zero bytes to zero bits
X * - Deflation (see memextract() in extract.c)
X */
Xstatic uch *extract_block(p, retlen, init, needlen)
X struct IZ_block *p;
X int *retlen;
X uch *init;
X int needlen;
X{
X uch *block; /* Pointer to block allocated */
X int cmptype;
X int usiz, csiz, max;
X
X cmptype = p->flags & BC_MASK;
X csiz = p->size - EXTBSL - RESL;
X usiz = (cmptype == BC_STORED ? csiz : p->length);
X
X if (needlen == 0)
X needlen = usiz;
X
X if (retlen)
X *retlen = usiz;
X
X#ifndef MAX
X#define MAX(a,b) ( (a) > (b) ? (a) : (b) )
X#endif
X
X if ((block = (uch *) malloc(MAX(needlen, usiz))) == NULL)
X return NULL;
X
X if (init && (usiz < needlen))
X memcpy(block, init, needlen);
X
X switch (cmptype)
X {
X case BC_STORED: /* The simplest case */
X memcpy(block, &(p->body[0]), usiz);
X break;
X case BC_00:
X decompress_bits(block, usiz, &(p->body[0]));
X break;
X case BC_DEFL:
X memextract(block, usiz, &(p->body[0]), csiz);
X break;
X default:
X free(block);
X block = NULL;
X }
X return block;
X}
X
X
X
X/*
X * Simple uncompression routine. The compression uses bit stream.
X * Compression scheme:
X *
X * if(byte!=0)
X * putbit(1),putbyte(byte)
X * else
X * putbit(0)
X */
Xstatic void decompress_bits(outptr, needlen, bitptr)
X uch *bitptr; /* Pointer into compressed data */
X uch *outptr; /* Pointer into output block */
X int needlen; /* Size of uncompressed block */
X{
X ulg bitbuf = 0;
X int bitcnt = 0;
X
X#define _FILL if(bitcnt+8 <= 32) \
X { bitbuf |= (*bitptr++) << bitcnt;\
X bitcnt += 8; \
X }
X
X while (needlen--)
X {
X if (bitcnt <= 0)
X _FILL;
X
X if (bitbuf & 1)
X {
X bitbuf >>= 1;
X if ((bitcnt -= 1) < 8)
X _FILL;
X *outptr++ = (uch) bitbuf;
X bitcnt -= 8;
X bitbuf >>= 8;
X }
X else
X {
X *outptr++ = 0;
X bitcnt -= 1;
X bitbuf >>= 1;
X }
X }
X}
X
X
X
Xstatic void UpdateCRC(s, len)
X register uch *s;
X register int len;
X{
X register ulg crcval = crc32val;
X
X /* update running CRC calculation with contents of a buffer */
X while (len--)
X crcval = crc_32_tab[((uch)crcval ^ (*s++)) & 0xff] ^ (crcval >> 8);
X crc32val = crcval;
X}
X
X
X
X/* flush contents of output buffer */
Xint flush(rawbuf, size, unshrink) /* return PK-type error code */
X uch *rawbuf;
X ulg size;
X int unshrink;
X{
X UpdateCRC(rawbuf, size);
X if (tflag)
X return PK_COOL; /* Do not output. Update CRC only */
X else
X return (*_flush_routine)(rawbuf, size, 0);
X}
X
X
X
Xstatic int _flush_blocks(rawbuf, size, final_flag) /* Asynchronous version */
X uch *rawbuf;
X unsigned size;
X int final_flag; /* 1 if this is the final flushout */
X{
X int round;
X int rest;
X int off = 0;
X int status;
X
X while (size > 0)
X {
X if (curbuf->bufcnt < BUFS512)
X {
X int ncpy;
X
X ncpy = size > (BUFS512 - curbuf->bufcnt) ?
X BUFS512 - curbuf->bufcnt :
X size;
X memcpy(curbuf->buf + curbuf->bufcnt, rawbuf + off, ncpy);
X size -= ncpy;
X curbuf->bufcnt += ncpy;
X off += ncpy;
X }
X if (curbuf->bufcnt == BUFS512)
X {
X status = WriteBuffer(curbuf->buf, curbuf->bufcnt);
X if (status)
X return status;
X curbuf = curbuf->next;
X curbuf->bufcnt = 0;
X }
X }
X
X return (final_flag && (curbuf->bufcnt > 0)) ?
X WriteBuffer(curbuf->buf, curbuf->bufcnt) :
X PK_COOL;
X}
X
X
X
Xstatic int _flush_qio(rawbuf, size, final_flag)
X uch *rawbuf;
X unsigned size;
X int final_flag; /* 1 if this is the final flushout -- currently ignored */
X{
X int status;
X uch *out_ptr=rawbuf;
X
X if( final_flag )
X {
X if( loccnt > 0 )
X { status = sys$qiow(0, pka_devchn, IO$_WRITEVBLK,
X &pka_io_sb, 0, 0,
X locbuf, ((loccnt+1)/2)*2, /* Round to event byte count */
X pka_vbn,
X 0, 0, 0);
X if(!ERR(status))
X status = pka_io_sb.status;
X if(ERR(status))
X { message("[ Write QIO failed ]\n",status);
X return PK_DISK;
X }
X }
X return PK_COOL;
X }
X
X if( loccnt > 0 )
X { /*
X * Fill local buffer upto 512 bytes then put it out
X */
X int ncpy;
X
X ncpy = 512-loccnt;
X if( ncpy > size )
X ncpy = size;
X
X memcpy(locptr,rawbuf,ncpy);
X locptr += ncpy;
X loccnt += ncpy;
X size -= ncpy;
X out_ptr += ncpy;
X if( loccnt == 512 )
X {
X status = sys$qiow(0, pka_devchn, IO$_WRITEVBLK,
X &pka_io_sb, 0, 0,
X locbuf, loccnt, pka_vbn,
X 0, 0, 0);
X if(!ERR(status))
X status = pka_io_sb.status;
X if(ERR(status))
X { message("[ Write QIO failed ]\n",status);
X return PK_DISK;
X }
X
X pka_vbn++;
X loccnt = 0;
X locptr = locbuf;
X }
X }
X
X if( size >= 512 )
X { int nblk,put_cnt;
X
X /*
X * Put rest of buffer as a single VB
X */
X put_cnt = (nblk = size>>9)<<9;
X status = sys$qiow(0, pka_devchn, IO$_WRITEVBLK,
X &pka_io_sb, 0, 0,
X out_ptr, put_cnt, pka_vbn,
X 0, 0, 0);
X if(!ERR(status))
X status = pka_io_sb.status;
X if(ERR(status))
X { message("[ Write QIO failed ]\n",status);
X return PK_DISK;
X }
X
X pka_vbn += nblk;
X out_ptr += put_cnt;
X size -= put_cnt;
X }
X
X if( size > 0 )
X { memcpy(locptr,out_ptr,size);
X loccnt += size;
X locptr += size;
X }
X
X
X return PK_COOL;
X}
X
X
X
Xstatic int _flush_varlen(rawbuf, size, final_flag)
X uch *rawbuf;
X unsigned size;
X int final_flag;
X{
X ush nneed;
X ush reclen;
X uch *inptr=rawbuf;
X
X /*
X * Flush local buffer
X */
X
X if( loccnt > 0 )
X { reclen = *(ush*)locbuf;
X if( (nneed = reclen + 2 - loccnt) > 0 )
X { if( nneed > size )
X { if( size+loccnt > BUFS512 )
X { fprintf(stderr,"[ Record too long (%d bytes) ]\n",reclen );
X return PK_DISK;
X }
X memcpy(locbuf+loccnt,rawbuf,size);
X loccnt += size;
X size = 0;
X }
X else
X { memcpy(locbuf+loccnt,rawbuf,nneed);
X loccnt += nneed;
X size -= nneed;
X inptr += nneed;
X if( reclen & 1 )
X { size--;
X inptr++;
X }
X if( WriteRecord(locbuf+2,reclen) )
X return PK_DISK;
X loccnt = 0;
X }
X }
X else
X { if(WriteRecord(locbuf+2,reclen))
X return PK_DISK;
X loccnt -= reclen+2;
X }
X }
X /*
X * Flush incoming records
X */
X while(size > 0)
X { reclen = *(ush*)inptr;
X if( reclen+2 <= size )
X { if(WriteRecord(inptr+2,reclen))
X return PK_DISK;
X size -= 2+reclen;
X inptr += 2+reclen;
X if( reclen & 1)
X { --size;
X ++inptr;
X }
X }
X else
X { memcpy(locbuf,inptr,size);
X loccnt = size;
X size = 0;
X }
X
X }
X /*
X * Final flush rest of local buffer
X */
X if( final_flag && loccnt > 0 )
X { fprintf(stderr,
X "[ Warning, incomplete record of length %d ]\n",
X *(ush*)locbuf);
X if( WriteRecord(locbuf+2,loccnt-2) )
X return PK_DISK;
X }
X return PK_COOL;
X}
X
X
X
X/*
X* Routine _flush_stream breaks decompressed stream into records
X* depending on format of the stream (fab->rfm, pInfo->textmode, etc.)
X* and puts out these records. It also handles CR LF sequences.
X* Should be used when extracting *text* files.
X*/
X
X#define VT 0x0B
X#define FF 0x0C
X
X/* The file is from MSDOS/OS2/NT -> handle CRLF as record end, throw out ^Z */
X
X/* GRR NOTES: cannot depend on hostnum! May have "flip'd" file or re-zipped
X * a Unix file, etc. */
X
X#ifdef USE_ORIG_DOS
X# define ORG_DOS (hostnum==FS_FAT_ || hostnum==FS_HPFS_ || hostnum==FS_NTFS_)
X#else
X# define ORG_DOS 1
X#endif
X
X/* Record delimiters */
X#ifdef undef
X#define RECORD_END(c,f) \
X( ( ORG_DOS || pInfo->textmode ) && c==CTRLZ \
X || ( f == FAB$C_STMLF && c==LF ) \
X || ( f == FAB$C_STMCR || ORG_DOS || pInfo->textmode ) && c==CR \
X || ( f == FAB$C_STM && (c==CR || c==LF || c==FF || c==VT) ) \
X)
X#else
X# define RECORD_END(c,f) ((c) == LF || (c) == (CR))
X#endif
X
Xstatic int find_eol(p,n,l)
X/*
X * Find first CR,LF,CR-LF or LF-CR in string 'p' of length 'n'.
X * Return offset of the sequence found or 'n' if not found.
X * If found, return in '*l' length of the sequence (1 or 2) or
X * zero if sequence end not seen, i.e. CR or LF is last char
X * in the buffer.
X */
Xchar *p;
Xint n;
Xint *l;
X{ int off = n;
X char *q;
X
X *l = 0;
X
X for(q=p ; n > 0 ; --n,++q)
X if( RECORD_END(*q,rfm) )
X { off = q-p;
X break;
X }
X
X if( n > 1 )
X {
X *l = 1;
X if( ( q[0] == CR && q[1] == LF ) || ( q[0] == LF && q[1] == CR ) )
X *l = 2;
X }
X
X return off;
X}
X
X/* Record delimiters that must be put out */
X#define PRINT_SPEC(c) ( (c)==FF || (c)==VT )
X
X
X
Xstatic int _flush_stream(rawbuf, size, final_flag)
X uch *rawbuf;
X unsigned size;
X int final_flag; /* 1 if this is the final flushout */
X{
X int rest;
X int end = 0, start = 0;
X int off = 0;
X
X if (size == 0 && loccnt == 0)
X return PK_COOL; /* Nothing to do ... */
X
X if( final_flag )
X { int recsize;
X
X /*
X * This is flush only call. size must be zero now.
X * Just eject everything we have in locbuf.
X */
X recsize = loccnt - (got_eol ? 1:0);
X /*
X * If the last char of file was ^Z ( end-of-file in MSDOS ),
X * we will see it now.
X */
X if( recsize==1 && locbuf[0] == CTRLZ )
X return PK_COOL;
X
X return WriteRecord(locbuf, recsize) ? PK_DISK : PK_COOL;
X }
X
X
X if ( loccnt > 0 )
X { /* Find end of record partialy saved in locbuf */
X
X int recsize;
X int complete=0;
X
X if( got_eol )
X { recsize = loccnt - 1;
X complete = 1;
X
X if( (got_eol == CR && rawbuf[0] == LF) || (got_eol == LF && rawbuf[0] == CR) )
X end = 1;
X
X got_eol = 0;
X }
X else
X { int eol_len;
X int eol_off;
X
X eol_off = find_eol(rawbuf,size,&eol_len);
X
X if( loccnt+eol_off > BUFS512 )
X { /*
X * No room in locbuf. Dump it and clear
X */
X recsize = loccnt;
X start = 0;
X fprintf(stderr, "[ Warning: Record too long (%d) ]\n",
X loccnt+eol_off);
X complete = 1;
X end = 0;
X }
X else
X { if( eol_off >= size )
X { end = size;
X complete = 0;
X }
X else if( eol_len == 0 )
X { got_eol = rawbuf[eol_off];
X end = size;
X complete = 0;
X }
X else
X { memcpy(locptr, rawbuf, eol_off);
X recsize = loccnt + eol_off;
X locptr += eol_off;
X loccnt += eol_off;
X end = eol_off + eol_len;
X complete = 1;
X }
X }
X }
X
X if( complete )
X { if (WriteRecord(locbuf, recsize))
X return PK_DISK;
X loccnt = 0;
X locptr = locbuf;
X }
X } /* end if( loccnt ) */
X
X for(start = end; start < size && end < size; )
X { int eol_off,eol_len;
X
X got_eol = 0;
X
X#ifdef undef
X if (cflag)
X /* skip CR's at the beginning of record */
X while (start < size && rawbuf[start] == CR)
X ++start;
X#endif
X
X if( start >= size )
X continue;
X
X /* Find record end */
X end = start+(eol_off = find_eol(rawbuf+start, size-start, &eol_len));
X
X if( end >= size )
X continue;
X
X if( eol_len > 0 )
X { if( WriteRecord(rawbuf+start, end-start) )
X return PK_DISK;
X start = end + eol_len;
X }
X else
X { got_eol = rawbuf[end];
X end = size;
X continue;
X }
X }
X
X rest = size - start;
X
X if (rest > 0)
X { if( rest > BUFS512 )
X { int recsize;
X
X recsize = rest - (got_eol ? 1:0 );
X fprintf(stderr, "[ Warning: Record too long (%d) ]\n", recsize);
X got_eol = 0;
X return WriteRecord(rawbuf+start,recsize) ? PK_DISK : PK_COOL;
X }
X else
X { memcpy(locptr, rawbuf + start, rest);
X locptr += rest;
X loccnt += rest;
X }
X }
X return PK_COOL;
X}
X
X
X
Xstatic int WriteBuffer(buf, len)
X unsigned char *buf;
X int len;
X{
X int status;
X
X status = sys$wait(outrab);
X if (ERR(status))
X {
X message("[ WriteBuffer failed ]\n", status);
X message("", outrab->rab$l_stv);
X }
X outrab->rab$w_rsz = len;
X outrab->rab$l_rbf = (char *) buf;
X
X if (ERR(status = sys$write(outrab)))
X {
X message("[ WriteBuffer failed ]\n", status);
X message("", outrab->rab$l_stv);
X return PK_DISK;
X }
X return PK_COOL;
X}
X
X
X
Xstatic int WriteRecord(rec, len)
X unsigned char *rec;
X int len;
X{
X int status;
X
X if (ERR(status = sys$wait(outrab)))
X {
X message("[ WriteRecord failed ]\n", status);
X message("", outrab->rab$l_stv);
X }
X outrab->rab$w_rsz = len;
X outrab->rab$l_rbf = (char *) rec;
X
X if (ERR(status = sys$put(outrab)))
X {
X message("[ WriteRecord failed ]\n", status);
X message("", outrab->rab$l_stv);
X return PK_DISK;
X }
X return PK_COOL;
X}
X
X
X
Xvoid close_outfile()
X{
X int status;
X
X status = (*_flush_routine)(0, 0, 1);
X if (status)
X return /* PK_DISK */;
X if (cflag)
X return; /* Don't close stdout */
X /* return */ (*_close_routine)();
X}
X
X
X
Xstatic int _close_rms()
X{
X int status;
X struct XABPRO pro;
X
X /* Link XABRDT,XABDAT and optionaly XABPRO */
X if (xabrdt != 0L)
X {
X xabrdt->xab$l_nxt = 0L;
X outfab->fab$l_xab = (void *) xabrdt;
X }
X else
X {
X rdt.xab$l_nxt = 0L;
X outfab->fab$l_xab = (void *) &rdt;
X }
X if (xabdat != 0L)
X {
X xabdat->xab$l_nxt = outfab->fab$l_xab;
X outfab->fab$l_xab = (void *)xabdat;
X }
X
X if( xabpro != 0L )
X {
X if( !secinf )
X xabpro->xab$l_uic = 0; /* Use default (user's) uic */
X xabpro->xab$l_nxt = outfab->fab$l_xab;
X outfab->fab$l_xab = (void *) xabpro;
X }
X else
X { pro = cc$rms_xabpro;
X pro.xab$w_pro = pInfo->file_attr;
X pro.xab$l_nxt = outfab->fab$l_xab;
X outfab->fab$l_xab = (void *) &pro;
X }
X
X sys$wait(outrab);
X
X status = sys$close(outfab);
X#ifdef DEBUG
X if (ERR(status))
X {
X message("\r[ Warning: cannot set owner/protection/time attributes ]\n",
X status);
X message("", outfab->fab$l_stv);
X }
X#endif
X free_up();
X return PK_COOL;
X}
X
X
X
Xstatic int _close_qio()
X{ int status;
X
X pka_fib.FIB$L_ACCTL =
X FIB$M_WRITE | FIB$M_NOTRUNC ;
X pka_fib.FIB$W_EXCTL = 0;
X
X pka_fib.FIB$W_FID[0] =
X pka_fib.FIB$W_FID[1] =
X pka_fib.FIB$W_FID[2] =
X pka_fib.FIB$W_DID[0] =
X pka_fib.FIB$W_DID[1] =
X pka_fib.FIB$W_DID[2] = 0;
X
X status = sys$qiow(0, pka_devchn, IO$_DEACCESS, &pka_acp_sb,
X 0, 0,
X &pka_fibdsc, 0, 0, 0,
X &pka_atr, 0);
X
X sys$dassgn(pka_devchn);
X if( !ERR(status) )
X status = pka_acp_sb.status;
X if( ERR(status) )
X { message("[ Deaccess QIO failed ]\n",status);
X return PK_DISK;
X }
X return PK_COOL;
X}
X
X
X
X#ifdef DEBUG
Xdump_rms_block(p)
X unsigned char *p;
X{
X unsigned char bid, len;
X int err;
X char *type;
X char buf[132];
X int i;
X
X err = 0;
X bid = p[0];
X len = p[1];
X switch (bid)
X {
X case FAB$C_BID:
X type = "FAB";
X break;
X case XAB$C_ALL:
X type = "xabALL";
X break;
X case XAB$C_KEY:
X type = "xabKEY";
X break;
X case XAB$C_DAT:
X type = "xabDAT";
X break;
X case XAB$C_RDT:
X type = "xabRDT";
X break;
X case XAB$C_FHC:
X type = "xabFHC";
X break;
X case XAB$C_PRO:
X type = "xabPRO";
X break;
X default:
X type = "Unknown";
X err = 1;
X break;
X }
X printf("Block @%08X of type %s (%d).", p, type, bid);
X if (err)
X {
X printf("\n");
X return;
X }
X printf(" Size = %d\n", len);
X printf(" Offset - Hex - Dec\n");
X for (i = 0; i < len; i += 8)
X {
X int j;
X
X printf("%3d - ", i);
X for (j = 0; j < 8; j++)
X if (i + j < len)
X printf("%02X ", p[i + j]);
X else
X printf(" ");
X printf(" - ");
X for (j = 0; j < 8; j++)
X if (i + j < len)
X printf("%03d ", p[i + j]);
X else
X printf(" ");
X printf("\n");
X }
X}
X
X#endif /* DEBUG */
X
X
X
Xstatic void message(string, status)
X int status;
Xchar *string;
X{
X char msgbuf[256];
X
X $DESCRIPTOR(msgd, msgbuf);
X int msglen = 0;
X
X if (ERR(lib$sys_getmsg(&status, &msglen, &msgd, 0, 0)))
X fprintf(stderr, "%s[ VMS status = %d ]\n", string, status);
X else
X {
X msgbuf[msglen] = 0;
X fprintf(stderr, "%s[ %s ]\n", string, msgbuf);
X }
X}
X
X
X
X#ifndef SFX
X
Xchar *do_wild( wld )
X char *wld;
X{
X int status;
X
X static char filename[256];
X static char efn[256];
X static char last_wild[256];
X static struct FAB fab;
X static struct NAM nam;
X static int first_call=1;
X static char deflt[] = "*.zip";
X
X if( first_call || strcmp(wld, last_wild) )
X { /* (Re)Initialize everything */
X
X strcpy( last_wild, wld );
X first_call = 1; /* New wild spec */
X
X fab = cc$rms_fab;
X fab.fab$l_fna = last_wild;
X fab.fab$b_fns = strlen(last_wild);
X fab.fab$l_dna = deflt;
X fab.fab$b_dns = strlen(deflt);
X fab.fab$l_nam = &nam;
X nam = cc$rms_nam;
X nam.nam$l_esa = efn;
X nam.nam$b_ess = sizeof(efn)-1;
X nam.nam$l_rsa = filename;
X nam.nam$b_rss = sizeof(filename)-1;
X
X if(!OK(sys$parse(&fab)))
X return (char *)NULL; /* Initialization failed */
X first_call = 0;
X if( !OK(sys$search(&fab)) )
X {
X strcpy( filename, wld );
X return filename;
X }
X }
X else
X {
X if( !OK(sys$search(&fab)) )
X {
X first_call = 1; /* Reinitialize next time */
X return (char *)NULL;
X }
X }
X filename[nam.nam$b_rsl] = 0;
X return filename;
X
X} /* end function do_wild() */
X
X#endif /* !SFX */
X
X
X
Xstatic ulg unix_to_vms[8]={ /* Map from UNIX rwx to VMS rwed */
X /* Note that unix w bit is mapped to VMS wd bits */
X XAB$M_NOREAD | XAB$M_NOWRITE | XAB$M_NODEL | XAB$M_NOEXE, /* --- no access*/
X XAB$M_NOREAD | XAB$M_NOWRITE | XAB$M_NODEL, /* --x */
X XAB$M_NOREAD | XAB$M_NOEXE, /* -w- */
X XAB$M_NOREAD, /* -wx */
X XAB$M_NOWRITE | XAB$M_NODEL | XAB$M_NOEXE, /* r-- */
X XAB$M_NOWRITE | XAB$M_NODEL, /* r-x */
X XAB$M_NOEXE, /* rw- */
X 0 /* rwx full access*/
X};
X
X#define SETDFPROT /* We are using undocumented VMS System Service */
X /* SYS$SETDFPROT here. If your version of VMS does */
X /* not have that service, undef SETDFPROT. */
X /* IM: Maybe it's better to put this to Makefile */
X /* and DESCRIP.MMS */
X
X
X
Xint mapattr()
X{
X ulg tmp=crec.external_file_attributes, theprot;
X static ulg defprot = -1L,
X sysdef,owndef,grpdef,wlddef; /* Default protection fields */
X
X
X /* IM: The only field of XABPRO we need to set here is */
X /* file protection, so we need not to change type */
X /* of pInfo->file_attr. WORD is quite enough. */
X
X if( defprot == -1L )
X {
X /*
X * First time here -- Get user default settings
X */
X
X#ifdef SETDFPROT /* Undef this if linker cat't resolve SYS$SETDFPROT */
X defprot = 0L;
X if( !ERR(SYS$SETDFPROT(0,&defprot)) )
X {
X sysdef = defprot & ( (1L<<XAB$S_SYS)-1 ) << XAB$V_SYS;
X owndef = defprot & ( (1L<<XAB$S_OWN)-1 ) << XAB$V_OWN;
X grpdef = defprot & ( (1L<<XAB$S_GRP)-1 ) << XAB$V_GRP;
X wlddef = defprot & ( (1L<<XAB$S_WLD)-1 ) << XAB$V_WLD;
X }
X else
X {
X#endif /* ?SETDFPROT */
X umask(defprot = umask(0));
X defprot = ~defprot;
X wlddef = unix_to_vms[defprot & 07] << XAB$V_WLD;
X grpdef = unix_to_vms[(defprot>>3) & 07] << XAB$V_GRP;
X owndef = unix_to_vms[(defprot>>6) & 07] << XAB$V_OWN;
X sysdef = owndef << (XAB$V_SYS - XAB$V_OWN);
X defprot = sysdef | owndef | grpdef | wlddef;
X#ifdef SETDFPROT
X }
X#endif /* ?SETDFPROT */
X }
X
X switch (pInfo->hostnum) {
X case UNIX_:
X case VMS_: /*IM: ??? Does VMS Zip store protection in UNIX format ?*/
X /* GRR: Yup. Bad decision on my part... */
X tmp = (unsigned)(tmp >> 16); /* drwxrwxrwx */
X theprot = (unix_to_vms[tmp & 07] << XAB$V_WLD)
X | (unix_to_vms[(tmp>>3) & 07] << XAB$V_GRP)
X | (unix_to_vms[(tmp>>6) & 07] << XAB$V_OWN);
X
X if( tmp & 0x4000 )
X /* Directory -- set D bits */
X theprot |= (XAB$M_NODEL << XAB$V_SYS)
X | (XAB$M_NODEL << XAB$V_OWN)
X | (XAB$M_NODEL << XAB$V_GRP)
X | (XAB$M_NODEL << XAB$V_WLD);
X pInfo->file_attr = theprot;
X break;
X
X case AMIGA_:
X tmp = (unsigned)(tmp>>16 & 0x0f); /* Amiga RWED bits */
X pInfo->file_attr = (tmp << XAB$V_OWN) | grpdef | sysdef | wlddef;
X break;
X
X /* all remaining cases: expand MSDOS read-only bit into write perms */
X case FS_FAT_:
X case FS_HPFS_:
X case FS_NTFS_:
X case MAC_:
X case ATARI_: /* (used to set = 0666) */
X case TOPS20_:
X default:
X theprot = defprot;
X if( tmp & 1 ) /* Test read-only bit */
X { /* Bit is set -- set bits in all fields */
X tmp = XAB$M_NOWRITE | XAB$M_NODEL;
X theprot |= (tmp << XAB$V_SYS) | (tmp << XAB$V_OWN) |
X (tmp << XAB$V_GRP) | (tmp << XAB$V_WLD);
X }
X pInfo->file_attr = theprot;
X break;
X } /* end switch (host-OS-created-by) */
X
X return 0;
X
X} /* end function mapattr() */
X
X
X
X#ifndef EEXIST
X# include <errno.h> /* For mkdir() status codes */
X#endif
X
X#include <fscndef.h> /* for filescan */
X
X# define FN_MASK 7
X# define USE_DEFAULT (FN_MASK+1)
X
X/*
X * Checkdir function codes:
X * ROOT - set root path from unzip qq d:[dir]
X * INIT - get ready for "filename"
X * APPEND_DIR - append pathcomp
X * APPEND_NAME - append filename
X * APPEND_NAME | USE_DEFAULT - expand filename using collected path
X * GETPATH - return resulting filespec
X */
X
Xstatic int created_dir;
X
Xint mapname(renamed) /* return 0 if no error, 1 if caution (filename trunc),*/
X int renamed; /* 2 if warning (skip file because dir doesn't exist), */
X{ /* 3 if error (skip file), 10 if no memory (skip file) */
X char pathcomp[FILNAMSIZ]; /* path-component buffer */
X char *pp, *cp=NULL; /* character pointers */
X char *lastsemi = NULL; /* pointer to last semi-colon in pathcomp */
X char *last_dot = NULL; /* last dot not converted to underscore */
X int quote = FALSE; /* flag: next char is literal */
X int dotname = FALSE; /* flag: path component begins with dot */
X int error = 0;
X register unsigned workch; /* hold the character being tested */
X
X if( renamed )
X {
X if( !(error = checkdir(pathcomp, APPEND_NAME | USE_DEFAULT)) )
X strcpy(filename, pathcomp);
X return error;
X }
X
X/*---------------------------------------------------------------------------
X Initialize various pointers and counters and stuff.
X ---------------------------------------------------------------------------*/
X
X /* can create path as long as not just freshening, or if user told us */
X create_dirs = !fflag;
X
X created_dir = FALSE; /* not yet */
X
X/* GRR: for VMS, convert to internal format now or later? or never? */
X if (checkdir(pathcomp, INIT) == 10)
X return 10; /* initialize path buffer, unless no memory */
X
X *pathcomp = '\0'; /* initialize translation buffer */
X pp = pathcomp; /* point to translation buffer */
X if (jflag) /* junking directories */
X/* GRR: watch out for VMS version... */
X cp = (char *)strrchr(filename, '/');
X if (cp == NULL) /* no '/' or not junking dirs */
X cp = filename; /* point to internal zipfile-member pathname */
X else
X ++cp; /* point to start of last component of path */
X
X/*---------------------------------------------------------------------------
X Begin main loop through characters in filename.
X ---------------------------------------------------------------------------*/
X
X while ((workch = (uch)*cp++) != 0) {
X
X if (quote) { /* if character quoted, */
X *pp++ = (char)workch; /* include it literally */
X quote = FALSE;
X } else
X switch (workch) {
X case '/': /* can assume -j flag not given */
X *pp = '\0';
X if (last_dot) { /* one dot in directory name is legal */
X *last_dot = '.';
X last_dot = NULL;
X }
X if ((error = checkdir(pathcomp, APPEND_DIR)) > 1)
X return error;
X pp = pathcomp; /* reset conversion buffer for next piece */
X lastsemi = NULL; /* leave directory semi-colons alone */
X break;
X
X case ':':
X *pp++ = '_'; /* drive names not stored in zipfile, */
X break; /* so no colons allowed */
X
X case '.':
X if (pp == pathcomp) { /* nothing appended yet... */
X if (*cp == '/') { /* don't bother appending a "./" */
X ++cp; /* component to the path: skip */
X break; /* to next char after the '/' */
X } else if (*cp == '.' && cp[1] == '/') { /* "../" */
X *pp++ = '.'; /* add first dot, unchanged... */
X ++cp; /* skip second dot, since it will */
X } /* added next (as '_' for now) */
X }
X last_dot = pp; /* point at last dot so far... */
X *pp++ = '_'; /* convert dot to underscore for now */
X break;
X
X case ';': /* start of VMS version? */
X if (lastsemi)
X *lastsemi = '_'; /* convert previous one to underscore */
X lastsemi = pp;
X *pp++ = ';'; /* keep for now; remove VMS vers. later */
X break;
X
X case ' ':
X *pp++ = '_';
X break;
X
X default:
X if( isalpha(workch) || isdigit(workch) ||
X workch=='$' || workch=='-' )
X *pp++ = (char)workch;
X else
X *pp++ = '_'; /* convert everything else to underscore */
X break;
X } /* end switch */
X
X } /* end while loop */
X
X *pp = '\0'; /* done with pathcomp: terminate it */
X
X /* if not saving them, remove VMS version numbers (appended "###") */
X if (lastsemi) {
X pp = lastsemi + 1; /* expect all digits after semi-colon */
X while (isdigit((uch)(*pp)))
X ++pp;
X if (*pp) /* not version number: convert ';' to '_' */
X *lastsemi = '_';
X else if (!V_flag) /* only digits between ';' and end: nuke */
X *lastsemi = '\0';
X /* else only digits and we're saving version number: do nothing */
X }
X
X if (last_dot != NULL) /* one dot is OK: put it back in */
X *last_dot = '.'; /* (already done for directories) */
X
X/*---------------------------------------------------------------------------
X Report if directory was created (and no file to create: filename ended
X in '/'), check name to be sure it exists, and combine path and name be-
X fore exiting.
X ---------------------------------------------------------------------------*/
X
X if (filename[strlen(filename) - 1] == '/') {
X checkdir("", APPEND_NAME); /* create directory, if not found */
X checkdir(filename, GETPATH);
X if (created_dir && QCOND2) {
X fprintf(stdout, " creating: %s\n", filename);
X return IZ_CREATED_DIR; /* set dir time (note trailing '/') */
X }
X return 2; /* dir existed already; don't look for data to extract */
X }
X
X if (*pathcomp == '\0') {
X fprintf(stderr, "mapname: conversion of %s failed\n", filename);
X return 3;
X }
X
X checkdir(pathcomp, APPEND_NAME); /* returns 1 if truncated: care? */
X checkdir(filename, GETPATH);
X
X return error;
X
X} /* end function mapname() */
X
X
X
Xint checkdir(pathcomp,fcn)
X/*
X * returns: 1 - (on APPEND_NAME) truncated filename
X * 2 - path doesn't exist, not allowed to create
X * 3 - path doesn't exist, tried to create and failed; or
X * path exists and is not a directory, but is supposed to be
X * 4 - path is too long
X * 10 - can't allocate memory for filename buffers
X */
X char *pathcomp;
X int fcn;
X{
X int function=fcn & FN_MASK;
X static char pathbuf[FILNAMSIZ];
X static char lastdir[FILNAMSIZ]="\t"; /* directory created last time */
X /* initially - impossible dir. spec. */
X static char *pathptr=pathbuf; /* For debugger */
X static char *devptr, *dirptr, *namptr;
X static int devlen, dirlen, namlen;
X static int root_dirlen;
X static char *end;
X static int first_comp,root_has_dir;
X static int rootlen=0;
X static char *rootend;
X static int mkdir_failed=0;
X int status;
X
X/************
X *** ROOT ***
X ************/
X
X#if (!defined(SFX) || defined(SFX_EXDIR))
X if(function==ROOT)
X { /* Assume VMS root spec */
X char *p = pathcomp;
X char *q;
X
X struct
X { short len;
X short code;
X char *addr;
X } itl [4] =
X {
X { 0, FSCN$_DEVICE, 0 },
X { 0, FSCN$_ROOT, 0 },
X { 0, FSCN$_DIRECTORY, 0 },
X { 0, 0, 0 } /* End of itemlist */
X };
X int fields = 0;
X struct dsc$descriptor pthcmp;
X
X /*
X * Initialize everything
X */
X end = devptr = dirptr = rootend = pathbuf;
X devlen = dirlen = rootlen = 0;
X
X pthcmp.dsc$a_pointer = pathcomp;
X if( (pthcmp.dsc$w_length = strlen(pathcomp)) > 255 )
X return 4;
X
X status = sys$filescan(&pthcmp, itl, &fields);
X if( !OK(status) )
X return 3;
X
X if( fields & FSCN$M_DEVICE )
X { strncpy(devptr = end, itl[0].addr, itl[0].len);
X dirptr = (end += (devlen = itl[0].len));
X }
X
X root_has_dir = 0;
X
X if( fields & FSCN$M_ROOT )
X { int len;
X
X strncpy(dirptr = end, itl[1].addr,
X len = itl[1].len - 1); /* Cut out trailing ']' */
X end += len;
X root_has_dir = 1;
X }
X
X if( fields & FSCN$M_DIRECTORY )
X { char *ptr;
X int len;
X
X len = itl[2].len-1;
X ptr = itl[2].addr;
X
X if( root_has_dir /* i.e. root specified */ )
X { --len; /* Cut out leading dot */
X ++ptr; /* ??? [a.b.c.][.d.e] */
X }
X
X strncpy(dirptr=end, ptr, len); /* Replace trailing ']' */
X *(end+=len) = '.'; /* ... with dot */
X ++end;
X root_has_dir = 1;
X }
X
X /* When user specified "[a.b.c.]" or "[qq...]", we have too many
X * trailing dots. Let's cut them out. Now we surely have at least
X * one trailing dot and "end" points just behind it. */
X
X dirlen = end - dirptr;
X while( dirlen > 1 && end[-2] == '.' )
X --dirlen,--end;
X
X first_comp = !root_has_dir;
X root_dirlen = end - dirptr;
X *(rootend = end) = 0;
X rootlen = rootend - devptr;
X return 0;
X }
X#endif /* !SFX || SFX_EXDIR */
X
X
X/************
X *** INIT ***
X ************/
X
X if( function == INIT )
X {
X if( strlen(filename) + rootlen + 13 > 255 )
X return 4;
X
X if( rootlen == 0 ) /* No root given, reset everything. */
X { devptr = dirptr = rootend = pathbuf;
X devlen = dirlen = 0;
X }
X end = rootend;
X first_comp = !root_has_dir;
X if( dirlen = root_dirlen )
X end[-1] = '.';
X *end = 0;
X return 0;
X }
X
X
X/******************
X *** APPEND_DIR ***
X ******************/
X if( function == APPEND_DIR )
X { int cmplen;
X
X cmplen = strlen(pathcomp);
X
X if( first_comp )
X { *end++ = '[';
X if( cmplen )
X *end++ = '.'; /* "dir/..." --> "[.dir...]" */
X /* else "/dir..." --> "[dir...]" */
X first_comp = 0;
X }
X
X if( cmplen == 1 && *pathcomp == '.' )
X ; /* "..././..." -- ignore */
X
X else if( cmplen == 2 && pathcomp[0] == '.' && pathcomp[1] == '.' )
X { /* ".../../..." -- convert to "...-..." */
X *end++ = '-';
X *end++ = '.';
X }
X
X else if( cmplen + (end-pathptr) > 255 )
X return 4;
X
X else
X { strcpy(end, pathcomp);
X *(end+=cmplen) = '.';
X ++end;
X }
X dirlen = end - dirptr;
X *end = 0;
X return 0;
X }
X
X
X/*******************
X *** APPEND_NAME ***
X *******************/
X if( function == APPEND_NAME )
X { if( fcn & USE_DEFAULT )
X { /* Expand renamed filename using collected path, return
X * at pathcomp */
X struct FAB fab;
X struct NAM nam;
X
X fab = cc$rms_fab;
X fab.fab$l_fna = filename;
X fab.fab$b_fns = strlen(filename);
X fab.fab$l_dna = pathptr;
X fab.fab$b_dns = end-pathptr;
X
X fab.fab$l_nam = &nam;
X nam = cc$rms_nam;
X nam.nam$l_esa = pathcomp;
X nam.nam$b_ess = 255; /* Assume large enaugh */
X
X if(!OK(status = sys$parse(&fab)) && status == RMS$_DNF ) /* Directory not found: */
X { char save; /* ... try to create it */
X char *dirend;
X int mkdir_failed;
X
X dirend = (char*)nam.nam$l_dir + nam.nam$b_dir;
X save = *dirend;
X *dirend = 0;
X if( (mkdir_failed = mkdir(nam.nam$l_dev, 0)) && errno == EEXIST )
X mkdir_failed = 0;
X *dirend = save;
X if( mkdir_failed )
X return 3;
X created_dir = TRUE;
X } /* if (sys$parse... */
X pathcomp[nam.nam$b_esl] = 0;
X return 0;
X } /* if (USE_DEFAULT) */
X else
X {
X *end = 0;
X if( dirlen )
X { dirptr[dirlen-1] = ']'; /* Close directory */
X
X /*
X * Try to create the target directory.
X * Don't waste time creating directory that was created
X * last time.
X */
X if( STRICMP(lastdir,pathbuf) )
X {
X mkdir_failed = 0;
X if( mkdir(pathbuf,0) )
X { if( errno != EEXIST )
X mkdir_failed = 1; /* Mine for GETPATH */
X }
X else
X created_dir = TRUE;
X strcpy(lastdir,pathbuf);
X }
X }
X else
X { /*
X * Target directory unspecified.
X * Try to create "sys$disk:[]"
X */
X if( strcmp(lastdir,"sys$disk:[]") )
X { strcpy(lastdir,"sys$disk:[]");
X mkdir_failed = 0;
X if( mkdir(lastdir,0) && errno != EEXIST )
X mkdir_failed = 1; /* Mine for GETPATH */
X }
X }
X if( strlen(pathcomp) + (end-pathbuf) > 255 )
X return 1;
X strcpy(end, pathcomp);
X end += strlen(pathcomp);
X return 0;
X }
X }
X
X
X/***************
X *** GETPATH ***
X ***************/
X if( function == GETPATH )
X {
X if( mkdir_failed )
X return 3;
X *end = 0; /* To be safe */
X strcpy( pathcomp, pathbuf );
X return 0;
X }
X}
X
X
X
Xint check_for_newer(filename) /* return 1 if existing file newer or equal; */
X char *filename; /* 0 if older; -1 if doesn't exist yet */
X{
X unsigned short timbuf[7];
X int dy, mo, yr, hh, mm, ss, dy2, mo2, yr2, hh2, mm2, ss2;
X struct FAB fab;
X struct XABDAT xdat;
X
X
X if (stat(filename, &statbuf))
X return DOES_NOT_EXIST;
X
X fab = cc$rms_fab;
X xdat = cc$rms_xabdat;
X
X fab.fab$l_xab = (char *) &xdat;
X fab.fab$l_fna = filename;
X fab.fab$b_fns = strlen(filename);
X fab.fab$l_fop = FAB$M_GET | FAB$M_UFO;
X
X if ((sys$open(&fab) & 1) == 0) /* open failure: report exists and */
X return EXISTS_AND_OLDER; /* older so new copy will be made */
X sys$numtim(&timbuf,&xdat.xab$q_cdt);
X fab.fab$l_xab = 0L;
X
X sys$dassgn(fab.fab$l_stv);
X sys$close(&fab); /* be sure file is closed and RMS knows about it */
X
X yr = timbuf[0];
X yr2 = ((lrec.last_mod_file_date >> 9) & 0x7f) + 1980;
X if (yr > yr2)
X return EXISTS_AND_NEWER;
X else if (yr < yr2)
X return EXISTS_AND_OLDER;
X
X mo = timbuf[1];
X mo2 = ((lrec.last_mod_file_date >> 5) & 0x0f);
X if (mo > mo2)
X return EXISTS_AND_NEWER;
X else if (mo < mo2)
X return EXISTS_AND_OLDER;
X
X dy = timbuf[2];
X dy2 = (lrec.last_mod_file_date & 0x1f);
X if (dy > dy2)
X return EXISTS_AND_NEWER;
X else if (dy < dy2)
X return EXISTS_AND_OLDER;
X
X hh = timbuf[3];
X hh2 = (lrec.last_mod_file_time >> 11) & 0x1f;
X if (hh > hh2)
X return EXISTS_AND_NEWER;
X else if (hh < hh2)
X return EXISTS_AND_OLDER;
X
X mm = timbuf[4];
X mm2 = (lrec.last_mod_file_time >> 5) & 0x3f;
X if (mm > mm2)
X return EXISTS_AND_NEWER;
X else if (mm < mm2)
X return EXISTS_AND_OLDER;
X
X /* round to nearest 2 secs--may become 60, but doesn't matter for compare */
X ss = (int)((float)timbuf[5] + (float)timbuf[6]*.01 + 1.) & -2;
X ss2 = (lrec.last_mod_file_time & 0x1f) * 2;
X if (ss >= ss2)
X return EXISTS_AND_NEWER;
X
X return EXISTS_AND_OLDER;
X}
X
X
X
Xvoid return_VMS(ziperr)
X int ziperr;
X{
X#ifdef RETURN_CODES
X/*---------------------------------------------------------------------------
X Do our own, explicit processing of error codes and print message, since
X VMS misinterprets return codes as rather obnoxious system errors ("access
X violation," for example).
X ---------------------------------------------------------------------------*/
X
X switch (ziperr) {
X
X case PK_COOL:
X break; /* life is fine... */
X case PK_WARN:
X fprintf(stderr, "\n[return-code 1: warning error \
X(e.g., failed CRC or unknown compression method)]\n");
X break;
X case PK_ERR:
X case PK_BADERR:
X fprintf(stderr, "\n[return-code %d: error in zipfile \
X(e.g., can't find local file header sig)]\n", ziperr);
X break;
X case PK_MEM:
X case PK_MEM2:
X case PK_MEM3:
X case PK_MEM4:
X case PK_MEM5:
X fprintf(stderr, "\n[return-code %d: insufficient memory]\n", ziperr);
X break;
X case PK_NOZIP:
X fprintf(stderr, "\n[return-code 9: zipfile not found]\n");
X break;
X case PK_PARAM: /* the one that gives "access violation," I think */
X fprintf(stderr, "\n[return-code 10: bad or illegal parameters \
Xspecified on command line]\n");
X break;
X case PK_FIND:
X fprintf(stderr,
X "\n[return-code 11: no files found to extract/view/etc.]\n");
X break;
X case PK_DISK:
X fprintf(stderr,
X "\n[return-code 50: disk full or other I/O error]\n");
X break;
X case PK_EOF:
X fprintf(stderr,
X "\n[return-code 51: unexpected EOF in zipfile (i.e., truncated)]\n");
X break;
X default:
X fprintf(stderr, "\n[return-code %d: unknown return-code (screw-up)]\n",
X ziperr);
X break;
X }
X#endif /* RETURN_CODES */
X
X/*---------------------------------------------------------------------------
X Return an intelligent status/severity level if RETURN_SEVERITY defined:
X
X $STATUS $SEVERITY = $STATUS & 7
X 31 .. 16 15 .. 3 2 1 0
X -----
X VMS 0 0 0 0 Warning
X FACILITY 0 0 1 1 Success
X Number 0 1 0 2 Error
X MESSAGE 0 1 1 3 Information
X Number 1 0 0 4 Severe (fatal) error
X
X 0x7FFF0000 was chosen (by experimentation) to be outside the range of
X VMS FACILITYs that have dedicated message numbers. Hopefully this will
X always result in silent exits--it does on VMS 5.4. Note that the C li-
X brary translates exit arguments of zero to a $STATUS value of 1 (i.e.,
X exit is both silent and has a $SEVERITY of "success").
X ---------------------------------------------------------------------------*/
X
X#ifdef RETURN_SEVERITY
X {
X int severity = (ziperr == 2 || (ziperr >= 9 && ziperr <= 11))? 2 : 4;
X
X exit( /* $SEVERITY: */
X (ziperr == PK_COOL) ? 1 : /* success */
X (ziperr == PK_WARN) ? 0x7FFF0000 : /* warning */
X (0x7FFF0000 | (ziperr << 4) | severity) /* error or fatal */
X );
X }
X#else
X exit(0); /* everything okey-dokey as far as VMS concerned */
X#endif
X
X} /* end function return_VMS() */
X
X
X
X
X
X#ifndef SFX
X
X/************************/
X/* Function version() */
X/************************/
X
Xvoid version()
X{
X extern char Far CompiledWith[];
X#ifdef VMS_VERSION
X char buf[40];
X#endif
X
X printf(LoadFarString(CompiledWith),
X
X#ifdef __GNUC__
X "gcc ", __VERSION__,
X#else
X# if 0
X "cc ", (sprintf(buf, " version %d", _RELEASE), buf),
X# else
X# if defined(DECC) || defined(__DECC) || defined (__DECC__)
X "DEC C", "",
X# else
X# ifdef VAXC
X "VAX C", "",
X# else
X "unknown compiler", "",
X# endif
X# endif
X# endif
X#endif
X
X#ifdef VMS_VERSION
X# if defined(__alpha)
X "OpenVMS", /* version has trailing spaces ("V6.1 "), so truncate: */
X (sprintf(buf, " (%.4s for Alpha)", VMS_VERSION), buf),
X# else /* VAX */
X (VMS_VERSION[1] >= '6')? "OpenVMS" : "VMS",
X (sprintf(buf, " (%.4s for VAX)", VMS_VERSION), buf),
X# endif
X#else
X "VMS",
X "",
X#endif /* ?VMS_VERSION */
X
X#ifdef __DATE__
X " on ", __DATE__
X#else
X "", ""
X#endif
X );
X
X} /* end function version() */
X
X#endif /* !SFX */
X#endif /* VMS */
END_OF_FILE
if test 66172 -ne `wc -c <'unzip-5.12/vms/vms.c'`; then
echo shar: \"'unzip-5.12/vms/vms.c'\" unpacked with wrong size!
fi
# end of 'unzip-5.12/vms/vms.c'
fi
echo shar: End of archive 3 \(of 20\).
cp /dev/null ark3isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 20 archives.
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still must unpack the following archives:
echo " " ${MISSING}
fi
exit 0
exit 0 # Just in case...