1 /*
2   qdos/qdos.c
3 
4   Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
5 
6   See the accompanying file LICENSE, version 2005-Feb-10 or later
7   (the contents of which are also included in zip.h) for terms of use.
8   If, for some reason, all these files are missing, the Info-ZIP license
9   also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
10 */
11 /*
12  * Yes this  file is necessary; the QDOS file system is the most
13  * ludicrous known to man (even more so than VMS!).
14  */
15 
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <sys/stat.h>
20 #include <fcntl.h>
21 #include <dirent.h>
22 #include <unistd.h>
23 
24 #include "zip.h"
25 #include "crypt.h"
26 #include "ttyio.h"
27 
28 #ifdef QDOS
29 
30 # include <qdos.h>
31 
32 #if CRYPT
33 
getp(m,p,n)34 char *getp(m, p, n)
35     ZCONST char *m;              /* prompt for password */
36     char *p;                    /* return value: line input */
37     int n;                      /* bytes available in p[] */
38 {
39     int c;                      /* one-byte buffer for read() to use */
40     int i;                      /* number of characters input */
41     char *w;                    /* warning on retry */
42 
43     /* get password */
44     w = "";
45     sd_cure(getchid(0), -1);    /* enable cursor */
46     do {
47         fputs(w, stderr);       /* warning if back again */
48         fputs(m, stderr);       /* display prompt and flush */
49         fflush(stderr);
50         i = 0;
51         do {
52             c = getch();
53             if (c == 0xc2) {
54                 if (i > 0) {
55                     i--; /* the `del' keys works */
56                     fputs("\b \b", stderr);
57                 }
58             }
59             else if (i < n) {
60                 p[i++] = c;     /* truncate past n */
61                 if(c != '\n') putc('*', stderr);
62             }
63         } while (c != '\n');
64 
65         putc('\n', stderr);  fflush(stderr);
66         w = "(line too long--try again)\n";
67     } while (p[i-1] != '\n');
68 
69     p[i-1] = 0;                 /* terminate at newline */
70     sd_curs(getchid(0), -1);    /* suppress cursor */
71     return p;                   /* return pointer to password */
72 
73 } /* end function getp() */
74 
75 #endif /* CRYPT */
76 
77 
78 #define __attribute__(p)
79 
80 int newname(char *, int, int);
81 
82 #else /* !QDOS */
83 #define QDOS_FLMAX 36
84 
85 short qlflag = 0;
86 
87 struct qdirect  {
88     long            d_length __attribute__ ((packed));  /* file length */
89     unsigned char   d_access __attribute__ ((packed));  /* file access type */
90     unsigned char   d_type __attribute__ ((packed));    /* file type */
91     long            d_datalen __attribute__ ((packed)); /* data length */
92     long            d_reserved __attribute__ ((packed));/* Unused */
93     short           d_szname __attribute__ ((packed));  /* size of name */
94     char            d_name[QDOS_FLMAX] __attribute__ ((packed));/* name area */
95     long            d_update __attribute__ ((packed));  /* last update */
96     long            d_refdate __attribute__ ((packed));
97     long            d_backup __attribute__ ((packed));   /* EOD */
98     } ;
99 #endif /* ?QDOS */
100 
101 #define SHORTID 0x4afb          /* in big-endian order !! */
102 #define LONGID  "QDOS02"
103 #define EXTRALEN (sizeof(struct qdirect) + 8)
104 
105 typedef struct
106 {
107     unsigned short shortid __attribute__ ((packed));
108     struct
109     {
110         unsigned char lo __attribute__ ((packed));
111         unsigned char hi __attribute__ ((packed));
112     } len __attribute__ ((packed));
113     char        longid[8] __attribute__ ((packed));
114     struct      qdirect     header __attribute__ ((packed));
115 } qdosextra;
116 
117 #ifdef USE_EF_UT_TIME
118 local int GetExtraTime(struct zlist far *z, iztimes *z_utim, unsigned ut_flg);
119 #endif
120 
121 #ifdef QDOS
122 
123 #define rev_short(x) (x)
124 #define rev_long(x) (x)
125 
126 char _prog_name[] = "zip";
127 char _copyright[] = "(c) Info-ZIP Group";
128 long _stack = 16*1024;
129 char *  _endmsg = NULL;
130 
131 extern void consetup_title(chanid_t,struct WINDOWDEF *);
132 void (*_consetup)(chanid_t,struct WINDOWDEF *) = consetup_title;
133 
134 struct WINDOWDEF _condetails =
135 {
136     2,
137     1,
138     0,
139     7,
140     500,
141     220,
142     2,
143     30
144 };
145 
146 extern short qlwait;
147 extern short dtype;
148 
149 #define CHECKDIR(p1) (((p1).d_type == dtype) && (((p1).d_length % 64) == 0))
150 
stpcpy(char * d,ZCONST char * s)151 char * stpcpy (char *d, ZCONST char *s)
152 {
153     while(*d++ = *s++)
154         ; /* Null loop */
155     return d-1;
156 }
157 
chowner(chanid_t chan)158 static jobid_t chowner(chanid_t chan)
159 {
160     extern char *_sys_var;
161     char *scht;
162     long *cdb;
163     long jid;
164 
165     scht = *((char **)(_sys_var + 0x78));
166     cdb = *(long **)((long *)scht  + (chan & 0xffff));
167     jid = *(cdb + 2);
168     return jid;
169 }
170 
QDOSexit(void)171 void QDOSexit(void)
172 {
173     jobid_t me,you;
174 
175     me = getpid();
176     you = chowner(getchid(0));
177 
178     if((me == you) && ((qlflag & 4) == 0))
179     {
180         if(isatty(0) && isatty(2) && qlwait)
181         {
182             char c = 0;
183             fputs("Press a key to exit", stderr);
184             if((io_fbyte(getchid(0), qlwait, &c) == 0) && c == 27)
185             {
186                 io_fbyte(getchid(0), -1, &c);
187             }
188         }
189     }
190     exit(ZE_OK);
191 }
192 
193 /* Access seems to be *always* broken in c68 */
194 /* Not accurate, just works */
195 
access(char * f,int mode)196 int access (char *f, int mode)
197 {
198     struct stat st;
199     int fd;
200 
201     if((fd = stat(f, &st)) == 0)
202     {
203         switch(fd)
204         {
205         case F_OK:
206             break;
207         case R_OK:
208             fd = (st.st_mode & 0444) == 0;
209             break;
210         case W_OK:
211             fd = (st.st_mode & 0222) == 0;
212             break;
213         case X_OK:
214             fd = (st.st_mode & 0111) == 0;
215             break;
216         default:
217             fd = -1;
218             break;
219         }
220     }
221     return fd;
222 }
223 
224 /* Fixup a Mickey Mouse file naming system */
225 
Unix2ql(char * qlname,char ** dot)226 char * Unix2ql (char *qlname, char **dot)
227 {
228     static char path[64];
229     char name[64];
230     char *q, *r, *s;
231 
232     strcpy(name, qlname);
233     if(*name == '~')
234     {
235         r = name+1;
236         getcwd(path, sizeof(path));
237         q = path + strlen(path);
238         if(*(q-1) != '_')
239         {
240             *q++ = '_';
241         }
242     }
243     else
244     {
245         q = path;
246         r = name;
247     }
248 
249     if(*r == '/')
250     {
251         r++;
252     }
253 
254     strcpy(q, r);
255 
256     while (*q)
257     {
258         if(*q == '/' || *q == '.')
259         {
260             if(*q == '.' && dot)
261             {
262                 *dot = name + (q - path);
263             }
264             *q = '_';
265         }
266 
267         q++;
268     }
269     return path;
270 }
271 
272 #if 0                                 /* Not used in ZIP */
273 
274 GuessAltName(char *name, char *dot)
275 {
276     if(dot)
277     {
278         *dot = '.';
279     }
280     else
281     {
282         if((dot = strrchr(name, '_')))
283         {
284             *dot = '.';
285         }
286     }
287 }
288 
289 #endif /* 0 */
290 
devlen(char * p)291 short devlen(char *p)
292 {
293     char defpath[40];
294     short deflen = 0, ok = 0;
295 
296     getcwd(defpath, sizeof(defpath));
297     deflen = strlen(defpath);
298     if(deflen)
299     {
300         if(strnicmp(p, defpath, deflen) == 0)
301         {
302             ok = 1;
303         }
304     }
305 
306     if(!ok)
307     {
308         if(isdirdev(p))
309         {
310             deflen = 5;
311         }
312         else
313         {
314             deflen = 0;
315         }
316     }
317     return deflen;
318 }
319 
ql2Unix(char * qlname)320 char * ql2Unix (char *qlname)
321 {
322     struct stat st;
323     int sts;
324     char *p, *r, *s, *ldp;
325     char *pnam = NULL;
326     static char path[64];
327     short  deflen;
328     char name[64];
329 
330     strcpy(name, qlname);
331     strcpy(path, name);
332 
333     deflen = devlen(qlname);
334 
335     p = name + deflen;
336     pnam = path + deflen;
337 
338     if(s = strrchr(p, '_'))
339     {
340         *s = 0;
341         sts = stat(name, &st);
342         if(deflen && sts ==0 && (st.st_mode & S_IFDIR))
343         {
344             *(path+(s-name)) = '/';
345         }
346         else
347         {
348             *(path+(s-name)) = '.';
349         }
350     }
351 
352     ldp = p;
353     for(r = p; *r; r++)
354     {
355         if(r != ldp && *r == '_')
356         {
357             *r = 0;
358             if(deflen)
359             {
360                 sts = stat(name, &st);
361             }
362             else
363                 sts = -1;
364 
365             if(sts ==0 && (st.st_mode & S_IFDIR))
366             {
367                 *(path+(r-name)) = '/';
368                 ldp = r + 1;
369             }
370             else
371             {
372                 *(path+(r-name)) = '_';
373             }
374             *r = '_';
375         }
376     }
377     return pnam;
378 }
379 
LastDir(char * ws)380 char *LastDir(char *ws)
381 {
382     char *p;
383     char *q = ws;
384     struct stat s;
385 
386     for(p = ws; *p; p++)
387     {
388         if(p != ws && *p == '_')
389         {
390             char c;
391 
392             p++;
393             c = *p;
394             *p = 0;
395             if(stat(ws, &s) == 0 && S_ISDIR(s.st_mode))
396             {
397                 q = p;
398             }
399             *p = c;
400         }
401     }
402     return q;
403 }
404 
405 # ifndef UTIL
406 
add_dir(char * dnam)407 static int add_dir(char * dnam)
408 {
409     int e = ZE_OK;
410     char *p;
411     short nlen;
412 
413     nlen = strlen(dnam);
414     if(p = malloc(nlen + 2))
415     {
416         strncpy (p, dnam, nlen);
417         if(*(p+nlen) != '_')
418         {
419             *(p+nlen) = '_';
420             *(p+nlen+1) = '\0';
421         }
422         if ((e = newname(p, 1, 0)) != ZE_OK)
423         {
424                 free(p);
425         }
426     }
427     else
428     {
429         e = ZE_MEM;
430     }
431     return e;
432 }
433 
qlwild(char * dnam,short dorecurse,short l)434 int qlwild (char *dnam, short dorecurse, short l)
435 {
436     static char match[40] = {0};
437     static char ddev[8] =  {0};
438     static short nc;
439     static short llen;
440     static char base[40];
441 
442     int chid;
443     struct qdirect qd;
444     char *dp;
445     int e = ZE_MISS;
446 
447     if (l == 0)
448     {
449         nc = 0;
450         *base = '\0';
451         if (isdirdev (dnam))
452         {
453             dp = dnam;
454             strncpy (ddev, dnam, 5);
455         }
456         else
457         {
458 
459             char *p;
460             char temp[40];
461 
462             getcwd (temp, 40);
463 
464             llen = strlen(temp);
465             p = (temp + llen - 1);
466             if (*p != '_')
467             {
468                 *p++ = '_';
469                 *p = 0;
470             }
471 
472             strncpy (ddev, temp, 5);
473             dp = base;
474             p = stpcpy (dp, temp);
475             strcpy (p, dnam);
476         }
477 
478         {
479             char *q = isshexp (dp);
480             if(q)
481             {
482                 strcpy (match, dp + 5);
483                 if (q)
484                 {
485                     while (q != dp && *q != '_')
486                     {
487                         q--;
488                     }
489                     *(++q) = '\0';
490                 }
491             }
492             else
493             {
494                 struct stat s;
495                 if (stat(dp, &s) == 0)
496                 {
497                     if (!(s.st_mode & S_IFDIR))
498                     {
499                         return procname(dp, 0);
500                     }
501                 }
502                 else
503                 {
504                     return ZE_MISS;  /* woops, no wildcards! */
505                 }
506             }
507 
508         }
509     }
510     else
511     {
512         dp = dnam;
513     }
514 
515     if ((chid = io_open (dp, 4L)) > 0)
516     {
517         int id = 0;
518         while (io_fstrg (chid, -1, &qd, 64) > 0)
519         {
520             short j;
521 
522             if (qd.d_szname)
523             {
524                 if (CHECKDIR(qd))
525                 {
526                     if(dorecurse)
527                     {
528                         char fnam[256], *p;
529 
530                         p = stpcpy (fnam, ddev);
531                         strncpy (p, qd.d_name, qd.d_szname);
532                         *(p + qd.d_szname) = 0;
533                         e = qlwild (fnam, dorecurse, l+1);
534                     }
535                     else
536                     {
537                         continue;
538                     }
539                 }
540                 else
541                 {
542                     char nam[48];
543                     strcpy(nam, ddev);
544 
545                     strncpy (nam + 5, qd.d_name, qd.d_szname);
546                     *(nam + 5 + qd.d_szname) = 0;
547 
548                     if (MATCH (match, nam + 5, 0) == 1)
549                     {
550                         if(dirnames && l && id == 0)
551                         {
552                             id = 1;
553                             if((e = add_dir(dp)) != ZE_OK)
554                             {
555                                 return e;
556                             }
557                         }
558 
559                         if((e = procname(nam, 0)) == ZE_OK)
560                         {
561                             nc++;
562                         }
563                     }
564                 }
565             }
566         }
567         io_close (chid);
568     }
569 
570     if (l == 0)
571     {
572         *ddev = 0;
573         *match = 0;
574         e = (nc) ? ZE_OK : ZE_MISS;
575     }
576     return e;
577 
578 }
579 
wild(char * p)580 int wild(char *p)
581 {
582     return qlwild(p, recurse, 0);
583 }
584 # endif /* !UTIL */
585 
586 /*
587  * Return QDOS error, 0 if exec 1 if found but not exe or rel
588  */
qlstat(char * name,struct qdirect * qs,char * flag)589 int qlstat(char *name, struct qdirect *qs, char *flag)
590 {
591     int r;
592     r = qstat(name, qs);
593     if(r == 0)
594     {
595         if(qs->d_type == 0)
596         {
597             r = 1;
598         }
599         else if(CHECKDIR(*qs))
600         {
601             r = 255;
602         }
603     }
604     return r;
605 }
606 
607 #else /* !QDOS */
608 
rev_long(ulg l)609 long rev_long (ulg l)
610 {
611     uch cc[4];
612     cc[0] = (uch)(l >> 24);
613     cc[1] = (uch)((l >> 16) & 0xff);
614     cc[2] = (uch)((l >> 8) & 0xff);
615     cc[3] = (uch)(l & 0xff);
616     return *(ulg *)cc;
617 }
618 
rev_short(ush s)619 short rev_short (ush s)
620 {
621     uch cc[2];
622     cc[0] = (uch)((s >> 8) & 0xff);
623     cc[1] = (uch)(s & 0xff);
624     return *(ush *)cc;
625 }
626 
627 #define O_BINARY 0
628 
qlstat(char * name,struct qdirect * qs,char * flag)629 int qlstat(char *name, struct qdirect *qs, char *flag)
630 {
631     int r = -1;
632     int n, fd;
633     struct stat s;
634     struct _ntc_
635     {
636         long id;
637         long dlen;
638     } ntc;
639 
640     *flag = 0;
641     if((fd = open(name, O_RDONLY | O_BINARY)) > 0)
642     {
643         short nl;
644 
645         fstat(fd, &s);
646         lseek(fd, -8, SEEK_END);
647         read(fd, &ntc, 8);
648         qs->d_length = rev_long(s.st_size);
649         qs->d_update = rev_long(s.st_ctime + 283996800);
650 
651         nl = strlen(name);
652         if(nl > QDOS_FLMAX)
653         {
654             nl = QDOS_FLMAX;
655             *flag = 1;
656         }
657         qs->d_szname = rev_short(nl);
658         memcpy(qs->d_name, name, nl);
659 
660         if(ntc.id == *(long *)"XTcc")
661         {
662             qs->d_datalen = ntc.dlen;    /* This is big endian */
663             qs->d_type = 1;
664             r = 0;
665         }
666         else
667         {
668             qs->d_type = 0;
669             qs->d_datalen = 0;
670             r = 1;
671         }
672         close(fd);
673         return r;
674     }
675     else
676     {
677         fprintf(stderr, "Fails %d\n", fd);
678         return r;
679     }
680 }
681 
682 #endif /* ?QDOS */
683 
684 #ifdef USE_EF_UT_TIME
685 
686 #define EB_L_UT_SIZE    (EB_HEADSIZE + eb_l_ut_len)
687 #define EB_C_UT_SIZE    (EB_HEADSIZE + eb_c_ut_len)
688 
689 #ifdef UNIX
690 #define EB_L_UX2_SIZE     (EB_HEADSIZE + EB_UX2_MINLEN)
691 #define EB_C_UX2_SIZE     EB_HEADSIZE
692 #define EF_L_UT_UX2_SIZE  (EB_L_UT_SIZE + EB_L_UX2_SIZE)
693 #define EF_C_UT_UX2_SIZE  (EB_C_UT_SIZE + EB_C_UX2_SIZE)
694 #else
695 #define EF_L_UT_UX2_SIZE  EB_L_UT_SIZE
696 #define EF_C_UT_UX2_SIZE  EB_C_UT_SIZE
697 #endif
698 
GetExtraTime(struct zlist far * z,iztimes * z_utim,unsigned ut_flg)699 local int GetExtraTime(struct zlist far *z, iztimes *z_utim, unsigned ut_flg)
700 {
701   char *eb_l_ptr;
702   char *eb_c_ptr;
703   char *eb_pt;
704   extent eb_l_ut_len = 0;
705   extent eb_c_ut_len = 0;
706 
707 #ifdef UNIX
708   struct stat s;
709 
710   /* For the full sized UT local field including the UID/GID fields, we
711    * have to stat the file, again.  */
712   if (stat(z->name, &s))
713     return ZE_OPEN;
714   /* update times in z_utim, stat() call might have changed atime... */
715   z_utim->mtime = s.st_mtime;
716   z_utim->atime = s.st_atime;
717   z_utim->ctime = s.st_mtime;   /* best guess (st_ctime != creation time) */
718 #endif /* UNIX */
719 
720 #ifdef IZ_CHECK_TZ
721   if (!zp_tz_is_valid)
722     ut_flg = 0;          /* disable UT e.f creation if no valid TZ info */
723 #endif
724   if (ut_flg != 0) {
725     if (ut_flg & EB_UT_FL_MTIME)
726       eb_l_ut_len = eb_c_ut_len = 1;
727     if (ut_flg & EB_UT_FL_ATIME)
728       eb_l_ut_len++;
729     if (ut_flg & EB_UT_FL_CTIME)
730       eb_l_ut_len++;
731 
732     eb_l_ut_len = EB_UT_LEN(eb_l_ut_len);
733     eb_c_ut_len = EB_UT_LEN(eb_c_ut_len);
734   }
735 
736   if (EF_L_UT_UX2_SIZE > EB_HEADSIZE) {
737     if(z->ext)
738       eb_l_ptr = realloc(z->extra, (z->ext + EF_L_UT_UX2_SIZE));
739     else
740       eb_l_ptr = malloc(EF_L_UT_UX2_SIZE);
741 
742     if (eb_l_ptr == NULL)
743       return ZE_MEM;
744 
745     if(z->cext)
746       eb_c_ptr = realloc(z->cextra, (z->cext + EF_C_UT_UX2_SIZE));
747     else
748       eb_c_ptr = malloc(EF_C_UT_UX2_SIZE);
749 
750     if (eb_c_ptr == NULL)
751       return ZE_MEM;
752 
753     z->extra = eb_l_ptr;
754     eb_l_ptr += z->ext;
755     z->ext += EF_L_UT_UX2_SIZE;
756 
757     if (ut_flg != 0) {
758       eb_l_ptr[0]  = 'U';
759       eb_l_ptr[1]  = 'T';
760       eb_l_ptr[2]  = eb_l_ut_len;       /* length of data part of e.f. */
761       eb_l_ptr[3]  = 0;
762       eb_l_ptr[4]  = ut_flg;
763       eb_pt = eb_l_ptr + 5;
764       if (ut_flg & EB_UT_FL_MTIME) {
765         *eb_pt++ = (char)(z_utim->mtime);
766         *eb_pt++ = (char)(z_utim->mtime >> 8);
767         *eb_pt++ = (char)(z_utim->mtime >> 16);
768         *eb_pt++ = (char)(z_utim->mtime >> 24);
769       }
770       if (ut_flg & EB_UT_FL_ATIME) {
771         *eb_pt++ = (char)(z_utim->atime);
772         *eb_pt++ = (char)(z_utim->atime >> 8);
773         *eb_pt++ = (char)(z_utim->atime >> 16);
774         *eb_pt++ = (char)(z_utim->atime >> 24);
775       }
776       if (ut_flg & EB_UT_FL_CTIME) {
777         *eb_pt++ = (char)(z_utim->ctime);
778         *eb_pt++ = (char)(z_utim->ctime >> 8);
779         *eb_pt++ = (char)(z_utim->ctime >> 16);
780         *eb_pt++ = (char)(z_utim->ctime >> 24);
781       }
782     }
783 #ifdef UNIX
784     else {
785       eb_pt = eb_l_ptr;
786     }
787     *eb_pt++ = 'U';
788     *eb_pt++ = 'x';
789     *eb_pt++ = EB_UX2_MINLEN;            /* length of data part of local e.f. */
790     *eb_pt++  = 0;
791     *eb_pt++ = (char)(s.st_uid);
792     *eb_pt++ = (char)(s.st_uid >> 8);
793     *eb_pt++ = (char)(s.st_gid);
794     *eb_pt++ = (char)(s.st_gid >> 8);
795 #endif /* UNIX */
796 
797     z->cextra = eb_c_ptr;
798     eb_c_ptr += z->cext;
799     z->cext += EF_C_UT_UX2_SIZE;
800 
801     if (ut_flg != 0) {
802       memcpy(eb_c_ptr, eb_l_ptr, EB_C_UT_SIZE);
803       eb_c_ptr[EB_LEN] = eb_c_ut_len;
804     }
805 #ifdef UNIX
806     memcpy(eb_c_ptr+EB_C_UT_SIZE, eb_l_ptr+EB_L_UT_SIZE, EB_C_UX2_SIZE);
807     eb_c_ptr[EB_LEN+EB_C_UT_SIZE] = 0;
808 #endif /* UNIX */
809   }
810 
811   return ZE_OK;
812 }
813 
814 #endif /* USE_EF_UT_TIME */
815 
816 
set_extra_field(struct zlist * z,iztimes * z_utim)817 int set_extra_field (struct zlist *z, iztimes *z_utim )
818 {
819     int rv = 0;
820     int last_rv = 0;
821     char flag = 0;
822 
823     if ((qlflag & 3) != 1)
824     {
825         qdosextra       *lq, *cq;
826         if ((lq = (qdosextra *) calloc(sizeof(qdosextra), 1)) == NULL)
827             return ZE_MEM;
828         if ((cq = (qdosextra *) calloc(sizeof(qdosextra), 1)) == NULL)
829             return ZE_MEM;
830 
831         rv = qlstat(z->name, &(lq->header), &flag);
832 
833         if (rv == 0 || (rv == 1 && (qlflag & 2)))
834         {
835             lq->shortid = rev_short((short) SHORTID);
836             lq->len.lo  = (unsigned char)(EXTRALEN & 0xff);
837             lq->len.hi  = (unsigned char)(EXTRALEN >> 8);
838             strcpy(lq->longid, LONGID);
839 
840             memcpy(cq, lq, sizeof(qdosextra));
841 
842             z->ext      =   sizeof(qdosextra);
843             z->cext     =   sizeof(qdosextra);
844             z->extra    =   (void *) lq;
845             z->cextra   =   (void *) cq;
846             fprintf (stderr, " %c",
847                      lq->header.d_datalen ? '*' : '#');
848         }
849         else if (rv == -1)
850         {
851             fprintf(stderr,
852                     "%s: warning: cannot stat %s, no file header added\n",
853                     "zip", z->name);
854         }
855         if(flag)
856         {
857             fputs (" !", stderr);
858         }
859      }
860     last_rv = (rv == -1 ? ZE_OPEN : ZE_OK);
861 
862 #ifdef USE_EF_UT_TIME
863 # ifdef QDOS
864 #   define IZ_UT_FLAGS EB_UT_FL_MTIME
865 # endif
866 # ifdef UNIX
867 #   define IZ_UT_FLAGS (EB_UT_FL_MTIME | EB_UT_FL_ATIME)
868 # endif
869 # ifndef IZ_UT_FLAGS
870 #   define IZ_UT_FLAGS EB_UT_FL_MTIME
871 # endif
872 
873     rv = GetExtraTime(z, z_utim, IZ_UT_FLAGS);
874     if (rv != ZE_OK)
875         last_rv = rv;
876 #endif /* USE_EF_UT_TIME */
877 
878     return last_rv;
879 }
880