summaryrefslogtreecommitdiff
path: root/amiga/stat.c
diff options
context:
space:
mode:
Diffstat (limited to 'amiga/stat.c')
-rw-r--r--amiga/stat.c293
1 files changed, 293 insertions, 0 deletions
diff --git a/amiga/stat.c b/amiga/stat.c
new file mode 100644
index 0000000..6075c21
--- /dev/null
+++ b/amiga/stat.c
@@ -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 */