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