Archive-Unzip-Burst
view release on metacpan or search on metacpan
unzip-6.0/vms/vms.c view on Meta::CPAN
mapname()
checkdir()
check_for_newer()
return_VMS
screensize()
screenlinewrap()
version()
---------------------------------------------------------------------------*/
#ifdef VMS /* VMS only! */
#define UNZIP_INTERNAL
#include "unzip.h"
#include "crc32.h"
#include "vms.h"
#include "vmsdefs.h"
#ifdef MORE
# include <ttdef.h>
#endif
#include <unixlib.h>
#include <dvidef.h>
#include <ssdef.h>
#include <stsdef.h>
/* Workaround for broken header files of older DECC distributions
* that are incompatible with the /NAMES=AS_IS qualifier. */
#define lib$getdvi LIB$GETDVI
#define lib$getsyi LIB$GETSYI
#define lib$sys_getmsg LIB$SYS_GETMSG
#include <lib$routines.h>
#ifndef EEXIST
# include <errno.h> /* For mkdir() status codes */
#endif
/* On VAX, define Goofy VAX Type-Cast to obviate /standard = vaxc.
Otherwise, lame system headers on VAX cause compiler warnings.
(GNU C may define vax but not __VAX.)
*/
#ifdef vax
# define __VAX 1
#endif
#ifdef __VAX
# define GVTC (unsigned int)
#else
# define GVTC
#endif
/* With GNU C, some FAB bits may be declared only as masks, not as
* structure bits.
*/
#ifdef __GNUC__
# define OLD_FABDEF 1
#endif
#define ASYNCH_QIO /* Use asynchronous PK-style QIO writes */
/* buffer size for a single block write (using RMS or QIO WRITEVBLK),
must be less than 64k and a multiple of 512 ! */
#define BUFS512 (((OUTBUFSIZ>0xFFFF) ? 0xFFFF : OUTBUFSIZ) & (~511))
/* buffer size for record output (RMS limit for max. record size) */
#define BUFSMAXREC 32767
/* allocation size for RMS and QIO output buffers */
#define BUFSALLOC (BUFS512 * 2 > BUFSMAXREC ? BUFS512 * 2 : BUFSMAXREC)
/* locbuf size */
/* VMS success or warning status */
#define OK(s) (((s) & STS$M_SUCCESS) != 0)
#define STRICMP(s1, s2) STRNICMP(s1, s2, 2147483647)
/* Interactive inquiry response codes for replace(). */
#define REPL_NO_EXTRACT 0
#define REPL_NEW_VERSION 1
#define REPL_OVERWRITE 2
#define REPL_ERRLV_WARN 256
#define REPL_TASKMASK 255
/* 2008-09-13 CS.
* Note: In extract.c, there are similar strings "InvalidResponse" and
* "AssumeNone" defined. However, as the UI functionality of the VMS
* "version-aware" query is slightly different from the generic variant,
* these strings are kept separate for now to allow independent
* "fine tuning" without affecting the other variant of the
* "overwrite or ..." user query.
*/
ZCONST char Far InvalidResponse[] =
"error: invalid response [%.1s]\n";
ZCONST char Far AssumeNo[] =
"\n(EOF or read error, treating as \"[N]o extract (all)\" ...)\n";
#ifdef SET_DIR_ATTRIB
/* Structure for holding directory attribute data for final processing
* after all files are in place.
*/
typedef struct vmsdirattr {
struct vmsdirattr *next; /* link to next in (linked) list */
char *fn; /* file (directory) name */
/* Non-VMS attributes data */
ulg mod_dos_datetime; /* G.lrec.last_mod_dos_datetime */
unsigned perms; /* same as min_info.file_attr */
unsigned xlen; /* G.lrec.extra_field_length */
char buf[1]; /* data buffer (extra_field, fn) */
} vmsdirattr;
#define VmsAtt(d) ((vmsdirattr *)d) /* typecast shortcut */
#endif /* SET_DIR_ATTRIB */
/*
* Local static storage
*/
static struct FAB fileblk; /* File Access Block */
static struct XABDAT dattim; /* date-time XAB */
static struct XABRDT rdt; /* revision date-time XAB */
static struct RAB rab; /* Record Access Block */
static struct NAM_STRUCT nam; /* name block */
static struct FAB *outfab = NULL;
static struct RAB *outrab = NULL;
static struct XABFHC *xabfhc = NULL; /* file header characteristics */
static struct XABDAT *xabdat = NULL; /* date-time */
static struct XABRDT *xabrdt = NULL; /* revision date-time */
static struct XABPRO *xabpro = NULL; /* protection */
static struct XABKEY *xabkey = NULL; /* key (indexed) */
static struct XABALL *xaball = NULL; /* allocation */
static struct XAB *first_xab = NULL, *last_xab = NULL;
static int replace_code_all = -1; /* All-file response for replace(). */
static uch rfm;
static uch locbuf[BUFSALLOC]; /* Space for 2 buffers of BUFS512 */
static unsigned loccnt = 0;
static uch *locptr;
static char got_eol = 0;
struct bufdsc
{
struct bufdsc *next;
uch *buf;
unsigned bufcnt;
};
static struct bufdsc b1, b2, *curbuf; /* buffer ring for asynchronous I/O */
static int _flush_blocks(__GPRO__ uch *rawbuf, unsigned size, int final_flag);
static int _flush_stream(__GPRO__ uch *rawbuf, unsigned size, int final_flag);
static int _flush_varlen(__GPRO__ uch *rawbuf, unsigned size, int final_flag);
static int _flush_qio(__GPRO__ uch *rawbuf, unsigned size, int final_flag);
static int _close_rms(__GPRO);
static int _close_qio(__GPRO);
#ifdef ASYNCH_QIO
static int WriteQIO(__GPRO__ uch *buf, unsigned len);
#endif
static int WriteBuffer(__GPRO__ uch *buf, unsigned len);
static int WriteRecord(__GPRO__ uch *rec, unsigned len);
static int (*_flush_routine)(__GPRO__ uch *rawbuf, unsigned size,
int final_flag);
static int (*_close_routine)(__GPRO);
#ifdef SYMLINKS
static int _read_link_rms(__GPRO__ int byte_count, char *link_text_buf);
#endif /* SYMLINKS */
static void init_buf_ring(void);
static void set_default_datetime_XABs(__GPRO);
static int create_default_output(__GPRO);
static int create_rms_output(__GPRO);
static int create_qio_output(__GPRO);
static int replace(__GPRO);
static int replace_rms_newversion(__GPRO);
static int replace_rms_overwrite(__GPRO);
static int find_vms_attrs(__GPRO__ int set_date_time);
static void free_up(void);
#ifdef CHECK_VERSIONS
static int get_vms_version(char *verbuf, int len);
#endif /* CHECK_VERSIONS */
static unsigned find_eol(ZCONST uch *p, unsigned n, unsigned *l);
#ifdef SET_DIR_ATTRIB
static char *vms_path_fixdown(ZCONST char *dir_spec, char *dir_file);
#endif
#ifdef TIMESTAMP
static time_t mkgmtime(struct tm *tm);
static void uxtime2vmstime(time_t utimeval, long int binval[2]);
#endif /* TIMESTAMP */
static int vms_msg_fetch(int status);
static void vms_msg(__GPRO__ ZCONST char *string, int status);
/*
2005-02-14 SMS.
Added some ODS5 support:
Use longer name structures in NAML, where available.
Locate special characters mindful of "^" escapes.
*/
/* Hex digit table. */
char hex_digit[16] = {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
};
unzip-6.0/vms/vms.c view on Meta::CPAN
first_xab = x;
}
/* Free FAB storage, if not the static one. */
if (outfab != NULL && outfab != &fileblk)
free(outfab);
}
#ifdef CHECK_VERSIONS
static int get_vms_version(verbuf, len)
char *verbuf;
int len;
{
int i = SYI$_VERSION;
int verlen = 0;
struct dsc$descriptor version;
char *m;
version.dsc$a_pointer = verbuf;
version.dsc$w_length = len - 1;
version.dsc$b_dtype = DSC$K_DTYPE_B;
version.dsc$b_class = DSC$K_CLASS_S;
if (ERR(lib$getsyi(&i, 0, &version, &verlen, 0, 0)) || verlen == 0)
return 0;
/* Cut out trailing spaces "V5.4-3 " -> "V5.4-3" */
for (m = verbuf + verlen, i = verlen - 1; i > 0 && verbuf[i] == ' '; --i)
--m;
*m = '\0';
/* Cut out release number "V5.4-3" -> "V5.4" */
if ((m = strrchr(verbuf, '-')) != NULL)
*m = '\0';
return strlen(verbuf) + 1; /* Transmit ending '\0' too */
}
#endif /* CHECK_VERSIONS */
/* flush contents of output buffer */
int flush(__G__ rawbuf, size, unshrink) /* return PK-type error code */
__GDEF
uch *rawbuf;
ulg size;
int unshrink;
{
G.crc32val = crc32(G.crc32val, rawbuf, (extent)size);
if (uO.tflag)
return PK_COOL; /* Do not output. Update CRC only */
else
return (*_flush_routine)(__G__ rawbuf, size, 0);
}
static int _flush_blocks(__G__ rawbuf, size, final_flag)
/* Asynchronous version */
__GDEF
uch *rawbuf;
unsigned size;
int final_flag; /* 1 if this is the final flushout */
{
int status;
unsigned off = 0;
while (size > 0)
{
if (curbuf->bufcnt < BUFS512)
{
unsigned ncpy;
ncpy = size > (BUFS512 - curbuf->bufcnt) ?
(BUFS512 - curbuf->bufcnt) : size;
memcpy(curbuf->buf + curbuf->bufcnt, rawbuf + off, ncpy);
size -= ncpy;
curbuf->bufcnt += ncpy;
off += ncpy;
}
if (curbuf->bufcnt == BUFS512)
{
status = WriteBuffer(__G__ curbuf->buf, curbuf->bufcnt);
if (status)
return status;
curbuf = curbuf->next;
curbuf->bufcnt = 0;
}
}
return (final_flag && (curbuf->bufcnt > 0)) ?
WriteBuffer(__G__ curbuf->buf, curbuf->bufcnt) :
PK_COOL;
}
#ifdef ASYNCH_QIO
static int WriteQIO(__G__ buf, len)
__GDEF
uch *buf;
unsigned len;
{
int status;
if (pka_io_pending) {
status = sys$synch(0, &pka_io_iosb);
if (!ERR(status))
status = pka_io_iosb.status;
if (ERR(status))
{
vms_msg(__G__ "[ WriteQIO: sys$synch found I/O failure ]\n",
status);
return PK_DISK;
}
pka_io_pending = FALSE;
}
/*
* Put content of buffer as a single VB
*/
status = sys$qio(0, pka_devchn, IO$_WRITEVBLK,
&pka_io_iosb, 0, 0,
buf, len, pka_vbn,
0, 0, 0);
if (ERR(status))
{
vms_msg(__G__ "[ WriteQIO: sys$qio failed ]\n", status);
return PK_DISK;
}
pka_io_pending = TRUE;
pka_vbn += (len>>9);
return PK_COOL;
}
/*
2004-10-01 SMS. Changed to clear the extra byte written out by qio()
and sys$write() when an odd byte count is incremented to the next
even value, either explicitly (qio), or implicitly (sys$write), on
the theory that a reliable NUL beats left-over garbage. Alpha and
VAX object files seem frequently to have even more than one byte of
extra junk past EOF, so this may not help them.
*/
static int _flush_qio(__G__ rawbuf, size, final_flag)
/* Asynchronous version */
__GDEF
uch *rawbuf;
unsigned size;
int final_flag; /* 1 if this is the final flushout */
{
int status;
unsigned off = 0;
while (size > 0)
{
if (curbuf->bufcnt < BUFS512)
{
unsigned ncpy;
ncpy = size > (BUFS512 - curbuf->bufcnt) ?
(BUFS512 - curbuf->bufcnt) : size;
memcpy(curbuf->buf + curbuf->bufcnt, rawbuf + off, ncpy);
size -= ncpy;
curbuf->bufcnt += ncpy;
off += ncpy;
}
if (curbuf->bufcnt == BUFS512)
{
status = WriteQIO(__G__ curbuf->buf, curbuf->bufcnt);
if (status)
return status;
curbuf = curbuf->next;
curbuf->bufcnt = 0;
}
}
if (final_flag && (curbuf->bufcnt > 0))
{
unsigned bufcnt_even;
/* Round up to an even byte count. */
bufcnt_even = (curbuf->bufcnt+1) & (~1);
/* If there is one, clear the extra byte. */
if (bufcnt_even > curbuf->bufcnt)
curbuf->buf[curbuf->bufcnt] = '\0';
return WriteQIO(curbuf->buf, bufcnt_even);
}
else
{
return PK_COOL;
}
}
#else /* !ASYNCH_QIO */
static int _flush_qio(__G__ rawbuf, size, final_flag)
__GDEF
uch *rawbuf;
unsigned size;
int final_flag; /* 1 if this is the final flushout */
{
int status;
uch *out_ptr=rawbuf;
( run in 1.379 second using v1.01-cache-2.11-cpan-5735350b133 )