1/* 2 Copyright (c) 1990-2000 Info-ZIP. All rights reserved. 3 4 See the accompanying file LICENSE, version 2000-Apr-09 or later 5 (the contents of which are also included in zip.h) for terms of use. 6 If, for some reason, all these files are missing, the Info-ZIP license 7 also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html 8*/ 9/* Here we have a handmade stat() function because Aztec's c.lib stat() */ 10/* does not support an st_mode field, which we need... also a chmod(). */ 11 12/* This stat() is by Paul Wells, modified by Paul Kienitz. */ 13/* Originally for use with Aztec C >= 5.0 and Lattice C <= 4.01 */ 14/* Adapted for SAS/C 6.5x by Haidinger Walter */ 15 16/* POLICY DECISION: We will not attempt to remove global variables from */ 17/* this source file for Aztec C. These routines are essentially just */ 18/* augmentations of Aztec's c.lib, which is itself not reentrant. If */ 19/* we want to produce a fully reentrant UnZip, we will have to use a */ 20/* suitable startup module, such as purify.a for Aztec by Paul Kienitz. */ 21 22#ifndef __amiga_stat_c 23#define __amiga_stat_c 24 25#include <exec/types.h> 26#include <exec/memory.h> 27#include "amiga/z-stat.h" /* fake version of stat.h */ 28#include <string.h> 29 30#ifdef AZTEC_C 31# include <libraries/dos.h> 32# include <libraries/dosextens.h> 33# include <clib/exec_protos.h> 34# include <clib/dos_protos.h> 35# include <pragmas/exec_lib.h> 36# include <pragmas/dos_lib.h> 37#endif 38#ifdef __SASC 39# include <sys/dir.h> /* SAS/C dir function prototypes */ 40# include <sys/types.h> 41# include <proto/exec.h> 42# include <proto/dos.h> 43#endif 44 45#ifndef SUCCESS 46# define SUCCESS (-1) 47# define FAILURE (0) 48#endif 49 50 51void close_leftover_open_dirs(void); /* prototype */ 52 53static DIR *dir_cleanup_list = NULL; /* for resource tracking */ 54 55/* CALL THIS WHEN HANDLING CTRL-C OR OTHER UNEXPECTED EXIT! */ 56void close_leftover_open_dirs(void) 57{ 58 while (dir_cleanup_list) 59 closedir(dir_cleanup_list); 60} 61 62 63unsigned short disk_not_mounted; 64 65extern int stat(const char *file, struct stat *buf); 66 67stat(file,buf) 68const char *file; 69struct stat *buf; 70{ 71 72 struct FileInfoBlock *inf; 73 BPTR lock; 74 time_t ftime; 75 struct tm local_tm; 76 77 if( (lock = Lock((char *)file,SHARED_LOCK))==0 ) 78 /* file not found */ 79 return(-1); 80 81 if( !(inf = (struct FileInfoBlock *)AllocMem( 82 (long)sizeof(struct FileInfoBlock),MEMF_PUBLIC|MEMF_CLEAR)) ) 83 { 84 UnLock(lock); 85 return(-1); 86 } 87 88 if( Examine(lock,inf)==FAILURE ) 89 { 90 FreeMem((char *)inf,(long)sizeof(*inf)); 91 UnLock(lock); 92 return(-1); 93 } 94 95 /* fill in buf */ 96 buf->st_dev = 97 buf->st_nlink = 98 buf->st_uid = 99 buf->st_gid = 100 buf->st_rdev = 0; 101 buf->st_ino = inf->fib_DiskKey; 102 buf->st_blocks = inf->fib_NumBlocks; 103 buf->st_size = inf->fib_Size; 104 105 /* now the date. AmigaDOS has weird datestamps--- 106 * ds_Days is the number of days since 1-1-1978; 107 * however, as Unix wants date since 1-1-1970... 108 */ 109 110 ftime = 111 (inf->fib_Date.ds_Days * 86400 ) + 112 (inf->fib_Date.ds_Minute * 60 ) + 113 (inf->fib_Date.ds_Tick / TICKS_PER_SECOND ) + 114 (86400 * 8 * 365 ) + 115 (86400 * 2 ); /* two leap years */ 116 117 /* tzset(); */ /* this should be handled by mktime(), instead */ 118 /* ftime += timezone; */ 119 local_tm = *gmtime(&ftime); 120 local_tm.tm_isdst = -1; 121 ftime = mktime(&local_tm); 122 123 buf->st_ctime = 124 buf->st_atime = 125 buf->st_mtime = ftime; 126 127 buf->st_mode = (inf->fib_DirEntryType < 0 ? S_IFREG : S_IFDIR); 128 129 /* lastly, throw in the protection bits */ 130 buf->st_mode |= ((inf->fib_Protection ^ 0xF) & 0xFF); 131 132 FreeMem((char *)inf, (long)sizeof(*inf)); 133 UnLock((BPTR)lock); 134 135 return(0); 136 137} 138 139int fstat(int handle, struct stat *buf) 140{ 141 /* fake some reasonable values for stdin */ 142 buf->st_mode = (S_IREAD|S_IWRITE|S_IFREG); 143 buf->st_size = -1; 144 buf->st_mtime = time(&buf->st_mtime); 145 return 0; 146} 147 148 149/* opendir(), readdir(), closedir(), rmdir(), and chmod() by Paul Kienitz. */ 150 151DIR *opendir(const char *path) 152{ 153 DIR *dd = AllocMem(sizeof(DIR), MEMF_PUBLIC); 154 if (!dd) return NULL; 155 if (!(dd->d_parentlock = Lock((char *)path, MODE_OLDFILE))) { 156 disk_not_mounted = IoErr() == ERROR_DEVICE_NOT_MOUNTED; 157 FreeMem(dd, sizeof(DIR)); 158 return NULL; 159 } else 160 disk_not_mounted = 0; 161 if (!Examine(dd->d_parentlock, &dd->d_fib) || dd->d_fib.fib_EntryType < 0) { 162 UnLock(dd->d_parentlock); 163 FreeMem(dd, sizeof(DIR)); 164 return NULL; 165 } 166 dd->d_cleanuplink = dir_cleanup_list; /* track them resources */ 167 if (dir_cleanup_list) 168 dir_cleanup_list->d_cleanupparent = &dd->d_cleanuplink; 169 dd->d_cleanupparent = &dir_cleanup_list; 170 dir_cleanup_list = dd; 171 return dd; 172} 173 174void closedir(DIR *dd) 175{ 176 if (dd) { 177 if (dd->d_cleanuplink) 178 dd->d_cleanuplink->d_cleanupparent = dd->d_cleanupparent; 179 *(dd->d_cleanupparent) = dd->d_cleanuplink; 180 if (dd->d_parentlock) 181 UnLock(dd->d_parentlock); 182 FreeMem(dd, sizeof(DIR)); 183 } 184} 185 186struct dirent *readdir(DIR *dd) 187{ 188 return (ExNext(dd->d_parentlock, &dd->d_fib) ? (struct dirent *)dd : NULL); 189} 190 191 192#ifdef AZTEC_C 193 194int rmdir(const char *path) 195{ 196 return (DeleteFile((char *)path) ? 0 : IoErr()); 197} 198 199int chmod(const char *filename, int bits) /* bits are as for st_mode */ 200{ 201 long protmask = (bits & 0xFF) ^ 0xF; 202 return !SetProtection((char *)filename, protmask); 203} 204 205 206/* This here removes unnecessary bulk from the executable with Aztec: */ 207void _wb_parse(void) { } 208 209/* fake a unix function that does not apply to amigados: */ 210int umask(void) { return 0; } 211 212 213# include <signal.h> 214 215/* C library signal() messes up debugging yet adds no actual usefulness */ 216typedef void (*__signal_return_type)(int); 217__signal_return_type signal() { return SIG_ERR; } 218 219 220/* The following replaces Aztec's argv-parsing function for compatibility with 221Unix-like syntax used on other platforms. It also fixes the problem the 222standard _cli_parse() has of accepting only lower-ascii characters. */ 223 224int _argc, _arg_len; 225char **_argv, *_arg_lin; 226 227void _cli_parse(struct Process *pp, long alen, register UBYTE *aptr) 228{ 229 register UBYTE *cp; 230 register struct CommandLineInterface *cli; 231 register short c; 232 register short starred = 0; 233# ifdef PRESTART_HOOK 234 void Prestart_Hook(void); 235# endif 236 237 cli = (struct CommandLineInterface *) (pp->pr_CLI << 2); 238 cp = (UBYTE *) (cli->cli_CommandName << 2); 239 _arg_len = cp[0] + alen + 2; 240 if (!(_arg_lin = AllocMem((long) _arg_len, 0L))) 241 return; 242 c = cp[0]; 243 strncpy(_arg_lin, cp + 1, c); 244 _arg_lin[c] = 0; 245 for (cp = _arg_lin + c + 1; alen && (*aptr < '\n' || *aptr > '\r'); alen--) 246 *cp++ = *aptr++; 247 *cp = 0; 248 aptr = cp = _arg_lin + c + 1; 249 for (_argc = 1; ; _argc++) { 250 while (*cp == ' ' || *cp == '\t') 251 cp++; 252 if (!*cp) 253 break; 254 if (*cp == '"') { 255 cp++; 256 while (c = *cp++) { 257 if (c == '"' && !starred) { 258 *aptr++ = 0; 259 starred = 0; 260 break; 261 } else if (c == '\\' && !starred) 262 starred = 1; 263 else { 264 *aptr++ = c; 265 starred = 0; 266 } 267 } 268 } else { 269 while ((c = *cp++) && c != ' ' && c != '\t') 270 *aptr++ = c; 271 *aptr++ = 0; 272 } 273 if (c == 0) 274 --cp; 275 } 276 *aptr = 0; 277 if (!(_argv = AllocMem((_argc + 1) * sizeof(*_argv), 0L))) { 278 _argc = 0; 279 return; 280 } 281 for (c = 0, cp = _arg_lin; c < _argc; c++) { 282 _argv[c] = cp; 283 cp += strlen(cp) + 1; 284 } 285 _argv[c] = NULL; 286# ifdef PRESTART_HOOK 287 Prestart_Hook(); 288# endif 289} 290 291#endif /* AZTEC_C */ 292 293#endif /* __amiga_stat_c */ 294