Archive-Unzip-Burst

 view release on metacpan or  search on metacpan

unzip-6.0/vms/vms.c  view on Meta::CPAN

#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'
};


/* Character property table for converting Zip file names to
   (simpler) ODS2 or (escaped) ODS5 extended file names.

   ODS2 valid characters: 0-9 A-Z a-z $ - _

   ODS5 Invalid characters:
      C0 control codes (0x00 to 0x1F inclusive)
      Asterisk (*)
      Question mark (?)

   ODS5 Invalid characters only in VMS V7.2 (which no one runs, right?):
      Double quotation marks (")
      Backslash (\)
      Colon (:)
      Left angle bracket (<)
      Right angle bracket (>)
      Slash (/)
      Vertical bar (|)

   Characters escaped by "^":
      SP  !  "  #  %  &  '  (  )  +  ,  .  :  ;  =
       @  [  \  ]  ^  `  {  |  }  ~

   Either "^_" or "^ " is accepted as a space.  Period (.) is a special
   case.  Note that un-escaped < and > can also confuse a directory
   spec.

   Characters put out as ^xx:
      7F (DEL)
      80-9F (C1 control characters)
      A0 (nonbreaking space)
      FF (Latin small letter y diaeresis)

   Other cases:

unzip-6.0/vms/vms.c  view on Meta::CPAN

        {
            /* File exists.
             * Consider command-line options, or ask the user what to do.
             */
            ierr = replace(__G);
            switch (ierr & REPL_TASKMASK)
            {
                case REPL_NO_EXTRACT:   /* No extract. */
                    free_up();
                    return ((ierr & REPL_ERRLV_WARN)
                            ? OPENOUT_SKIPWARN : OPENOUT_SKIPOK);
                case REPL_NEW_VERSION:  /* Create a new version. */
                    ierr = replace_rms_newversion(__G);
                    break;
                case REPL_OVERWRITE:    /* Overwrite the existing file. */
                    ierr = replace_rms_overwrite(__G);
                    break;
            }
        }

        if (ERR(ierr))
        {
            char buf[NAM_MAXRSS + 128]; /* Name length + message length. */

            sprintf(buf, "[ Cannot create ($create) output file %s ]\n",
              G.filename);
            vms_msg(__G__ buf, ierr);
            if (fileblk.fab$l_stv != 0)
            {
                vms_msg(__G__ "", fileblk.fab$l_stv);
            }
            free_up();
            return OPENOUT_FAILED;
        }

        if (!text_output)
        {
            rab.rab$l_rop |= (RAB$M_BIO | RAB$M_ASY);
        }
        rab.rab$b_rac = RAB$C_SEQ;

        if ((ierr = sys$connect(&rab)) != RMS$_NORMAL)
        {
#ifdef DEBUG
            vms_msg(__G__ "create_default_output: sys$connect failed.\n", ierr);
            if (fileblk.fab$l_stv != 0)
            {
                vms_msg(__G__ "", fileblk.fab$l_stv);
            }
#endif
            Info(slide, 1, ((char *)slide,
                 "Cannot create ($connect) output file:  %s\n",
                 FnFilter1(G.filename)));
            free_up();
            return OPENOUT_FAILED;
        }
    }                   /* end if (!uO.cflag) */

    init_buf_ring();

    _flush_routine = text_output ? got_eol=0,_flush_stream : _flush_blocks;
    _close_routine = _close_rms;
    return OPENOUT_OK;
}



/* The following return codes are supported:
 *      OPENOUT_OK            a file has been opened normally
 *      OPENOUT_FAILED        the file open process failed
 *      OPENOUT_SKIPOK        file open skipped at user request, err level OK
 *      OPENOUT_SKIPWARN      file open skipped at user request, err level WARN
 */
