879 lines
19 KiB
C
879 lines
19 KiB
C
/*
|
|
qdos/qdos.c
|
|
|
|
Copyright (c) 1990-2005 Info-ZIP. All rights reserved.
|
|
|
|
See the accompanying file LICENSE, version 2005-Feb-10 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
|
|
*/
|
|
/*
|
|
* Yes this file is necessary; the QDOS file system is the most
|
|
* ludicrous known to man (even more so than VMS!).
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include <dirent.h>
|
|
#include <unistd.h>
|
|
|
|
#include "zip.h"
|
|
#include "crypt.h"
|
|
#include "ttyio.h"
|
|
|
|
#ifdef QDOS
|
|
|
|
# include <qdos.h>
|
|
|
|
#if CRYPT
|
|
|
|
char *getp(m, p, n)
|
|
ZCONST char *m; /* prompt for password */
|
|
char *p; /* return value: line input */
|
|
int n; /* bytes available in p[] */
|
|
{
|
|
int c; /* one-byte buffer for read() to use */
|
|
int i; /* number of characters input */
|
|
char *w; /* warning on retry */
|
|
|
|
/* get password */
|
|
w = "";
|
|
sd_cure(getchid(0), -1); /* enable cursor */
|
|
do {
|
|
fputs(w, stderr); /* warning if back again */
|
|
fputs(m, stderr); /* display prompt and flush */
|
|
fflush(stderr);
|
|
i = 0;
|
|
do {
|
|
c = getch();
|
|
if (c == 0xc2) {
|
|
if (i > 0) {
|
|
i--; /* the `del' keys works */
|
|
fputs("\b \b", stderr);
|
|
}
|
|
}
|
|
else if (i < n) {
|
|
p[i++] = c; /* truncate past n */
|
|
if(c != '\n') putc('*', stderr);
|
|
}
|
|
} while (c != '\n');
|
|
|
|
putc('\n', stderr); fflush(stderr);
|
|
w = "(line too long--try again)\n";
|
|
} while (p[i-1] != '\n');
|
|
|
|
p[i-1] = 0; /* terminate at newline */
|
|
sd_curs(getchid(0), -1); /* suppress cursor */
|
|
return p; /* return pointer to password */
|
|
|
|
} /* end function getp() */
|
|
|
|
#endif /* CRYPT */
|
|
|
|
|
|
#define __attribute__(p)
|
|
|
|
int newname(char *, int, int);
|
|
|
|
#else /* !QDOS */
|
|
#define QDOS_FLMAX 36
|
|
|
|
short qlflag = 0;
|
|
|
|
struct qdirect {
|
|
long d_length __attribute__ ((packed)); /* file length */
|
|
unsigned char d_access __attribute__ ((packed)); /* file access type */
|
|
unsigned char d_type __attribute__ ((packed)); /* file type */
|
|
long d_datalen __attribute__ ((packed)); /* data length */
|
|
long d_reserved __attribute__ ((packed));/* Unused */
|
|
short d_szname __attribute__ ((packed)); /* size of name */
|
|
char d_name[QDOS_FLMAX] __attribute__ ((packed));/* name area */
|
|
long d_update __attribute__ ((packed)); /* last update */
|
|
long d_refdate __attribute__ ((packed));
|
|
long d_backup __attribute__ ((packed)); /* EOD */
|
|
} ;
|
|
#endif /* ?QDOS */
|
|
|
|
#define SHORTID 0x4afb /* in big-endian order !! */
|
|
#define LONGID "QDOS02"
|
|
#define EXTRALEN (sizeof(struct qdirect) + 8)
|
|
|
|
typedef struct
|
|
{
|
|
unsigned short shortid __attribute__ ((packed));
|
|
struct
|
|
{
|
|
unsigned char lo __attribute__ ((packed));
|
|
unsigned char hi __attribute__ ((packed));
|
|
} len __attribute__ ((packed));
|
|
char longid[8] __attribute__ ((packed));
|
|
struct qdirect header __attribute__ ((packed));
|
|
} qdosextra;
|
|
|
|
#ifdef USE_EF_UT_TIME
|
|
local int GetExtraTime(struct zlist far *z, iztimes *z_utim, unsigned ut_flg);
|
|
#endif
|
|
|
|
#ifdef QDOS
|
|
|
|
#define rev_short(x) (x)
|
|
#define rev_long(x) (x)
|
|
|
|
char _prog_name[] = "zip";
|
|
char _copyright[] = "(c) Info-ZIP Group";
|
|
long _stack = 16*1024;
|
|
char * _endmsg = NULL;
|
|
|
|
extern void consetup_title(chanid_t,struct WINDOWDEF *);
|
|
void (*_consetup)(chanid_t,struct WINDOWDEF *) = consetup_title;
|
|
|
|
struct WINDOWDEF _condetails =
|
|
{
|
|
2,
|
|
1,
|
|
0,
|
|
7,
|
|
500,
|
|
220,
|
|
2,
|
|
30
|
|
};
|
|
|
|
extern short qlwait;
|
|
extern short dtype;
|
|
|
|
#define CHECKDIR(p1) (((p1).d_type == dtype) && (((p1).d_length % 64) == 0))
|
|
|
|
char * stpcpy (char *d, ZCONST char *s)
|
|
{
|
|
while(*d++ = *s++)
|
|
; /* Null loop */
|
|
return d-1;
|
|
}
|
|
|
|
static jobid_t chowner(chanid_t chan)
|
|
{
|
|
extern char *_sys_var;
|
|
char *scht;
|
|
long *cdb;
|
|
long jid;
|
|
|
|
scht = *((char **)(_sys_var + 0x78));
|
|
cdb = *(long **)((long *)scht + (chan & 0xffff));
|
|
jid = *(cdb + 2);
|
|
return jid;
|
|
}
|
|
|
|
void QDOSexit(void)
|
|
{
|
|
jobid_t me,you;
|
|
|
|
me = getpid();
|
|
you = chowner(getchid(0));
|
|
|
|
if((me == you) && ((qlflag & 4) == 0))
|
|
{
|
|
if(isatty(0) && isatty(2) && qlwait)
|
|
{
|
|
char c = 0;
|
|
fputs("Press a key to exit", stderr);
|
|
if((io_fbyte(getchid(0), qlwait, &c) == 0) && c == 27)
|
|
{
|
|
io_fbyte(getchid(0), -1, &c);
|
|
}
|
|
}
|
|
}
|
|
exit(ZE_OK);
|
|
}
|
|
|
|
/* Access seems to be *always* broken in c68 */
|
|
/* Not accurate, just works */
|
|
|
|
int access (char *f, int mode)
|
|
{
|
|
struct stat st;
|
|
int fd;
|
|
|
|
if((fd = stat(f, &st)) == 0)
|
|
{
|
|
switch(fd)
|
|
{
|
|
case F_OK:
|
|
break;
|
|
case R_OK:
|
|
fd = (st.st_mode & 0444) == 0;
|
|
break;
|
|
case W_OK:
|
|
fd = (st.st_mode & 0222) == 0;
|
|
break;
|
|
case X_OK:
|
|
fd = (st.st_mode & 0111) == 0;
|
|
break;
|
|
default:
|
|
fd = -1;
|
|
break;
|
|
}
|
|
}
|
|
return fd;
|
|
}
|
|
|
|
/* Fixup a Mickey Mouse file naming system */
|
|
|
|
char * Unix2ql (char *qlname, char **dot)
|
|
{
|
|
static char path[64];
|
|
char name[64];
|
|
char *q, *r, *s;
|
|
|
|
strcpy(name, qlname);
|
|
if(*name == '~')
|
|
{
|
|
r = name+1;
|
|
getcwd(path, sizeof(path));
|
|
q = path + strlen(path);
|
|
if(*(q-1) != '_')
|
|
{
|
|
*q++ = '_';
|
|
}
|
|
}
|
|
else
|
|
{
|
|
q = path;
|
|
r = name;
|
|
}
|
|
|
|
if(*r == '/')
|
|
{
|
|
r++;
|
|
}
|
|
|
|
strcpy(q, r);
|
|
|
|
while (*q)
|
|
{
|
|
if(*q == '/' || *q == '.')
|
|
{
|
|
if(*q == '.' && dot)
|
|
{
|
|
*dot = name + (q - path);
|
|
}
|
|
*q = '_';
|
|
}
|
|
|
|
q++;
|
|
}
|
|
return path;
|
|
}
|
|
|
|
#if 0 /* Not used in ZIP */
|
|
|
|
GuessAltName(char *name, char *dot)
|
|
{
|
|
if(dot)
|
|
{
|
|
*dot = '.';
|
|
}
|
|
else
|
|
{
|
|
if((dot = strrchr(name, '_')))
|
|
{
|
|
*dot = '.';
|
|
}
|
|
}
|
|
}
|
|
|
|
#endif /* 0 */
|
|
|
|
short devlen(char *p)
|
|
{
|
|
char defpath[40];
|
|
short deflen = 0, ok = 0;
|
|
|
|
getcwd(defpath, sizeof(defpath));
|
|
deflen = strlen(defpath);
|
|
if(deflen)
|
|
{
|
|
if(strnicmp(p, defpath, deflen) == 0)
|
|
{
|
|
ok = 1;
|
|
}
|
|
}
|
|
|
|
if(!ok)
|
|
{
|
|
if(isdirdev(p))
|
|
{
|
|
deflen = 5;
|
|
}
|
|
else
|
|
{
|
|
deflen = 0;
|
|
}
|
|
}
|
|
return deflen;
|
|
}
|
|
|
|
char * ql2Unix (char *qlname)
|
|
{
|
|
struct stat st;
|
|
int sts;
|
|
char *p, *r, *s, *ldp;
|
|
char *pnam = NULL;
|
|
static char path[64];
|
|
short deflen;
|
|
char name[64];
|
|
|
|
strcpy(name, qlname);
|
|
strcpy(path, name);
|
|
|
|
deflen = devlen(qlname);
|
|
|
|
p = name + deflen;
|
|
pnam = path + deflen;
|
|
|
|
if(s = strrchr(p, '_'))
|
|
{
|
|
*s = 0;
|
|
sts = stat(name, &st);
|
|
if(deflen && sts ==0 && (st.st_mode & S_IFDIR))
|
|
{
|
|
*(path+(s-name)) = '/';
|
|
}
|
|
else
|
|
{
|
|
*(path+(s-name)) = '.';
|
|
}
|
|
}
|
|
|
|
ldp = p;
|
|
for(r = p; *r; r++)
|
|
{
|
|
if(r != ldp && *r == '_')
|
|
{
|
|
*r = 0;
|
|
if(deflen)
|
|
{
|
|
sts = stat(name, &st);
|
|
}
|
|
else
|
|
sts = -1;
|
|
|
|
if(sts ==0 && (st.st_mode & S_IFDIR))
|
|
{
|
|
*(path+(r-name)) = '/';
|
|
ldp = r + 1;
|
|
}
|
|
else
|
|
{
|
|
*(path+(r-name)) = '_';
|
|
}
|
|
*r = '_';
|
|
}
|
|
}
|
|
return pnam;
|
|
}
|
|
|
|
char *LastDir(char *ws)
|
|
{
|
|
char *p;
|
|
char *q = ws;
|
|
struct stat s;
|
|
|
|
for(p = ws; *p; p++)
|
|
{
|
|
if(p != ws && *p == '_')
|
|
{
|
|
char c;
|
|
|
|
p++;
|
|
c = *p;
|
|
*p = 0;
|
|
if(stat(ws, &s) == 0 && S_ISDIR(s.st_mode))
|
|
{
|
|
q = p;
|
|
}
|
|
*p = c;
|
|
}
|
|
}
|
|
return q;
|
|
}
|
|
|
|
# ifndef UTIL
|
|
|
|
static int add_dir(char * dnam)
|
|
{
|
|
int e = ZE_OK;
|
|
char *p;
|
|
short nlen;
|
|
|
|
nlen = strlen(dnam);
|
|
if(p = malloc(nlen + 2))
|
|
{
|
|
strncpy (p, dnam, nlen);
|
|
if(*(p+nlen) != '_')
|
|
{
|
|
*(p+nlen) = '_';
|
|
*(p+nlen+1) = '\0';
|
|
}
|
|
if ((e = newname(p, 1, 0)) != ZE_OK)
|
|
{
|
|
free(p);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
e = ZE_MEM;
|
|
}
|
|
return e;
|
|
}
|
|
|
|
int qlwild (char *dnam, short dorecurse, short l)
|
|
{
|
|
static char match[40] = {0};
|
|
static char ddev[8] = {0};
|
|
static short nc;
|
|
static short llen;
|
|
static char base[40];
|
|
|
|
int chid;
|
|
struct qdirect qd;
|
|
char *dp;
|
|
int e = ZE_MISS;
|
|
|
|
if (l == 0)
|
|
{
|
|
nc = 0;
|
|
*base = '\0';
|
|
if (isdirdev (dnam))
|
|
{
|
|
dp = dnam;
|
|
strncpy (ddev, dnam, 5);
|
|
}
|
|
else
|
|
{
|
|
|
|
char *p;
|
|
char temp[40];
|
|
|
|
getcwd (temp, 40);
|
|
|
|
llen = strlen(temp);
|
|
p = (temp + llen - 1);
|
|
if (*p != '_')
|
|
{
|
|
*p++ = '_';
|
|
*p = 0;
|
|
}
|
|
|
|
strncpy (ddev, temp, 5);
|
|
dp = base;
|
|
p = stpcpy (dp, temp);
|
|
strcpy (p, dnam);
|
|
}
|
|
|
|
{
|
|
char *q = isshexp (dp);
|
|
if(q)
|
|
{
|
|
strcpy (match, dp + 5);
|
|
if (q)
|
|
{
|
|
while (q != dp && *q != '_')
|
|
{
|
|
q--;
|
|
}
|
|
*(++q) = '\0';
|
|
}
|
|
}
|
|
else
|
|
{
|
|
struct stat s;
|
|
if (stat(dp, &s) == 0)
|
|
{
|
|
if (!(s.st_mode & S_IFDIR))
|
|
{
|
|
return procname(dp, 0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return ZE_MISS; /* woops, no wildcards! */
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
dp = dnam;
|
|
}
|
|
|
|
if ((chid = io_open (dp, 4L)) > 0)
|
|
{
|
|
int id = 0;
|
|
while (io_fstrg (chid, -1, &qd, 64) > 0)
|
|
{
|
|
short j;
|
|
|
|
if (qd.d_szname)
|
|
{
|
|
if (CHECKDIR(qd))
|
|
{
|
|
if(dorecurse)
|
|
{
|
|
char fnam[256], *p;
|
|
|
|
p = stpcpy (fnam, ddev);
|
|
strncpy (p, qd.d_name, qd.d_szname);
|
|
*(p + qd.d_szname) = 0;
|
|
e = qlwild (fnam, dorecurse, l+1);
|
|
}
|
|
else
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
char nam[48];
|
|
strcpy(nam, ddev);
|
|
|
|
strncpy (nam + 5, qd.d_name, qd.d_szname);
|
|
*(nam + 5 + qd.d_szname) = 0;
|
|
|
|
if (MATCH (match, nam + 5, 0) == 1)
|
|
{
|
|
if(dirnames && l && id == 0)
|
|
{
|
|
id = 1;
|
|
if((e = add_dir(dp)) != ZE_OK)
|
|
{
|
|
return e;
|
|
}
|
|
}
|
|
|
|
if((e = procname(nam, 0)) == ZE_OK)
|
|
{
|
|
nc++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
io_close (chid);
|
|
}
|
|
|
|
if (l == 0)
|
|
{
|
|
*ddev = 0;
|
|
*match = 0;
|
|
e = (nc) ? ZE_OK : ZE_MISS;
|
|
}
|
|
return e;
|
|
|
|
}
|
|
|
|
int wild(char *p)
|
|
{
|
|
return qlwild(p, recurse, 0);
|
|
}
|
|
# endif /* !UTIL */
|
|
|
|
/*
|
|
* Return QDOS error, 0 if exec 1 if found but not exe or rel
|
|
*/
|
|
int qlstat(char *name, struct qdirect *qs, char *flag)
|
|
{
|
|
int r;
|
|
r = qstat(name, qs);
|
|
if(r == 0)
|
|
{
|
|
if(qs->d_type == 0)
|
|
{
|
|
r = 1;
|
|
}
|
|
else if(CHECKDIR(*qs))
|
|
{
|
|
r = 255;
|
|
}
|
|
}
|
|
return r;
|
|
}
|
|
|
|
#else /* !QDOS */
|
|
|
|
long rev_long (ulg l)
|
|
{
|
|
uch cc[4];
|
|
cc[0] = (uch)(l >> 24);
|
|
cc[1] = (uch)((l >> 16) & 0xff);
|
|
cc[2] = (uch)((l >> 8) & 0xff);
|
|
cc[3] = (uch)(l & 0xff);
|
|
return *(ulg *)cc;
|
|
}
|
|
|
|
short rev_short (ush s)
|
|
{
|
|
uch cc[2];
|
|
cc[0] = (uch)((s >> 8) & 0xff);
|
|
cc[1] = (uch)(s & 0xff);
|
|
return *(ush *)cc;
|
|
}
|
|
|
|
#define O_BINARY 0
|
|
|
|
int qlstat(char *name, struct qdirect *qs, char *flag)
|
|
{
|
|
int r = -1;
|
|
int n, fd;
|
|
struct stat s;
|
|
struct _ntc_
|
|
{
|
|
long id;
|
|
long dlen;
|
|
} ntc;
|
|
|
|
*flag = 0;
|
|
if((fd = open(name, O_RDONLY | O_BINARY)) > 0)
|
|
{
|
|
short nl;
|
|
|
|
fstat(fd, &s);
|
|
lseek(fd, -8, SEEK_END);
|
|
read(fd, &ntc, 8);
|
|
qs->d_length = rev_long(s.st_size);
|
|
qs->d_update = rev_long(s.st_ctime + 283996800);
|
|
|
|
nl = strlen(name);
|
|
if(nl > QDOS_FLMAX)
|
|
{
|
|
nl = QDOS_FLMAX;
|
|
*flag = 1;
|
|
}
|
|
qs->d_szname = rev_short(nl);
|
|
memcpy(qs->d_name, name, nl);
|
|
|
|
if(ntc.id == *(long *)"XTcc")
|
|
{
|
|
qs->d_datalen = ntc.dlen; /* This is big endian */
|
|
qs->d_type = 1;
|
|
r = 0;
|
|
}
|
|
else
|
|
{
|
|
qs->d_type = 0;
|
|
qs->d_datalen = 0;
|
|
r = 1;
|
|
}
|
|
close(fd);
|
|
return r;
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr, "Fails %d\n", fd);
|
|
return r;
|
|
}
|
|
}
|
|
|
|
#endif /* ?QDOS */
|
|
|
|
#ifdef USE_EF_UT_TIME
|
|
|
|
#define EB_L_UT_SIZE (EB_HEADSIZE + eb_l_ut_len)
|
|
#define EB_C_UT_SIZE (EB_HEADSIZE + eb_c_ut_len)
|
|
|
|
#ifdef UNIX
|
|
#define EB_L_UX2_SIZE (EB_HEADSIZE + EB_UX2_MINLEN)
|
|
#define EB_C_UX2_SIZE EB_HEADSIZE
|
|
#define EF_L_UT_UX2_SIZE (EB_L_UT_SIZE + EB_L_UX2_SIZE)
|
|
#define EF_C_UT_UX2_SIZE (EB_C_UT_SIZE + EB_C_UX2_SIZE)
|
|
#else
|
|
#define EF_L_UT_UX2_SIZE EB_L_UT_SIZE
|
|
#define EF_C_UT_UX2_SIZE EB_C_UT_SIZE
|
|
#endif
|
|
|
|
local int GetExtraTime(struct zlist far *z, iztimes *z_utim, unsigned ut_flg)
|
|
{
|
|
char *eb_l_ptr;
|
|
char *eb_c_ptr;
|
|
char *eb_pt;
|
|
extent eb_l_ut_len = 0;
|
|
extent eb_c_ut_len = 0;
|
|
|
|
#ifdef UNIX
|
|
struct stat s;
|
|
|
|
/* For the full sized UT local field including the UID/GID fields, we
|
|
* have to stat the file, again. */
|
|
if (stat(z->name, &s))
|
|
return ZE_OPEN;
|
|
/* update times in z_utim, stat() call might have changed atime... */
|
|
z_utim->mtime = s.st_mtime;
|
|
z_utim->atime = s.st_atime;
|
|
z_utim->ctime = s.st_mtime; /* best guess (st_ctime != creation time) */
|
|
#endif /* UNIX */
|
|
|
|
#ifdef IZ_CHECK_TZ
|
|
if (!zp_tz_is_valid)
|
|
ut_flg = 0; /* disable UT e.f creation if no valid TZ info */
|
|
#endif
|
|
if (ut_flg != 0) {
|
|
if (ut_flg & EB_UT_FL_MTIME)
|
|
eb_l_ut_len = eb_c_ut_len = 1;
|
|
if (ut_flg & EB_UT_FL_ATIME)
|
|
eb_l_ut_len++;
|
|
if (ut_flg & EB_UT_FL_CTIME)
|
|
eb_l_ut_len++;
|
|
|
|
eb_l_ut_len = EB_UT_LEN(eb_l_ut_len);
|
|
eb_c_ut_len = EB_UT_LEN(eb_c_ut_len);
|
|
}
|
|
|
|
if (EF_L_UT_UX2_SIZE > EB_HEADSIZE) {
|
|
if(z->ext)
|
|
eb_l_ptr = realloc(z->extra, (z->ext + EF_L_UT_UX2_SIZE));
|
|
else
|
|
eb_l_ptr = malloc(EF_L_UT_UX2_SIZE);
|
|
|
|
if (eb_l_ptr == NULL)
|
|
return ZE_MEM;
|
|
|
|
if(z->cext)
|
|
eb_c_ptr = realloc(z->cextra, (z->cext + EF_C_UT_UX2_SIZE));
|
|
else
|
|
eb_c_ptr = malloc(EF_C_UT_UX2_SIZE);
|
|
|
|
if (eb_c_ptr == NULL)
|
|
return ZE_MEM;
|
|
|
|
z->extra = eb_l_ptr;
|
|
eb_l_ptr += z->ext;
|
|
z->ext += EF_L_UT_UX2_SIZE;
|
|
|
|
if (ut_flg != 0) {
|
|
eb_l_ptr[0] = 'U';
|
|
eb_l_ptr[1] = 'T';
|
|
eb_l_ptr[2] = eb_l_ut_len; /* length of data part of e.f. */
|
|
eb_l_ptr[3] = 0;
|
|
eb_l_ptr[4] = ut_flg;
|
|
eb_pt = eb_l_ptr + 5;
|
|
if (ut_flg & EB_UT_FL_MTIME) {
|
|
*eb_pt++ = (char)(z_utim->mtime);
|
|
*eb_pt++ = (char)(z_utim->mtime >> 8);
|
|
*eb_pt++ = (char)(z_utim->mtime >> 16);
|
|
*eb_pt++ = (char)(z_utim->mtime >> 24);
|
|
}
|
|
if (ut_flg & EB_UT_FL_ATIME) {
|
|
*eb_pt++ = (char)(z_utim->atime);
|
|
*eb_pt++ = (char)(z_utim->atime >> 8);
|
|
*eb_pt++ = (char)(z_utim->atime >> 16);
|
|
*eb_pt++ = (char)(z_utim->atime >> 24);
|
|
}
|
|
if (ut_flg & EB_UT_FL_CTIME) {
|
|
*eb_pt++ = (char)(z_utim->ctime);
|
|
*eb_pt++ = (char)(z_utim->ctime >> 8);
|
|
*eb_pt++ = (char)(z_utim->ctime >> 16);
|
|
*eb_pt++ = (char)(z_utim->ctime >> 24);
|
|
}
|
|
}
|
|
#ifdef UNIX
|
|
else {
|
|
eb_pt = eb_l_ptr;
|
|
}
|
|
*eb_pt++ = 'U';
|
|
*eb_pt++ = 'x';
|
|
*eb_pt++ = EB_UX2_MINLEN; /* length of data part of local e.f. */
|
|
*eb_pt++ = 0;
|
|
*eb_pt++ = (char)(s.st_uid);
|
|
*eb_pt++ = (char)(s.st_uid >> 8);
|
|
*eb_pt++ = (char)(s.st_gid);
|
|
*eb_pt++ = (char)(s.st_gid >> 8);
|
|
#endif /* UNIX */
|
|
|
|
z->cextra = eb_c_ptr;
|
|
eb_c_ptr += z->cext;
|
|
z->cext += EF_C_UT_UX2_SIZE;
|
|
|
|
if (ut_flg != 0) {
|
|
memcpy(eb_c_ptr, eb_l_ptr, EB_C_UT_SIZE);
|
|
eb_c_ptr[EB_LEN] = eb_c_ut_len;
|
|
}
|
|
#ifdef UNIX
|
|
memcpy(eb_c_ptr+EB_C_UT_SIZE, eb_l_ptr+EB_L_UT_SIZE, EB_C_UX2_SIZE);
|
|
eb_c_ptr[EB_LEN+EB_C_UT_SIZE] = 0;
|
|
#endif /* UNIX */
|
|
}
|
|
|
|
return ZE_OK;
|
|
}
|
|
|
|
#endif /* USE_EF_UT_TIME */
|
|
|
|
|
|
int set_extra_field (struct zlist *z, iztimes *z_utim )
|
|
{
|
|
int rv = 0;
|
|
int last_rv = 0;
|
|
char flag = 0;
|
|
|
|
if ((qlflag & 3) != 1)
|
|
{
|
|
qdosextra *lq, *cq;
|
|
if ((lq = (qdosextra *) calloc(sizeof(qdosextra), 1)) == NULL)
|
|
return ZE_MEM;
|
|
if ((cq = (qdosextra *) calloc(sizeof(qdosextra), 1)) == NULL)
|
|
return ZE_MEM;
|
|
|
|
rv = qlstat(z->name, &(lq->header), &flag);
|
|
|
|
if (rv == 0 || (rv == 1 && (qlflag & 2)))
|
|
{
|
|
lq->shortid = rev_short((short) SHORTID);
|
|
lq->len.lo = (unsigned char)(EXTRALEN & 0xff);
|
|
lq->len.hi = (unsigned char)(EXTRALEN >> 8);
|
|
strcpy(lq->longid, LONGID);
|
|
|
|
memcpy(cq, lq, sizeof(qdosextra));
|
|
|
|
z->ext = sizeof(qdosextra);
|
|
z->cext = sizeof(qdosextra);
|
|
z->extra = (void *) lq;
|
|
z->cextra = (void *) cq;
|
|
fprintf (stderr, " %c",
|
|
lq->header.d_datalen ? '*' : '#');
|
|
}
|
|
else if (rv == -1)
|
|
{
|
|
fprintf(stderr,
|
|
"%s: warning: cannot stat %s, no file header added\n",
|
|
"zip", z->name);
|
|
}
|
|
if(flag)
|
|
{
|
|
fputs (" !", stderr);
|
|
}
|
|
}
|
|
last_rv = (rv == -1 ? ZE_OPEN : ZE_OK);
|
|
|
|
#ifdef USE_EF_UT_TIME
|
|
# ifdef QDOS
|
|
# define IZ_UT_FLAGS EB_UT_FL_MTIME
|
|
# endif
|
|
# ifdef UNIX
|
|
# define IZ_UT_FLAGS (EB_UT_FL_MTIME | EB_UT_FL_ATIME)
|
|
# endif
|
|
# ifndef IZ_UT_FLAGS
|
|
# define IZ_UT_FLAGS EB_UT_FL_MTIME
|
|
# endif
|
|
|
|
rv = GetExtraTime(z, z_utim, IZ_UT_FLAGS);
|
|
if (rv != ZE_OK)
|
|
last_rv = rv;
|
|
#endif /* USE_EF_UT_TIME */
|
|
|
|
return last_rv;
|
|
}
|