📄 vmszip.c
字号:
/* Copyright (c) 1990-2005 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2004-May-22 or later (the contents of which are also included in zip.h) for terms of use. If, for some reason, both of these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html*//* 2004-09-25 SMS. Added case-insensitive file name comparisons, with the option of preserving case in file names. Defining VMS_PRESERVE_CASE will cause incompatibility with Zip 2.3 and earlier.*//* #define VMS_PRESERVE_CASE */ /* Not for general use. */#include "zip.h"#include <ctype.h>#include <time.h>#include <unixlib.h>/* Judge availability of str[n]casecmp() in C RTL. (Note: This must follow a "#include <decc$types.h>" in something to ensure that __CRTL_VER is as defined as it will ever be. DEC C on VAX may not define it itself.)*/#ifdef __CRTL_VER#if __CRTL_VER >= 70000000#define HAVE_STRCASECMP#endif /* __CRTL_VER >= 70000000 */#endif /* def __CRTL_VER */#ifdef HAVE_STRCASECMP#include <strings.h> /* str[n]casecmp() */#endif /* def HAVE_STRCASECMP */#include <descrip.h>#include <rms.h>#include <ssdef.h>#include <starlet.h>#define PATH_START '['#define PATH_END ']'#define PATH_START2 '<'#define PATH_END2 '>'#include "vms/vmsmunch.h"/* Extra malloc() space in names for cutpath() */#define PAD 5 /* may have to change .FOO] to ]FOO.DIR;1 */#ifndef UTIL /* the companion #endif is a bit of ways down ... *//* The C RTL from OpenVMS 7.0 and newer supplies POSIX compatible versions of * opendir() et al. Thus, we have to use other names in our private code for * directory scanning to prevent symbol name conflicts at link time. * For now, we do not use the library supplied "dirent.h" functions, since * our private implementation provides some functionality which may not be * present in the library versions. For example: * ==> zopendir("DISK:[DIR.SUB1]SUB2.DIR") scans "DISK:[DIR.SUB1.SUB2]". */typedef struct zdirent { int d_wild; /* flag for wildcard vs. non-wild */ struct FAB fab; struct NAM nam; char d_qualwildname[NAM$C_MAXRSS + 1]; char d_name[NAM$C_MAXRSS + 1];} zDIR;extern char *label;local ulg label_time = 0;local ulg label_mode = 0;local time_t label_utim = 0;/* Local functions */local void vms_wild OF((char *, zDIR *));local zDIR *zopendir OF((ZCONST char *));local char *readd OF((zDIR *));local char *strlower OF((char *));local char *strupper OF((char *));/* 2004-09-25 SMS. str[n]casecmp() replacement for old C RTL. Assumes a prehistorically incompetent toupper().*/#ifndef HAVE_STRCASECMPint strncasecmp( s1, s2, n)char *s1;char *s2;size_t n;{ /* Initialization prepares for n == 0. */ char c1 = '\0'; char c2 = '\0'; while (n-- > 0) { /* Set c1 and c2. Convert lower-case characters to upper-case. */ if (islower( c1 = *s1)) c1 = toupper( c1); if (islower( c2 = *s2)) c2 = toupper( c2); /* Quit at inequality or NUL. */ if ((c1 != c2) || (c1 == '\0')) break; s1++; s2++; }return ((unsigned int)c1 - (unsigned int)c2);}#ifndef UINT_MAX#define UINT_MAX 4294967295U#endif#define strcasecmp( s1, s2) strncasecmp( s1, s2, UINT_MAX)#endif /* ndef HAVE_STRCASECMP *//* 2004-09-27 SMS. eat_carets(). Delete ODS5 extended file name escape characters ("^") in the original buffer. Note that the current scheme handles only simple EFN cases, but it could be made more complicated.*/local void eat_carets( str)char *str; /* Source pointer. */{ char *strd; /* Destination pointer. */ /* Skip ahead to the first "^", if any. */ while ((*str != '\0') && (*str != '^')) str++; /* If no caret was found, quit early. */ if (*str != '\0') { /* Shift characters leftward as carets are found. */ strd = str; while (*str != '\0') { if (*str == '^') { /* Found a caret. Skip it, and take the next character. */ *strd = *(++str); } else { /* Found a non-caret. Take it. */ *strd = *str; } /* Advance destination and source pointers. */ strd++; str++; } /* Terminate the destination string. */ *strd = '\0'; }}/*--------------------------------------------------------------------------- _vms_findfirst() and _vms_findnext(), based on public-domain DECUS C fwild() and fnext() routines (originally written by Martin Minow, poss- ibly modified by Jerry Leichter for bintnxvms.c), were written by Greg Roelofs and are still in the public domain. Routines approximate the behavior of MS-DOS (MSC and Turbo C) findfirst and findnext functions. ---------------------------------------------------------------------------*/static char wild_version_part[10]="\0";local void vms_wild(p, d)char *p;zDIR *d;{ /* * Do wildcard setup */ /* set up the FAB and NAM blocks. */ d->fab = cc$rms_fab; /* initialize fab */ d->nam = cc$rms_nam; /* initialize nam */ d->fab.fab$l_nam = &d->nam; /* fab -> nam */ d->fab.fab$l_fna = p; /* argument wild name */ d->fab.fab$b_fns = strlen(p); /* length */ d->fab.fab$l_dna = "sys$disk:[]"; /* Default fspec */ d->fab.fab$b_dns = sizeof("sys$disk:[]")-1; d->nam.nam$l_esa = d->d_qualwildname; /* qualified wild name */ d->nam.nam$b_ess = NAM$C_MAXRSS; /* max length */ d->nam.nam$l_rsa = d->d_name; /* matching file name */ d->nam.nam$b_rss = NAM$C_MAXRSS; /* max length */ /* parse the file name */ if (sys$parse(&d->fab) != RMS$_NORMAL) return; /* Does this replace d->fab.fab$l_fna with a new string in its own space? I sure hope so, since p is free'ed before this routine returns. */ /* have qualified wild name (i.e., disk:[dir.subdir]*.*); null-terminate * and set wild-flag */ d->d_qualwildname[d->nam.nam$b_esl] = '\0'; d->d_wild = (d->nam.nam$l_fnb & NAM$M_WILDCARD)? 1 : 0; /* not used... */#ifdef DEBUG fprintf(mesg, " incoming wildname: %s\n", p); fprintf(mesg, " qualified wildname: %s\n", d->d_qualwildname);#endif /* DEBUG */}local zDIR *zopendir(n)ZCONST char *n; /* directory to open *//* Start searching for files in the VMS directory n */{ char *c; /* scans VMS path */ zDIR *d; /* malloc'd return value */ int m; /* length of name */ char *p; /* malloc'd temporary string */ if ((d = (zDIR *)malloc(sizeof(zDIR))) == NULL || (p = malloc((m = strlen(n)) + 4)) == NULL) { if (d != NULL) free((zvoid *)d); return NULL; } /* Directory may be in form "[DIR.SUB1.SUB2]" or "[DIR.SUB1]SUB2.DIR;1". If latter, convert to former. */ if (m > 0 && *(c = strcpy(p,n)+m-1) != ']') { while (--c > p && *c != ';') ; if ((c- p < 5) || strncasecmp( (c- 4), ".DIR", 4)) { free((zvoid *)d); free((zvoid *)p); return NULL; } c -= 3; *c-- = '\0'; /* terminate at "DIR;#" */ *c = ']'; /* "." --> "]" */ while (c > p && *--c != ']') ; *c = '.'; /* "]" --> "." */ } strcat(p, "*.*"); strcat(p, wild_version_part); vms_wild(p, d); /* set up wildcard */ free((zvoid *)p); return d;}local char *readd(d)zDIR *d; /* directory stream to read from *//* Return a pointer to the next name in the directory stream d, or NULL if no more entries or an error occurs. */{ int r; /* return code */ do { d->fab.fab$w_ifi = 0; /* internal file index: what does this do? */ /* get next match to possible wildcard */ if ((r = sys$search(&d->fab)) == RMS$_NORMAL) { d->d_name[d->nam.nam$b_rsl] = '\0'; /* null terminate */ return (char *)d->d_name; /* OK */ } } while (r == RMS$_PRV); return NULL;}int wild(p)char *p; /* path/pattern to match *//* Expand the pattern based on the contents of the file system. Return an error code in the ZE_ class. */{ zDIR *d; /* stream for reading directory */ char *e; /* name found in directory */ int f; /* true if there was a match */ /* special handling of stdin request */ if (strcmp(p, "-") == 0) /* if compressing stdin */ return newname(p, 0, 0); /* Search given pattern for matching names */ if ((d = (zDIR *)malloc(sizeof(zDIR))) == NULL) return ZE_MEM; vms_wild(p, d); /* pattern may be more than just directory name */ /* * Save version specified by user to use in recursive drops into * subdirectories. */ strncpy(wild_version_part,d->nam.nam$l_ver,d->nam.nam$b_ver); wild_version_part[d->nam.nam$b_ver] = '\0'; f = 0; while ((e = readd(d)) != NULL) /* "dosmatch" is already built in */ if (procname(e, 0) == ZE_OK) f = 1; free(d); /* Done */ return f ? ZE_OK : ZE_MISS;}int procname(n, caseflag)char *n; /* name to process */int caseflag; /* true to force case-sensitive match *//* Process a name or sh expression to operate on (or exclude). Return an error code in the ZE_ class. */{ zDIR *d; /* directory stream from zopendir() */ char *e; /* pointer to name from readd() */ int m; /* matched flag */ char *p; /* path for recursion */ struct stat s; /* result of stat() */ struct zlist far *z; /* steps through zfiles list */ if (strcmp(n, "-") == 0) /* if compressing stdin */ return newname(n, 0, caseflag); else if (LSSTAT(n, &s)#if defined(__TURBOC__) || defined(VMS) || defined(__WATCOMC__) /* For these 3 compilers, stat() succeeds on wild card names! */ || isshexp(n)#endif ) { /* Not a file or directory--search for shell expression in zip file */ if (caseflag) { p = malloc(strlen(n) + 1); if (p != NULL) strcpy(p, n); } else p = ex2in(n, 0, (int *)NULL); /* shouldn't affect matching chars */ m = 1; for (z = zfiles; z != NULL; z = z->nxt) { if (MATCH(p, z->iname, caseflag)) { z->mark = pcount ? filter(z->zname, caseflag) : 1; if (verbose) fprintf(mesg, "zip diagnostic: %scluding %s\n",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -