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 )