1 /*
2   Copyright (c) 1990-2003 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   macstat.c
12 
13  *  This file provides a unix like file-stat routine
14  *  for V7 Unix systems that don't have such procedures.
15  *
16  *
17   ---------------------------------------------------------------------------*/
18 
19 
20 /*****************************************************************************/
21 /*  Includes                                                                 */
22 /*****************************************************************************/
23 
24 #include <string.h>
25 #include <stdio.h>
26 #include <sound.h>
27 
28 #define UNZIP_INTERNAL
29 #include "unzip.h"
30 
31 #include "macstat.h"
32 #include "helpers.h"
33 #include "pathname.h"
34 #include "macstuff.h"
35 #include "mactime.h"
36 
37 
38 /*****************************************************************************/
39 /*  Global Vars                                                              */
40 /*****************************************************************************/
41 
42 extern int errno;
43 extern MACINFO newExtraField;  /* contains all extra-field data */
44 extern short MacZipMode;
45 
46 
47 /*****************************************************************************/
48 /*  Prototypes                                                               */
49 /*****************************************************************************/
50 
51 
52 
53 /*****************************************************************************/
54 /*  Functions                                                                */
55 /*****************************************************************************/
56 
57 
UZmacstat(const char * path,struct stat * buf)58 int UZmacstat(const char *path, struct stat *buf)
59 {
60     Boolean isDirectory;
61     long dirID;
62     char fullpath[NAME_MAX], UnmangledPath[NAME_MAX];
63     CInfoPBRec fpb;
64     HVolumeParam vpb;
65     FSSpec fileSpec;
66     OSErr err, err2;
67     short CurrentFork;
68 
69     AssertStr(path,path)
70     Assert_it(buf,"","")
71 
72     memset(buf, 0, sizeof(struct stat));        /* zero out all fields */
73 
74     RfDfFilen2Real(UnmangledPath, path, MacZipMode,
75                    (newExtraField.flags & EB_M3_FL_NOCHANGE), &CurrentFork);
76     GetCompletePath(fullpath, path, &fileSpec, &err);
77     err2 = PrintUserHFSerr((err != -43) && (err != 0) && (err != -120),
78                            err, path);
79     printerr("GetCompletePath:", err2, err2, __LINE__, __FILE__, path);
80 
81     if (err != noErr) {
82         errno = err;
83         return -1;
84     }
85 
86     /*
87      * Fill the fpb & vpb struct up with info about file or directory.
88      */
89 
90     FSpGetDirectoryID(&fileSpec, &dirID, &isDirectory);
91     vpb.ioVRefNum = fpb.hFileInfo.ioVRefNum = fileSpec.vRefNum;
92     vpb.ioNamePtr = fpb.hFileInfo.ioNamePtr = fileSpec.name;
93     if (isDirectory) {
94         fpb.hFileInfo.ioDirID = fileSpec.parID;
95     } else {
96         fpb.hFileInfo.ioDirID = dirID;
97     }
98 
99     fpb.hFileInfo.ioFDirIndex = 0;
100     err = PBGetCatInfo(&fpb, false);
101     if (err == noErr) {
102         vpb.ioVolIndex = 0;
103         err = PBHGetVInfoSync((HParmBlkPtr)&vpb);
104         if (err == noErr && buf != NULL) {
105             /*
106              * Files are always readable by everyone.
107              */
108             buf->st_mode |= S_IRUSR | S_IRGRP | S_IROTH;
109 
110             /*
111              * Use the Volume Info & File Info to fill out stat buf.
112              */
113             if (fpb.hFileInfo.ioFlAttrib & 0x10) {
114                 buf->st_mode |= S_IFDIR;
115                 buf->st_nlink = 2;
116             } else {
117                 buf->st_nlink = 1;
118                 if (fpb.hFileInfo.ioFlFndrInfo.fdFlags & 0x8000) {
119                     buf->st_mode |= S_IFLNK;
120                 } else {
121                     buf->st_mode |= S_IFREG;
122                 }
123             }
124             if ((fpb.hFileInfo.ioFlAttrib & 0x10) ||
125                 (fpb.hFileInfo.ioFlFndrInfo.fdType == 'APPL')) {
126                 /*
127                  * Directories and applications are executable by everyone.
128                  */
129 
130                 buf->st_mode |= S_IXUSR | S_IXGRP | S_IXOTH;
131             }
132             if ((fpb.hFileInfo.ioFlAttrib & 0x01) == 0) {
133                 /*
134                  * If not locked, then everyone has write acces.
135                  */
136 
137                 buf->st_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
138             }
139             buf->st_ino = fpb.hFileInfo.ioDirID;
140             buf->st_dev = fpb.hFileInfo.ioVRefNum;
141             buf->st_uid = -1;
142             buf->st_gid = -1;
143             buf->st_rdev = 0;
144 
145             if (CurrentFork == ResourceFork)
146                 buf->st_size = fpb.hFileInfo.ioFlRLgLen;
147             else
148                 buf->st_size = fpb.hFileInfo.ioFlLgLen;
149 
150             buf->st_blksize = vpb.ioVAlBlkSiz;
151             buf->st_blocks = (buf->st_size + buf->st_blksize - 1)
152                             / buf->st_blksize;
153 
154             /*
155              * The times returned by the Mac file system are in the
156              * local time zone.  We convert them to GMT so that the
157              * epoch starts from GMT.  This is also consistent with
158              * what is returned from "clock seconds".
159              */
160 
161             buf->st_mtime = MacFtime2UnixFtime(fpb.hFileInfo.ioFlMdDat);
162             buf->st_ctime = MacFtime2UnixFtime(fpb.hFileInfo.ioFlCrDat);
163             buf->st_atime = buf->st_ctime;         /* best guess */
164 
165 #ifdef DEBUG_TIME
166             {
167             struct tm *tp = localtime(&buf->st_mtime);
168             printf(
169               "\nUZmacstat: local buf->st_mtime is %ld = %d/%2d/%2d  %2d:%2d:%2d",
170               buf->st_mtime, tp->tm_year, tp->tm_mon+1, tp->tm_mday,
171               tp->tm_hour, tp->tm_min, tp->tm_sec);
172             tp = gmtime(&buf->st_mtime);
173             printf(
174               "\nUZmacstat: UTC   buf->st_mtime is %ld = %d/%2d/%2d  %2d:%2d:%2d\n",
175               buf->st_mtime, tp->tm_year, tp->tm_mon+1, tp->tm_mday,
176               tp->tm_hour, tp->tm_min, tp->tm_sec);
177             }
178 #endif /* DEBUG_TIME */
179         }
180     }
181 
182     if (err != noErr) {
183         errno = err;
184     }
185 
186     return (err == noErr ? 0 : -1);
187 }
188