home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume23
/
zip
/
part02
< prev
next >
Wrap
Text File
|
1991-10-21
|
55KB
|
2,044 lines
Newsgroups: comp.sources.misc
From: kirsch@usasoc.soc.mil (David Kirschbaum)
Subject: v23i089: zip - Portable zip v1.0, Part02/09
Message-ID: <1991Oct21.042040.7851@sparky.imd.sterling.com>
X-Md4-Signature: 669c19bba3344b485495d627dd694d7b
Date: Mon, 21 Oct 1991 04:20:40 GMT
Approved: kent@sparky.imd.sterling.com
Submitted-by: kirsch@usasoc.soc.mil (David Kirschbaum)
Posting-number: Volume 23, Issue 89
Archive-name: zip/part02
Environment: UNIX, Minix, MSDOS, OS/2, VMS
#! /bin/sh
# into a shell via "sh file" or similar. To overwrite existing files,
# type "sh file -c".
# The tool that generated this appeared in the comp.sources.unix newsgroup;
# send mail to comp-sources-unix@uunet.uu.net if you want that tool.
# Contents: dir_os2.c fileio.c zip.prj
# Wrapped by kent@sparky on Sun Oct 20 22:58:52 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
echo If this archive is complete, you will see the following message:
echo ' "shar: End of archive 2 (of 9)."'
if test -f 'dir_os2.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'dir_os2.c'\"
else
echo shar: Extracting \"'dir_os2.c'\" \(5569 characters\)
sed "s/^X//" >'dir_os2.c' <<'END_OF_FILE'
X/*
X * @(#)dir.c 1.4 87/11/06 Public Domain.
X *
X * A public domain implementation of BSD directory routines for
X * MS-DOS. Written by Michael Rendell ({uunet,utai}michael@garfield),
X * August 1897
X * Ported to OS/2 by Kai Uwe Rommel
X * December 1989, February 1990
X * Change for HPFS support, October 1990
X */
X
X#include <sys/types.h>
X#include <sys/stat.h>
X
X#include <stdio.h>
X#include <stdlib.h>
X#include <malloc.h>
X#include <string.h>
X#include <ctype.h>
X
X#define INCL_NOPM
X#include <os2.h>
X
X#include "dir_os2.h"
X
X
Xint attributes = A_DIR | A_HIDDEN;
X
X
Xstatic char *getdirent(char *);
Xstatic void free_dircontents(struct _dircontents *);
X
Xstatic HDIR hdir;
Xstatic USHORT count;
Xstatic FILEFINDBUF find;
X
X
XDIR *opendir(char *name)
X{
X struct stat statb;
X DIR *dirp;
X char c;
X char *s;
X struct _dircontents *dp;
X char nbuf[MAXPATHLEN + 1];
X int len;
X
X strcpy(nbuf, name);
X len = strlen (nbuf);
X s = nbuf + len;
X
X#if 1
X if ( ((c = nbuf[strlen(nbuf) - 1]) == '\\' || c == '/') &&
X (strlen(nbuf) > 1) )
X {
X nbuf[strlen(nbuf) - 1] = 0;
X
X if ( nbuf[strlen(nbuf) - 1] == ':' )
X strcat(nbuf, "\\.");
X }
X else
X if ( nbuf[strlen(nbuf) - 1] == ':' )
X strcat(nbuf, ".");
X#else
X if ( len && ((c = nbuf[len-1]) == '\\' || c == '/' || c == ':') )
X {
X nbuf[len++] = '.'; /* s now points to '.' */
X nbuf[len] = 0;
X }
X#endif
X
X if (stat(nbuf, &statb) < 0 || (statb.st_mode & S_IFMT) != S_IFDIR)
X return NULL;
X
X if ( (dirp = malloc(sizeof(DIR))) == NULL )
X return NULL;
X
X#if 1
X if ( nbuf[strlen(nbuf) - 1] == '.' )
X strcpy(nbuf + strlen(nbuf) - 1, "*.*");
X else
X if ( ((c = nbuf[strlen(nbuf) - 1]) == '\\' || c == '/') &&
X (strlen(nbuf) == 1) )
X strcat(nbuf, "*.*");
X else
X strcat(nbuf, "\\*.*");
X#else
X if ( *s == 0 )
X *s++ = '\\';
X
X strcpy (s, "*.*");
X#endif
X
X dirp -> dd_loc = 0;
X dirp -> dd_contents = dirp -> dd_cp = NULL;
X
X if ((s = getdirent(nbuf)) == NULL)
X return dirp;
X
X do
X {
X if (((dp = malloc(sizeof(struct _dircontents))) == NULL) ||
X ((dp -> _d_entry = malloc(strlen(s) + 1)) == NULL) )
X {
X if (dp)
X free(dp);
X free_dircontents(dirp -> dd_contents);
X
X return NULL;
X }
X
X if (dirp -> dd_contents)
X {
X dirp -> dd_cp -> _d_next = dp;
X dirp -> dd_cp = dirp -> dd_cp -> _d_next;
X }
X else
X dirp -> dd_contents = dirp -> dd_cp = dp;
X
X strcpy(dp -> _d_entry, s);
X dp -> _d_next = NULL;
X
X dp -> _d_size = find.cbFile;
X dp -> _d_mode = find.attrFile;
X dp -> _d_time = *(unsigned *) &(find.ftimeLastWrite);
X dp -> _d_date = *(unsigned *) &(find.fdateLastWrite);
X }
X while ((s = getdirent(NULL)) != NULL);
X
X dirp -> dd_cp = dirp -> dd_contents;
X
X return dirp;
X}
X
X
Xvoid closedir(DIR * dirp)
X{
X free_dircontents(dirp -> dd_contents);
X free(dirp);
X}
X
X
Xstruct direct *readdir(DIR * dirp)
X{
X static struct direct dp;
X
X if (dirp -> dd_cp == NULL)
X return NULL;
X
X dp.d_namlen = dp.d_reclen =
X strlen(strcpy(dp.d_name, dirp -> dd_cp -> _d_entry));
X
X dp.d_ino = 0;
X
X dp.d_size = dirp -> dd_cp -> _d_size;
X dp.d_mode = dirp -> dd_cp -> _d_mode;
X dp.d_time = dirp -> dd_cp -> _d_time;
X dp.d_date = dirp -> dd_cp -> _d_date;
X
X dirp -> dd_cp = dirp -> dd_cp -> _d_next;
X dirp -> dd_loc++;
X
X return &dp;
X}
X
X
Xvoid seekdir(DIR * dirp, long off)
X{
X long i = off;
X struct _dircontents *dp;
X
X if (off >= 0)
X {
X for (dp = dirp -> dd_contents; --i >= 0 && dp; dp = dp -> _d_next);
X
X dirp -> dd_loc = off - (i + 1);
X dirp -> dd_cp = dp;
X }
X}
X
X
Xlong telldir(DIR * dirp)
X{
X return dirp -> dd_loc;
X}
X
X
Xstatic void free_dircontents(struct _dircontents * dp)
X{
X struct _dircontents *odp;
X
X while (dp)
X {
X if (dp -> _d_entry)
X free(dp -> _d_entry);
X
X dp = (odp = dp) -> _d_next;
X free(odp);
X }
X}
X
X
Xstatic char *getdirent(char *dir)
X{
X int done;
X
X if (dir != NULL)
X { /* get first entry */
X hdir = HDIR_CREATE;
X count = 1;
X done = DosFindFirst(dir, &hdir, attributes,
X &find, sizeof(find), &count, 0L);
X }
X else /* get next entry */
X done = DosFindNext(hdir, &find, sizeof(find), &count);
X
X if (done == 0)
X return find.achName;
X else
X {
X DosFindClose(hdir);
X return NULL;
X }
X}
X
X
X/* ISFAT.C
X *
X * Autor: Kai Uwe Rommel
X * Datum: Sun 28-Oct-1990
X *
X * Compiler: MS C ab 6.00
X * System: OS/2 ab 1.2
X */
X
X#define LABEL "isfat.c"
X#define VERSION "1.0"
X
X
X/* #include <stdio.h>
X#include <stdlib.h>
X#include <string.h>
X#include <ctype.h>
X
X#define INCL_NOPM
X#include <os2.h> */
X
X
Xint IsFileSystemFAT(char *dir)
X{
X USHORT nDrive;
X ULONG lMap;
X BYTE bData[64], bName[3];
X USHORT cbData;
X static USHORT nLastDrive = -1, nResult;
X
X if ( _osmode == DOS_MODE )
X return TRUE;
X else
X {
X /* We separate FAT and HPFS+other file systems here.
X at the moment I consider other systems to be similar to HPFS,
X i.e. support long file names and beeing case sensitive */
X
X if ( isalpha(dir[0]) && (dir[1] == ':') )
X nDrive = toupper(dir[0]) - '@';
X else
X DosQCurDisk(&nDrive, &lMap);
X
X if ( nDrive == nLastDrive )
X return nResult;
X
X bName[0] = (char) (nDrive + '@');
X bName[1] = ':';
X bName[2] = 0;
X
X nLastDrive = nDrive;
X cbData = sizeof(bData);
X
X if ( !DosQFSAttach(bName, 0U, 1U, bData, &cbData, 0L) )
X nResult = !strcmp(bData + (*(USHORT *) (bData + 2) + 7), "FAT");
X else
X nResult = FALSE;
X
X /* End of this ugly code */
X return nResult;
X }
X}
X
X
X
X/* End of ISFAT.C */
END_OF_FILE
if test 5569 -ne `wc -c <'dir_os2.c'`; then
echo shar: \"'dir_os2.c'\" unpacked with wrong size!
fi
# end of 'dir_os2.c'
fi
if test -f 'fileio.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'fileio.c'\"
else
echo shar: Extracting \"'fileio.c'\" \(44358 characters\)
sed "s/^X//" >'fileio.c' <<'END_OF_FILE'
X/*
X
X Copyright (C) 1990,1991 Mark Adler, Richard B. Wales, and Jean-loup Gailly.
X Permission is granted to any individual or institution to use, copy, or
X redistribute this software so long as all of the original files are included
X unmodified, that it is not sold for profit, and that this copyright notice
X is retained.
X
X*/
X
X/*
X * fileio.c by Mark Adler.
X */
X
X#include "zip.h"
X
X#include <time.h>
X#include <errno.h>
X
X#ifdef S_IWUSR /* For MINIX */
X# ifdef S_IWRITE
X# undef S_IWRITE
X# endif /* S_IWRITE */
X# define S_IWRITE S_IWUSR
X#endif /* S_IWUSR */
X
X#ifdef MSDOS
X# include <io.h>
X# ifdef __TURBOC__
X# include <dir.h>
X# else /* !__TURBOC__ */
X# include <direct.h>
X# endif /* ?__TURBOC__ */
X# define link rename
X# ifdef OS2
X# define MATCH shmatch
X# else /* !OS2 */
X# define MATCH dosmatch
X# endif /* ?OS2 */
X#else /* !MSDOS */
X extern int errno; /* error number from system functions */
X# ifdef VMS
X# define RMDIR
X# define link rename
X# endif /* VMS */
X# define MATCH shmatch
X#endif /* ?MSDOS */
X
X#ifdef UTS
X# define RMDIR
X#endif /* UTS */
X
X
X/* Extra malloc() space in names for cutpath() */
X#ifdef VMS
X# define PAD 3 /* may have to change .FOO] to ]FOO.DIR */
X#else /* !VMS */
X# define PAD 0
X#endif /* ?VMS */
X
X
X/* For now, assume DIRENT implies System V implies TERMIO */
X#ifdef DIRENT
X# ifndef MINIX
X# ifndef TERMIO
X# define TERMIO
X# endif /* !TERMIO */
X# endif /* !MINIX */
X#endif /* DIRENT */
X
X
X#ifndef EXPORT
X# ifdef MSVMS
X# ifdef MSDOS
X# include <conio.h>
X# else /* !MSDOS */
X# define getch() getc(stderr)
X# endif /* ?MSDOS */
X# else /* !MSVMS */
X# ifdef TERMIO /* Amdahl, Cray, all SysV? */
X# ifdef CONVEX
X# include <sys/termios.h>
X# include <sgtty.h>
X# else /* !CONVEX */
X# include <sys/termio.h>
X# define sgttyb termio
X# define sg_flags c_lflag
X# endif /* ?CONVEX */
X int ioctl OF((int, int, voidp *));
X# define GTTY(f,s) ioctl(f,TCGETA,s)
X# define STTY(f,s) ioctl(f,TCSETAW,s)
X# else /* !TERMIO */
X# ifndef MINIX
X# include <sys/ioctl.h>
X# endif /* !MINIX */
X# include <sgtty.h>
X int gtty OF((int, struct sgttyb *));
X int stty OF((int, struct sgttyb *));
X# define GTTY gtty
X# define STTY stty
X# endif /* ?TERMIO */
X int isatty OF((int));
X char *ttyname OF((int));
X int open OF((char *, int, ...));
X int close OF((int));
X int read OF((int, voidp *, int));
X# endif /* ?MSVMS */
X#endif /* !EXPORT */
X
X
X
X/* For directory access */
X#ifndef UTIL
X#ifdef DIRENT /* use getdents() */
X# ifdef MINIX
X# include <dirent.h>
X# else /* !MINIX */
X# include <sys/dirent.h>
X# endif /* ?MINIX */
X# define direct dirent
X# ifdef MINIX
X int getdents OF((int, char *, unsigned));
X# else /* !MINIX */
X int getdents OF((int, char *, int));
X# endif /* ?MINIX */
X# define DBSZ 4096 /* This has to be bigger than a directory block */
X typedef struct { /* directory stream buffer */
X int f; /* file descriptor for the directory "file" */
X char *p; /* pointer to next entry in buffer */
X char *q; /* pointer after end of buffer contents */
X char b[DBSZ]; /* buffer */
X } dstrm;
X#else /* !DIRENT */ /* use opendir(), etc. */
X# ifdef CONVEX
X# include <dirent.h>
X# define direct dirent
X# endif /* CONVEX */
X# ifdef NDIR
X# include "ndir.h" /* for HPUX */
X# else /* !NDIR */
X# ifdef MSDOS
X# ifdef OS2
X# include "dir_os2.h"
X# else /* !OS2 */
X# include <dos.h>
X# ifdef __TURBOC__
X# define FATTR FA_HIDDEN+FA_SYSTEM+FA_DIREC
X# define FFIRST(n,d) findfirst(n,(struct ffblk *)d,FATTR)
X# define FNEXT(d) findnext((struct ffblk *)d)
X# else /* !__TURBOC__ */
X# define FATTR _A_HIDDEN+_A_SYSTEM+_A_SUBDIR
X# define FFIRST(n,d) _dos_findfirst(n,FATTR,(struct find_t *)d)
X# define FNEXT(d) _dos_findnext((struct find_t *)d)
X# endif /* ?__TURBOC__ */
X typedef struct direct {
X char d_reserved[30];
X char d_name[13];
X int d_first;
X } DIR;
X# endif /* ?OS2 */
X# else /* !MSDOS */
X# ifdef VMS
X# include <rms.h>
X# include <ssdef.h>
X# include <descrip.h>
X typedef struct direct {
X int d_wild; /* flag for wildcard vs. non-wild */
X struct FAB fab;
X struct NAM nam;
X char d_qualwildname[NAM$C_MAXRSS + 1];
X char d_name[NAM$C_MAXRSS + 1];
X } DIR;
X# else /* !VMS */
X# include <sys/dir.h>
X# ifdef NODIR /* for AT&T 3B1 */
X# define dirent direct
X typedef FILE DIR;
X# define dstrm DIR
X# endif /* NODIR */
X# endif /* ?VMS */
X# endif /* ?MSDOS */
X# endif /* ?NDIR */
X# define dstrm DIR
X# ifndef NODIR
X DIR *opendir OF((char *));
X# endif /* !NODIR */
X# ifndef CONVEX
X struct direct *readdir OF((DIR *));
X# endif /* !CONVEX */
X#endif /* ?DIRENT */
X#endif /* !UTIL */
X
X
X/* Library functions not in (most) header files */
Xchar *mktemp OF((char *));
Xint link OF((char *, char *));
Xint unlink OF((char *));
X#ifndef CONVEX
X# ifndef AIX
X int chmod OF((char *, int));
X# endif /* !AIX */
X#endif /* !CONVEX */
X
X
X#ifndef UTIL /* the companion #endif is a bit of ways down ... */
X
X#ifndef __TURBOC__
X int utime OF((char *, time_t *));
X#endif /* !__TURBOC__ */
X#ifndef MSDOS
X int open OF((char *, int, ...));
X int close OF((int));
X# ifndef RMDIR
X int rmdir OF((char *));
X# endif /* !RMDIR */
X#endif /* !MSDOS */
X
X
X/* Local globals (kinda like "military intelligence" or "broadcast quality") */
Xlocal int exflag = 0; /* Exclude flag */
X
X/* Local functions */
X#ifdef PROTO
X# ifdef VMS
X local void vms_wild(char *, dstrm *);
X# endif /* VMS */
X# ifdef DIRENT
X local dstrm *opend(char *);
X local void closed(dstrm *);
X# endif /* DIRENT */
X local char *readd(dstrm *);
X local int fqcmp(voidp *, voidp *);
X local int fqcmpz(voidp *, voidp *);
X local char *last(char *);
X local char *msname(char *);
X# ifdef VMS
X local char *strlower(char *);
X local char *strupper(char *);
X# endif /* VMS */
X local char *ex2in(char *);
X local int newname(char *);
X local void inctime(struct tm *);
X local ulg unix2dostime(time_t *);
X# ifndef __TURBOC__
X local int cmptime(struct tm *, struct tm *);
X local time_t invlocal(struct tm *);
X# endif /* !__TURBOC__ */
X#endif /* PROTO */
X
X
X
X#ifndef OS2
X#ifdef MSDOS
Xdstrm *opendir(n)
Xchar *n; /* directory to open */
X/* Start searching for files in the MSDOS directory n */
X{
X dstrm *d; /* malloc'd return value */
X char *p; /* malloc'd temporary string */
X
X if ((d = (dstrm *)malloc(sizeof(dstrm))) == NULL ||
X (p = malloc(strlen(n) + 5)) == NULL)
X return NULL;
X strcat(strcpy(p, n), "/*.*");
X if (FFIRST(p, d))
X {
X free((voidp *)p);
X return NULL;
X }
X free((voidp *)p);
X d->d_first = 1;
X return d;
X}
X
Xstruct direct *readdir(d)
Xdstrm *d; /* directory stream to read from */
X/* Return pointer to first or next directory entry, or NULL if end. */
X{
X if (d->d_first)
X d->d_first = 0;
X else
X if (FNEXT(d))
X return NULL;
X return (struct direct *)d;
X}
X# define closedir free
X#endif /* MSDOS */
X#endif /* !OS2 */
X
X
X#ifdef VMS
X/*---------------------------------------------------------------------------
X
X _vms_findfirst() and _vms_findnext(), based on public-domain DECUS C
X fwild() and fnext() routines (originally written by Martin Minow, poss-
X ibly modified by Jerry Leichter for bintnxvms.c), were written by Greg
X Roelofs and are still in the public domain. Routines approximate the
X behavior of MS-DOS (MSC and Turbo C) findfirst and findnext functions.
X
X ---------------------------------------------------------------------------*/
Xlocal void vms_wild(p, d)
Xchar *p;
Xdstrm *d;
X{
X /*
X * Do wildcard setup
X */
X /* set up the FAB and NAM blocks. */
X d->fab = cc$rms_fab; /* initialize fab */
X d->nam = cc$rms_nam; /* initialize nam */
X
X d->fab.fab$l_nam = &d->nam; /* fab -> nam */
X d->fab.fab$l_fna = p; /* argument wild name */
X d->fab.fab$b_fns = strlen(p); /* length */
X
X d->nam.nam$l_esa = d->d_qualwildname; /* qualified wild name */
X d->nam.nam$b_ess = NAM$C_MAXRSS; /* max length */
X d->nam.nam$l_rsa = d->d_name; /* matching file name */
X d->nam.nam$b_rss = NAM$C_MAXRSS; /* max length */
X
X /* parse the file name */
X if (sys$parse(&d->fab) != RMS$_NORMAL)
X return -1;
X /* Does this replace d->fab.fab$l_fna with a new string in its own space?
X I sure hope so, since p is free'ed before this routine returns. */
X
X /* have qualified wild name (i.e., disk:[dir.subdir]*.*); null-terminate
X * and set wild-flag */
X d->d_qualwildname[d->nam.nam$b_esl] = '\0';
X d->d_wild = (d->nam.nam$l_fnb & NAM$M_WILDCARD)? 1 : 0; /* not used... */
X#ifdef DEBUG
X printf(" incoming wildname: %s\n", p);
X printf(" qualified wildname: %s\n", d->d_qualwildname);
X#endif /* DEBUG */
X}
X
Xdstrm *opendir(n)
Xchar *n; /* directory to open */
X/* Start searching for files in the VMS directory n */
X{
X char *c; /* scans VMS path */
X dstrm *d; /* malloc'd return value */
X int m; /* length of name */
X char *p; /* malloc'd temporary string */
X
X if ((d = (dstrm *)malloc(sizeof(dstrm))) == NULL ||
X (p = malloc((m = strlen(n)) + 4)) == NULL)
X return NULL;
X /* Directory may be in form "[DIR.SUB1.SUB2]" or "[DIR.SUB1]SUB2.DIR;1".
X If latter, convert to former. */
X if (m > 0 && *(c = strcpy(p,n)+m-1) != ']')
X {
X while (--c > p && *c != ';')
X ;
X if (c-p < 5 || strncmp(c-4, ".DIR", 4))
X {
X free((voidp *)d); free((voidp *)p);
X return NULL;
X }
X c -= 3;
X *c-- = '\0'; /* terminate at "DIR;#" */
X *c = ']'; /* "." --> "]" */
X while (c > p && *--c != ']')
X ;
X *c = '.'; /* "]" --> "." */
X }
X strcat(p, "*.*");
X vms_wild(p, d); /* set up wildcard */
X free((voidp *)p);
X return d;
X}
X
Xstruct direct *readdir(d)
Xdstrm *d; /* directory stream to read from */
X/* Return pointer to first or next directory entry, or NULL if end. */
X{
X int r; /* return code */
X
X do {
X d->fab.fab$w_ifi = 0; /* internal file index: what does this do? */
X
X /* get next match to possible wildcard */
X if ((r = sys$search(&d->fab)) == RMS$_NORMAL)
X {
X d->d_name[d->nam.nam$b_rsl] = '\0'; /* null terminate */
X return (struct direct *)d; /* OK */
X }
X } while (r == RMS$_PRV);
X return NULL;
X}
X# define closedir free
X#endif /* VMS */
X
X
X#ifdef NODIR /* for AT&T 3B1 */
X/*
X** Apparently originally by Rich Salz.
X** Cleaned up and modified by James W. Birdsall.
X*/
X
X# define opendir(path) fopen(path, "r")
X
Xstruct direct *readdir(dirp)
XDIR *dirp;
X{
X static struct direct entry;
X
X if (dirp == NULL)
X return NULL;
X for (;;)
X if (fread (&entry, sizeof (struct direct), 1, dirp) == 0)
X return NULL;
X else if (entry.d_ino)
X return (&entry);
X} /* end of readdir() */
X
X# define closedir(dirp) fclose(dirp)
X#endif /* NODIR */
X
X
X#ifdef DIRENT
Xlocal dstrm *opend(n)
Xchar *n; /* directory name to open */
X/* Open the directory *n, returning a pointer to an allocated dstrm, or
X NULL if error. */
X{
X dstrm *d; /* pointer to malloc'ed directory stream */
X
X if ((d = (dstrm *)malloc(sizeof(dstrm))) == NULL)
X return NULL;
X if ((d->f = open(n, 0, 0)) < 0) /* open directory */
X return NULL;
X d->p = d->q = d->b; /* buffer is empty */
X return d;
X}
X#else /* !DIRENT */
X# define opend opendir /* just use opendir() */
X#endif /* ?DIRENT */
X
X
Xlocal char *readd(d)
Xdstrm *d; /* directory stream to read from */
X/* Return a pointer to the next name in the directory stream d, or NULL if
X no more entries or an error occurs. */
X{
X struct direct *e; /* directory entry read */
X
X#ifdef DIRENT
X int n; /* number of entries read by getdents */
X
X if (d->p >= d->q) /* if empty, fill buffer */
X if ((n = getdents(d->f, d->b, DBSZ)) <= 0)
X return NULL;
X else
X d->q = n + (d->p = d->b);
X e = (struct direct *)(d->p); /* point to entry */
X d->p += ((struct direct *)(d->p))->d_reclen; /* advance */
X return e->d_name; /* return name */
X#else /* !DIRENT */
X return (e = readdir(d)) == NULL ? (char *)NULL : e->d_name;
X#endif /* ?DIRENT */
X}
X
X
X#ifdef DIRENT
Xlocal void closed(d)
Xdstrm *d; /* directory stream to close */
X/* Close the directory stream */
X{
X close(d->f);
X free((voidp *)d);
X}
X#else /* !DIRENT */
X# define closed closedir
X#endif /* ?DIRENT */
X
X
X#ifdef MSDOS
Xint wild(p)
Xchar *p; /* path/pattern to match */
X/* If not in exclude mode, expand the pattern based on the contents of the
X file system. Return an error code in the ZE_ class. */
X{
X dstrm *d; /* stream for reading directory */
X char *e; /* name found in directory */
X int f; /* true if there was a match */
X char *n; /* constructed name from directory */
X char *q; /* temporary variable */
X int r; /* temporary variable */
X char v[4]; /* space for device current directory */
X
X /* If excluding, don't bother with file system */
X if (exflag)
X return procname(p);
X
X /* Normalize pattern to upper case, path delimiter as '/'. */
X#ifndef OS2
X strupr(p); /* convert to upper case */
X#endif /* !OS2 */
X for (q = p; *q; q++) /* use / consistently */
X if (*q == '\\')
X *q = '/';
X
X /* Only name can have special matching characters */
X if ((q = isshexp(p)) != NULL &&
X (strrchr(q, '/') != NULL || strrchr(q, ':') != NULL))
X return ZE_PARMS;
X
X /* Separate path and name */
X if ((q = strrchr(p, '/')) != NULL)
X *q++ = 0;
X else if (*p && *(p+1) == ':')
X {
X q = p + 2;
X v[0] = *p;
X strcpy(v+1, ":.");
X p = v;
X }
X else
X {
X q = p;
X p = ".";
X }
X if (*p == 0)
X p = "/";
X
X /* Search that level for matching names */
X if ((d = opend(p)) == NULL)
X return ZE_MISS;
X if (strcmp(p+1, ":.") == 0)
X *(p+2) = 0;
X f = 0;
X while ((e = readd(d)) != NULL)
X if (strcmp(e, ".") && strcmp(e, "..") && MATCH(q, e))
X {
X f = 1;
X if (strcmp(p, ".") == 0)
X procname(e);
X else if (*p && strcmp(p+1, ":") == 0)
X {
X if ((n = malloc(strlen(e) + 3)) == NULL)
X return ZE_MEM;
X r = procname(strcat(strcpy(n, p), e));
X free((voidp *)n);
X if (r)
X return r;
X }
X else
X {
X if ((n = malloc(strlen(p) + strlen(e) + 2)) == NULL)
X return ZE_MEM;
X if (strcmp(p, "/"))
X strcpy(n, p);
X else
X *n = 0;
X r = procname(strcat(strcat(n, "/"), e));
X free((voidp *)n);
X if (r)
X return r;
X }
X }
X closed(d);
X
X /* Done */
X return f ? ZE_OK : ZE_MISS;
X}
X#endif /* MSDOS */
X
X
X#ifdef VMS
Xint wild(p)
Xchar *p; /* path/pattern to match */
X/* Expand the pattern based on the contents of the file system. Return an
X error code in the ZE_ class. */
X{
X dstrm *d; /* stream for reading directory */
X char *e; /* name found in directory */
X int f; /* true if there was a match */
X
X /* Search given pattern for matching names */
X if ((d = (dstrm *)malloc(sizeof(dstrm))) == NULL)
X return ZE_MEM;
X vms_wild(p, d); /* pattern may be more than just directory name */
X f = 0;
X while ((e = readd(d)) != NULL) /* "dosmatch" is already built in */
X if (procname(e) == ZE_OK)
X f = 1;
X closed(d);
X
X /* Done */
X return f ? ZE_OK : ZE_MISS;
X}
X#endif /* VMS */
X
X
Xchar *getnam(n)
Xchar *n; /* where to put name (must have >=FNMAX+1 bytes) */
X/* Read a space, \n, \r, or \t delimited name from stdin into n, and return
X n. If EOF, then return NULL. Also, if the name read is too big, return
X NULL. */
X{
X int c; /* last character read */
X char *p; /* pointer into name area */
X
X p = n;
X while ((c = getchar()) == ' ' || c == '\n' || c == '\r' || c == '\t')
X ;
X if (c == EOF)
X return NULL;
X do {
X if (p - n >= FNMAX)
X return NULL;
X *p++ = (char)c;
X c = getchar();
X } while (c != EOF && c != ' ' && c != '\n' && c != '\r' && c != '\t');
X *p = 0;
X return n;
X}
X
X
Xstruct flist far *fexpel(f)
Xstruct flist far *f; /* entry to delete */
X/* Delete the entry *f in the doubly-linked found list. Return pointer to
X next entry to allow stepping through list. */
X{
X struct flist far *t; /* temporary variable */
X
X t = f->nxt;
X *(f->lst) = t; /* point last to next, */
X if (t != NULL)
X t->lst = f->lst; /* and next to last */
X if (f->name != NULL) /* free memory used */
X free((voidp *)(f->name));
X if (f->zname != NULL)
X free((voidp *)(f->zname));
X farfree((voidp far *)f);
X fcount--; /* decrement count */
X return t; /* return pointer to next */
X}
X
X
Xlocal int fqcmp(a, b)
Xvoidp *a, *b; /* pointers to pointers to found entries */
X/* Used by qsort() to compare entries in the found list by name. */
X{
X return strcmp((*(struct flist far **)a)->name,
X (*(struct flist far **)b)->name);
X}
X
X
Xlocal int fqcmpz(a, b)
Xvoidp *a, *b; /* pointers to pointers to found entries */
X/* Used by qsort() to compare entries in the found list by zname. */
X{
X return strcmp((*(struct flist far **)a)->zname,
X (*(struct flist far **)b)->zname);
X}
X
X
Xlocal char *last(p)
Xchar *p; /* sequence of / delimited path components */
X/* Return a pointer to the start of the last path component. */
X{
X char *t; /* temporary variable */
X
X#ifdef VMS
X if ((t = strrchr(p, ']')) != NULL)
X#else /* !VMS */
X if ((t = strrchr(p, '/')) != NULL)
X#endif /* ?VMS */
X return t + 1;
X else
X return p;
X}
X
X
X#define TOUP(c) ((c) >= 'a' && (c) <= 'z' ? (c)-'a'+'A' : (c))
X
Xlocal char *msname(n)
Xchar *n;
X/* Reduce all path components to MSDOS upper case 8.3 style names. Probably
X should also check for invalid characters, but I don't know which ones
X those are. */
X{
X int c; /* current character */
X int f; /* characters in current component */
X char *p; /* source pointer */
X char *q; /* destination pointer */
X
X p = q = n;
X f = 0;
X while ((c = *p++) != 0)
X if (c == '/')
X {
X *q++ = (char)c;
X f = 0; /* new component */
X }
X else if (c == '.')
X if (f < 9)
X {
X *q++ = (char)c;
X f = 9; /* now in file type */
X }
X else
X f = 12; /* now just excess characters */
X else
X if (f < 12 && f != 8)
X {
X *q++ = (char)(TOUP(c));
X f++; /* do until end of name or type */
X }
X *q = 0;
X return n;
X}
X
X
X#ifdef VMS
Xlocal char *strlower(s)
Xchar *s; /* string to convert */
X/* Convert all uppercase letters to lowercase in string s */
X{
X char *p; /* scans string */
X
X for (p = s; *p; p++)
X if (*p >= 'A' && *p <= 'Z')
X *p += 'a' - 'A';
X return s;
X}
X
Xlocal char *strupper(s)
Xchar *s; /* string to convert */
X/* Convert all lowercase letters to uppercase in string s */
X{
X char *p; /* scans string */
X
X for (p = s; *p; p++)
X if (*p >= 'a' && *p <= 'a')
X *p -= 'a' - 'A';
X return s;
X}
X#endif /* VMS */
X
X
Xlocal char *ex2in(x)
Xchar *x; /* external file name */
X/* Convert the external file name to a zip file name, returning the malloc'ed
X string or NULL if not enough memory. */
X{
X char *n; /* internal file name (malloc'ed) */
X char *t; /* shortened name */
X
X /* Find starting point in name before doing malloc */
X#ifdef MSDOS /* msdos */
X t = *x && *(x + 1) == ':' ? x + 2 : x;
X while (*t == '/' || *t == '\\')
X t++;
X#else /* !MSDOS */
X# ifdef VMS /* vms */
X t = x;
X if ((n = strrchr(t, ':')) != NULL)
X t = n + 1;
X if (*t == '[' && (n = strrchr(t, ']')) != NULL)
X if ((x = strchr(t, '.')) != NULL && x < n)
X t = x + 1;
X else
X t = n + 1;
X# else /* !VMS */ /* unix */
X for (t = x; *t == '/'; t++)
X ;
X# endif /* ?VMS */
X#endif /* ?MSDOS */
X if (!pathput)
X t = last(t);
X
X /* Malloc space for internal name and copy it */
X if ((n = malloc(strlen(t) + 1)) == NULL)
X return NULL;
X strcpy(n, t);
X
X /* Make changes, if any, to the copied name (leave original intact) */
X#ifdef MSDOS
X for (t = n; *t; t++)
X if (*t == '\\')
X *t = '/';
X#endif /* MSDOS */
X#ifdef VMS
X if ((t = strrchr(n, ']')) != NULL)
X {
X *t = '/';
X while (--t > n)
X if (*t == '.')
X *t = '/';
X }
X
X /* Fix from Greg Roelofs: */
X /* Get current working directory and strip from n (t now = n) */
X {
X char cwd[256], *p, *q;
X int c;
X
X if (getcwd(cwd, 256) && ((p = strchr(cwd, '.')) != NULL))
X {
X ++p;
X if ((q = strrchr(p, ']')) != NULL)
X {
X *q = '/';
X while (--q > p)
X if (*q == '.')
X *q = '/';
X /* strip bogus path parts from n */
X if (strncmp(n, p, (c=strlen(p))) == 0)
X {
X q = n + c;
X while (*t++ = *q++)
X ;
X }
X }
X }
X }
X strlower(n);
X if (!vmsver)
X if ((t = strrchr(n, ';')) != NULL)
X *t = 0;
X#endif /* VMS */
X if (dosify)
X msname(n);
X
X /* Returned malloc'ed name */
X return n;
X}
X
X
Xchar *in2ex(n)
Xchar *n; /* internal file name */
X/* Convert the zip file name to an external file name, returning the malloc'ed
X string or NULL if not enough memory. */
X{
X char *x; /* external file name */
X#ifdef VMS
X char *t; /* scans name */
X
X if ((t = strrchr(n, '/')) == NULL)
X#endif /* VMS */
X {
X if ((x = malloc(strlen(n) + 1 + PAD)) == NULL)
X return NULL;
X strcpy(x, n);
X }
X#ifdef VMS
X else
X {
X if ((x = malloc(strlen(n) + 3 + PAD)) == NULL)
X return NULL;
X strcpy(x, "[.");
X strcpy(x + 2, n);
X *(t = x + 2 + (t - n)) = ']';
X while (--t > x)
X if (*t == '/')
X *t = '.';
X }
X strupper(x);
X#endif /* VMS */
X return x;
X}
X
X
Xint exclude()
X/* Change from including to excluding names when procname() called. Return
X an error code in the ZE_ class. */
X{
X struct flist far *f; /* steps through found linked list */
X int j; /* index for s */
X struct flist far **s; /* sorted table */
X
X /* sort found list, remove duplicates */
X if (fcount)
X {
X if ((s = (struct flist far **)malloc(
X fcount * sizeof(struct flist far *))) == NULL)
X return ZE_MEM;
X for (j = 0, f = found; f != NULL; f = f->nxt)
X s[j++] = f;
X qsort((char *)s, fcount, sizeof(struct flist far *), fqcmp);
X for (j = fcount - 1; j > 0; j--)
X if (strcmp(s[j - 1]->name, s[j]->name) == 0)
X fexpel(s[j]); /* fexpel() changes fcount */
X qsort((char *)s, fcount, sizeof(struct flist far *), fqcmpz);
X for (j = 1; j < fcount; j++)
X if (strcmp(s[j - 1]->zname, s[j]->zname) == 0)
X {
X warn("name in zip file repeated: ", s[j]->zname);
X warn(" first full name: ", s[j - 1]->name);
X warn(" second full name: ", s[j]->name);
X return ZE_PARMS;
X }
X free((voidp *)s);
X }
X exflag = 1;
X return ZE_OK;
X}
X
X
Xlocal int newname(n)
Xchar *n; /* name to add (or exclude) */
X/* Add (or exclude) a name that is not in the zip file. Return an error
X code in the ZE_ class. */
X{
X char *m;
X struct flist far *f; /* where in found, or new found entry */
X struct zlist far *z; /* where in zfiles (if found) */
X
X /* Search for name in zip file. If there, mark it, else add to
X list of new names to do (or remove from that list). */
X if ((m = ex2in(n)) == NULL)
X return ZE_MEM;
X if ((z = zsearch(m)) != NULL)
X if (exflag)
X {
X z->mark = 0;
X free((voidp *)m);
X if (verbose)
X printf("zip diagnostic: excluding %s\n", z->name);
X }
X else
X {
X free((voidp *)(z->name));
X free((voidp *)(z->zname));
X if ((z->name = malloc(strlen(n) + 1 + PAD)) == NULL)
X return ZE_MEM;
X strcpy(z->name, n);
X z->zname = m;
X z->mark = 1;
X if (verbose)
X printf("zip diagnostic: including %s\n", z->name);
X }
X else
X if (exflag)
X {
X /* search list for name--if there, remove it */
X for (f = found; f != NULL; f = f->nxt)
X if (strcmp(n, f->name) == 0)
X {
X fexpel(f);
X break;
X }
X free((voidp *)m);
X }
X else
X {
X /* allocate space and add to list */
X if ((f = (struct flist far *)farmalloc(sizeof(struct flist))) == NULL ||
X (f->name = malloc(strlen(n) + 1 + PAD)) == NULL)
X {
X if (f != NULL)
X farfree((voidp far *)f);
X return ZE_MEM;
X }
X strcpy(f->name, n);
X f->zname = m;
X *fnxt = f;
X f->lst = fnxt;
X f->nxt = NULL;
X fnxt = &f->nxt;
X fcount++;
X }
X return ZE_OK;
X}
X
X
Xint procname(n)
Xchar *n; /* name to process */
X/* Process a name or sh expression to operate on (or exclude). Return
X an error code in the ZE_ class. */
X{
X char *a; /* path and name for recursion */
X dstrm *d; /* directory stream from opend() */
X char *e; /* pointer to name from readd() */
X struct flist far *f; /* steps through found list */
X int m; /* matched flag */
X char *p; /* path for recursion */
X struct stat s; /* result of stat() */
X struct zlist far *z; /* steps through zfiles list */
X
X if (
X#ifdef S_IFLNK /* if symbolic links exist ... */
X linkput ? lstat(n, &s) :
X#endif /* S_IFLNK */
X stat(n, &s)
X#ifdef __TURBOC__ /* Borland bug: stat() succeeds on wild card names! */
X || isshexp(n)
X#endif /* __TURBOC__ */
X )
X {
X /* Not a file--search for shell expression in zip file */
X p = ex2in(n); /* shouldn't affect matching chars */
X m = 1;
X for (z = zfiles; z != NULL; z = z->nxt)
X if (MATCH(p, z->zname))
X {
X z->mark = !exflag;
X if (verbose)
X printf("zip diagnostic: %scluding %s\n",
X exflag ? "ex" : "in", z->name);
X m = 0;
X }
X /* If excluding, also search for expression in found list */
X if (exflag)
X {
X for (f = found; f != NULL;)
X if (MATCH(p, f->zname))
X {
X f = fexpel(f);
X m = 0;
X }
X else
X f = f->nxt;
X }
X free((voidp *)p);
X if (m)
X return ZE_MISS; /* no match */
X }
X else
X {
X /* Live name--use if file, recurse if directory */
X#ifdef MSDOS
X#ifndef OS2
X strupr(n); /* convert to upper case */
X#endif /* !OS2 */
X for (p = n; *p; p++) /* use / consistently */
X if (*p == '\\')
X *p = '/';
X#endif /* MSDOS */
X switch (s.st_mode & S_IFMT)
X {
X case S_IFREG: /* add or remove name of file */
X#ifdef S_IFLNK
X case S_IFLNK:
X#endif /* S_IFLNK */
X if ((m = newname(n)) != ZE_OK)
X return m;
X break;
X case S_IFDIR: /* recurse into directory */
X if (recurse && (d = opend(n)) != NULL)
X {
X#ifdef VMS
X while ((e = readd(d)) != NULL)
X if ((m = procname(e)) != ZE_OK) /* recurse on name */
X {
X /* want to just set warning error and continue */
X closed(d);
X return m;
X }
X#else /* !VMS */
X if ((p = malloc(strlen(n)+2)) == NULL)
X return ZE_MEM;
X if (strcmp(n, ".") == 0)
X *p = 0; /* avoid "./" prefix */
X else
X {
X strcpy(p, n);
X a = p + strlen(p);
X if (a[-1] != '/')
X strcpy(a, "/");
X }
X while ((e = readd(d)) != NULL)
X if (strcmp(e, ".") && strcmp(e, ".."))
X {
X if ((a = malloc(strlen(p) + strlen(e) + 1)) == NULL)
X {
X free((voidp *)p);
X closed(d);
X return ZE_MEM;
X }
X strcat(strcpy(a, p), e);
X if ((m = procname(a)) != ZE_OK) /* recurse on name */
X {
X free((voidp *)a); free((voidp *)p);
X closed(d);
X return m;
X }
X free((voidp *)a);
X }
X free((voidp *)p);
X#endif /* ?VMS */
X closed(d);
X }
X }
X }
X return ZE_OK;
X}
X
X
X#ifndef __TURBOC__
Xlocal int cmptime(p, q)
Xstruct tm *p, *q; /* times to compare */
X/* Return negative if time p is before time q, positive if after, and
X zero if the same */
X{
X int r; /* temporary variable */
X
X if ((r = p->tm_year - q->tm_year) != 0)
X return r;
X else if ((r = p->tm_mon - q->tm_mon) != 0)
X return r;
X else if ((r = p->tm_mday - q->tm_mday) != 0)
X return r;
X else if ((r = p->tm_hour - q->tm_hour) != 0)
X return r;
X else if ((r = p->tm_min - q->tm_min) != 0)
X return r;
X else
X return p->tm_sec - q->tm_sec;
X}
X
X
Xlocal time_t invlocal(t)
Xstruct tm *t; /* time to convert */
X/* Find inverse of localtime() using bisection. This routine assumes that
X time_t is an integer type, either signed or unsigned. The expectation
X is that sometime before the year 2038, time_t will be made a 64-bit
X integer, and this routine will still work. */
X{
X time_t i; /* midpoint of current root range */
X time_t l; /* lower end of root range */
X time_t u; /* upper end of root range */
X
X /* Bracket the root [0,largest time_t]. Note: if time_t is a 32-bit signed
X integer, then the upper bound is GMT 1/19/2038 03:14:07, after which all
X the Unix systems in the world come to a grinding halt. Either that, or
X all those systems will suddenly find themselves transported to December
X of 1901 ... */
X l = 0;
X u = 1;
X while (u < (u << 1))
X u = (u << 1) + 1;
X
X /* Find the root */
X while (u - l > 1)
X {
X i = l + ((u - l) >> 1);
X if (cmptime(localtime(&i), t) <= 0)
X l = i;
X else
X u = i;
X }
X return l;
X}
X#endif /* !__TURBOC__ */
X
X
Xvoid stamp(f, d)
Xchar *f; /* name of file to change */
Xulg d; /* dos-style time to change it to */
X/* Set last updated and accessed time of file f to the DOS time d. */
X{
X#ifdef __TURBOC__
X int h; /* file handle */
X
X if ((h = open(f, 0)) != -1)
X {
X setftime(h, (struct ftime *)&d);
X close(h);
X }
X#else /* !__TURBOC__ */
X#ifdef VMS
X warn("timestamp not implemented yet under VMS", "");
X#else /* !VMS */
X struct tm t; /* argument for invlocal() */
X time_t u[2]; /* argument for utime() */
X
X /* Convert DOS time to time_t format in u[0] and u[1] */
X t.tm_sec = (int)(d << 1) & 0x3e;
X t.tm_min = (int)(d >> 5) & 0x3f;
X t.tm_hour = (int)(d >> 11) & 0x1f;
X t.tm_mday = (int)(d >> 16) & 0x1f;
X t.tm_mon = ((int)(d >> 21) & 0xf) - 1;
X t.tm_year = ((int)(d >> 25) & 0x7f) + 80;
X u[0] = u[1] = invlocal(&t);
X
X /* Set updated and accessed times of f */
X utime(f, u);
X#endif /* ?VMS */
X#endif /* ?__TURBOC__ */
X}
X
X
Xlocal void inctime(s)
Xstruct tm *s; /* time to increment in place */
X/* Increment the time structure *s by one second, return the result in
X place. */
X{
X int y; /* temporary variable */
X
X /* days in each month, except for February */
X static int days[] = {31,0,31,30,31,30,31,31,30,31,30,31};
X
X /* Set days in February from year (1900 is a leap year, 2000 is not) */
X y = s->tm_year + 1900;
X days[1] = y % 4 == 0 && (y % 100 != 0 || y % 400 == 0) ? 29 : 28;
X
X /* Increment time with carry */
X if (s->tm_sec != 59)
X s->tm_sec++;
X else if (s->tm_sec = 0, s->tm_min != 59)
X s->tm_min++;
X else if (s->tm_min = 0, s->tm_hour != 23)
X s->tm_hour++;
X else if (s->tm_hour = 0, s->tm_mday != days[s->tm_mon])
X s->tm_mday++;
X else if (s->tm_mday = 1, s->tm_mon != 11)
X s->tm_mon++;
X else
X {
X s->tm_mon = 0;
X s->tm_year++;
X }
X}
X
X
Xulg dostime(y, n, d, h, m, s)
Xint y; /* year */
Xint n; /* month */
Xint d; /* day */
Xint h; /* hour */
Xint m; /* minute */
Xint s; /* second */
X/* Convert the date y/n/d and time h:m:s to a four byte DOS date and
X time (date in high two bytes, time in low two bytes allowing magnitude
X comparison). */
X{
X return y < 1980 ? dostime(1980, 1, 1, 0, 0, 0) :
X (((ulg)y - 1980) << 25) | ((ulg)n << 21) | ((ulg)d << 16) |
X ((ulg)h << 11) | ((ulg)m << 5) | ((ulg)s >> 1);
X}
X
X
Xlocal ulg unix2dostime(t)
Xtime_t *t; /* unix time to convert */
X/* Return the Unix time t in DOS format, rounded up to the next two
X second boundary. */
X{
X struct tm *s; /* result of localtime() */
X
X s = localtime(t); /* Use local time since MSDOS does */
X inctime(s); /* Add one second to round up */
X return dostime(s->tm_year + 1900, s->tm_mon + 1, s->tm_mday,
X s->tm_hour, s->tm_min, s->tm_sec);
X}
X
X
Xulg filetime(f, a, n)
Xchar *f; /* name of file to get info on */
Xulg *a; /* return value: file attributes */
Xlong *n; /* return value: file size */
X/* If file *f does not exist, return 0. Else, return the file's last
X modified date and time as an MSDOS date and time. The date and
X time is returned in a long with the date most significant to allow
X unsigned integer comparison of absolute times. Also, if a is not
X a NULL pointer, store the file attributes there, with the high two
X bytes being the Unix attributes, and the low byte being a mapping
X of that to DOS attributes. If n is not NULL, store the file size
X there. */
X{
X struct stat s; /* results of stat() */
X
X#ifdef S_IFLNK
X if (linkput ? lstat(f, &s) == 0 && ((s.st_mode & S_IFMT) == S_IFREG ||
X (s.st_mode & S_IFMT) == S_IFLNK) :
X#else /* !S_IFLNK */
X if (
X#endif /* ?S_IFLNK */
X stat(f, &s) == 0 && (s.st_mode & S_IFMT) == S_IFREG)
X {
X if (a != NULL)
X *a = (s.st_mode << 16) | !(s.st_mode & S_IWRITE);
X if (n != NULL)
X *n = s.st_size;
X#ifdef VMS
X return unix2dostime(&s.st_ctime); /* Use creation time in VMS */
X#else /* !VMS */
X return unix2dostime(&s.st_mtime);
X#endif /* ?VMS */
X }
X else
X return 0;
X}
X
X
Xint issymlnk(a)
Xulg a; /* Attributes returned by filetime() */
X/* Return true if the attributes are those of a symbolic link */
X{
X#ifdef S_IFLNK
X return ((a >> 16) & S_IFMT) == S_IFLNK;
X#else /* !S_IFLNK */
X return (int)a & 0; /* avoid warning on unused parameter */
X#endif /* ?S_IFLNK */
X}
X
X
Xint deletedir(d)
Xchar *d; /* directory to delete */
X/* Delete the (empty) directory *d. Return the result of rmdir(), delete(),
X or system(). */
X{
X#ifdef RMDIR
X /* code from Greg Roelofs, who horked it from Mark Edwards (unzip) */
X int r, len;
X char *s; /* malloc'd string for system command */
X
X len = strlen(d);
X if ((s = malloc(len + 34)) == NULL)
X return 127;
X
X#ifdef VMS
X {
X char *c; /* pointer into VMS path */
X /* convert "DEV:[DIR.SUB1.SUB2]" form to "DEV:[DIR.SUB1]SUB2.DIR;0" */
X strcat(strcpy(s, "set prot=(o:rwed) "), d); /* d starts at s+18 */
X if (*(c = s+17+len) != ']')
X {
X free(s);
X return 127;
X }
X strcpy(c, ".DIR;0"); /* 0 translates to highest version */
X while (--c > s+18 && *c != '.' && *c != '[') ;
X if (c == s+18)
X {
X free(s);
X return 127;
X }
X if (*c == '.')
X *c = ']';
X else if (*--c == ']') /* presumably of form "DEV:[DIR.SUB1.][SUB2]" */
X { /* (possible to have "DEV:[DIR.SUB1.][][SUB2]"?) */
X char *b = c + 2;
X c[-1] = ']';
X while (*c++ = *b++) ;
X }
X else /* must have reached device name: can't delete top level */
X {
X free(s);
X return 127;
X }
X }
X /* unprotect directory and delete it as a file. May fail if exists
X normal file "foo.dir" on top of directory "foo.dir" */
X system(s);
X r = delete(s+18);
X#else /* !VMS */
X sprintf(s, "IFS=\" \t\n\" /bin/rmdir %s 2>/dev/null", d);
X r = system(s);
X#endif /* ?VMS */
X free(s);
X return r;
X#else /* !RMDIR */
X return rmdir(d);
X#endif /* ?RMDIR */
X}
X
X
X#endif /* !UTIL */
X
X
Xint destroy(f)
Xchar *f; /* file to delete */
X/* Delete the file *f, returning non-zero on failure. */
X{
X return unlink(f);
X}
X
X
Xint replace(d, s)
Xchar *d, *s; /* destination and source file names */
X/* Replace file *d by file *s, removing the old *s. Return an error code
X in the ZE_ class. */
X{
X struct stat t; /* results of stat() */
X
X if (stat(d, &t) == 0 && unlink(d))
X return ZE_CREAT; /* Can't erase zip file--give up */
X if (link(s, d)) /* Just move s on top of d */
X#ifndef VMS /* For VMS, assume failure is EXDEV */
X if (errno != EXDEV)
X return ZE_CREAT;
X else
X#endif /* !VMS */
X {
X FILE *f, *g; /* source and destination files */
X int r; /* temporary variable */
X
X if ((f = fopen(s, FOPR)) == NULL)
X return ZE_TEMP;
X if ((g = fopen(d, FOPW)) == NULL)
X {
X fclose(f);
X return ZE_CREAT;
X }
X r = fcopy(f, g, (ulg)-1L);
X fclose(f);
X if (fclose(g) || r != ZE_OK)
X {
X unlink(d);
X return r ? (r == ZE_TEMP ? ZE_WRITE : r) : ZE_WRITE;
X }
X#ifdef VMS /* only delete if rename failed: previous version may exist */
X unlink(s);
X }
X#else /* !VMS */
X }
X unlink(s);
X#endif /* !VMS */
X return ZE_OK;
X}
X
X
Xint getfileattr(f)
Xchar *f; /* file path */
X/* Return the file attributes for file f or -1 if failure */
X{
X struct stat s;
X
X return stat(f, &s) == 0 ? s.st_mode : 0;
X}
X
X
Xint setfileattr(f, a)
Xchar *f; /* file path */
Xint a; /* attributes returned by getfileattr() */
X/* Give the file f the attributes a, return non-zero on failure */
X{
X#ifdef VMS
X return 0;
X#else /* !VMS */
X return chmod(f, a);
X#endif /* ?VMS */
X}
X
X
Xchar *tempname(c)
Xint c; /* character to insert in name */
X/* Return a temporary file name in its own malloc'ed space, using tempath. */
X{
X char *p; /* temporary pointer */
X char *t; /* malloc'ed space for name */
X
X if (tempath != NULL)
X {
X if ((t = malloc(strlen(tempath)+10)) == NULL)
X return NULL;
X strcpy(t, tempath);
X if (t[strlen(t)-1] != '/')
X strcat(t, "/");
X }
X else
X {
X if ((t = malloc(9)) == NULL)
X return NULL;
X *t = 0;
X }
X p = t + strlen(t);
X *p++ = '_';
X *p++ = (char)c;
X strcpy(p, "XXXXXX");
X return mktemp(t);
X}
X
X
Xint fcopy(f, g, n)
XFILE *f, *g; /* source and destination files */
Xulg n; /* number of bytes to copy or -1 for all */
X/* Copy n bytes from file *f to file *g, or until EOF if n == -1. Return
X an error code in the ZE_ class. */
X{
X char *b; /* malloc'ed buffer for copying */
X extent k; /* result of fread() */
X ulg m; /* bytes copied so far */
X
X if ((b = malloc(BSZ)) == NULL)
X return ZE_MEM;
X m = 0;
X while (n == -1L || m < n)
X {
X if ((k = fread(b, 1, n == -1 ?
X BSZ : (n - m < BSZ ? (extent)(n - m) : BSZ), f)) == 0)
X if (ferror(f))
X {
X free((voidp *)b);
X return ZE_READ;
X }
X else
X break;
X if (fwrite(b, 1, k, g) != k)
X {
X free((voidp *)b);
X return ZE_TEMP;
X }
X m += k;
X }
X free((voidp *)b);
X return ZE_OK;
X}
X
X
X#ifndef EXPORT
X
X#ifndef MSVMS
X
Xlocal int echofd = -1; /* file descriptor whose echo is off */
X
Xvoid echoff(f)
Xint f; /* file descriptor to turn echo off on */
X/* Turn echo off for file descriptor f. Assumes that f is a tty device. */
X{
X struct sgttyb sg; /* tty device structure */
X
X echofd = f;
X GTTY(f, &sg); /* get settings */
X sg.sg_flags &= ~ECHO; /* turn echo off */
X STTY(f, &sg);
X}
X
Xvoid echon()
X/* Turn echo back on for file descriptor echofd. */
X{
X struct sgttyb sg; /* tty device structure */
X
X if (echofd != -1)
X {
X GTTY(echofd, &sg); /* get settings */
X sg.sg_flags |= ECHO; /* turn echo on */
X STTY(echofd, &sg);
X echofd = -1;
X }
X}
X
X#endif /* !MSVMS */
X
X
Xchar *getp(m, p, n)
Xchar *m; /* prompt for password */
Xchar *p; /* return value: line input */
Xint n; /* bytes available in p[] */
X/* Get a password of length n-1 or less into *p using the prompt *m.
X The entered password is not echoed. Return p on success, NULL on
X failure (can't get controlling tty). */
X{
X char c; /* one-byte buffer for read() to use */
X int i; /* number of characters input */
X char *w; /* warning on retry */
X
X#ifndef MSVMS
X int f; /* file decsriptor for tty device */
X
X /* Turn off echo on tty */
X if (!isatty(2))
X return NULL; /* error if not tty */
X if ((f = open(ttyname(2), 0, 0)) == -1)
X return NULL;
X echoff(f); /* turn echo off */
X#endif /* !MSVMS */
X
X /* Get password */
X w = "";
X do {
X fputs(w, stderr); /* warning if back again */
X fputs(m, stderr); /* prompt */
X fflush(stderr);
X i = 0;
X do { /* read line, keeping n */
X#ifdef MSVMS
X if ((c = (char)getch()) == '\r')
X c = '\n';
X#else /* !MSVMS */
X read(f, &c, 1);
X#endif /* ?MSVMS */
X if (i < n)
X p[i++] = c;
X } while (c != '\n');
X putc('\n', stderr); fflush(stderr);
X w = "(line too long--try again)\n";
X } while (p[i-1] != '\n');
X p[i-1] = 0; /* terminate at newline */
X
X#ifndef MSVMS
X /* Turn echo back on */
X echon(); /* turn echo back on */
X close(f);
X#endif /* !MSVMS */
X
X /* Return pointer to password */
X return p;
X}
X
X#endif /* !EXPORT */
X
X
X#ifdef ZMEM
X
X/************************/
X/* Function memset() */
X/************************/
X
X/*
X * memset - for systems without it
X * bill davidsen - March 1990
X */
X
Xchar *
Xmemset(buf, init, len)
Xregister char *buf; /* buffer loc */
Xregister int init; /* initializer */
Xregister unsigned int len; /* length of the buffer */
X{
X char *start;
X
X start = buf;
X while (len--) *(buf++) = init;
X return(start);
X}
X
X
X/************************/
X/* Function memcpy() */
X/************************/
X
Xchar *
Xmemcpy(dst,src,len) /* v2.0f */
Xregister char *dst, *src;
Xregister unsigned int len;
X{
X char *start;
X
X start = dst;
X while (len--)
X *dst++ = *src++;
X return(start);
X}
X
X
X/************************/
X/* Function memcmp() */
X/************************/
X
Xint
Xmemcmp(b1,b2,len) /* jpd@usl.edu -- 11/16/90 */
Xregister char *b1, *b2;
Xregister unsigned int len;
X{
X
X if (len) do { /* examine each byte (if any) */
X if (*b1++ != *b2++)
X return (*--((uch *)b1) - *--((uch *)b2)); /* exit when miscompare */
X } while (--len);
X
X return(0); /* no miscompares, yield 0 result */
X}
X
X#endif /* ZMEM */
END_OF_FILE
if test 44358 -ne `wc -c <'fileio.c'`; then
echo shar: \"'fileio.c'\" unpacked with wrong size!
fi
# end of 'fileio.c'
fi
if test -f 'zip.prj' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'zip.prj'\"
else
echo shar: Extracting \"'zip.prj'\" \(620 characters\)
sed "s/^X//" >'zip.prj' <<'END_OF_FILE'
Xzip.c (zip.h ziperr.h tailor.h revision.h)
Xzipfile.c (zip.h ziperr.h tailor.h)
Xzipup.c (zip.h ziperr.h tailor.h revision.h)
Xfileio.c (zip.h ziperr.h tailor.h)
Xutil.c (zip.h ziperr.h tailor.h)
Xtempf.c (tempf.h tailor.h)
Xshrink.c (zip.h ziperr.h tempf.h tailor.h)
Xcrypt.c (zip.h ziperr.h tailor.h)
Xglobals.c (zip.h ziperr.h tailor.h)
Ximplode.c (implode.h crypt.h ziperr.h tempf.h tailor.h)
Xim_lmat.c (implode.h crypt.h ziperr.h tempf.h tailor.h)
Xim_ctree.c (implode.h crypt.h ziperr.h tempf.h tailor.h)
Xim_bits.c (implode.h crypt.h ziperr.h tempf.h tailor.h)
Xim_lm.obj
END_OF_FILE
if test 620 -ne `wc -c <'zip.prj'`; then
echo shar: \"'zip.prj'\" unpacked with wrong size!
fi
# end of 'zip.prj'
fi
echo shar: End of archive 2 \(of 9\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 9 archives.
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still must unpack the following archives:
echo " " ${MISSING}
fi
exit 0
exit 0 # Just in case...
--
Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM
Sterling Software, IMD UUCP: uunet!sparky!kent
Phone: (402) 291-8300 FAX: (402) 291-4362
Please send comp.sources.misc-related mail to kent@uunet.uu.net.