ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/MacOSX/extfs_macosx.mm
Revision: 1.2
Committed: 2002-03-18T11:05:43Z (22 years, 4 months ago) by nigel
Branch: MAIN
CVS Tags: nigel-build-12, nigel-build-13, nigel-build-10
Changes since 1.1: +3 -2 lines
Log Message:
Added to comment for add_rsrc()

File Contents

# Content
1 /*
2 * $Id: extfs_macosx.mm,v 1.2 2002/03/16 10:00:19 nigel Exp $
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. Note that the 'correct' way to do this is to
81 * append '/..namedfork/rsrc', but I use this short form to save chars.
82 */
83
84 void add_rsrc(const char *path, char *dest)
85 {
86 int l = strlen(path);
87
88 if ( l > MAX_PATH_LENGTH-5 ) // If there is no room to add "rsrc\0"
89 return;
90
91 *dest = '\0';
92 strncat(dest, path, l);
93
94 if (l < MAX_PATH_LENGTH-1 && path[l-1] != '/') {
95 dest[l] = '/';
96 dest[l+1] = 0;
97 }
98 strcat(dest, "rsrc");
99 }
100
101
102 /*
103 * Resource forks on Mac OS X are kept on a UFS volume as /path/file/rsrc
104 *
105 * On HFS volumes, there is of course the data and rsrc fork, but the Darwin
106 * filesystem layer presents the resource fork using the above psuedo path
107 */
108
109 static int open_rsrc(const char *path, int flag)
110 {
111 char path_rsrc[MAX_PATH_LENGTH];
112
113 add_rsrc(path, path_rsrc);
114 return open(path_rsrc, flag);
115 }
116
117 /*
118 * Finder info is a little bit harder. We need to use Carbon library calls to access them
119 */
120
121
122 /*
123 * Get/set finder info for file/directory specified by full path
124 */
125
126 struct ext2type {
127 const char *ext;
128 uint32 type;
129 uint32 creator;
130 };
131
132 static const ext2type e2t_translation[] = {
133 {".Z", FOURCC('Z','I','V','M'), FOURCC('L','Z','I','V')},
134 {".gz", FOURCC('G','z','i','p'), FOURCC('G','z','i','p')},
135 {".hqx", FOURCC('T','E','X','T'), FOURCC('S','I','T','x')},
136 {".bin", FOURCC('T','E','X','T'), FOURCC('S','I','T','x')},
137 {".pdf", FOURCC('P','D','F',' '), FOURCC('C','A','R','O')},
138 {".ps", FOURCC('T','E','X','T'), FOURCC('t','t','x','t')},
139 {".sit", FOURCC('S','I','T','!'), FOURCC('S','I','T','x')},
140 {".tar", FOURCC('T','A','R','F'), FOURCC('T','A','R',' ')},
141 {".uu", FOURCC('T','E','X','T'), FOURCC('S','I','T','x')},
142 {".uue", FOURCC('T','E','X','T'), FOURCC('S','I','T','x')},
143 {".zip", FOURCC('Z','I','P',' '), FOURCC('Z','I','P',' ')},
144 {".8svx", FOURCC('8','S','V','X'), FOURCC('S','N','D','M')},
145 {".aifc", FOURCC('A','I','F','C'), FOURCC('T','V','O','D')},
146 {".aiff", FOURCC('A','I','F','F'), FOURCC('T','V','O','D')},
147 {".au", FOURCC('U','L','A','W'), FOURCC('T','V','O','D')},
148 {".mid", FOURCC('M','I','D','I'), FOURCC('T','V','O','D')},
149 {".midi", FOURCC('M','I','D','I'), FOURCC('T','V','O','D')},
150 {".mp2", FOURCC('M','P','G',' '), FOURCC('T','V','O','D')},
151 {".mp3", FOURCC('M','P','G',' '), FOURCC('T','V','O','D')},
152 {".wav", FOURCC('W','A','V','E'), FOURCC('T','V','O','D')},
153 {".bmp", FOURCC('B','M','P','f'), FOURCC('o','g','l','e')},
154 {".gif", FOURCC('G','I','F','f'), FOURCC('o','g','l','e')},
155 {".lbm", FOURCC('I','L','B','M'), FOURCC('G','K','O','N')},
156 {".ilbm", FOURCC('I','L','B','M'), FOURCC('G','K','O','N')},
157 {".jpg", FOURCC('J','P','E','G'), FOURCC('o','g','l','e')},
158 {".jpeg", FOURCC('J','P','E','G'), FOURCC('o','g','l','e')},
159 {".pict", FOURCC('P','I','C','T'), FOURCC('o','g','l','e')},
160 {".png", FOURCC('P','N','G','f'), FOURCC('o','g','l','e')},
161 {".sgi", FOURCC('.','S','G','I'), FOURCC('o','g','l','e')},
162 {".tga", FOURCC('T','P','I','C'), FOURCC('o','g','l','e')},
163 {".tif", FOURCC('T','I','F','F'), FOURCC('o','g','l','e')},
164 {".tiff", FOURCC('T','I','F','F'), FOURCC('o','g','l','e')},
165 {".htm", FOURCC('T','E','X','T'), FOURCC('M','O','S','S')},
166 {".html", FOURCC('T','E','X','T'), FOURCC('M','O','S','S')},
167 {".txt", FOURCC('T','E','X','T'), FOURCC('t','t','x','t')},
168 {".rtf", FOURCC('T','E','X','T'), FOURCC('M','S','W','D')},
169 {".c", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
170 {".C", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
171 {".cc", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
172 {".cpp", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
173 {".cxx", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
174 {".h", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
175 {".hh", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
176 {".hpp", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
177 {".hxx", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
178 {".s", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
179 {".S", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
180 {".i", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
181 {".mpg", FOURCC('M','P','E','G'), FOURCC('T','V','O','D')},
182 {".mpeg", FOURCC('M','P','E','G'), FOURCC('T','V','O','D')},
183 {".mov", FOURCC('M','o','o','V'), FOURCC('T','V','O','D')},
184 {".fli", FOURCC('F','L','I',' '), FOURCC('T','V','O','D')},
185 {".avi", FOURCC('V','f','W',' '), FOURCC('T','V','O','D')},
186 {".qxd", FOURCC('X','D','O','C'), FOURCC('X','P','R','3')},
187 {".hfv", FOURCC('D','D','i','m'), FOURCC('d','d','s','k')},
188 {".dsk", FOURCC('D','D','i','m'), FOURCC('d','d','s','k')},
189 {".img", FOURCC('r','o','h','d'), FOURCC('d','d','s','k')},
190 {NULL, 0, 0} // End marker
191 };
192
193 // Mac OS X way of doing the above
194
195 #import <Foundation/NSString.h>
196
197 extern "C"
198 {
199 NSString *NSHFSTypeOfFile (const NSString *);
200 uint32 NSHFSTypeCodeFromFileType (const NSString *); // Actually returns an OSType
201 }
202
203 uint32 fileType (const char *cPath)
204 {
205 NSString *copy = [NSString stringWithCString: cPath],
206 *type = NSHFSTypeOfFile(copy);
207
208 if ( type == nil )
209 {
210 D(NSLog(@"No type for file %s", cPath));
211 return 0; // Should this be '????' or ' ' ?
212 }
213
214 D(NSLog(@"Got type %@ for %s", type, cPath));
215 return NSHFSTypeCodeFromFileType(type);
216 }
217
218
219 void get_finfo(const char *path, uint32 finfo, uint32 fxinfo, bool is_dir)
220 {
221 FSRef fsRef;
222 int32 status;
223
224 // Set default finder info
225 Mac_memset(finfo, 0, SIZEOF_FInfo);
226 if (fxinfo)
227 Mac_memset(fxinfo, 0, SIZEOF_FXInfo);
228 WriteMacInt16(finfo + fdFlags, DEFAULT_FINDER_FLAGS);
229 WriteMacInt32(finfo + fdLocation, (uint32)-1);
230
231 status = FSPathMakeRef((const uint8 *)path, &fsRef, NULL);
232 if ( status == noErr )
233 {
234 FSCatalogInfo cInfo;
235 uint32 AllFinderInfo = kFSCatInfoFinderInfo + kFSCatInfoFinderXInfo;
236
237 status = FSGetCatalogInfo(&fsRef, AllFinderInfo, &cInfo, NULL, NULL, NULL);
238 if ( status == noErr )
239 {
240 D(printf("get_finfo(%s,...) - Got info of '%16.16s'\n", path, cInfo.finderInfo));
241 Host2Mac_memcpy(finfo, cInfo.finderInfo, SIZEOF_FInfo);
242 if (fxinfo)
243 Host2Mac_memcpy(fxinfo, cInfo.extFinderInfo, SIZEOF_FXInfo);
244 return;
245 }
246 else
247 printf("get_finfo(%s,...) failed to get catalog info\n", path);
248 }
249 else
250 printf("get_finfo(%s,...) failed to get FSRef\n", path);
251
252
253 // No Finder info file, translate file name extension to MacOS type/creator
254 if (!is_dir) {
255 int path_len = strlen(path);
256 for (int i=0; e2t_translation[i].ext; i++) {
257 int ext_len = strlen(e2t_translation[i].ext);
258 if (path_len < ext_len)
259 continue;
260 if (!strcmp(path + path_len - ext_len, e2t_translation[i].ext)) {
261 WriteMacInt32(finfo + fdType, e2t_translation[i].type);
262 WriteMacInt32(finfo + fdCreator, e2t_translation[i].creator);
263 break;
264 }
265 }
266 }
267
268
269 // Use alternate code to get type
270 uint32 type = fileType(path);
271
272 if ( type )
273 WriteMacInt32(finfo + fdType, type);
274 }
275
276 void set_finfo(const char *path, uint32 finfo, uint32 fxinfo, bool is_dir)
277 {
278 FSRef fsRef;
279 OSErr status;
280
281 status = FSPathMakeRef((const uint8 *)path, &fsRef, NULL);
282 if ( status == noErr )
283 {
284 FSCatalogInfo cInfo;
285
286 status = FSGetCatalogInfo(&fsRef, kFSCatInfoFinderInfo, &cInfo, NULL, NULL, NULL);
287 if ( status == noErr )
288 {
289 Mac2Host_memcpy(cInfo.finderInfo, finfo, SIZEOF_FInfo);
290 Mac2Host_memcpy(cInfo.extFinderInfo, fxinfo, SIZEOF_FXInfo);
291 FSSetCatalogInfo(&fsRef, kFSCatInfoFinderInfo, &cInfo);
292 }
293 }
294 }
295
296
297 /*
298 * Resource fork emulation functions
299 */
300
301 uint32 get_rfork_size(const char *path)
302 {
303 // Open resource file
304 int fd = open_rsrc(path, O_RDONLY);
305 if (fd < 0)
306 return 0;
307
308 // Get size
309 off_t size = lseek(fd, 0, SEEK_END);
310
311 // Close file and return size
312 close(fd);
313 return size < 0 ? 0 : size;
314 }
315
316 int open_rfork(const char *path, int flag)
317 {
318 return open_rsrc(path, flag);
319 }
320
321 void close_rfork(const char *path, int fd)
322 {
323 close(fd);
324 }
325
326
327 /*
328 * Read "length" bytes from file to "buffer",
329 * returns number of bytes read (or -1 on error)
330 */
331
332 ssize_t extfs_read(int fd, void *buffer, size_t length)
333 {
334 return read(fd, buffer, length);
335 }
336
337
338 /*
339 * Write "length" bytes from "buffer" to file,
340 * returns number of bytes written (or -1 on error)
341 */
342
343 ssize_t extfs_write(int fd, void *buffer, size_t length)
344 {
345 return write(fd, buffer, length);
346 }
347
348
349 /*
350 * Remove file/directory (and associated helper files),
351 * returns false on error (and sets errno)
352 */
353
354 bool extfs_remove(const char *path)
355 {
356 // Remove helpers first, don't complain if this fails
357 char helper_path[MAX_PATH_LENGTH];
358 add_rsrc(path, helper_path);
359 remove(helper_path);
360
361 // Now remove file or directory (and helper directories in the directory)
362 if (remove(path) < 0) {
363 if (errno == EISDIR || errno == ENOTEMPTY) {
364 return rmdir(path) == 0;
365 } else
366 return false;
367 }
368 return true;
369 }
370
371
372 /*
373 * Rename/move file/directory (and associated helper files),
374 * returns false on error (and sets errno)
375 */
376
377 bool extfs_rename(const char *old_path, const char *new_path)
378 {
379 // Rename helpers first, don't complain if this fails
380 char old_helper_path[MAX_PATH_LENGTH], new_helper_path[MAX_PATH_LENGTH];
381 add_rsrc(old_path, old_helper_path);
382 add_rsrc(new_path, new_helper_path);
383 rename(old_helper_path, new_helper_path);
384
385 // Now rename file
386 return rename(old_path, new_path) == 0;
387 }