home *** CD-ROM | disk | FTP | other *** search
- 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...
-