static int create_rms_output(__GPRO)
{
    int ierr;
    int text_output;

    /* extract the file in text (variable-length) format, when
     * piping to SYS$OUTPUT, unless "binary" piping was requested
     * by the user (through the -b option); the "-a" option is
     * ignored when extracting zip entries with VMS attributes saved
     */
    text_output = uO.cflag &&
                  (!uO.bflag || (!(uO.bflag - 1) && G.pInfo->textfile));

    rfm = outfab->fab$b_rfm;    /* Use record format from VMS extra field */

    if (uO.cflag)               /* SYS$OUTPUT */
    {
        if (text_output && !PRINTABLE_FORMAT(rfm))
        {
            Info(slide, 1, ((char *)slide,
               "[ File %s has illegal record format to put to screen ]\n",
               FnFilter1(G.filename)));
            free_up();
            return OPENOUT_FAILED;
        }
    }
    else                        /* File output */
    {
        rab = cc$rms_rab;               /* Initialize RAB. */

        /* The output FAB has already been initialized with the values
         * found in the Zip file's "VMS attributes" extra field.
         */

#ifdef NAML$C_MAXRSS

        nam = CC_RMS_NAM;               /* Initialize NAML. */
        outfab->FAB_NAM = &nam;         /* Point FAB to NAML. */

        outfab->fab$l_dna = (char *) -1;    /* Using NAML for default name. */
        outfab->fab$l_fna = (char *) -1;    /* Using NAML for file name. */

#endif /* NAML$C_MAXRSS */

        FAB_OR_NAML(*outfab, nam).FAB_OR_NAML_FNA = G.filename;
        FAB_OR_NAML(*outfab, nam).FAB_OR_NAML_FNS = strlen(G.filename);

        /* Prepare date-time XABs, unless user requests not to. */

unzip-6.0/vms/vms.c  view on Meta::CPAN

                vms_msg(__G__ "", outfab->fab$l_stv);
            }
            free_up();
            return OPENOUT_FAILED;
        }

        if (outfab->fab$b_org & (FAB$C_REL | FAB$C_IDX)) {
            /* relative and indexed files require explicit allocation */
            ierr = sys$extend(outfab);
            if (ERR(ierr))
            {
                char buf[NAM_MAXRSS + 128];    /* Name length + msg length. */

                sprintf(buf, "[ Cannot allocate space for %s ]\n", G.filename);
                vms_msg(__G__ buf, ierr);
                if (outfab->fab$l_stv != 0)
                {
                    vms_msg(__G__ "", outfab->fab$l_stv);
                }
                free_up();
                return OPENOUT_FAILED;
            }
        }

        outrab = &rab;
        rab.rab$l_fab = outfab;
        {
            rab.rab$l_rop |= (RAB$M_BIO | RAB$M_ASY);
        }
        rab.rab$b_rac = RAB$C_SEQ;

        if ((ierr = sys$connect(outrab)) != RMS$_NORMAL)
        {
#ifdef DEBUG
            vms_msg(__G__ "create_rms_output: sys$connect failed.\n", ierr);
            if (outfab->fab$l_stv != 0)
            {
                vms_msg(__G__ "", outfab->fab$l_stv);
            }
#endif
            Info(slide, 1, ((char *)slide,
                 "Cannot create ($connect) output file:  %s\n",
                 FnFilter1(G.filename)));
            free_up();
            return OPENOUT_FAILED;
        }
    }                   /* end if (!uO.cflag) */

    init_buf_ring();

    if ( text_output )
        switch (rfm)
        {
            case FAB$C_VAR:
                _flush_routine = _flush_varlen;
                break;
            case FAB$C_STM:
            case FAB$C_STMCR:
            case FAB$C_STMLF:
                _flush_routine = _flush_stream;
                got_eol = 0;
                break;
            default:
                _flush_routine = _flush_blocks;
                break;
        }
    else
        _flush_routine = _flush_blocks;
    _close_routine = _close_rms;
    return OPENOUT_OK;
}



static  int pka_devchn;
static  int pka_io_pending;
static  unsigned pka_vbn;

/* IOSB for QIO[W] read and write operations. */
#if defined(__DECC) || defined(__DECCXX)
#pragma __member_alignment __save
#pragma __nomember_alignment
#endif /* __DECC || __DECCXX */
static struct
{
    unsigned short  status;
    unsigned int    count;      /* Unaligned ! */
    unsigned short  dummy;
} pka_io_iosb;
#if defined(__DECC) || defined(__DECCXX)
#pragma __member_alignment __restore
#endif /* __DECC || __DECCXX */

/* IOSB for QIO[W] miscellaneous ACP operations. */
static struct
{
    unsigned short  status;
    unsigned short  dummy;
    unsigned int    count;
} pka_acp_iosb;

static struct fibdef    pka_fib;
static struct atrdef    pka_atr[VMS_MAX_ATRCNT];
static int              pka_idx;
static ulg              pka_uchar;
static struct fatdef    pka_rattr;

/* Directory attribute storage, descriptor (list). */
static struct atrdef pka_recattr[2] =
 { { sizeof(pka_rattr), ATR$C_RECATTR, GVTC &pka_rattr},        /* RECATTR. */
   { 0, 0, 0 }                                          /* List terminator. */
 };

