diff options
Diffstat (limited to 'amiga/stat.c')
-rw-r--r-- | amiga/stat.c | 293 |
1 files changed, 293 insertions, 0 deletions
diff --git a/amiga/stat.c b/amiga/stat.c new file mode 100644 index 0000000..c453273 --- /dev/null +++ b/amiga/stat.c @@ -0,0 +1,293 @@ +/* + Copyright (c) 1990-2005 Info-ZIP. All rights reserved. + + See the accompanying file LICENSE, version 2004-May-22 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.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(); + /* 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 */ |