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

File Contents

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