2
Copyright (c) 1990-2002 Info-ZIP. All rights reserved.
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
9
/* Low-level Amiga routines shared between Zip and UnZip.
11
* Contains: FileDate()
12
* getenv() [replaces inadequate standard library version]
13
* setenv() [SAS/C only, replaces standard library version]
14
* set_TZ() [SAS/C only]
15
* GetPlatformLocalTimezone() [callback from timezone.c tzset()]
20
* The first five are used by most Info-ZIP programs except fUnZip.
21
* The last two are used by all except the non-CRYPT version of fUnZip.
22
* Probably some of the stuff in here is unused by ZipNote and ZipSplit too...
23
* sendpkt() is used by Agetch() and FileDate(), and by screensize() in
24
* amiga/amiga.c (UnZip); time() is used only by Zip.
29
* 2 Sep 92, Greg Roelofs, Original coding.
30
* 6 Sep 92, John Bush, Incorporated into UnZip 5.1
31
* 6 Sep 92, John Bush, Interlude "FileDate()" defined, which calls or
32
* redefines SetFileDate() depending upon AMIGADOS2 definition.
33
* 11 Oct 92, John Bush, Eliminated AMIGADOS2 switch by determining
34
* revision via OpenLibrary() call. Now only one version of
35
* the program runs on both platforms (1.3.x vs. 2.x)
36
* 11 Oct 92, John Bush, Merged with Zip version and changed arg passing
37
* to take time_t input instead of struct DateStamp.
38
* Arg passing made to conform with utime().
39
* 22 Nov 92, Paul Kienitz, fixed includes for Aztec and cleaned up some
40
* lint-ish errors; simplified test for AmigaDOS version.
41
* 11 Nov 95, Paul Kienitz, added Agetch() for crypt password input and
42
* UnZip's "More" prompt -- simplifies crypt.h and avoids
43
* use of library code redundant with sendpkt(). Made it
44
* available to fUnZip, which does not use FileDate().
45
* 22 Nov 95, Paul Kienitz, created a new tzset() that gets the current
46
* timezone from the Locale preferences. These exist only under
47
* AmigaDOS 2.1 and up, but it is probably correctly set on more
48
* Amigas than the TZ environment variable is. We check that
49
* only if TZ is not validly set. We do not parse daylight
50
* savings syntax except to check for presence vs. absence of a
51
* DST part; United States rules are assumed. This is better
52
* than the tzset()s in the Amiga compilers' libraries do.
53
* 15 Jan 96, Chr. Spieler, corrected the logic when to select low level
54
* sendpkt() (when FileDate(), Agetch() or windowheight() is used),
55
* and AMIGA's Agetch() (CRYPT, and UnZip(SFX)'s UzpMorePause()).
56
* 10 Feb 96, Paul Kienitz, re-fiddled that selection logic again, moved
57
* stuff around for clarity.
58
* 16 Mar 96, Paul Kienitz, created a replacement localtime() to go with the
59
* new tzset(), because Aztec's is hopelessly broken. Also
60
* gmtime(), which localtime() calls.
61
* 12 Apr 96, Paul Kienitz, daylight savings was being handled incorrectly.
62
* 21 Apr 96, Paul Kienitz, had to replace time() as well, Aztec's returns
63
* local time instead of GMT. That's why their localtime() was bad,
64
* because it assumed time_t was already local, and gmtime() was
65
* the one that checked TZ.
66
* 23 Apr 96, Chr. Spieler, deactivated time() replacement for UnZip stuff.
67
* Currently, the UnZip sources do not make use of time() (and do
68
* not supply the working mktime() replacement, either!).
69
* 29 Apr 96, Paul Kienitz, created a replacement getenv() out of code that
70
* was previously embedded in tzset(), for reliable global test
71
* of whether TZ is set or not.
72
* 19 Jun 96, Haidinger Walter, re-adapted for current SAS/C compiler.
73
* 7 Jul 96, Paul Kienitz, smoothed together compiler-related changes.
74
* 4 Feb 97, Haidinger Walter, added set_TZ() for SAS/C.
75
* 23 Apr 97, Paul Kienitz, corrected Unix->Amiga DST error by adding
76
* mkgmtime() so localtime() could be used.
77
* 28 Apr 97, Christian Spieler, deactivated mkgmtime() definition for ZIP;
78
* the Zip sources supply this function as part of util.c.
79
* 24 May 97, Haidinger Walter, added time_lib support for SAS/C and moved
80
* set_TZ() to time_lib.c.
81
* 12 Jul 97, Paul Kienitz, adapted time_lib stuff for Aztec.
82
* 26 Jul 97, Chr. Spieler, old mkgmtime() fixed (ydays[] def, sign vs unsign).
83
* 30 Dec 97, Haidinger Walter, adaptation for SAS/C using z-stat.h functions.
84
* 19 Feb 98, Haidinger Walter, removed alloc_remember, more SAS.C fixes.
85
* 23 Apr 98, Chr. Spieler, removed mkgmtime(), changed FileDate to convert to
86
* Amiga file-time directly.
87
* 24 Apr 98, Paul Kienitz, clip Unix dates earlier than 1978 in FileDate().
88
* 02 Sep 98, Paul Kienitz, C. Spieler, always include zip.h to get a defined
89
* header inclusion sequence that resolves all header dependencies.
90
* 06 Jun 00, Paul Kienitz, removed time_lib.c due to its incompatible license,
91
* moved set_TZ() back here, replaced minimal tzset() and localtime()
92
* with new versions derived from GNU glibc source. Gave locale_TZ()
93
* reasonable European defaults for daylight savings.
94
* 17 Jun 00, Paul Kienitz, threw out GNU code because of objections to the GPL
95
* virus, replaced with similar functions based on the public domain
96
* timezone code at ftp://elsie.nci.nih.gov/pub. As with the GNU
97
* stuff, support for timezone files and leap seconds was removed.
98
* 23 Aug 00, Paul Kienitz, moved timezone code out from here into separate
99
* platform-independent module 'timezone.c'.
100
* 31 Dec 00, Christian Spieler, moved system-specific timezone help funcions
101
* back in here, from 'timezone.c'.
102
* 07 Jan 01, Paul Kienitz, Chr. Spieler, added missing #include "timezone.h"
103
* and "symbolic" preprocessor constants for time calculations.
104
* 15 Jan 02, Paul Kienitz, excluded all time handling code from compilation
105
* for Zip utilities (when "defined(UTIL)")
108
#ifndef __amiga_filedate_c
109
#define __amiga_filedate_c
116
#include <exec/types.h>
117
#include <exec/execbase.h>
118
#include <exec/memory.h>
119
#include <dos/dosextens.h>
122
# include <libraries/dos.h>
123
# include <libraries/dosextens.h>
124
# include <clib/exec_protos.h>
125
# include <clib/dos_protos.h>
126
# include <clib/locale_protos.h>
127
# include <pragmas/exec_lib.h>
128
# include <pragmas/dos_lib.h>
129
# include <pragmas/locale_lib.h>
130
# define ESRCH ENOENT
136
# if (defined(_M68020) && (!defined(__USE_SYSBASE)))
137
/* on 68020 or higher processors it is faster */
138
# define __USE_SYSBASE /* to use the pragma libcall instead of syscall */
139
# endif /* to access functions of the exec.library */
140
# include <proto/exec.h> /* see SAS/C manual:part 2,chapter 2,pages 6-7 */
141
# include <proto/dos.h>
142
# include <proto/locale.h>
147
# include <stdio.h> /* include both before memwatch.h again just */
148
# include <stdlib.h> /* to be safe */
149
# include "memwatch.h"
150
# endif /* MWDEBUG */
153
#include "crypt.h" /* just so we can tell if CRYPT is supported */
156
#if (!defined(FUNZIP) && !defined(UTIL))
158
#include "timezone.h" /* for AMIGA-specific timezone callbacks */
161
# define SUCCESS (-1L)
165
#define ReqVers 36L /* required library version for SetFileDate() */
166
#define ENVSIZE 100 /* max space allowed for an environment var */
168
extern struct ExecBase *SysBase;
171
# define min(a, b) ((a) < (b) ? (a) : (b))
172
# define max(a, b) ((a) < (b) ? (b) : (a))
175
#if defined(ZIP) || defined(HAVE_MKTIME)
176
static const unsigned short ydays[] =
177
{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
179
extern const unsigned short ydays[]; /* in unzip's fileio.c */
182
#define LEAP(y) (((y) % 4 == 0 && (y) % 100 != 0) || (y) % 400 == 0)
183
#define YDAYS(m, y) (ydays[m] + (m > 1 && LEAP(y)))
184
/* Number of leap years from 1978 to `y' (not including `y' itself). */
185
#define ANLEAP(y) (((y) - 1977) / 4 - ((y) - 1901) / 100 + ((y) - 1601) / 400)
186
#define SECSPERMIN 60
187
#define MINSPERHOUR 60
188
#define SECSPERHOUR (SECSPERMIN * MINSPERHOUR)
189
#define SECSPERDAY 86400L
192
char *getenv(const char *var);
194
/* XXX !! We have really got to find a way to operate without these. */
195
int setenv(const char *var, const char *value, int overwrite);
196
void set_TZ(long time_zone, int day_light);
199
LONG FileDate(char *filename, time_t u[]);
200
LONG sendpkt(struct MsgPort *pid, LONG action, LONG *args, LONG nargs);
203
/* =============================================================== */
205
/***********************/
206
/* Function filedate() */
207
/***********************/
209
/* FileDate() (originally utime.c), by Paul Wells. Modified by John Bush
210
* and others (see also sendpkt() comments, below); NewtWare SetFileDate()
211
* clone cheaply ripped off from utime().
215
* This routine chooses between 2 methods to set the file date on AMIGA.
216
* Since AmigaDOS 2.x came out, SetFileDate() was available in ROM (v.36
217
* and higher). Under AmigaDOS 1.3.x (less than v.36 ROM), SetFileDate()
218
* must be accomplished by constructing a message packet and sending it
219
* to the file system handler of the file to be stamped.
221
* The system's ROM version is extracted from the external system Library
224
* NOTE: although argument passing conforms with utime(), note the
225
* following differences:
226
* - Return value is boolean success/failure.
227
* - If a structure or array is passed, only the first value
228
* is used, which *may* correspond to date accessed and not
232
LONG FileDate(filename, u)
236
LONG SetFileDate(UBYTE *filename, struct DateStamp *pDate);
237
LONG sendpkt(struct MsgPort *pid, LONG action, LONG *args, LONG nargs);
238
struct MsgPort *taskport;
240
struct FileInfoBlock *fib;
245
struct DateStamp pDate;
250
/* Amiga file date is based on 01-Jan-1978 00:00:00 (local time):
251
* 8 years and 2 leapdays difference from Unix time.
253
ltm = localtime(&u[0]);
254
years = ltm->tm_year + 1900;
256
pDate.ds_Days = pDate.ds_Minute = pDate.ds_Tick = 0;
258
pDate.ds_Days = (years - 1978) * 365L + (ANLEAP(years)) +
259
YDAYS(ltm->tm_mon, years) + (ltm->tm_mday - 1);
260
pDate.ds_Minute = ltm->tm_hour * 60 + ltm->tm_min;
261
pDate.ds_Tick = ltm->tm_sec * TICKS_PER_SECOND;
264
if (SysBase->LibNode.lib_Version >= ReqVers)
266
return (SetFileDate(filename,&pDate)); /* native routine at 2.0+ */
268
else /* !(SysBase->lib_Version >=ReqVers) */
270
if( !(taskport = (struct MsgPort *)DeviceProc(filename)) )
272
errno = ESRCH; /* no such process */
276
if( !(lock = Lock(filename,SHARED_LOCK)) )
278
errno = ENOENT; /* no such file */
282
if( !(fib = (struct FileInfoBlock *)AllocMem(
283
(long)sizeof(struct FileInfoBlock),MEMF_PUBLIC|MEMF_CLEAR)) )
285
errno = ENOMEM; /* insufficient memory */
290
if( Examine(lock,fib)==FAILURE )
292
errno = EOSERR; /* operating system error */
294
FreeMem(fib,(long)sizeof(*fib));
298
dirlock = ParentDir(lock);
299
ptr = (UBYTE *)AllocMem(64L,MEMF_PUBLIC);
300
strcpy((ptr+1),fib->fib_FileName);
301
*ptr = strlen(fib->fib_FileName);
302
FreeMem(fib,(long)sizeof(*fib));
305
/* now fill in argument array */
308
pktargs[1] = (LONG)dirlock;
309
pktargs[2] = (LONG)&ptr[0] >> 2;
310
pktargs[3] = (LONG)&pDate;
312
errno = ret = sendpkt(taskport,ACTION_SET_DATE,pktargs,4L);
318
} /* ?(SysBase->lib_Version >= ReqVers) */
322
char *getenv(const char *var) /* not reentrant! */
324
static char space[ENVSIZE];
325
struct Process *me = (void *) FindTask(NULL);
326
void *old_window = me->pr_WindowPtr;
329
me->pr_WindowPtr = (void *) -1; /* suppress any "Please insert" popups */
330
if (SysBase->LibNode.lib_Version >= ReqVers) {
331
if (GetVar((char *) var, space, ENVSIZE - 1, /*GVF_GLOBAL_ONLY*/ 0) > 0)
333
} else { /* early AmigaDOS, get env var the crude way */
334
BPTR hand, foot, spine;
336
if (foot = Lock("ENV:", ACCESS_READ)) {
337
spine = CurrentDir(foot);
338
if (hand = Open((char *) var, MODE_OLDFILE)) {
339
z = Read(hand, space, ENVSIZE - 1);
342
UnLock(CurrentDir(spine));
349
me->pr_WindowPtr = old_window;
354
int setenv(const char *var, const char *value, int overwrite)
356
struct Process *me = (void *) FindTask(NULL);
357
void *old_window = me->pr_WindowPtr;
360
me->pr_WindowPtr = (void *) -1; /* suppress any "Please insert" popups */
361
if (SysBase->LibNode.lib_Version >= ReqVers)
362
ret = !SetVar((char *)var, (char *)value, -1, GVF_GLOBAL_ONLY | LV_VAR);
364
BPTR hand, foot, spine;
365
long len = value ? strlen(value) : 0;
366
if (foot = Lock("ENV:", ACCESS_READ)) {
367
spine = CurrentDir(foot);
369
if (hand = Open((char *) var, MODE_NEWFILE)) {
370
ret = Write(hand, (char *) value, len + 1) >= len;
374
ret = DeleteFile((char *) var);
375
UnLock(CurrentDir(spine));
378
me->pr_WindowPtr = old_window;
382
/* Stores data from timezone and daylight to ENV:TZ. */
383
/* ENV:TZ is required to exist by some other SAS/C library functions, */
384
/* like stat() or fstat(). */
385
void set_TZ(long time_zone, int day_light)
387
char put_tz[MAXTIMEZONELEN]; /* string for putenv: "TZ=aaabbb:bb:bbccc" */
389
void *exists; /* dummy ptr to see if global envvar TZ already exists */
390
exists = (void *)getenv(TZ_ENVVAR);
391
/* see if there is already an envvar TZ_ENVVAR. If not, create it */
392
if (exists == NULL) {
393
/* create TZ string by pieces: */
394
sprintf(put_tz, "GMT%+ld", time_zone / 3600L);
395
if (time_zone % 3600L) {
396
offset = (int) labs(time_zone % 3600L);
397
sprintf(put_tz + strlen(put_tz), ":%02d", offset / 60);
399
sprintf(put_tz + strlen(put_tz), ":%02d", offset % 60);
402
strcat(put_tz,"DST");
403
setenv(TZ_ENVVAR, put_tz, 1);
408
/* set state as well as possible from settings found in locale.library */
409
int GetPlatformLocalTimezone(sp, fill_tzstate_from_rules)
410
register struct state * ZCONST sp;
411
void (*fill_tzstate_from_rules)(struct state * ZCONST sp_res,
412
ZCONST struct rule * ZCONST start,
413
ZCONST struct rule * ZCONST end);
415
struct Library *LocaleBase;
417
struct Process *me = (void *) FindTask(NULL);
418
void *old_window = me->pr_WindowPtr;
420
int z, valid = FALSE;
422
/* read timezone from locale.library if TZ envvar missing */
423
me->pr_WindowPtr = (void *) -1; /* suppress any "Please insert" popups */
424
if (LocaleBase = OpenLibrary("locale.library", 0)) {
425
if (ll = OpenLocale(NULL)) {
426
z = ll->loc_GMTOffset; /* in minutes */
428
if (eh = Lock("ENV:sys/locale.prefs", ACCESS_READ)) {
432
z = 300; /* bug: locale not initialized, default bogus! */
436
struct rule startrule, stoprule;
441
sp->chars[0] = sp->chars[1] = '\0';
442
sp->ttis[0].tt_abbrind = 0;
443
sp->ttis[1].tt_abbrind = 1;
444
sp->ttis[0].tt_gmtoff = -z * MINSPERHOUR;
445
sp->ttis[1].tt_gmtoff = -z * MINSPERHOUR + SECSPERHOUR;
446
sp->ttis[0].tt_isdst = 0;
447
sp->ttis[1].tt_isdst = 1;
448
stoprule.r_type = MONTH_NTH_DAY_OF_WEEK;
452
stoprule.r_time = 2 * SECSPERHOUR;
453
startrule = stoprule;
455
startrule.r_week = 1;
456
if (z >= -180 && z < 150) {
457
/* At this point we make a really gratuitous assumption: */
458
/* if the time zone could be Europe, we use the European */
459
/* Union rules without checking what country we're in. */
460
/* The AmigaDOS locale country codes do not, at least in */
461
/* 2.x versions of the OS, recognize very many countries */
462
/* outside of Europe and North America. */
464
startrule.r_mon = 3; /* one week earlier than US DST */
465
startrule.r_week = 5;
466
} else if (z >= 150 && z <= 480 &&
467
/* no DST in alaska, hawaii */
468
(ll->loc_CountryCode == 0x55534100 /*"USA"*/ ||
469
ll->loc_CountryCode == 0x43414E00 /*"CAN"*/))
471
/* We check the country code for U.S. or Canada because */
472
/* most of Latin America has no DST. Even in these two */
473
/* countries there are some exceptions... */
474
/* else if... Feel free to add more cases here! */
477
(*fill_tzstate_from_rules)(sp, &startrule, &stoprule);
481
CloseLibrary(LocaleBase);
483
me->pr_WindowPtr = old_window;
488
time_t time(time_t *tp)
493
t = ds.ds_Tick / TICKS_PER_SECOND + ds.ds_Minute * 60
494
+ (ds.ds_Days + 2922) * SECSPERDAY;
495
t = mktime(gmtime(&t));
496
/* gmtime leaves ds in the local timezone, mktime converts it to GMT */
502
#endif /* !FUNZIP && !UTIL */
505
#if CRYPT || !defined(FUNZIP)
508
* by A. Finkel, P. Lindsay, C. Sheppner
509
* returns Res1 of the reply packet
512
#include <exec/types.h>
513
#include <exec/memory.h>
514
#include <libraries/dos.h>
515
#include <libraries/dosextens.h>
516
#include <proto/exec.h>
517
#include <proto/dos.h>
520
LONG sendpkt(struct MsgPort *pid, LONG action, LONG *args, LONG nargs);
522
LONG sendpkt(pid,action,args,nargs)
523
struct MsgPort *pid; /* process identifier (handler message port) */
524
LONG action, /* packet type (desired action) */
525
*args, /* a pointer to argument list */
526
nargs; /* number of arguments in list */
529
struct MsgPort *replyport, *CreatePort(UBYTE *, long);
530
void DeletePort(struct MsgPort *);
531
struct StandardPacket *packet;
532
LONG count, *pargs, res1;
534
replyport = CreatePort(NULL,0L);
535
if( !replyport ) return(0);
537
packet = (struct StandardPacket *)AllocMem(
538
(long)sizeof(struct StandardPacket),MEMF_PUBLIC|MEMF_CLEAR);
541
DeletePort(replyport);
545
packet->sp_Msg.mn_Node.ln_Name = (char *)&(packet->sp_Pkt);
546
packet->sp_Pkt.dp_Link = &(packet->sp_Msg);
547
packet->sp_Pkt.dp_Port = replyport;
548
packet->sp_Pkt.dp_Type = action;
550
/* copy the args into the packet */
551
pargs = &(packet->sp_Pkt.dp_Arg1); /* address of 1st argument */
552
for( count=0; count<nargs; count++ )
553
pargs[count] = args[count];
555
PutMsg(pid,(struct Message *)packet); /* send packet */
560
res1 = packet->sp_Pkt.dp_Res1;
562
FreeMem((char *)packet,(long)sizeof(*packet));
563
DeletePort(replyport);
569
#endif /* CRYPT || !FUNZIP */
572
#if CRYPT || (defined(UNZIP) && !defined(FUNZIP))
574
/* Agetch() reads one raw keystroke -- uses sendpkt() */
578
LONG sendpkt(struct MsgPort *pid, LONG action, LONG *args, LONG nargs);
579
struct Task *me = FindTask(NULL);
580
struct CommandLineInterface *cli = BADDR(((struct Process *) me)->pr_CLI);
581
BPTR fh = cli->cli_StandardInput; /* this is immune to < redirection */
582
void *conp = ((struct FileHandle *) BADDR(fh))->fh_Type;
584
long *flag = (long *) ((ULONG) &longspace[4] & ~3); /* LONGWORD ALIGNED! */
588
sendpkt(conp, ACTION_SCREEN_MODE, flag, 1); /* assume success */
591
sendpkt(conp, ACTION_SCREEN_MODE, flag, 1);
592
if (c == 3) /* ^C in input */
593
Signal(me, SIGBREAKF_CTRL_C);
597
#endif /* CRYPT || (UNZIP && !FUNZIP) */
599
#endif /* __amiga_filedate_c*/