static struct dsc$descriptor    pka_fibdsc =
{   sizeof(pka_fib), DSC$K_DTYPE_Z, DSC$K_CLASS_S, (void *) &pka_fib  };

static struct dsc$descriptor_s  pka_devdsc =
{   0, DSC$K_DTYPE_T, DSC$K_CLASS_S, &nam.NAM_DVI[1]  };

static struct dsc$descriptor_s  pka_fnam =
{   0, DSC$K_DTYPE_T, DSC$K_CLASS_S, NULL  };

unzip-6.0/vms/vms.c  view on Meta::CPAN

#ifdef NAML$C_MAXRSS
static char sys_nam[NAML$C_MAXRSS];     /* Probably need less here. */
#endif /* NAML$C_MAXRSS */

#define PK_PRINTABLE_RECTYP(x)   ( (x) == FAT$C_VARIABLE \
                                || (x) == FAT$C_STREAMLF \
                                || (x) == FAT$C_STREAMCR \
                                || (x) == FAT$C_STREAM   )


/* The following return codes are supported:
 *      OPENOUT_OK            a file has been opened normally
 *      OPENOUT_FAILED        the file open process failed
 *      OPENOUT_SKIPOK        file open skipped at user request, err level OK
 *      OPENOUT_SKIPWARN      file open skipped at user request, err level WARN
 */
