ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/MacOSX/extfs_macosx.mm
Revision: 1.1
Committed: 2002-03-16T04:00:20Z (22 years, 8 months ago) by nigel
Branch: MAIN
Log Message:
Initial revision of Mac OS X port code. Uses Objective-C++. Needs Mac OS 10.1

File Contents

# User Rev Content
1 nigel 1.1 /*
2     * $Id$
3     *
4     * extfs_macosx.mm - Access Mac OS X Finder and resource information (using Carbon calls).
5     * Based on:
6     *
7     * extfs_unix.cpp - MacOS file system for access native file system access, Unix specific stuff
8     *
9     * Basilisk II (C) 1997-2002 Christian Bauer
10     *
11     * This program is free software; you can redistribute it and/or modify
12     * it under the terms of the GNU General Public License as published by
13     * the Free Software Foundation; either version 2 of the License, or
14     * (at your option) any later version.
15     *
16     * This program is distributed in the hope that it will be useful,
17     * but WITHOUT ANY WARRANTY; without even the implied warranty of
18     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19     * GNU General Public License for more details.
20     *
21     * You should have received a copy of the GNU General Public License
22     * along with this program; if not, write to the Free Software
23     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24     */
25    
26     #include <sys/types.h>
27     #include <sys/stat.h>
28     #include <stdio.h>
29     #include <stdlib.h>
30     #include <unistd.h>
31     #include <dirent.h>
32     #include <errno.h>
33    
34     #include "sysdeps.h"
35     #include "extfs_macosx.h"
36     #include "extfs.h"
37    
38     #define DEBUG 0
39     #include "debug.h"
40    
41    
42     // Default Finder flags
43     const uint16 DEFAULT_FINDER_FLAGS = kHasBeenInited;
44    
45    
46     /*
47     * Initialization
48     */
49    
50     void extfs_init(void)
51     {
52     }
53    
54    
55     /*
56     * Deinitialization
57     */
58    
59     void extfs_exit(void)
60     {
61     }
62    
63    
64     /*
65     * Add component to path name
66     */
67    
68     void add_path_component(char *path, const char *component)
69     {
70     int l = strlen(path);
71     if (l < MAX_PATH_LENGTH-1 && path[l-1] != '/') {
72     path[l] = '/';
73     path[l+1] = 0;
74     }
75     strncat(path, component, MAX_PATH_LENGTH-1);
76     }
77    
78    
79     /*
80     * Add rsrc to path name
81     */
82    
83     void add_rsrc(const char *path, char *dest)
84     {
85     int l = strlen(path);
86    
87     if ( l > MAX_PATH_LENGTH-5 ) // If there is no room to add "rsrc\0"
88     return;
89    
90     *dest = '\0';
91     strncat(dest, path, l);
92    
93     if (l < MAX_PATH_LENGTH-1 && path[l-1] != '/') {
94     dest[l] = '/';
95     dest[l+1] = 0;
96     }
97     strcat(dest, "rsrc");
98     }
99    
100    
101     /*
102     * Resource forks on Mac OS X are kept on a UFS volume as /path/file/rsrc
103     *
104     * On HFS volumes, there is of course the data and rsrc fork, but the Darwin
105     * filesystem layer presents the resource fork using the above psuedo path
106     */
107    
108     static int open_rsrc(const char *path, int flag)
109     {
110     char path_rsrc[MAX_PATH_LENGTH];
111    
112     add_rsrc(path, path_rsrc);
113     return open(path_rsrc, flag);
114     }
115    
116     /*
117     * Finder info is a little bit harder. We need to use Carbon library calls to access them
118     */
119    
120    
121     /*
122     * Get/set finder info for file/directory specified by full path
123     */
124    
125     struct ext2type {
126     const char *ext;
127     uint32 type;
128     uint32 creator;
129     };
130    
131     static const ext2type e2t_translation[] = {
132     {".Z", FOURCC('Z','I','V','M'), FOURCC('L','Z','I','V')},
133     {".gz", FOURCC('G','z','i','p'), FOURCC('G','z','i','p')},
134     {".hqx", FOURCC('T','E','X','T'), FOURCC('S','I','T','x')},
135     {".bin", FOURCC('T','E','X','T'), FOURCC('S','I','T','x')},
136     {".pdf", FOURCC('P','D','F',' '), FOURCC('C','A','R','O')},
137     {".ps", FOURCC('T','E','X','T'), FOURCC('t','t','x','t')},
138     {".sit", FOURCC('S','I','T','!'), FOURCC('S','I','T','x')},
139     {".tar", FOURCC('T','A','R','F'), FOURCC('T','A','R',' ')},
140     {".uu", FOURCC('T','E','X','T'), FOURCC('S','I','T','x')},
141     {".uue", FOURCC('T','E','X','T'), FOURCC('S','I','T','x')},
142     {".zip", FOURCC('Z','I','P',' '), FOURCC('Z','I','P',' ')},
143     {".8svx", FOURCC('8','S','V','X'), FOURCC('S','N','D','M')},
144     {".aifc", FOURCC('A','I','F','C'), FOURCC('T','V','O','D')},
145     {".aiff", FOURCC('A','I','F','F'), FOURCC('T','V','O','D')},
146     {".au", FOURCC('U','L','A','W'), FOURCC('T','V','O','D')},
147     {".mid", FOURCC('M','I','D','I'), FOURCC('T','V','O','D')},
148     {".midi", FOURCC('M','I','D','I'), FOURCC('T','V','O','D')},
149     {".mp2", FOURCC('M','P','G',' '), FOURCC('T','V','O','D')},
150     {".mp3", FOURCC('M','P','G',' '), FOURCC('T','V','O','D')},
151     {".wav", FOURCC('W','A','V','E'), FOURCC('T','V','O','D')},
152     {".bmp", FOURCC('B','M','P','f'), FOURCC('o','g','l','e')},
153     {".gif", FOURCC('G','I','F','f'), FOURCC('o','g','l','e')},
154     {".lbm", FOURCC('I','L','B','M'), FOURCC('G','K','O','N')},
155     {".ilbm", FOURCC('I','L','B','M'), FOURCC('G','K','O','N')},
156     {".jpg", FOURCC('J','P','E','G'), FOURCC('o','g','l','e')},
157     {".jpeg", FOURCC('J','P','E','G'), FOURCC('o','g','l','e')},
158     {".pict", FOURCC('P','I','C','T'), FOURCC('o','g','l','e')},
159     {".png", FOURCC('P','N','G','f'), FOURCC('o','g','l','e')},
160     {".sgi", FOURCC('.','S','G','I'), FOURCC('o','g','l','e')},
161     {".tga", FOURCC('T','P','I','C'), FOURCC('o','g','l','e')},
162     {".tif", FOURCC('T','I','F','F'), FOURCC('o','g','l','e')},
163     {".tiff", FOURCC('T','I','F','F'), FOURCC('o','g','l','e')},
164     {".htm", FOURCC('T','E','X','T'), FOURCC('M','O','S','S')},
165     {".html", FOURCC('T','E','X','T'), FOURCC('M','O','S','S')},
166     {".txt", FOURCC('T','E','X','T'), FOURCC('t','t','x','t')},
167     {".rtf", FOURCC('T','E','X','T'), FOURCC('M','S','W','D')},
168     {".c", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
169     {".C", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
170     {".cc", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
171     {".cpp", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
172     {".cxx", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
173     {".h", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
174     {".hh", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
175     {".hpp", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
176     {".hxx", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
177     {".s", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
178     {".S", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
179     {".i", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
180     {".mpg", FOURCC('M','P','E','G'), FOURCC('T','V','O','D')},
181     {".mpeg", FOURCC('M','P','E','G'), FOURCC('T','V','O','D')},
182     {".mov", FOURCC('M','o','o','V'), FOURCC('T','V','O','D')},
183     {".fli", FOURCC('F','L','I',' '), FOURCC('T','V','O','D')},
184     {".avi", FOURCC('V','f','W',' '), FOURCC('T','V','O','D')},
185     {".qxd", FOURCC('X','D','O','C'), FOURCC('X','P','R','3')},
186     {".hfv", FOURCC('D','D','i','m'), FOURCC('d','d','s','k')},
187     {".dsk", FOURCC('D','D','i','m'), FOURCC('d','d','s','k')},
188     {".img", FOURCC('r','o','h','d'), FOURCC('d','d','s','k')},
189     {NULL, 0, 0} // End marker
190     };
191    
192     // Mac OS X way of doing the above
193    
194     #import <Foundation/NSString.h>
195    
196     extern "C"
197     {
198     NSString *NSHFSTypeOfFile (const NSString *);
199     uint32 NSHFSTypeCodeFromFileType (const NSString *); // Actually returns an OSType
200     }
201    
202     uint32 fileType (const char *cPath)
203     {
204     NSString *copy = [NSString stringWithCString: cPath],
205     *type = NSHFSTypeOfFile(copy);
206    
207     if ( type == nil )
208     {
209     D(NSLog(@"No type for file %s", cPath));
210     return 0; // Should this be '????' or ' ' ?
211     }
212    
213     D(NSLog(@"Got type %@ for %s", type, cPath));
214     return NSHFSTypeCodeFromFileType(type);
215     }
216    
217    
218     void get_finfo(const char *path, uint32 finfo, uint32 fxinfo, bool is_dir)
219     {
220     FSRef fsRef;
221     int32 status;
222    
223     // Set default finder info
224     Mac_memset(finfo, 0, SIZEOF_FInfo);
225     if (fxinfo)
226     Mac_memset(fxinfo, 0, SIZEOF_FXInfo);
227     WriteMacInt16(finfo + fdFlags, DEFAULT_FINDER_FLAGS);
228     WriteMacInt32(finfo + fdLocation, (uint32)-1);
229    
230     status = FSPathMakeRef((const uint8 *)path, &fsRef, NULL);
231     if ( status == noErr )
232     {
233     FSCatalogInfo cInfo;
234     uint32 AllFinderInfo = kFSCatInfoFinderInfo + kFSCatInfoFinderXInfo;
235    
236     status = FSGetCatalogInfo(&fsRef, AllFinderInfo, &cInfo, NULL, NULL, NULL);
237     if ( status == noErr )
238     {
239     D(printf("get_finfo(%s,...) - Got info of '%16.16s'\n", path, cInfo.finderInfo));
240     Host2Mac_memcpy(finfo, cInfo.finderInfo, SIZEOF_FInfo);
241     if (fxinfo)
242     Host2Mac_memcpy(fxinfo, cInfo.extFinderInfo, SIZEOF_FXInfo);
243     return;
244     }
245     else
246     printf("get_finfo(%s,...) failed to get catalog info\n", path);
247     }
248     else
249     printf("get_finfo(%s,...) failed to get FSRef\n", path);
250    
251    
252     // No Finder info file, translate file name extension to MacOS type/creator
253     if (!is_dir) {
254     int path_len = strlen(path);
255     for (int i=0; e2t_translation[i].ext; i++) {
256     int ext_len = strlen(e2t_translation[i].ext);
257     if (path_len < ext_len)
258     continue;
259     if (!strcmp(path + path_len - ext_len, e2t_translation[i].ext)) {
260     WriteMacInt32(finfo + fdType, e2t_translation[i].type);
261     WriteMacInt32(finfo + fdCreator, e2t_translation[i].creator);
262     break;
263     }
264     }
265     }
266    
267    
268     // Use alternate code to get type
269     uint32 type = fileType(path);
270    
271     if ( type )
272     WriteMacInt32(finfo + fdType, type);
273     }
274    
275     void set_finfo(const char *path, uint32 finfo, uint32 fxinfo, bool is_dir)
276     {
277     FSRef fsRef;
278     OSErr status;
279    
280     status = FSPathMakeRef((const uint8 *)path, &fsRef, NULL);
281     if ( status == noErr )
282     {
283     FSCatalogInfo cInfo;
284    
285     status = FSGetCatalogInfo(&fsRef, kFSCatInfoFinderInfo, &cInfo, NULL, NULL, NULL);
286     if ( status == noErr )
287     {
288     Mac2Host_memcpy(cInfo.finderInfo, finfo, SIZEOF_FInfo);
289     Mac2Host_memcpy(cInfo.extFinderInfo, fxinfo, SIZEOF_FXInfo);
290     FSSetCatalogInfo(&fsRef, kFSCatInfoFinderInfo, &cInfo);
291     }
292     }
293     }
294    
295    
296     /*
297     * Resource fork emulation functions
298     */
299    
300     uint32 get_rfork_size(const char *path)
301     {
302     // Open resource file
303     int fd = open_rsrc(path, O_RDONLY);
304     if (fd < 0)
305     return 0;
306    
307     // Get size
308     off_t size = lseek(fd, 0, SEEK_END);
309    
310     // Close file and return size
311     close(fd);
312     return size < 0 ? 0 : size;
313     }
314    
315     int open_rfork(const char *path, int flag)
316     {
317     return open_rsrc(path, flag);
318     }
319    
320     void close_rfork(const char *path, int fd)
321     {
322     close(fd);
323     }
324    
325    
326     /*
327     * Read "length" bytes from file to "buffer",
328     * returns number of bytes read (or -1 on error)
329     */
330    
331     ssize_t extfs_read(int fd, void *buffer, size_t length)
332     {
333     return read(fd, buffer, length);
334     }
335    
336    
337     /*
338     * Write "length" bytes from "buffer" to file,
339     * returns number of bytes written (or -1 on error)
340     */
341    
342     ssize_t extfs_write(int fd, void *buffer, size_t length)
343     {
344     return write(fd, buffer, length);
345     }
346    
347    
348     /*
349     * Remove file/directory (and associated helper files),
350     * returns false on error (and sets errno)
351     */
352    
353     bool extfs_remove(const char *path)
354     {
355     // Remove helpers first, don't complain if this fails
356     char helper_path[MAX_PATH_LENGTH];
357     add_rsrc(path, helper_path);
358     remove(helper_path);
359    
360     // Now remove file or directory (and helper directories in the directory)
361     if (remove(path) < 0) {
362     if (errno == EISDIR || errno == ENOTEMPTY) {
363     return rmdir(path) == 0;
364     } else
365     return false;
366     }
367     return true;
368     }
369    
370    
371     /*
372     * Rename/move file/directory (and associated helper files),
373     * returns false on error (and sets errno)
374     */
375    
376     bool extfs_rename(const char *old_path, const char *new_path)
377     {
378     // Rename helpers first, don't complain if this fails
379     char old_helper_path[MAX_PATH_LENGTH], new_helper_path[MAX_PATH_LENGTH];
380     add_rsrc(old_path, old_helper_path);
381     add_rsrc(new_path, new_helper_path);
382     rename(old_helper_path, new_helper_path);
383    
384     // Now rename file
385     return rename(old_path, new_path) == 0;
386     }