ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/extfs_unix.cpp
Revision: 1.23
Committed: 2008-01-01T09:40:33Z (16 years, 5 months ago) by gbeauche
Branch: MAIN
CVS Tags: HEAD
Changes since 1.22: +1 -1 lines
Log Message:
Happy New Year!

File Contents

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