123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461 |
- /*
- Copyright (c) 1990-1999 Info-ZIP. All rights reserved.
- See the accompanying file LICENSE, version 1999-Oct-05 or later
- (the contents of which are also included in zip.h) for terms of use.
- If, for some reason, both of these files are missing, the Info-ZIP license
- also may be found at: ftp://ftp.cdrom.com/pub/infozip/license.html
- */
- #pragma library
- #include <stdio.h>
- #include <stdlib.h>
- #include <errno.h>
- #include <string.h>
- #include <sc.h>
- #include <peek.h>
- #include <lub.h>
- #include <fdb.h>
- #include <fsa.h>
- #include "theos/stat.h"
- /* replacement for standard library functions stat and fstat */
- int _stat_(struct stat* st, struct fdb* fdb);
- int _dstat_(struct stat* st);
- #define peekucb() peeknuc()
- /* map THEOS protection code to Unix modes */
- unsigned short _tm2um_(char protect)
- {
- unsigned short umask = 0;
- if (!(protect & _FDB_READ_PROTECT))
- umask = S_IRUSR|S_IRGRP;
- if (!(protect & _FDB_WRITE_PROTECT))
- umask |= S_IWUSR|S_IWGRP;
- if (!(protect & _FDB_EXECUTE_PROTECT))
- umask |= S_IXUSR|S_IXGRP;
- if (!(protect & _FDB_ERASE_PROTECT))
- umask |= S_IEUSR|S_IEGRP;
- if (!(protect & _FDB_SHARED_READ_PROTECT)) {
- if (_osmajor > 3)
- umask |= S_IROTH|S_IXOTH;
- else
- umask |= S_IROTH;
- }
- if (!(protect & _FDB_SHARED_WRITE_PROTECT))
- umask |= S_IWOTH;
- if (!(protect & _FDB_MODIFIED)) {
- if (_osmajor > 3)
- umask |= S_IMODF;
- else
- umask |= S_IXOTH;
- }
- if (protect & _FDB_NOT_HIDDEN)
- umask |= S_INHID;
- return umask;
- }
- /* map Unix modes to THEOS protections */
- char _um2tm_(unsigned short mask)
- {
- char protect = 0;
- if (!(mask & (S_IRUSR|S_IRGRP)))
- protect |= _FDB_READ_PROTECT;
- if (!(mask & (S_IWUSR|S_IWGRP)))
- protect |= _FDB_WRITE_PROTECT;
- if (!(mask & (S_IXUSR|S_IXGRP)))
- protect |= _FDB_EXECUTE_PROTECT;
- if (!(mask & (S_IEUSR|S_IEGRP)))
- protect |= _FDB_ERASE_PROTECT;
- if (_osmajor < 4) {
- if (!(mask & S_IROTH))
- protect |= _FDB_SHARED_READ_PROTECT;
- } else {
- if (!(mask & (S_IROTH|S_IXOTH)))
- protect |= _FDB_SHARED_READ_PROTECT;
- }
- if (!(mask & S_IWOTH))
- protect |= _FDB_SHARED_WRITE_PROTECT;
- if (mask & S_IMODF && _osmajor > 3)
- protect |= _FDB_MODIFIED;
- if (mask & S_INHID && _osmajor > 3)
- protect |= _FDB_NOT_HIDDEN;
- return protect;
- }
- /* root directory stat */
- static int rdirstat(const char* fn, struct stat *st)
- {
- register char* p = strchr(fn, ':');
- char drive;
- drive = p ? p[1] : 'S';
- if (drive >= 'a' && drive <= 'Z')
- drive -= 0x40;
- memset(st, 0, sizeof(struct stat));
- if (getlub(drive - 'A') != 255) {
- st->st_org = _FDB_STAT_DIRECTORY;
- st->st_mode = S_IFDIR|S_IRUSR|S_IWUSR|S_IROTH|S_IWOTH;
- st->st_nlink = 1;
- st->st_dev = st->st_rdev = drive - 'A';
- st->st_uid = st->st_gid = getuid();
- st->st_protect = _FDB_ERASE_PROTECT;
- return 0;
- }
- errno = _errnum = ENOENT;
- _errarg = fn;
- return -1;
- }
- #ifdef LOCATE_BUG
- /* locate fails when stating a file in root dir from a directory with a
- * relative path. Workaround by setting directory to root dir
- * getting the file directory block, then restoring the current directory.
- */
- struct fdb* __locate(const char* fn, char* buf, short* drv)
- {
- struct fdb* fdb;
- char buf2[FILENAME_MAX];
- char cwd[FILENAME_MAX];
- char drive[3];
- char* p;
- char* q;
- /* return if file found */
- if (fdb = _locate(fn, buf, drv))
- return fdb;
- /* if file name does not contain a path delimiter it really does not exist.
- */
- strcpy(buf2, fn);
- if ((p = strrchr(buf2, '/')) == NULL)
- return NULL;
- /* get drive name from file path */
- q = strrchr(buf2, ':');
- /* cat drive name if any to directory path */
- if (q) {
- strncpy(drive, q, 2);
- drive[2] = '\0';
- strcpy(p, q);
- } else
- *p = '\0';
- /* save current directory */
- getcwd(cwd, FILENAME_MAX);
- /* chdir to directory path */
- chdir(buf2);
- /* get File Directory Block */
- p = strrchr(fn, '/');
- fdb = _locate(p + 1, buf, drv);
- /* restore current directory */
- chdir(cwd);
- return fdb;
- }
- #undef _locate
- #define _locate() __locate()
- /* same cause, same consequence for fopen and open.
- */
- FILE* _fopen(const char* fn, const char* mode)
- {
- FILE* fp;
- char buf[FILENAME_MAX];
- short drv;
- /* prepend a path to current dir to avoid use of default library */
- if (*fn != '.' && *fn != '/') {
- strcpy(buf, "./");
- strcat(buf, fn);
- return fopen(buf, mode);
- }
- if (fp = fopen(fn, mode))
- return fp;
- /* see comment for _locate */
- if (_locate(fn, buf, &drv)) {
- fn = strrchr(fn, '/');
- return fopen(fn, mode);
- }
- return NULL;
- }
- #undef open
- int open(const char*, int, ...);
- int __open(const char* fn, int mode)
- {
- int fd;
- char buf[FILENAME_MAX];
- short drv;
- /* prepend a path to current dir to avoid use of default library */
- if (*fn != '.' && *fn != '/') {
- strcpy(buf, "./");
- strcat(buf, fn);
- return open(buf, mode);
- }
- if ((fd = open(fn, mode)) != EOF)
- return fd;
- /* see comment for _locate */
- if (_locate(fn, buf, &drv)) {
- fn = strrchr(fn, '/');
- if (fn)
- return open(fn, mode);
- }
- return EOF;
- }
- #endif
- /* replacement for standard file stat */
- int _stat(const char *_fn, struct stat *st)
- {
- char buf[FILENAME_MAX], buf2[FILENAME_MAX], buf3[FILENAME_MAX];
- register struct fdb* fdb;
- register char* p;
- register char* fn;
- fn = strcpy(buf3, _fn);
- if (p = strrchr(fn, ':'))
- *p = 0;
- /* on current drive ./:d and .:m point to current dir
- * on another drive to root directory, workaround to avoid it */
- if (! strcmp(fn, "/") || ! strcmp(fn, ".") || ! strcmp(fn, "./")) {
- if (p == NULL) {
- /* current dir on current drive */
- fn = getcwd(buf2, FILENAME_MAX);
- /* getcwd returns NULL on root dir on drive S */
- if (fn == NULL)
- fn = strcpy(buf2, "/:S");
- /* getcwd returns /:d on root dir on any other drive */
- if (fn[1] == ':')
- return rdirstat(fn, st);
- } else {
- *p = ':';
- return rdirstat(fn, st);
- }
- if (p)
- *p = ':';
- } else {
- if (p)
- *p = ':';
- if (*fn != '.' && *fn != '/') {
- strcpy(buf2, "./");
- fn = strcat(buf2, fn);
- }
- }
- if (buf2 != fn)
- strcpy(buf2, fn);
- /* remove trailing slash before optional disk name */
- if (p = strrchr(buf2, '/')) {
- if (p[1] == ':') {
- *p = p[1];
- p[1] = p[2];
- p[2] = p[3];
- } else if (p[1] == '\0')
- *p = '\0';
- }
- /* if fn is a file get file directory block structure and device */
- if (fdb = _locate(buf2, buf, &st->st_dev)) {
- /* is it a file from another user... */
- if (strchr(buf2, '\\')
- /* a public system file... */
- || fdb->fileowner == 0
- /* or a file from the current user account ? */
- || fdb->fileowner == getuid())
- /* yes, return stat */
- return _stat_(st, fdb);
- else {
- /* no, say file doesn't exist */
- errno = _errnum = ENOENT;
- _errarg = fn;
- return -1;
- }
- }
- /* else should be a device, get device number from device name */
- st->st_rdev = st->st_dev = _lub_name(*fn == ':' ? fn+1 : fn);
- /* if it is really a device return device status */
- if (st->st_dev != -1 && getlub(st->st_dev) != 255)
- return _dstat_(st);
- /* neither an existing file or a device name, return EOF */
- st->st_rdev = st->st_dev = 0;
- errno = _errnum = ENOENT;
- _errarg = fn;
- return -1;
- }
- /* replacement for fstat */
- int _fstat(int fd, struct stat *st)
- {
- unsigned short fsanum;
- struct fsa fsa;
- register FILE *fp;
- int status;
- register int i;
- register char *p;
- if (fd < FOPEN_MAX) {
- fp = &stdin[fd];
- /* get File Save Area number */
- if (_fcntl(fp,1,0) & 0x80) {
- fsanum = (unsigned short) _fcntl(fp,83,0);
- st->st_dev = (unsigned short) _fcntl(fp,5,0);
- if (st->st_dev >= A_DISK && st->st_dev <= Z_DISK) {
- /* if opened file is a disk file */
- /* copy far fsa in protected segment to local fsa */
- for (i = 0, fsanum *= sizeof(fsa), p = (char *) &fsa;
- i < (sizeof(fsa));
- i++, fsanum++, p++)
- *p = _peekfsa((char *) fsanum);
- /* build stat structure from fsa */
- status = _stat_(st, (struct fdb*) &fsa);
- /* get blocksize */
- if ((st->st_blksize = _fcntl(fp,817,0)) == 0)
- st->st_blksize = BUFSIZ;
- return status;
- }
- /* return device status */
- return _dstat_(st);
- }
- }
- errno = _errnum = EBADF;
- return -1;
- }
- static int _isprt(int dev)
- {
- return IS_PRT_LUB(dev);
- }
- /* device stat */
- int _dstat_(st)
- register struct stat* st;
- {
- register struct ucb* ucb;
- ucb = getucb(st->st_dev);
- st->st_ino = 0;
- if (st->st_dev <= Z_DISK
- || (st->st_dev >= TAPE1 && st->st_dev <= TAPE4)) {
- st->st_mode = S_IFBLK | S_IWUSR | S_IRUSR;
- if (peekucb(&ucb->devowner) == 255)
- st->st_mode |= S_IWGRP | S_IWOTH | S_IRGRP | S_IROTH;
- } else {
- st->st_mode = S_IFCHR | S_IWUSR;
- if (_isprt(st->st_dev))
- st->st_mode |= S_IRUSR;
- if (peekucb(&ucb->devowner) == 255) {
- st->st_mode |= S_IWGRP | S_IWOTH;
- if (_isprt(st->st_dev))
- st->st_mode |= S_IRGRP | S_IROTH;
- }
- }
- st->st_nlink = 1;
- st->st_uid = st->st_gid = getuid();
- st->st_size = 0;
- st->st_atime = st->st_mtime = st->st_ctime = 0;
- st->st_rlen = 0;
- st->st_klen = 0;
- st->st_grow = 0;
- st->st_blksize = 0;
- return 0;
- }
- /* regular file stat */
- int _stat_(st, fdb)
- register struct stat* st;
- register struct fdb* fdb;
- {
- st->st_rdev = st->st_dev;
- st->st_ino = 0;
- st->st_org = fdb->filestat;
- /* map fdb file status to stat mode */
- switch (fdb->filestat) {
- case _FDB_STAT_LIBRARY: st->st_mode = S_IFLIB; break;
- case _FDB_STAT_DIRECTORY: st->st_mode = S_IFDIR; break;
- case _FDB_STAT_STREAM: st->st_mode = S_IFREG; break;
- case _FDB_STAT_RELATIVE: st->st_mode = S_IFREL; break;
- case _FDB_STAT_KEYED: st->st_mode = S_IFKEY; break;
- case _FDB_STAT_INDEXED: st->st_mode = S_IFIND; break;
- case _FDB_STAT_RANDOM: st->st_mode = S_IFRND; break;
- case _FDB_STAT_PROGRAM: st->st_mode = S_IFR16; break;
- case _FDB_STAT_16_BIT_PROGRAM: st->st_mode = S_IFP16; break;
- case _FDB_STAT_32_BIT_PROGRAM: st->st_mode = S_IFP32; break;
- }
- /* map theos file protection codes to stat mode */
- st->st_mode |= _tm2um_(st->st_protect = fdb->protect);
- st->st_nlink = 1;
- st->st_uid = st->st_gid = fdb->fileowner;
- st->st_size = fdb->filesize;
- st->st_atime = st->st_mtime = st->st_ctime = getfiledate(fdb);
- st->st_blksize = 0;
- /* specific theos information */
- st->st_rlen = fdb->reclen;
- st->st_klen = fdb->keylen;
- st->st_grow = fdb->filegrow;
- return 0;
- }
- #include <direct.h>
- /* standard diropen fails on path endung with a '/', workaround */
- struct dirent* _opendir(const char* dirpath)
- {
- int l;
- char dirp[FILENAME_MAX];
- struct dirent* dir;
- if (dirpath && (l = strlen(dirpath))) {
- if (dirpath[l - 1] == '/') {
- strcpy(dirp, dirpath);
- dirp[l - 1] = '\0';
- return opendir(dirp);
- }
- }
- return opendir(dirpath);
- }
|