forked from KolibriOS/kolibrios
890 lines
24 KiB
C
890 lines
24 KiB
C
|
/*
|
||
|
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 common to TANDEM (ZIP and UNZIP)
|
||
|
*/
|
||
|
|
||
|
#include "zip.h" /* This sets up ZIP / UNZIP define */
|
||
|
|
||
|
#include <tal.h>
|
||
|
#include "$system.zsysdefs.zsysc" nolist
|
||
|
#include <cextdecs> nolist
|
||
|
#include "tannsk.h"
|
||
|
|
||
|
static time_t gmt_to_time_t (long long *);
|
||
|
|
||
|
int isatty (fnum)
|
||
|
int fnum;
|
||
|
{
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
/********************/
|
||
|
/* Function in2ex() */
|
||
|
/********************/
|
||
|
|
||
|
#ifdef UNZIP
|
||
|
char *in2ex(__G__ n)
|
||
|
__GDEF
|
||
|
#else
|
||
|
char *in2ex(n)
|
||
|
#endif
|
||
|
char *n; /* internal file name */
|
||
|
/* Convert the zip file name to an external file name, returning the malloc'ed
|
||
|
string or NULL if not enough memory. */
|
||
|
{
|
||
|
char *x; /* external file name buffer */
|
||
|
char *y; /* pointer to external buffer */
|
||
|
char *max; /* pointer to max end of next file part */
|
||
|
char *t; /* pointer to internal - start of substring */
|
||
|
char *p; /* pointer to internal - TANDEM delimiter */
|
||
|
char *e; /* pointer to internal - DOS extension delimiter */
|
||
|
char *z; /* pointer to internal - end of substring */
|
||
|
int len; /* length of substring to copy to external name */
|
||
|
int allow_dollar; /* $ symbol allowed as next character */
|
||
|
|
||
|
if ((x = malloc(strlen(n) + 4)) == NULL) /* + 4 for safety */
|
||
|
return NULL;
|
||
|
|
||
|
*x = '\0';
|
||
|
|
||
|
/* Junk pathname as requested */
|
||
|
#ifdef UNZIP
|
||
|
if (uO.jflag && (t = strrchr(n, INTERNAL_DELIMITER)) != NULL)
|
||
|
++t;
|
||
|
else
|
||
|
t = n;
|
||
|
#endif /* UNZIP */
|
||
|
#ifdef ZIP
|
||
|
if (!pathput)
|
||
|
t = last(n, INTERNAL_DELIMITER);
|
||
|
else
|
||
|
t = n;
|
||
|
#endif /* ZIP */
|
||
|
|
||
|
allow_dollar = TRUE;
|
||
|
|
||
|
while (*t != '\0') { /* File part could be sys, vol, subvol or file */
|
||
|
if (*t == INTERNAL_DELIMITER) { /* System, Volume or Subvol Name */
|
||
|
t++;
|
||
|
if (*t == INTERNAL_DELIMITER) { /* System */
|
||
|
strcat(x, TANDEM_NODE_STR);
|
||
|
t++;
|
||
|
}
|
||
|
else {
|
||
|
strcat(x, TANDEM_DELIMITER_STR);
|
||
|
allow_dollar = FALSE;
|
||
|
}
|
||
|
}
|
||
|
/* Work out where end of current external string is */
|
||
|
y = x + strlen(x);
|
||
|
|
||
|
/* Work out substring to copy and externalise */
|
||
|
p = strchr(t, INTERNAL_DELIMITER);
|
||
|
e = strchr(t, DOS_EXTENSION);
|
||
|
if (p != NULL) {
|
||
|
if (e > p)
|
||
|
e = NULL;
|
||
|
}
|
||
|
|
||
|
z = e;
|
||
|
if (z == NULL)
|
||
|
z = p;
|
||
|
if (z == NULL)
|
||
|
z = t + strlen(t);
|
||
|
|
||
|
/* can't have Tandem name longer than 8 characters */
|
||
|
max = y + MAXFILEPARTLEN;
|
||
|
|
||
|
/* Allow $ symbol as first character in some cases */
|
||
|
if (*t == '$') {
|
||
|
if (allow_dollar)
|
||
|
*y++ = *t++;
|
||
|
else;
|
||
|
*t++;
|
||
|
}
|
||
|
|
||
|
/* Make sure first real character is alpha */
|
||
|
if (! isalpha(*t) )
|
||
|
*y++ = 'A';
|
||
|
|
||
|
/* Characters left to process */
|
||
|
len = z - t;
|
||
|
|
||
|
while ( len > 0 ) {
|
||
|
if ( isalnum(*t) ) {
|
||
|
*y++ = toupper(*t++);
|
||
|
if (y >= max)
|
||
|
break;
|
||
|
}
|
||
|
else
|
||
|
t++;
|
||
|
len--;
|
||
|
}
|
||
|
*y = '\0';
|
||
|
t = p;
|
||
|
|
||
|
if (p == NULL) {
|
||
|
/* Last part of filename, store pseudo extension if available */
|
||
|
if (e != NULL) {
|
||
|
strcat(x, TANDEM_EXTENSION_STR);
|
||
|
y = x + strlen(x);
|
||
|
|
||
|
/* no restriction on extension length as its virtual */
|
||
|
z = e + 1;
|
||
|
while ( *z != '\0' ) {
|
||
|
*y++ = toupper(*z++);
|
||
|
}
|
||
|
*y = '\0';
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return x;
|
||
|
}
|
||
|
|
||
|
void zexit(status)
|
||
|
int status;
|
||
|
{
|
||
|
/* Exit(>0) creates saveabend files */
|
||
|
terminate_program (0,0,(short)status,,,);
|
||
|
}
|
||
|
|
||
|
/************************/
|
||
|
/* Function zputc() */
|
||
|
/************************/
|
||
|
|
||
|
#ifdef putc
|
||
|
# undef putc
|
||
|
#endif
|
||
|
|
||
|
int zputc(ch, fptr)
|
||
|
int ch;
|
||
|
FILE *fptr;
|
||
|
{
|
||
|
int err;
|
||
|
err = putc(ch,fptr);
|
||
|
fflush(fptr);
|
||
|
return err;
|
||
|
}
|
||
|
#define putc zputc
|
||
|
|
||
|
#ifdef LICENSED
|
||
|
_tal _priv short FILE_CHANGELABEL_ (
|
||
|
short, /* IN */
|
||
|
short, /* IN */
|
||
|
const short _far * /* IN */
|
||
|
);
|
||
|
|
||
|
_c _callable int changelabel OF((short, const short *, const short *));
|
||
|
|
||
|
_c _callable int changelabel(fnum, modtime, actime)
|
||
|
short fnum;
|
||
|
const short *modtime;
|
||
|
const short *actime;
|
||
|
{
|
||
|
int err;
|
||
|
|
||
|
err = FILE_CHANGELABEL_(fnum, 16, modtime);
|
||
|
if (!err)
|
||
|
err = FILE_CHANGELABEL_(fnum, 17, actime);
|
||
|
return err;
|
||
|
}
|
||
|
|
||
|
int islicensed(void)
|
||
|
{
|
||
|
#define plist_items 1
|
||
|
#define plist_size 10
|
||
|
|
||
|
short myphandle[ZSYS_VAL_PHANDLE_WLEN];
|
||
|
short licensetag[plist_items] = {37};
|
||
|
short licensed[plist_size];
|
||
|
short maxlen = plist_size;
|
||
|
short items = plist_items;
|
||
|
short resultlen[1], err;
|
||
|
|
||
|
err = PROCESSHANDLE_NULLIT_(myphandle);
|
||
|
|
||
|
if (!err)
|
||
|
err = PROCESS_GETINFO_(myphandle);
|
||
|
|
||
|
if (!err)
|
||
|
err = PROCESS_GETINFOLIST_(/*cpu*/,
|
||
|
/*pin*/,
|
||
|
/*nodename*/,
|
||
|
/*nodenamelen*/,
|
||
|
myphandle,
|
||
|
licensetag,
|
||
|
items,
|
||
|
licensed,
|
||
|
maxlen,
|
||
|
resultlen
|
||
|
);
|
||
|
|
||
|
if (err != 0)
|
||
|
return 0;
|
||
|
else
|
||
|
return licensed[0];
|
||
|
}
|
||
|
#endif /* LICENSED */
|
||
|
|
||
|
int utime(file, time)
|
||
|
const char *file;
|
||
|
const ztimbuf *time;
|
||
|
{
|
||
|
#ifdef LICENSED
|
||
|
int result, err;
|
||
|
union timestamp_ov {
|
||
|
long long fulltime;
|
||
|
short wordtime[4];
|
||
|
};
|
||
|
union timestamp_ov lasttime, opentime;
|
||
|
struct tm *modt, *opent;
|
||
|
short datetime[8], errormask[1];
|
||
|
short len, fnum, access, exclus, options;
|
||
|
char fname[FILENAME_MAX + 1];
|
||
|
short extension;
|
||
|
char ext[EXTENSION_MAX + 1];
|
||
|
|
||
|
if (islicensed() ) {
|
||
|
/* Attempt to update file label */
|
||
|
modt = gmtime( &time->modtime );
|
||
|
|
||
|
datetime[0] = modt->tm_year + 1900;
|
||
|
datetime[1] = modt->tm_mon + 1;
|
||
|
datetime[2] = modt->tm_mday;
|
||
|
datetime[3] = modt->tm_hour;
|
||
|
datetime[4] = modt->tm_min;
|
||
|
datetime[5] = modt->tm_sec;
|
||
|
datetime[6] = datetime[7] = 0;
|
||
|
errormask[0] = 0;
|
||
|
lasttime.fulltime = COMPUTETIMESTAMP (datetime, errormask);
|
||
|
|
||
|
opent = gmtime( &time->actime );
|
||
|
|
||
|
datetime[0] = opent->tm_year + 1900;
|
||
|
datetime[1] = opent->tm_mon + 1;
|
||
|
datetime[2] = opent->tm_mday;
|
||
|
datetime[3] = opent->tm_hour;
|
||
|
datetime[4] = opent->tm_min;
|
||
|
datetime[5] = opent->tm_sec;
|
||
|
datetime[6] = datetime[7] = 0;
|
||
|
errormask[0] = 0;
|
||
|
opentime.fulltime = COMPUTETIMESTAMP (datetime, errormask);
|
||
|
|
||
|
/* Remove any (pseudo) file extension */
|
||
|
extension = parsename (file,fname,ext);
|
||
|
len = strlen(fname);
|
||
|
|
||
|
access = NSK_WRONLY;
|
||
|
exclus = NSK_SHARED;
|
||
|
options = NSK_NOUPDATEOPENTIME;
|
||
|
|
||
|
extension = parsename (file,fname,ext);
|
||
|
len = strlen(fname);
|
||
|
|
||
|
err = FILE_OPEN_((char *)fname, len, &fnum, access, exclus,,,options,,,);
|
||
|
result = changelabel(fnum,lasttime.wordtime,opentime.wordtime);
|
||
|
err = FILE_CLOSE_(fnum);
|
||
|
return result;
|
||
|
}
|
||
|
return -1;
|
||
|
#else /* !LICENSED */
|
||
|
return 0; /* "no error", to suppress annoying failure messages */
|
||
|
#endif /* ?LICENSED */
|
||
|
}
|
||
|
|
||
|
/* TANDEM version of chmod() function */
|
||
|
|
||
|
int chmod(file, unix_sec)
|
||
|
const char *file;
|
||
|
mode_t unix_sec;
|
||
|
{
|
||
|
FILE *stream;
|
||
|
struct nsk_sec_type {
|
||
|
unsigned progid : 1;
|
||
|
unsigned clear : 1;
|
||
|
unsigned null : 2;
|
||
|
unsigned read : 3;
|
||
|
unsigned write : 3;
|
||
|
unsigned execute: 3;
|
||
|
unsigned purge : 3;
|
||
|
};
|
||
|
union nsk_sec_ov {
|
||
|
struct nsk_sec_type bit_ov;
|
||
|
short int_ov;
|
||
|
};
|
||
|
union nsk_sec_ov nsk_sec;
|
||
|
short fnum, err, nsk_sec_int;
|
||
|
short len, access, exclus, extension, options;
|
||
|
char fname[FILENAME_MAX + 1];
|
||
|
char ext[EXTENSION_MAX + 1];
|
||
|
|
||
|
nsk_sec.bit_ov.progid = 0;
|
||
|
nsk_sec.bit_ov.clear = 0;
|
||
|
nsk_sec.bit_ov.null = 0;
|
||
|
|
||
|
/* 4="N", 5="C", 6="U", 7="-" */
|
||
|
|
||
|
if (unix_sec & S_IROTH) nsk_sec.bit_ov.read = 4;
|
||
|
else if (unix_sec & S_IRGRP) nsk_sec.bit_ov.read = 5;
|
||
|
else if (unix_sec & S_IRUSR) nsk_sec.bit_ov.read = 6;
|
||
|
else nsk_sec.bit_ov.read = 7;
|
||
|
|
||
|
if (unix_sec & S_IWOTH) nsk_sec.bit_ov.write = 4;
|
||
|
else if (unix_sec & S_IWGRP) nsk_sec.bit_ov.write = 5;
|
||
|
else if (unix_sec & S_IWUSR) nsk_sec.bit_ov.write = 6;
|
||
|
else nsk_sec.bit_ov.write = 7;
|
||
|
|
||
|
if (unix_sec & S_IXOTH) nsk_sec.bit_ov.execute = 4;
|
||
|
else if (unix_sec & S_IXGRP) nsk_sec.bit_ov.execute = 5;
|
||
|
else if (unix_sec & S_IXUSR) nsk_sec.bit_ov.execute = 6;
|
||
|
else nsk_sec.bit_ov.execute = 7;
|
||
|
|
||
|
nsk_sec.bit_ov.purge = nsk_sec.bit_ov.write;
|
||
|
|
||
|
nsk_sec_int = nsk_sec.int_ov;
|
||
|
|
||
|
access = NSK_RDONLY;
|
||
|
exclus = NSK_SHARED;
|
||
|
options = NSK_NOUPDATEOPENTIME;
|
||
|
|
||
|
extension = parsename (file,fname,ext);
|
||
|
len = strlen(fname);
|
||
|
|
||
|
err = FILE_OPEN_((char *)fname, len, &fnum, access, exclus,,,options,,,);
|
||
|
err = (SETMODE(fnum, SET_FILE_SECURITY, nsk_sec_int) != CCE);
|
||
|
err = FILE_CLOSE_(fnum);
|
||
|
|
||
|
return (err != 0 ? -1 : 0);
|
||
|
}
|
||
|
|
||
|
/* TANDEM version of chown() function */
|
||
|
|
||
|
int chown(file, uid, gid)
|
||
|
const char *file;
|
||
|
uid_t uid;
|
||
|
gid_t gid;
|
||
|
{
|
||
|
FILE *stream;
|
||
|
struct nsk_own_type {
|
||
|
unsigned group : 8;
|
||
|
unsigned user : 8;
|
||
|
};
|
||
|
union nsk_own_ov {
|
||
|
struct nsk_own_type bit_ov;
|
||
|
short int_ov;
|
||
|
};
|
||
|
union nsk_own_ov nsk_own;
|
||
|
short fnum, err, nsk_own_int;
|
||
|
short len, access, exclus, extension, options;
|
||
|
char fname[FILENAME_MAX + 1];
|
||
|
char ext[EXTENSION_MAX + 1];
|
||
|
|
||
|
nsk_own.bit_ov.group = gid;
|
||
|
nsk_own.bit_ov.user = uid;
|
||
|
|
||
|
nsk_own_int = nsk_own.int_ov;
|
||
|
|
||
|
access = NSK_RDONLY;
|
||
|
exclus = NSK_SHARED;
|
||
|
options = NSK_NOUPDATEOPENTIME;
|
||
|
|
||
|
extension = parsename (file,fname,ext);
|
||
|
len = strlen(fname);
|
||
|
|
||
|
err = FILE_OPEN_((char *)fname, len, &fnum, access, exclus,,,options,,,);
|
||
|
err = (SETMODE(fnum, SET_FILE_OWNER, nsk_own_int) != CCE);
|
||
|
err = FILE_CLOSE_(fnum);
|
||
|
return (err != 0 ? -1 : 0);
|
||
|
}
|
||
|
|
||
|
/* TANDEM version of getch() - non-echo character reading */
|
||
|
int zgetch(void)
|
||
|
{
|
||
|
char ch;
|
||
|
short f, err, count, fnum, rlen;
|
||
|
|
||
|
rlen = 1;
|
||
|
f = (short)fileno(stdin);
|
||
|
fnum = fdtogfn (f);
|
||
|
#define ECHO_MODE 20
|
||
|
err = (SETMODE(fnum, ECHO_MODE, 0) != CCE);
|
||
|
err = (READX(fnum, &ch, rlen, (short *) &count) != CCE);
|
||
|
err = (SETMODE(fnum, ECHO_MODE, 1) != CCE);
|
||
|
|
||
|
if (err)
|
||
|
if (err != 1)
|
||
|
return EOF;
|
||
|
else
|
||
|
ch = 'q';
|
||
|
else
|
||
|
if (count == 0)
|
||
|
ch = '\r';
|
||
|
|
||
|
return (int)ch;
|
||
|
}
|
||
|
|
||
|
short parsename(srce, fname, ext)
|
||
|
const char *srce;
|
||
|
char *fname;
|
||
|
char *ext;
|
||
|
{
|
||
|
/* As a way of supporting DOS extensions from Tandem we look for a space
|
||
|
separated extension string after the Guardian filename
|
||
|
e.g. ZIP ZIPFILE "$DATA4.TESTING.INVOICE TXT"
|
||
|
*/
|
||
|
|
||
|
char *fstart;
|
||
|
char *fptr;
|
||
|
short extension = 0;
|
||
|
|
||
|
*fname = *ext = '\0'; /* set to null string */
|
||
|
|
||
|
fstart = (char *) srce;
|
||
|
|
||
|
if ((fptr = strrchr(fstart, TANDEM_EXTENSION)) != NULL) {
|
||
|
extension = 1;
|
||
|
|
||
|
fptr++;
|
||
|
strncat(ext, fptr, _min(EXTENSION_MAX, strlen(fptr)));
|
||
|
|
||
|
fptr = strchr(fstart, TANDEM_EXTENSION); /* End of filename */
|
||
|
strncat(fname, fstart, _min(FILENAME_MAX, (fptr - fstart)));
|
||
|
}
|
||
|
else {
|
||
|
/* just copy string */
|
||
|
strncat(fname, srce, _min(FILENAME_MAX, strlen(srce)));
|
||
|
}
|
||
|
|
||
|
return extension;
|
||
|
}
|
||
|
|
||
|
static time_t gmt_to_time_t (gmt)
|
||
|
long long *gmt;
|
||
|
{
|
||
|
#define GMT_TO_LCT 0
|
||
|
#define GMT_TO_LST 1
|
||
|
|
||
|
struct tm temp_tm;
|
||
|
short date_time[8];
|
||
|
long julian_dayno;
|
||
|
long long lct, lst, itime;
|
||
|
short err[1], type;
|
||
|
|
||
|
type = GMT_TO_LCT;
|
||
|
lct = CONVERTTIMESTAMP(*gmt, type,, err);
|
||
|
|
||
|
if (!err[0]) {
|
||
|
type = GMT_TO_LST;
|
||
|
lst = CONVERTTIMESTAMP(*gmt, type,, err);
|
||
|
}
|
||
|
|
||
|
itime = (err[0] ? *gmt : lct);
|
||
|
/* If we have no DST in force then make sure we give it a value,
|
||
|
else mktime screws up if we set the isdst flag to -1 */
|
||
|
temp_tm.tm_isdst = (err[0] ? 0 : ((lct == lst) ? 0 : 1));
|
||
|
|
||
|
julian_dayno = INTERPRETTIMESTAMP(itime, date_time);
|
||
|
|
||
|
temp_tm.tm_sec = date_time[5];
|
||
|
temp_tm.tm_min = date_time[4];
|
||
|
temp_tm.tm_hour = date_time[3];
|
||
|
temp_tm.tm_mday = date_time[2];
|
||
|
temp_tm.tm_mon = date_time[1] - 1; /* C's so sad */
|
||
|
temp_tm.tm_year = date_time[0] - 1900; /* it's almost funny */
|
||
|
|
||
|
return (mktime(&temp_tm));
|
||
|
}
|
||
|
|
||
|
/* TANDEM version of stat() function */
|
||
|
int stat(n, s)
|
||
|
const char *n;
|
||
|
struct stat *s;
|
||
|
{
|
||
|
#define ilist_items 26
|
||
|
#define klist_items 4
|
||
|
#define slist_items 3
|
||
|
#define ulist_items 1
|
||
|
#define flist_size 100
|
||
|
|
||
|
short err, i, extension;
|
||
|
char fname[FILENAME_MAX + 1];
|
||
|
short fnamelen;
|
||
|
char ext[EXTENSION_MAX + 1];
|
||
|
|
||
|
/* #0 #1 #2 #3 #4 #5 #6 #7 #8 #9 */
|
||
|
short ilist[ilist_items]={56,144, 54,142, 58, 62, 60, 41, 42, 44,
|
||
|
50, 51, 52, 61, 63, 66, 67, 70, 72, 73,
|
||
|
74, 75, 76, 77, 78, 79 };
|
||
|
short ilen[ilist_items] ={ 4, 4, 4, 2, 1, 2, 1, 1, 1, 1,
|
||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||
|
1, 1, 1, 1, 1, 1 };
|
||
|
short ioff[ilist_items];
|
||
|
|
||
|
/* #0 #1 #2 #3 #4 #5 #6 #7 #8 #9 */
|
||
|
short klist[klist_items]={45, 46, 68, 69 };
|
||
|
short klen[klist_items] ={ 1, 1, 1, 1 };
|
||
|
short koff[klist_items];
|
||
|
|
||
|
/* #0 #1 #2 #3 #4 #5 #6 #7 #8 #9 */
|
||
|
short slist[slist_items]={43, 80, 90 };
|
||
|
short slen[slist_items] ={ 1, 1, 1 };
|
||
|
short soff[slist_items];
|
||
|
|
||
|
/* #0 #1 #2 #3 #4 #5 #6 #7 #8 #9 */
|
||
|
short ulist[ulist_items]={65 };
|
||
|
short ulen[ulist_items] ={ 1 };
|
||
|
short uoff[ulist_items];
|
||
|
|
||
|
short flist[flist_size];
|
||
|
short extra[2];
|
||
|
short *rlen=&extra[0];
|
||
|
short *err_item=&extra[1];
|
||
|
unsigned short *fowner;
|
||
|
unsigned short *fprogid;
|
||
|
char *fsec;
|
||
|
|
||
|
nsk_stat_ov *nsk_ov;
|
||
|
nsk_file_attrs *nsk_attr;
|
||
|
|
||
|
short end, count, kind, level, options, searchid;
|
||
|
short info[5];
|
||
|
|
||
|
/* Initialise stat structure */
|
||
|
s->st_dev = _S_GUARDIANOBJECT;
|
||
|
s->st_ino = 0;
|
||
|
s->st_nlink = 0;
|
||
|
s->st_rdev = 0;
|
||
|
s->st_uid = s->st_gid = 0;
|
||
|
s->st_size = 0;
|
||
|
s->st_atime = s->st_ctime = s->st_mtime = 0;
|
||
|
s->st_reserved[0] = 0;
|
||
|
s->st_reserved[1] = 0;
|
||
|
s->st_reserved[2] = 0;
|
||
|
nsk_ov = (nsk_stat_ov *)&s->st_reserved[0];
|
||
|
nsk_attr = (nsk_file_attrs *)&nsk_ov->ov.nsk_ef_region;
|
||
|
|
||
|
/* Check to see if name contains a (pseudo) file extension */
|
||
|
extension = parsename (n,fname,ext);
|
||
|
|
||
|
fnamelen = strlen(fname);
|
||
|
|
||
|
options = 3; /* Allow Subvols and Templates */
|
||
|
err = FILENAME_SCAN_( fname,
|
||
|
fnamelen,
|
||
|
&count,
|
||
|
&kind,
|
||
|
&level,
|
||
|
options
|
||
|
);
|
||
|
|
||
|
/* allow kind == 2 (DEFINE names) */
|
||
|
if (err != 0) return -1;
|
||
|
|
||
|
if (kind == 1 || (kind == 0 && level < 2)) {
|
||
|
/* Pattern, Subvol Name or One part Filename - lets see if it exists */
|
||
|
err = FILENAME_FINDSTART_ ( &searchid,
|
||
|
fname,
|
||
|
fnamelen,
|
||
|
,
|
||
|
DISK_DEVICE
|
||
|
);
|
||
|
|
||
|
if (err != 0) {
|
||
|
end = FILENAME_FINDFINISH_ ( searchid );
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
err = FILENAME_FINDNEXT_ ( searchid,
|
||
|
fname,
|
||
|
FILENAME_MAX,
|
||
|
&fnamelen,
|
||
|
info
|
||
|
);
|
||
|
end = FILENAME_FINDFINISH_ ( searchid );
|
||
|
|
||
|
if (err != 0)
|
||
|
return -1; /* Non existing template, subvol or file */
|
||
|
|
||
|
if (kind == 1 || info[2] == -1) {
|
||
|
s->st_mode = S_IFDIR; /* Its an existing template or directory */
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/* Must be a real file so drop to code below to get info on it */
|
||
|
}
|
||
|
|
||
|
err = FILE_GETINFOLISTBYNAME_( fname,
|
||
|
fnamelen,
|
||
|
ilist,
|
||
|
ilist_items,
|
||
|
flist,
|
||
|
flist_size,
|
||
|
rlen,
|
||
|
err_item
|
||
|
);
|
||
|
if (err != 0) return -1;
|
||
|
|
||
|
ioff[0] = 0;
|
||
|
|
||
|
/* Build up table of offets into result list */
|
||
|
for (i=1; i < ilist_items; i++)
|
||
|
ioff[i] = ioff[i-1] + ilen[i-1];
|
||
|
|
||
|
/* Set up main stat fields */
|
||
|
|
||
|
/* Setup timestamps */
|
||
|
s->st_atime = gmt_to_time_t ((long long *)&flist[ioff[0]]);
|
||
|
s->st_mtime = s->st_ctime = gmt_to_time_t ((long long *)&flist[ioff[1]]);
|
||
|
nsk_ov->ov.creation_time = gmt_to_time_t ((long long *)&flist[ioff[2]]);
|
||
|
|
||
|
s->st_size = *(off_t *)&flist[ioff[3]];
|
||
|
|
||
|
fowner = (unsigned short *)&flist[ioff[4]];
|
||
|
s->st_uid = *fowner & 0x00ff;
|
||
|
s->st_gid = *fowner >> 8;
|
||
|
|
||
|
/* Note that Purge security (fsec[3]) in NSK has no relevance to stat() */
|
||
|
fsec = (char *)&flist[ioff[5]];
|
||
|
fprogid = (unsigned short *)&flist[ioff[6]];
|
||
|
|
||
|
s->st_mode = S_IFREG | /* Regular File */
|
||
|
/* Parse Read Flag */
|
||
|
((fsec[0] & 0x03) == 0x00 ? S_IROTH : 0) |
|
||
|
((fsec[0] & 0x02) == 0x00 ? S_IRGRP : 0) |
|
||
|
((fsec[0] & 0x03) != 0x03 ? S_IRUSR : 0) |
|
||
|
/* Parse Write Flag */
|
||
|
((fsec[1] & 0x03) == 0x00 ? S_IWOTH : 0) |
|
||
|
((fsec[1] & 0x02) == 0x00 ? S_IWGRP : 0) |
|
||
|
((fsec[1] & 0x03) != 0x03 ? S_IWUSR : 0) |
|
||
|
/* Parse Execute Flag */
|
||
|
((fsec[2] & 0x03) == 0x00 ? S_IXOTH : 0) |
|
||
|
((fsec[2] & 0x02) == 0x00 ? S_IXGRP : 0) |
|
||
|
((fsec[2] & 0x03) != 0x03 ? S_IXUSR : 0) |
|
||
|
/* Parse Progid */
|
||
|
(*fprogid == 1 ? (S_ISUID | S_ISGID) : 0) ;
|
||
|
|
||
|
/* Set up NSK additional stat fields */
|
||
|
nsk_attr->progid = (unsigned) flist[ioff[6]];
|
||
|
nsk_attr->filetype = (unsigned) flist[ioff[7]];
|
||
|
nsk_attr->filecode = (unsigned) flist[ioff[8]];
|
||
|
nsk_attr->block = (unsigned short) flist[ioff[9]];
|
||
|
nsk_attr->priext = (unsigned short) flist[ioff[10]];
|
||
|
nsk_attr->secext = (unsigned short) flist[ioff[11]];
|
||
|
nsk_attr->maxext = (unsigned short) flist[ioff[12]];
|
||
|
nsk_attr->flags.clearonpurge = (unsigned) flist[ioff[13]];
|
||
|
nsk_attr->licensed = (unsigned) flist[ioff[14]];
|
||
|
nsk_attr->flags.audited = (unsigned) flist[ioff[15]];
|
||
|
nsk_attr->flags.acompress = (unsigned) flist[ioff[16]];
|
||
|
nsk_attr->flags.refresheof = (unsigned) flist[ioff[17]];
|
||
|
nsk_attr->flags.buffered = (unsigned) (flist[ioff[18]] == 0 ? 1 : 0);
|
||
|
nsk_attr->flags.verified = (unsigned) flist[ioff[19]];
|
||
|
nsk_attr->flags.serial = (unsigned) flist[ioff[20]];
|
||
|
nsk_attr->flags.crashopen = (unsigned) flist[ioff[22]];
|
||
|
nsk_attr->flags.rollforward = (unsigned) flist[ioff[23]];
|
||
|
nsk_attr->flags.broken = (unsigned) flist[ioff[24]];
|
||
|
nsk_attr->flags.corrupt = (unsigned) flist[ioff[25]];
|
||
|
nsk_attr->fileopen = (unsigned) flist[ioff[21]];
|
||
|
|
||
|
|
||
|
if (nsk_attr->filetype == NSK_UNSTRUCTURED) {
|
||
|
/* extra info for Unstructured files */
|
||
|
err = FILE_GETINFOLISTBYNAME_( fname,
|
||
|
fnamelen,
|
||
|
ulist,
|
||
|
ulist_items,
|
||
|
flist,
|
||
|
flist_size,
|
||
|
rlen,
|
||
|
err_item
|
||
|
);
|
||
|
if (err != 0) return -1;
|
||
|
|
||
|
uoff[0] = 0;
|
||
|
|
||
|
/* Build up table of offets into result list */
|
||
|
for (i=1; i < ulist_items; i++)
|
||
|
uoff[i] = uoff[i-1] + ulen[i-1];
|
||
|
}
|
||
|
else {
|
||
|
/* extra info for Structured files */
|
||
|
err = FILE_GETINFOLISTBYNAME_( fname,
|
||
|
fnamelen,
|
||
|
slist,
|
||
|
slist_items,
|
||
|
flist,
|
||
|
flist_size,
|
||
|
rlen,
|
||
|
err_item
|
||
|
);
|
||
|
if (err != 0) return -1;
|
||
|
|
||
|
soff[0] = 0;
|
||
|
|
||
|
/* Build up table of offets into result list */
|
||
|
for (i=1; i < slist_items; i++)
|
||
|
soff[i] = soff[i-1] + slen[i-1];
|
||
|
|
||
|
nsk_attr->reclen = (unsigned) flist[soff[0]];
|
||
|
nsk_attr->flags.secpart = (unsigned) flist[soff[1]];
|
||
|
nsk_attr->flags.primpart = (unsigned)
|
||
|
( (flist[soff[2]] > 0 && nsk_attr->flags.secpart == 0) ? 1 : 0 );
|
||
|
|
||
|
if (nsk_attr->filetype == NSK_KEYSEQUENCED) {
|
||
|
/* extra info for Key Sequenced files */
|
||
|
err = FILE_GETINFOLISTBYNAME_( fname,
|
||
|
fnamelen,
|
||
|
klist,
|
||
|
klist_items,
|
||
|
flist,
|
||
|
flist_size,
|
||
|
rlen,
|
||
|
err_item
|
||
|
);
|
||
|
if (err != 0) return -1;
|
||
|
|
||
|
koff[0] = 0;
|
||
|
|
||
|
/* Build up table of offets into result list */
|
||
|
for (i=1; i < klist_items; i++)
|
||
|
koff[i] = koff[i-1] + klen[i-1];
|
||
|
|
||
|
nsk_attr->keyoff = (unsigned) flist[koff[0]];
|
||
|
nsk_attr->keylen = (unsigned) flist[koff[1]];
|
||
|
nsk_attr->flags.dcompress = (unsigned) flist[koff[2]];
|
||
|
nsk_attr->flags.icompress = (unsigned) flist[koff[3]];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
#ifndef SFX
|
||
|
/* TANDEM Directory processing */
|
||
|
|
||
|
DIR *opendir(const char *dirname)
|
||
|
{
|
||
|
short i, resolve;
|
||
|
char sname[FILENAME_MAX + 1];
|
||
|
short snamelen;
|
||
|
char fname[FILENAME_MAX + 1];
|
||
|
short fnamelen;
|
||
|
char *p;
|
||
|
short searchid, err, end;
|
||
|
struct dirent *entry;
|
||
|
DIR *dirp;
|
||
|
char ext[EXTENSION_MAX + 1];
|
||
|
short extension;
|
||
|
|
||
|
extension = parsename(dirname, sname, ext);
|
||
|
snamelen = strlen(sname);
|
||
|
|
||
|
/* First we work out how detailed the template is...
|
||
|
* e.g. If the template is DAVES*.* we want the search result
|
||
|
* in the same format
|
||
|
*/
|
||
|
|
||
|
p = sname;
|
||
|
i = 0;
|
||
|
while ((p = strchr(p, TANDEM_DELIMITER)) != NULL){
|
||
|
i++;
|
||
|
p++;
|
||
|
};
|
||
|
resolve = 2 - i;
|
||
|
|
||
|
/* Attempt to start a filename template */
|
||
|
err = FILENAME_FINDSTART_ ( &searchid,
|
||
|
sname,
|
||
|
snamelen,
|
||
|
resolve,
|
||
|
DISK_DEVICE
|
||
|
);
|
||
|
if (err != 0) {
|
||
|
end = FILENAME_FINDFINISH_(searchid);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
/* Create DIR structure */
|
||
|
if ((dirp = malloc(sizeof(DIR))) == NULL ) {
|
||
|
end = FILENAME_FINDFINISH_(searchid);
|
||
|
return NULL;
|
||
|
}
|
||
|
dirp->D_list = dirp->D_curpos = NULL;
|
||
|
strcpy(dirp->D_path, dirname);
|
||
|
|
||
|
while ((err = FILENAME_FINDNEXT_(searchid,
|
||
|
fname,
|
||
|
FILENAME_MAX,
|
||
|
&fnamelen
|
||
|
)
|
||
|
) == 0 ){
|
||
|
/* Create space for entry */
|
||
|
if ((entry = malloc (sizeof(struct dirent))) == NULL) {
|
||
|
end = FILENAME_FINDFINISH_(searchid);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
/* Link to last entry */
|
||
|
if (dirp->D_curpos == NULL)
|
||
|
dirp->D_list = dirp->D_curpos = entry; /* First name */
|
||
|
else {
|
||
|
dirp->D_curpos->d_next = entry; /* Link */
|
||
|
dirp->D_curpos = entry;
|
||
|
};
|
||
|
/* Add directory entry */
|
||
|
*dirp->D_curpos->d_name = '\0';
|
||
|
strncat(dirp->D_curpos->d_name,fname,fnamelen);
|
||
|
if (extension) {
|
||
|
strcat(dirp->D_curpos->d_name,TANDEM_EXTENSION_STR);
|
||
|
strcat(dirp->D_curpos->d_name,ext);
|
||
|
};
|
||
|
dirp->D_curpos->d_next = NULL;
|
||
|
};
|
||
|
|
||
|
end = FILENAME_FINDFINISH_(searchid);
|
||
|
|
||
|
if (err == 1) { /* Should return EOF at end of search */
|
||
|
dirp->D_curpos = dirp->D_list; /* Set current pos to start */
|
||
|
return dirp;
|
||
|
}
|
||
|
else
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
struct dirent *readdir(DIR *dirp)
|
||
|
{
|
||
|
struct dirent *cur;
|
||
|
|
||
|
cur = dirp->D_curpos;
|
||
|
dirp->D_curpos = dirp->D_curpos->d_next;
|
||
|
return cur;
|
||
|
}
|
||
|
|
||
|
void rewinddir(DIR *dirp)
|
||
|
{
|
||
|
dirp->D_curpos = dirp->D_list;
|
||
|
}
|
||
|
|
||
|
int closedir(DIR *dirp)
|
||
|
{
|
||
|
struct dirent *node;
|
||
|
|
||
|
while (dirp->D_list != NULL) {
|
||
|
node = dirp->D_list;
|
||
|
dirp->D_list = dirp->D_list->d_next;
|
||
|
free( node );
|
||
|
}
|
||
|
free( dirp );
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
#endif /* !SFX */
|