static int create_qio_output(__GPRO)
{
    int status;
    int i;
    int text_output;

    /* extract the file in text (variable-length) format, when
     * piping to SYS$OUTPUT, unless "binary" piping was requested
     * by the user (through the -b option); the "-a" option is
     * ignored when extracting zip entries with VMS attributes saved
     */
    text_output = uO.cflag &&
                  (!uO.bflag || (!(uO.bflag - 1) && G.pInfo->textfile));

    if ( uO.cflag )
    {
        int rtype;

        if (text_output)
        {
            rtype = pka_rattr.fat$v_rtype;
            if (!PK_PRINTABLE_RECTYP(rtype))
            {
                Info(slide, 1, ((char *)slide,
                   "[ File %s has illegal record format to put to screen ]\n",
                   FnFilter1(G.filename)));
                return OPENOUT_FAILED;
            }
        }
        else
            /* force "block I/O" for binary piping mode */
            rtype = FAT$C_UNDEFINED;

        init_buf_ring();

        switch (rtype)
        {
            case FAT$C_VARIABLE:
                _flush_routine = _flush_varlen;
                break;
            case FAT$C_STREAM:
            case FAT$C_STREAMCR:
            case FAT$C_STREAMLF:
                _flush_routine = _flush_stream;
                got_eol = 0;
                break;
            default:
                _flush_routine = _flush_blocks;
                break;
        }
        _close_routine = _close_rms;
    }
    else                        /* !(uO.cflag) : redirect output */
    {
        fileblk = cc$rms_fab;           /* Initialize FAB. */
        nam = CC_RMS_NAM;               /* Initialize NAM[L]. */
        fileblk.FAB_NAM = &nam;         /* Point FAB to NAM[L]. */

#ifdef NAML$C_MAXRSS

        fileblk.fab$l_dna = (char *) -1;    /* Using NAML for default name. */
        fileblk.fab$l_fna = (char *) -1;    /* Using NAML for file name. */

        /* Special ODS5-QIO-compatible name storage. */
        nam.naml$l_filesys_name = sys_nam;
        nam.naml$l_filesys_name_alloc = sizeof(sys_nam);

#endif /* NAML$C_MAXRSS */

        /* VMS-format file name, derived from archive. */
        FAB_OR_NAML(fileblk, nam).FAB_OR_NAML_FNA = G.filename;
        FAB_OR_NAML(fileblk, nam).FAB_OR_NAML_FNS = strlen(G.filename);

        /* Expanded and resultant name storage. */
        nam.NAM_ESA = exp_nam;
        nam.NAM_ESS = sizeof(exp_nam);
        nam.NAM_RSA = res_nam;
        nam.NAM_RSS = sizeof(res_nam);

        if ( ERR(status = sys$parse(&fileblk)) )
        {
            vms_msg(__G__ "create_qio_output: sys$parse failed.\n", status);
            return OPENOUT_FAILED;
        }

        pka_devdsc.dsc$w_length = (unsigned short)nam.NAM_DVI[0];

        if ( ERR(status = sys$assign(&pka_devdsc, &pka_devchn, 0, 0)) )
        {
            vms_msg(__G__ "create_qio_output: sys$assign failed.\n", status);
            return OPENOUT_FAILED;
        }

#ifdef NAML$C_MAXRSS

        /* Enable fancy name characters.  Note that "fancy" here does
           not include Unicode, for which there's no support elsewhere.
        */
        pka_fib.fib$v_names_8bit = 1;
        pka_fib.fib$b_name_format_in = FIB$C_ISL1;

        /* ODS5 Extended names used as input to QIO have peculiar
           encoding (perhaps to minimize storage?), so the special
           filesys_name result (typically containing fewer carets) must
           be used here.

unzip-6.0/vms/vms.c  view on Meta::CPAN

            memcpy(locbuf, inptr, size);
            loccnt = size;
            size = 0;
        }

    }
    /*
     * Final flush rest of local buffer
     */
    if ( final_flag && loccnt > 0 )
    {
        char buf[80];

        Info(buf, 1, (buf,
             "[ Warning, incomplete record of length %u ]\n",
             (unsigned)*(ush*)locbuf));
        if ( WriteRecord(__G__ locbuf+2, loccnt-2) )
            return PK_DISK;
    }
    return PK_COOL;
}



/*
 *   Routine _flush_stream breaks decompressed stream into records
 *   depending on format of the stream (fab->rfm, G.pInfo->textmode, etc.)
 *   and puts out these records. It also handles CR LF sequences.
 *   Should be used when extracting *text* files.
 */

#define VT      0x0B
#define FF      0x0C

/* The file is from MSDOS/OS2/NT -> handle CRLF as record end, throw out ^Z */

/* GRR NOTES:  cannot depend on hostnum!  May have "flip'd" file or re-zipped
 * a Unix file, etc. */

#ifdef USE_ORIG_DOS
# define ORG_DOS \
          (G.pInfo->hostnum==FS_FAT_    \
        || G.pInfo->hostnum==FS_HPFS_   \
        || G.pInfo->hostnum==FS_NTFS_)
#else
# define ORG_DOS    1
#endif

/* Record delimiters */
#ifdef undef
#define RECORD_END(c, f)                                                \
(    ( ORG_DOS || G.pInfo->textmode ) && c==CTRLZ                       \
  || ( f == FAB$C_STMLF && c==LF )                                      \
  || ( f == FAB$C_STMCR || ORG_DOS || G.pInfo->textmode ) && c==CR      \
  || ( f == FAB$C_STM && (c==CR || c==LF || c==FF || c==VT) )           \
)
#else
#   define  RECORD_END(c, f)   ((c) == LF || (c) == (CR))
#endif

static unsigned find_eol(p, n, l)
/*
 *  Find first CR, LF, CR/LF or LF/CR in string 'p' of length 'n'.
 *  Return offset of the sequence found or 'n' if not found.
 *  If found, return in '*l' length of the sequence (1 or 2) or
 *  zero if sequence end not seen, i.e. CR or LF is last char
 *  in the buffer.
 */
    ZCONST uch *p;
    unsigned n;
    unsigned *l;
{
    unsigned off = n;
    ZCONST uch *q;

    *l = 0;

    for (q=p ; n > 0 ; --n, ++q)
        if ( RECORD_END(*q, rfm) )
        {
            off = q-p;
            break;
        }

    if ( n > 1 )
    {
        *l = 1;
        if ( ( q[0] == CR && q[1] == LF ) || ( q[0] == LF && q[1] == CR ) )
            *l = 2;
    }

    return off;
}

/* Record delimiters that must be put out */
#define PRINT_SPEC(c)   ( (c)==FF || (c)==VT )



static int _flush_stream(__G__ rawbuf, size, final_flag)
    __GDEF
    uch *rawbuf;
    unsigned size;
    int final_flag; /* 1 if this is the final flushout */
{
    int rest;
    unsigned end = 0, start = 0;

    if (size == 0 && loccnt == 0)
        return PK_COOL;         /* Nothing to do ... */

    if ( final_flag )
    {
        unsigned recsize;

        /*
         * This is flush only call. size must be zero now.
         * Just eject everything we have in locbuf.
         */
        recsize = loccnt - (got_eol ? 1 : 0);
        /*
         *  If the last char of file was ^Z ( end-of-file in MSDOS ),
         *  we will see it now.
         */
        if ( recsize==1 && locbuf[0] == CTRLZ )
            return PK_COOL;

        return WriteRecord(__G__ locbuf, recsize);
    }


    if ( loccnt > 0 )
    {
        /* Find end of record partially saved in locbuf */

        unsigned recsize;
        int complete=0;

        if ( got_eol )
        {
            recsize = loccnt - 1;
            complete = 1;

            if ( (got_eol == CR && rawbuf[0] == LF) ||
                 (got_eol == LF && rawbuf[0] == CR) )
                end = 1;

            got_eol = 0;
        }
        else
        {
            unsigned eol_len;
            unsigned eol_off;

            eol_off = find_eol(rawbuf, size, &eol_len);

            if ( loccnt+eol_off > BUFSMAXREC )
            {
                /*
                 *  No room in locbuf. Dump it and clear
                 */
                char buf[80];           /* CANNOT use slide for Info() */

                recsize = loccnt;
                start = 0;
                Info(buf, 1, (buf,
                     "[ Warning: Record too long (%u) ]\n", loccnt+eol_off));
                complete = 1;
                end = 0;
            }
            else
            {
                if ( eol_off >= size )
                {
                    end = size;
                    complete = 0;
                }
                else if ( eol_len == 0 )
                {
                    got_eol = rawbuf[eol_off];
                    end = size;
                    complete = 0;
                }
                else
                {
                    memcpy(locptr, rawbuf, eol_off);
                    recsize = loccnt + eol_off;
                    locptr += eol_off;
                    loccnt += eol_off;
                    end = eol_off + eol_len;
                    complete = 1;
                }
            }
        }

        if ( complete )
        {
            if (WriteRecord(__G__ locbuf, recsize))
                return PK_DISK;
            loccnt = 0;
            locptr = locbuf;
        }
    }                           /* end if ( loccnt ) */

    for (start = end; start < size && end < size; )
    {
        unsigned eol_off, eol_len;

        got_eol = 0;

#ifdef undef
        if (uO.cflag)
            /* skip CR's at the beginning of record */
            while (start < size && rawbuf[start] == CR)
                ++start;
#endif

        if ( start >= size )
            continue;

        /* Find record end */
        end = start+(eol_off = find_eol(rawbuf+start, size-start, &eol_len));

        if ( end >= size )
            continue;

        if ( eol_len > 0 )
        {
            if ( WriteRecord(__G__ rawbuf+start, end-start) )
                return PK_DISK;
            start = end + eol_len;
        }
        else
        {
            got_eol = rawbuf[end];
            end = size;
            continue;
        }
    }

    rest = size - start;

    if (rest > 0)
    {
        if ( rest > BUFSMAXREC )
        {
            unsigned recsize;
            char buf[80];               /* CANNOT use slide for Info() */

            recsize = rest - (got_eol ? 1 : 0 );
            Info(buf, 1, (buf,
                 "[ Warning: Record too long (%u) ]\n", recsize));
            got_eol = 0;
            return WriteRecord(__G__ rawbuf+start, recsize);
        }
        else
        {
            memcpy(locptr, rawbuf + start, rest);
            locptr += rest;
            loccnt += rest;
        }
    }
    return PK_COOL;
}



static int WriteBuffer(__G__ buf, len)
    __GDEF
    uch *buf;
    unsigned len;
{
    int status;

    if (uO.cflag)
    {
        (void)(*G.message)((zvoid *)&G, buf, len, 0);
    }
    else
    {
        status = sys$wait(outrab);
        if (ERR(status))
        {
            vms_msg(__G__ "[ WriteBuffer: sys$wait failed ]\n", status);
            if (outrab->rab$l_stv != 0)
            {
                vms_msg(__G__ "", outrab->rab$l_stv);
            }
        }

        /* If odd byte count, then this must be the final record.
           Clear the extra byte past EOF to help keep the file clean.
        */
        if (len & 1)
            buf[len] = '\0';

        outrab->rab$w_rsz = len;
        outrab->rab$l_rbf = (char *) buf;

        if (ERR(status = sys$write(outrab)))
        {
            vms_msg(__G__ "[ WriteBuffer: sys$write failed ]\n", status);
            if (outrab->rab$l_stv != 0)
            {
                vms_msg(__G__ "", outrab->rab$l_stv);
            }
            return PK_DISK;
        }
    }
    return PK_COOL;
}




( run in 1.634 second using v1.01-cache-2.11-cpan-5b529ec07f3 )