0,0 → 1,293 |
/* |
Copyright (c) 1990-2000 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 |
*/ |
/* Here we have a handmade stat() function because Aztec's c.lib stat() */ |
/* does not support an st_mode field, which we need... also a chmod(). */ |
|
/* This stat() is by Paul Wells, modified by Paul Kienitz. */ |
/* Originally for use with Aztec C >= 5.0 and Lattice C <= 4.01 */ |
/* Adapted for SAS/C 6.5x by Haidinger Walter */ |
|
/* POLICY DECISION: We will not attempt to remove global variables from */ |
/* this source file for Aztec C. These routines are essentially just */ |
/* augmentations of Aztec's c.lib, which is itself not reentrant. If */ |
/* we want to produce a fully reentrant UnZip, we will have to use a */ |
/* suitable startup module, such as purify.a for Aztec by Paul Kienitz. */ |
|
#ifndef __amiga_stat_c |
#define __amiga_stat_c |
|
#include <exec/types.h> |
#include <exec/memory.h> |
#include "amiga/z-stat.h" /* fake version of stat.h */ |
#include <string.h> |
|
#ifdef AZTEC_C |
# include <libraries/dos.h> |
# include <libraries/dosextens.h> |
# include <clib/exec_protos.h> |
# include <clib/dos_protos.h> |
# include <pragmas/exec_lib.h> |
# include <pragmas/dos_lib.h> |
#endif |
#ifdef __SASC |
# include <sys/dir.h> /* SAS/C dir function prototypes */ |
# include <sys/types.h> |
# include <proto/exec.h> |
# include <proto/dos.h> |
#endif |
|
#ifndef SUCCESS |
# define SUCCESS (-1) |
# define FAILURE (0) |
#endif |
|
|
void close_leftover_open_dirs(void); /* prototype */ |
|
static DIR *dir_cleanup_list = NULL; /* for resource tracking */ |
|
/* CALL THIS WHEN HANDLING CTRL-C OR OTHER UNEXPECTED EXIT! */ |
void close_leftover_open_dirs(void) |
{ |
while (dir_cleanup_list) |
closedir(dir_cleanup_list); |
} |
|
|
unsigned short disk_not_mounted; |
|
extern int stat(const char *file, struct stat *buf); |
|
stat(file,buf) |
const char *file; |
struct stat *buf; |
{ |
|
struct FileInfoBlock *inf; |
BPTR lock; |
time_t ftime; |
struct tm local_tm; |
|
if( (lock = Lock((char *)file,SHARED_LOCK))==0 ) |
/* file not found */ |
return(-1); |
|
if( !(inf = (struct FileInfoBlock *)AllocMem( |
(long)sizeof(struct FileInfoBlock),MEMF_PUBLIC|MEMF_CLEAR)) ) |
{ |
UnLock(lock); |
return(-1); |
} |
|
if( Examine(lock,inf)==FAILURE ) |
{ |
FreeMem((char *)inf,(long)sizeof(*inf)); |
UnLock(lock); |
return(-1); |
} |
|
/* fill in buf */ |
buf->st_dev = |
buf->st_nlink = |
buf->st_uid = |
buf->st_gid = |
buf->st_rdev = 0; |
buf->st_ino = inf->fib_DiskKey; |
buf->st_blocks = inf->fib_NumBlocks; |
buf->st_size = inf->fib_Size; |
|
/* now the date. AmigaDOS has weird datestamps--- |
* ds_Days is the number of days since 1-1-1978; |
* however, as Unix wants date since 1-1-1970... |
*/ |
|
ftime = |
(inf->fib_Date.ds_Days * 86400 ) + |
(inf->fib_Date.ds_Minute * 60 ) + |
(inf->fib_Date.ds_Tick / TICKS_PER_SECOND ) + |
(86400 * 8 * 365 ) + |
(86400 * 2 ); /* two leap years */ |
|
/* tzset(); */ /* this should be handled by mktime(), instead */ |
/* ftime += timezone; */ |
local_tm = *gmtime(&ftime); |
local_tm.tm_isdst = -1; |
ftime = mktime(&local_tm); |
|
buf->st_ctime = |
buf->st_atime = |
buf->st_mtime = ftime; |
|
buf->st_mode = (inf->fib_DirEntryType < 0 ? S_IFREG : S_IFDIR); |
|
/* lastly, throw in the protection bits */ |
buf->st_mode |= ((inf->fib_Protection ^ 0xF) & 0xFF); |
|
FreeMem((char *)inf, (long)sizeof(*inf)); |
UnLock((BPTR)lock); |
|
return(0); |
|
} |
|
int fstat(int handle, struct stat *buf) |
{ |
/* fake some reasonable values for stdin */ |
buf->st_mode = (S_IREAD|S_IWRITE|S_IFREG); |
buf->st_size = -1; |
buf->st_mtime = time(&buf->st_mtime); |
return 0; |
} |
|
|
/* opendir(), readdir(), closedir(), rmdir(), and chmod() by Paul Kienitz. */ |
|
DIR *opendir(const char *path) |
{ |
DIR *dd = AllocMem(sizeof(DIR), MEMF_PUBLIC); |
if (!dd) return NULL; |
if (!(dd->d_parentlock = Lock((char *)path, MODE_OLDFILE))) { |
disk_not_mounted = IoErr() == ERROR_DEVICE_NOT_MOUNTED; |
FreeMem(dd, sizeof(DIR)); |
return NULL; |
} else |
disk_not_mounted = 0; |
if (!Examine(dd->d_parentlock, &dd->d_fib) || dd->d_fib.fib_EntryType < 0) { |
UnLock(dd->d_parentlock); |
FreeMem(dd, sizeof(DIR)); |
return NULL; |
} |
dd->d_cleanuplink = dir_cleanup_list; /* track them resources */ |
if (dir_cleanup_list) |
dir_cleanup_list->d_cleanupparent = &dd->d_cleanuplink; |
dd->d_cleanupparent = &dir_cleanup_list; |
dir_cleanup_list = dd; |
return dd; |
} |
|
void closedir(DIR *dd) |
{ |
if (dd) { |
if (dd->d_cleanuplink) |
dd->d_cleanuplink->d_cleanupparent = dd->d_cleanupparent; |
*(dd->d_cleanupparent) = dd->d_cleanuplink; |
if (dd->d_parentlock) |
UnLock(dd->d_parentlock); |
FreeMem(dd, sizeof(DIR)); |
} |
} |
|
struct dirent *readdir(DIR *dd) |
{ |
return (ExNext(dd->d_parentlock, &dd->d_fib) ? (struct dirent *)dd : NULL); |
} |
|
|
#ifdef AZTEC_C |
|
int rmdir(const char *path) |
{ |
return (DeleteFile((char *)path) ? 0 : IoErr()); |
} |
|
int chmod(const char *filename, int bits) /* bits are as for st_mode */ |
{ |
long protmask = (bits & 0xFF) ^ 0xF; |
return !SetProtection((char *)filename, protmask); |
} |
|
|
/* This here removes unnecessary bulk from the executable with Aztec: */ |
void _wb_parse(void) { } |
|
/* fake a unix function that does not apply to amigados: */ |
int umask(void) { return 0; } |
|
|
# include <signal.h> |
|
/* C library signal() messes up debugging yet adds no actual usefulness */ |
typedef void (*__signal_return_type)(int); |
__signal_return_type signal() { return SIG_ERR; } |
|
|
/* The following replaces Aztec's argv-parsing function for compatibility with |
Unix-like syntax used on other platforms. It also fixes the problem the |
standard _cli_parse() has of accepting only lower-ascii characters. */ |
|
int _argc, _arg_len; |
char **_argv, *_arg_lin; |
|
void _cli_parse(struct Process *pp, long alen, register UBYTE *aptr) |
{ |
register UBYTE *cp; |
register struct CommandLineInterface *cli; |
register short c; |
register short starred = 0; |
# ifdef PRESTART_HOOK |
void Prestart_Hook(void); |
# endif |
|
cli = (struct CommandLineInterface *) (pp->pr_CLI << 2); |
cp = (UBYTE *) (cli->cli_CommandName << 2); |
_arg_len = cp[0] + alen + 2; |
if (!(_arg_lin = AllocMem((long) _arg_len, 0L))) |
return; |
c = cp[0]; |
strncpy(_arg_lin, cp + 1, c); |
_arg_lin[c] = 0; |
for (cp = _arg_lin + c + 1; alen && (*aptr < '\n' || *aptr > '\r'); alen--) |
*cp++ = *aptr++; |
*cp = 0; |
aptr = cp = _arg_lin + c + 1; |
for (_argc = 1; ; _argc++) { |
while (*cp == ' ' || *cp == '\t') |
cp++; |
if (!*cp) |
break; |
if (*cp == '"') { |
cp++; |
while (c = *cp++) { |
if (c == '"' && !starred) { |
*aptr++ = 0; |
starred = 0; |
break; |
} else if (c == '\\' && !starred) |
starred = 1; |
else { |
*aptr++ = c; |
starred = 0; |
} |
} |
} else { |
while ((c = *cp++) && c != ' ' && c != '\t') |
*aptr++ = c; |
*aptr++ = 0; |
} |
if (c == 0) |
--cp; |
} |
*aptr = 0; |
if (!(_argv = AllocMem((_argc + 1) * sizeof(*_argv), 0L))) { |
_argc = 0; |
return; |
} |
for (c = 0, cp = _arg_lin; c < _argc; c++) { |
_argv[c] = cp; |
cp += strlen(cp) + 1; |
} |
_argv[c] = NULL; |
# ifdef PRESTART_HOOK |
Prestart_Hook(); |
# endif |
} |
|
#endif /* AZTEC_C */ |
|
#endif /* __amiga_stat_c */ |