/* Copyright (c) 1990-2002 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2000-Apr-09 or later (the contents of which are also included in zip.h) for terms of use. If, for some reason, all these files are missing, the Info-ZIP license also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html */ /* * routines only used by TANDEM ZIP */ #include "zip.h" #include "crypt.h" #include #include "$system.zsysdefs.zsysc" nolist #include nolist #include "tannsk.h" /******************************/ /* Function version_local() */ /******************************/ void version_local() { static ZCONST char CompiledWith[] = "Compiled with %s%s for %s%s%s%s.\n\n"; #if 0 char buf[40]; #endif printf(CompiledWith, #ifdef __GNUC__ "gcc ", __VERSION__, #else "C ", "T9255D44 - (16OCT98)", #endif "NonStop ", "(Tandem/NSK)", #ifdef __DATE__ " on ", __DATE__ #else "", "" #endif ); } /* end function version_local() */ /************************/ /* Function nskopen() */ /************************/ #ifdef fopen # undef fopen #endif FILE *nskopen(fname, opt) const char *fname; const char *opt; { int fdesc; short fnum, err, len; int priext, secext; short maxext, filecode, blocksize; #define alist_items 1 #define vlist_bytes 2 short alist[alist_items]={42}; unsigned short vlist[alist_items]; short extra, *err_item=&extra; char nsk_work[FILENAME_MAX + 1], *nsk_fname=&nsk_work[0]; /* See if we want to create a new file */ if ((strcmp(opt,FOPW) == 0) || (strcmp(opt,FOPWT) == 0)) { blocksize = TANDEM_BLOCKSIZE; priext = 100; secext = 500; maxext = 978; filecode = NSK_ZIPFILECODE; if ((fdesc = creat(fname,,priext,secext)) != -1){ fnum = fdtogfn ((short)fdesc); err = (SETMODE (fnum, SET_FILE_BUFFERSIZE, blocksize) != CCE); err = (SETMODE (fnum, SET_FILE_BUFFERED, 0, 0) != CCE); err = (SETMODE (fnum, SET_FILE_BUFFERED, 0, 1) != CCE); err = (SETMODE (fnum, SET_FILE_MAXEXTENTS, maxext) != CCE); err = close(fdesc); vlist[0] = filecode; /* Note that FILE_ALTERLIST_ expects uppercase names */ /* Need to call strlen and upshift */ len = strlen(fname); err = STRING_UPSHIFT_((char *)fname, len, nsk_fname, len); err = FILE_ALTERLIST_(nsk_fname, len, alist, alist_items, vlist, vlist_bytes, , err_item); }; }; return fopen(fname,opt); } #define fopen nskopen int Bflag = 0; /* Special formatting options for Tandem */ /* Bit 0 = Add delimiter (0 = Yes, 1 = No) */ /* Bit 1 = Delimiter Type (0 = CR/LF, 1 = LF) */ /* Bit 2 = Space Fill records (0 = No, 1 = Yes) */ /* Bit 3 = Trim trailing space(0 = No, 1 = Yes) */ /* Thus, default is to add CR/LF, no padding */ /* Bit 8 = Use 'safe' large read size (Expand) */ char nsk_delim[2] = {'\r', '\n'}; /* CR/LF */ int nsk_delim_len = 2; int nsk_space_fill = 0; /* 0 = No, 1 = Yes */ int nsk_trim_space = 0; /* 0 = No, 1 = Yes */ unsigned short nsk_large_read = MAX_LARGE_READ; /* Following holds details of file currently used by zopen & zread */ struct stat znsk_stat; nsk_stat_ov *znsk_ov = (nsk_stat_ov *)&znsk_stat.st_reserved[0]; nsk_file_attrs *znsk_attr = (nsk_file_attrs *) ( (char *)(&znsk_stat.st_reserved[0]) + offsetof (struct nsk_stat_overlay, nsk_ef_region) ); /* Following items used by zread to avoid overwriting window */ char zreadbuf[MAX_LARGE_READ]; /* Buffer as large as biggest read */ char *zreadptr = (char *) zreadbuf; /* pointer to start of buffer */ char *zread_ovptr = NULL; /* pointer to left overs */ long zread_ovlen = 0; /* size of remaining left overs */ int zopen (filename, opt) const char *filename; int opt; { /* Currently ignore opt. Choose method of I/O based on NSK file type */ short err, len, fnum, access, exclus, bufferlen, options; long recnum; char fname[FILENAME_MAX + 1]; short extension; char ext[EXTENSION_MAX + 1]; /* Remove any (pseudo) file extension */ extension = parsename (filename,fname,ext); len = strlen(fname); fnum = 0; access = NSK_RDONLY; exclus = NSK_SHARED; err = stat(fname, &znsk_stat); /* Setup global struct, used by zread */ if (znsk_attr->filetype == NSK_UNSTRUCTURED) if (znsk_attr->filecode == NSK_EDITFILECODE) { /* Edit File */ fnum = -1; /* Ask OPENEDIT_ to open the file for us */ err = OPENEDIT_ ((char *)fname, len, &fnum, access, exclus); if (!err) { recnum = -1; /* Position to first line */ err = POSITIONEDIT (fnum, recnum); } } else { /* Unstructured File */ options = NSK_UNSTRUCTUREDACCESS; err = FILE_OPEN_((char *)fname, len, &fnum, access, exclus, ,,options,,,); if (!err) /* Ask for large transfer mode */ err = (SETMODE (fnum, SET_LARGE_TRANSFERS, 1) != CCE); } else { /* Structured File */ bufferlen = 4096; /* request SBB */ err = FILE_OPEN_((char *)fname, len, &fnum, access, exclus, ,,,, bufferlen ,); if (err == 4) err = 0; /* Allow saving of files that have missing altkeys */ } return (err == 0 ? (int)fnum : -1); } unsigned zread (fnum, buf, len) int fnum; char *buf; unsigned len; { short err, trail; long total, movelen; unsigned short countread; unsigned readlen; /* typed to match incoming arg */ char *bufptr, *readptr; total = err = 0; bufptr = buf; /* We use a separate buffer to read in data as it can be larger than WSIZE, and hence would overwrite memory */ /* We always attempt to give the user the exact requested size Hence we make use of an overfow buffer for previously truncated data */ /* see if we have some left over characters from last time */ if (zread_ovlen) { movelen = _min(len,zread_ovlen); memcpy(bufptr, zread_ovptr, movelen); bufptr += movelen; total += movelen; zread_ovptr += movelen; zread_ovlen -= movelen; } while (!err && (total < len)) { readptr = zreadptr; if (znsk_attr->filetype == NSK_UNSTRUCTURED) if (znsk_attr->filecode == NSK_EDITFILECODE){ /* Edit File */ trail = 1; readlen = MAX_EDIT_READ; /* guarantee it fits in buffer */ /* get line and preserve any trailing space characters */ err = READEDIT (fnum,, zreadptr, (short) readlen, (short *) &countread,,, trail); /* if countread is ever negative then we will skip a line */ if (!err) { readptr = zreadptr + countread; /* Note it is possible for Edit files to hold trailing space */ if (nsk_trim_space) while (*(readptr-1) == ' ') { readptr--; countread--; } if (nsk_delim_len) { memcpy(readptr, nsk_delim, nsk_delim_len); readptr += nsk_delim_len; countread += nsk_delim_len; } } } else { /* Unstructured File */ /* Using large transfer mode so we have to use 2K multiples Use largest size possible and put remains in overflow */ readlen = nsk_large_read; /* use largest read, overflow into buffer*/ err = (READX(fnum, zreadptr, readlen, (short *)&countread) != CCE); if (err && (errno == EINVAL)) { /* Read too big so scale back to smaller value */ readlen = nsk_large_read = MAX_LARGE_READ_EXPAND; err = (READX(fnum, zreadptr, readlen, (short *)&countread) != CCE); } if (!err) readptr = zreadptr + countread; } else { /* Structured File */ readlen = znsk_attr->reclen; err = (READX(fnum, zreadptr, readlen, (short *)&countread)!= CCE); if (!err) { readptr = zreadptr + countread; if (nsk_space_fill) while (countread < readlen) { *readptr++ = ' '; countread++; } else if (nsk_trim_space) while (*(readptr-1) == ' ') { readptr--; countread--; } if (nsk_delim_len) { memcpy(readptr, nsk_delim, nsk_delim_len); readptr += nsk_delim_len; countread += nsk_delim_len; } } } if (!err) { movelen = _min((len-total), countread); memcpy(bufptr, zreadptr, movelen); bufptr += movelen; total += movelen; if (movelen < countread) { /* still stuff in Read buffer */ zread_ovptr = zreadptr + movelen; /* pointer to whats left */ zread_ovlen = countread - movelen; /* how much is left */ } } } return ((unsigned)total); } int zclose (fnum) int fnum; { short err; if ((znsk_attr->filetype == NSK_UNSTRUCTURED) && (znsk_attr->filecode == NSK_EDITFILECODE)) err = CLOSEEDIT_(fnum); else err = FILE_CLOSE_(fnum); return (err != 0); } /* modified to work with get_option which returns a string with the number value without leading option */ void nskformatopt(p) char *p; { /* set up formatting options for ZIP */ Bflag = 0; /* default option */ Bflag = strtoul(p, NULL, 10); if (Bflag & NSK_SPACE_FILL) nsk_space_fill = 1; else nsk_space_fill = 0; if (Bflag & NSK_TRIM_TRAILING_SPACE) nsk_trim_space = 1; else nsk_trim_space = 0; if (Bflag & NSK_NO_DELIMITER) nsk_delim_len = 0; else { if (Bflag & NSK_USE_FF_DELIMITER) { nsk_delim[0] = '\n'; nsk_delim_len = 1; } else { /* CR/LF */ nsk_delim[0] = '\r'; nsk_delim[1] = '\n'; nsk_delim_len = 2; } } if (Bflag & NSK_LARGE_READ_EXPAND) nsk_large_read = MAX_LARGE_READ_EXPAND; else nsk_large_read = MAX_LARGE_READ; } int deletedir(d) char *d; /* directory to delete */ /* Delete the directory *d if it is empty, do nothing otherwise. Return the result of rmdir(), delete(), or system(). For VMS, d must be in format [x.y]z.dir;1 (not [x.y.z]). */ { return rmdir(d); } local char *readd(d) DIR *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. */ { struct dirent *e; e = readdir(d); return e == NULL ? (char *) NULL : e->d_name; } 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. */ { char *a; /* path and name for recursion */ DIR *d; /* directory stream from opendir() */ 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 (stat(n, &s)) { /* Not a file or directory--search for shell expression in zip file */ 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->zname, caseflag)) { z->mark = pcount ? filter(z->zname, caseflag) : 1; if (verbose) fprintf(mesg, "zip diagnostic: %scluding %s\n", z->mark ? "in" : "ex", z->name); m = 0; } } free((zvoid *)p); return m ? ZE_MISS : ZE_OK; } /* Live name--use if file, recurse if directory */ if ((s.st_mode & S_IFDIR) == 0) { /* add or remove name of file */ if ((m = newname(n, 0, caseflag)) != ZE_OK) return m; } else { if ((p = malloc(strlen(n)+4)) == NULL) return ZE_MEM; strcpy(p, n); /* No concept of directories on Tandem - so do not store them ...*/ /* code removed from which attempted to save dir name if dirnames set */ /* Test for recurse being set removed, since Tandem has no dir concept*/ /* recurse into template */ if ((d = opendir(n)) != NULL) { while ((e = readd(d)) != NULL) { if ((m = procname(e, caseflag)) != ZE_OK) /* recurse on name */ { if (m == ZE_MISS) zipwarn("name not matched: ", e); else ziperr(m, e); } } closedir(d); } free((zvoid *)p); } /* (s.st_mode & S_IFDIR) == 0) */ return ZE_OK; } char *ex2in(x, isdir, pdosflag) char *x; /* external file name */ int isdir; /* input: x is a directory */ int *pdosflag; /* output: force MSDOS file attributes? */ /* Convert the external file name to a zip file name, returning the malloc'ed string or NULL if not enough memory. */ { char *n; /* internal file name (malloc'ed) */ char *t; /* shortened name */ int dosflag; char *p; /* pointer to temp area */ char fname[FILENAME_MAX + 1]= ""; /* file name */ char ext[EXTENSION_MAX + 1] = ""; /* extension name */ short extension; /* does the filename contain an extension */ dosflag = dosify; /* default for non-DOS non-OS/2 */ /* Find starting point in name before doing malloc */ if (*x == '=') t = x + 1; /* store DEFINE names without the '=' */ else t = x; /* Make changes, if any, to the copied name (leave original intact) */ if (!pathput) t = last(t, TANDEM_DELIMITER); /* Malloc space for internal name and copy it */ if ((n = malloc(strlen(t) + 4)) == NULL) /* + 4 for safety */ return NULL; extension = parsename(t,fname,ext); t = fname; *n= '\0'; while (*t != '\0') { /* File part could be sys,vol,subvol or file */ if (*t == TANDEM_NODE) { /* System Name */ strcat(n, INTERNAL_NODE_STR); t++; } else if (*t == TANDEM_DELIMITER) { /* Volume or Subvol */ strcat(n, INTERNAL_DELIMITER_STR); t++; }; p = strchr(t,TANDEM_DELIMITER); if (p == NULL) break; strncat(n,t,(p - t)); t = p; } strcat(n,t); /* mop up any left over characters */ if (extension) { strcat(n,DOS_EXTENSION_STR); strcat(n,ext); }; if (isdir == 42) return n; /* avoid warning on unused variable */ if (dosify) msname(n); /* Returned malloc'ed name */ if (pdosflag) *pdosflag = dosflag; return n; } void stamp(f, d) char *f; /* name of file to change */ ulg d; /* dos-style time to change it to */ /* Set last updated and accessed time of file f to the DOS time d. */ { ztimbuf u; /* argument for utime() */ /* Convert DOS time to time_t format in u.actime and u.modtime */ u.actime = u.modtime = dos2unixtime(d); utime(f, &u); } ulg filetime(f, a, n, t) char *f; /* name of file to get info on */ ulg *a; /* return value: file attributes */ long *n; /* return value: file size */ iztimes *t; /* return value: access and modification time */ { struct stat s; nsk_stat_ov *nsk_ov; if (strcmp(f, "-") == 0) { /* if compressing stdin */ if (n != NULL) { *n = -1L; } } if (stat(f, &s) != 0) return 0; if (a!= NULL) { *a = ((ulg)s.st_mode << 16) | !(s.st_mode & S_IWUSR); if ((s.st_mode & S_IFMT) == S_IFDIR) { *a |= MSDOS_DIR_ATTR; } } if (n!= NULL) *n = (s.st_mode & S_IFMT) == S_IFREG ? s.st_size : -1L; if (t != NULL) { t->atime = s.st_atime; t->mtime = s.st_mtime; nsk_ov = (nsk_stat_ov *)&s.st_reserved[0]; t->ctime = nsk_ov->ov.creation_time; } return unix2dostime(&s.st_mtime); } int set_extra_field(z, z_utim) struct zlist far *z; iztimes *z_utim; /* create extra field and change z->att if desired */ /* store full data in local header but just modification time stamp info in central header */ { struct stat s; nsk_stat_ov *nsk_ov = (nsk_stat_ov *)&s.st_reserved[0]; nsk_file_attrs *nsk_attr = (nsk_file_attrs *)&nsk_ov->ov.nsk_ef_region; char *ext, *cext; int lsize, csize; #ifdef USE_EF_UT_TIME char *UTptr, *Uxptr; #endif /* USE_EF_UT_TIME */ /* For the Tandem and UT local field including the UID/GID fields, we have to stat the file again. */ if (LSSTAT(z->name, &s)) return ZE_OPEN; z->ext = z->cext = 0; #define EB_TANDEM_SIZE 20 #define EF_TANDEM_SIZE (EB_HEADSIZE + EB_TANDEM_SIZE) /* allocate size of buffers to allow Tandem field */ lsize = EF_TANDEM_SIZE; csize = EF_TANDEM_SIZE; #ifdef USE_EF_UT_TIME #define EB_L_UT_SIZE (EB_HEADSIZE + EB_UT_LEN(3)) #define EB_C_UT_SIZE (EB_HEADSIZE + EB_UT_LEN(1)) #define EB_L_UX2_SIZE (EB_HEADSIZE + EB_UX2_MINLEN) #define EB_C_UX2_SIZE EB_HEADSIZE #define EF_L_UNIX_SIZE (EB_L_UT_SIZE + EB_L_UX2_SIZE) #define EF_C_UNIX_SIZE (EB_C_UT_SIZE + EB_C_UX2_SIZE) /* resize to allow for UT fields */ lsize += EF_L_UNIX_SIZE; csize += EF_C_UNIX_SIZE; #endif /* USE_EF_UT_TIME */ if ((z->extra = (char *)malloc(lsize)) == NULL) return ZE_MEM; ext = z->extra; if ((z->cextra = (char *)malloc(csize)) == NULL) return ZE_MEM; cext = z->cextra; /* Place Tandem field first so its on an even boundary */ *ext++ = *cext++ = 'T'; *ext++ = *cext++ = 'A'; *ext++ = *cext++ = (char)EB_TANDEM_SIZE; /*length of data part of e.f.*/ *ext++ = *cext++ = 0; /* Copy Tandem specific file information */ memcpy(ext, (char *)nsk_attr, EB_TANDEM_SIZE); ext += EB_TANDEM_SIZE; z->ext += EF_TANDEM_SIZE; /* Copy same data to central field */ memcpy(cext, (char *)nsk_attr, EB_TANDEM_SIZE); cext += EB_TANDEM_SIZE; z->cext += EF_TANDEM_SIZE; #ifdef USE_EF_UT_TIME UTptr = ext; *ext++ = 'U'; *ext++ = 'T'; *ext++ = (char)EB_UT_LEN(3); /* length of data part of local e.f. */ *ext++ = 0; *ext++ = EB_UT_FL_MTIME | EB_UT_FL_ATIME | EB_UT_FL_CTIME; *ext++ = (char)(s.st_mtime); *ext++ = (char)(s.st_mtime >> 8); *ext++ = (char)(s.st_mtime >> 16); *ext++ = (char)(s.st_mtime >> 24); *ext++ = (char)(s.st_atime); *ext++ = (char)(s.st_atime >> 8); *ext++ = (char)(s.st_atime >> 16); *ext++ = (char)(s.st_atime >> 24); *ext++ = (char)(nsk_ov->ov.creation_time); *ext++ = (char)(nsk_ov->ov.creation_time >> 8); *ext++ = (char)(nsk_ov->ov.creation_time >> 16); *ext++ = (char)(nsk_ov->ov.creation_time >> 24); Uxptr = ext; *ext++ = 'U'; *ext++ = 'x'; *ext++ = (char)EB_UX2_MINLEN; /* length of data part of local e.f. */ *ext++ = 0; *ext++ = (char)(s.st_uid); *ext++ = (char)(s.st_uid >> 8); *ext++ = (char)(s.st_gid); *ext++ = (char)(s.st_gid >> 8); z->ext += EF_L_UNIX_SIZE; memcpy(cext, UTptr, EB_C_UT_SIZE); cext[EB_LEN] = (char)EB_UT_LEN(1); memcpy(cext+EB_C_UT_SIZE, Uxptr, EB_C_UX2_SIZE); cext[EB_LEN+EB_C_UT_SIZE] = 0; z->cext += EF_C_UNIX_SIZE; cext += EF_C_UNIX_SIZE; #endif /* USE_EF_UT_TIME */ return ZE_OK; } #if CRYPT /* getpid() only available on OSS so make up dummy version using NSK PID */ unsigned zgetpid (void) { short myphandle[ZSYS_VAL_PHANDLE_WLEN]; short err; unsigned retval; err = PROCESSHANDLE_NULLIT_(myphandle); if (!err) err = PROCESS_GETINFO_(myphandle); if (!err) retval = (unsigned) myphandle[ZSYS_VAL_PHANDLE_WLEN - 3]; else #ifndef __INT32 retval = (unsigned) 31415; #else retval = (unsigned) 3141592654L; #endif /* __INT32 */ return retval; } #endif /* CRYPT */