1/*
2  Copyright (c) 1990-2007 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 unzip.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/*---------------------------------------------------------------------------
10
11  tops20.c
12
13  TOPS20-specific routines for use with Info-ZIP's UnZip 5.1 and later.
14
15  Contains:  mapattr()
16             close_outfile()
17             version()
18             upper()
19             enquote()
20             dequote()
21             fnlegal()
22
23  (not yet ported:  do_wild(), mapname(), checkdir(), ...)
24
25  ---------------------------------------------------------------------------*/
26
27
28#define UNZIP_INTERNAL
29#include "unzip.h"
30
31
32/**********************/
33/* Function mapattr() */
34/**********************/
35
36int mapattr(__G)        /* just like Unix except no umask() */
37    __GDEF
38{
39    ulg  tmp = G.crec.external_file_attributes;
40
41    switch (G.pInfo->hostnum) {
42        case UNIX_:
43        case VMS_:
44        case ACORN_:
45        case ATARI_:
46        case ATHEOS_:
47        case BEOS_:
48        case QDOS_:
49            G.pInfo->file_attr = (unsigned)(tmp >> 16);
50            break;
51        case AMIGA_:
52            tmp = (unsigned)(tmp>>1 & 7);   /* Amiga RWE bits */
53            G.pInfo->file_attr = (unsigned)(tmp<<6 | tmp<<3 | tmp);
54            break;
55        case FS_FAT_:   /* MSDOS half of attributes should always be correct */
56        case FS_HPFS_:
57        case FS_NTFS_:
58        case MAC_:
59        case TOPS20_:
60        default:
61            tmp = !(tmp & 1) << 1;   /* read-only bit --> write perms bits */
62            G.pInfo->file_attr = (unsigned)(0444 | tmp<<6 | tmp<<3 | tmp);
63            break;
64#if 0
65        case ATARI_:
66        case TOPS20_:
67        default:
68            G.pInfo->file_attr = 0666;
69            break;
70#endif
71    } /* end switch (host-OS-created-by) */
72
73    return 0;
74
75} /* end function mapattr() */
76
77
78
79
80
81/****************************/
82/* Function close_outfile() */
83/****************************/
84
85void close_outfile(__G)
86    __GDEF
87{
88#   define JSYS_CLASS           0070000000000
89#   define FLD(val,mask)        (((unsigned)(val)*((mask)&(-(mask))))&(mask))
90#   define _DEFJS(name,class)   (FLD(class,JSYS_CLASS) | (monsym(name)&0777777))
91#   define IDTIM                _DEFJS("IDTIM%", 1)
92#   define SFTAD                _DEFJS("SFTAD%", 0)
93#   define YRBASE               1900
94    int ablock[5], tblock[2];
95    int yr, mo, dy, hh, mm, ss;
96    char temp[100];
97    unsigned tad;
98#ifdef USE_EF_UT_TIME
99    iztimes z_utime;
100    struct tm *t;
101
102
103    /* skip restoring time stamps on user's request */
104    if (uO.D_flag <= 1) {
105
106        if (G.extra_field &&
107#ifdef IZ_CHECK_TZ
108            G.tz_is_valid &&
109#endif
110            (ef_scan_for_izux(G.extra_field, G.lrec.extra_field_length, 0,
111                              G.lrec.last_mod_dos_date, &z_utime, NULL)
112             & EB_UT_FL_MTIME))
113            t = localtime(&(z_utime.mtime));
114        else
115            t = (struct tm *)NULL;
116
117        if (t != (struct tm *)NULL)
118        {
119            yr = t->tm_year + 1900;
120            mo = t->tm_mon;
121            dy = t->tm_mday;
122            hh = t->tm_hour;
123            mm = t->tm_min;
124            ss = t->tm_sec;
125        }
126        else
127        {
128            /* dissect the date */
129            yr = ((G.lrec.last_mod_dos_date >> 9) & 0x7f) + 1980;
130            mo = ((G.lrec.last_mod_dos_date >> 5) & 0x0f) - 1;
131            dy = (G.lrec.last_mod_dos_date & 0x1f);
132
133            /* dissect the time */
134            hh = (G.lrec.last_mod_dos_time >> 11) & 0x1f;
135            mm = (G.lrec.last_mod_dos_time >> 5) & 0x3f;
136            ss = (G.lrec.last_mod_dos_time & 0x1f) * 2;
137        }
138#else /* !USE_EF_UT_TIME */
139
140        /* dissect the date */
141        yr = ((G.lrec.last_mod_dos_datetime >> 25) & 0x7f) + (1980 - YRBASE);
142        mo = (G.lrec.last_mod_dos_datetime >> 21) & 0x0f;
143        dy = (G.lrec.last_mod_dos_datetime >> 16) & 0x1f;
144
145        /* dissect the time */
146        hh = (G.lrec.last_mod_dos_datetime >> 11) & 0x1f;
147        mm = (G.lrec.last_mod_dos_datetime >> 5) & 0x3f;
148        ss = (G.lrec.last_mod_dos_datetime << 1) & 0x1f;
149#endif /* ?USE_EF_UT_TIME */
150
151        sprintf(temp, "%02d/%02d/%02d %02d:%02d:%02d", mo, dy, yr, hh, mm, ss);
152
153        ablock[1] = (int)(temp - 1);
154        ablock[2] = 0;
155        if (!jsys(IDTIM, ablock)) {
156            Info(slide, 1, ((char *)slide, "error:  IDTIM failure for %s\n",
157              G.filename));
158            fclose(G.outfile);
159            return;
160        }
161
162        tad = ablock[2];
163        tblock[0] = tad;
164        tblock[1] = tad;
165        tblock[2] = -1;
166
167        ablock[1] = fcntl(fileno(G.outfile), F_GETSYSFD, 0);
168                                                    /* _uffd[outfd]->uf_ch */
169        ablock[2] = (int) tblock;
170        ablock[3] = 3;
171        if (!jsys(SFTAD, ablock))
172            Info(slide, 1,((char *)slide,
173              "error:  cannot set the time for %s\n", G.filename));
174
175    } /* if (uO.D_flag <= 1) */
176
177    fclose(G.outfile);
178
179} /* end function close_outfile() */
180
181
182
183
184
185#ifndef SFX
186
187/************************/
188/*  Function version()  */
189/************************/
190
191void version(__G)
192    __GDEF
193{
194#if 0
195    char buf[40];
196#endif
197
198    sprintf((char *)slide, LoadFarString(CompiledWith),
199
200#ifdef __GNUC__
201      "gcc ", __VERSION__,
202#else
203#  if 0
204      "cc ", (sprintf(buf, " version %d", _RELEASE), buf),
205#  else
206#  ifdef __COMPILER_KCC__
207      "KCC", "",
208#  else
209      "unknown compiler", "",
210#  endif
211#  endif
212#endif
213
214      "TOPS-20",
215
216#if defined(foobar) || defined(FOOBAR)
217      " (Foo BAR)",   /* OS version or hardware */
218#else
219      "",
220#endif /* Foo BAR */
221
222#ifdef __DATE__
223      " on ", __DATE__
224#else
225      "", ""
226#endif
227    );
228
229    (*G.message)((zvoid *)&G, slide, (ulg)strlen((char *)slide), 0);
230
231} /* end function version() */
232
233#endif /* !SFX */
234
235
236
237
238
239/**********************/
240/*  Function upper()  */
241/**********************/
242
243int upper(s)        /* returns s in uppercase */
244    char *s;        /* string to be uppercased */
245{
246    for (;  *s;  ++s)
247        *s = toupper(*s);
248}
249
250
251
252
253
254/************************/
255/*  Function enquote()  */
256/************************/
257
258int enquote(s)      /* calls dequote(s) to normalize string, then */
259    char *s;        /*  inserts ^Vs before otherwise illegal characters */
260{                   /*  in s, assuming that s is a TOPS-20 filename */
261    char d[100];
262    char *p, *q;
263    char c;
264
265    if (s && *s) {
266        dequote(s);
267        p = s - 1;
268        q = d - 1;
269        while (c = *++p) {
270            if (!fnlegal(c))
271                *++q = '\026';
272            *++q = c;
273        }
274        *++q = '\0';
275        strcpy(s, d);
276    }
277    return 0;
278}
279
280
281
282
283
284/************************/
285/*  Function dequote()  */
286/************************/
287
288int dequote(s)        /* returns s without ^Vs */
289    char *s;          /* string to be dequoted */
290{
291    char d[100];
292    char *p, *q;
293    int c;
294
295    if (s && *s) {
296        p = s - 1;
297        q = d - 1;
298        while (c = *++p)
299            if (c != '\026')
300                *++q = c;
301        *++q = '\0';
302        strcpy(s, d);
303    }
304    return 0;
305}
306
307
308
309
310
311/************************/
312/*  Function fnlegal()  */
313/************************/
314
315int fnlegal(c)         /* returns TRUE if c is a member of the */
316    char c;            /*  legal character set for filenames */
317{
318    char *q;
319    static char *legals = {"$%**-<>>AZ[[]]__az"};
320
321    q = legals;
322    while (*q)
323        if (c < *q++)
324            break;
325        else if (c <= *q++)
326            return TRUE;
327
328    return FALSE;
329}
330