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

# User Rev Content
1 cebix 1.1 /*
2     * extfs_amiga.cpp - MacOS file system for access native file system access, AmigaOS specific stuff
3     *
4 gbeauche 1.15 * Basilisk II (C) 1997-2008 Christian Bauer
5 cebix 1.1 *
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 jlachmann 1.14 #define __USE_SYSBASE
23 cebix 1.1 #include <proto/dos.h>
24 jlachmann 1.14 #include <inline/dos.h>
25 cebix 1.1
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 cebix 1.8 *
83     * The .finf files store a FInfo/DInfo, followed by a FXInfo/DXInfo
84     * (16+16 bytes)
85 cebix 1.1 */
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 cebix 1.8 if (helper_dir[strlen(helper_dir) - 1] == '/') // Remove trailing "/"
111     helper_dir[strlen(helper_dir) - 1] = 0;
112 cebix 1.1 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 cebix 1.2 if ((flag & O_ACCMODE) == O_RDWR || (flag & O_ACCMODE) == O_WRONLY)
121 cebix 1.1 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 cebix 1.9 {".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 cebix 1.10 {".bin", FOURCC('T','E','X','T'), FOURCC('S','I','T','x')},
162 cebix 1.9 {".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 cebix 1.1 {NULL, 0, 0} // End marker
214     };
215    
216 cebix 1.12 void get_finfo(const char *path, uint32 finfo, uint32 fxinfo, bool is_dir)
217 cebix 1.1 {
218 cebix 1.8 // 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 cebix 1.1
225 cebix 1.8 // Read Finder info file
226 cebix 1.1 int fd = open_finf(path, O_RDONLY);
227     if (fd >= 0) {
228 cebix 1.8 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 cebix 1.1 return;
234     }
235    
236     // No Finder info file, translate file name extension to MacOS type/creator
237 cebix 1.12 if (!is_dir) {
238 cebix 1.8 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 cebix 1.1 }
249     }
250     }
251    
252 cebix 1.12 void set_finfo(const char *path, uint32 finfo, uint32 fxinfo, bool is_dir)
253 cebix 1.1 {
254     // Open Finder info file
255     int fd = open_finf(path, O_RDWR);
256     if (fd < 0)
257     return;
258    
259 cebix 1.8 // Write file
260     write(fd, Mac2HostAddr(finfo), SIZEOF_FInfo);
261     if (fxinfo)
262     write(fd, Mac2HostAddr(fxinfo), SIZEOF_FXInfo);
263 cebix 1.1 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 cebix 1.5 * returns number of bytes read (or -1 on error)
300 cebix 1.1 */
301    
302 cebix 1.5 ssize_t extfs_read(int fd, void *buffer, size_t length)
303 cebix 1.1 {
304     return read(fd, buffer, length);
305     }
306    
307    
308     /*
309     * Write "length" bytes from "buffer" to file,
310 cebix 1.5 * returns number of bytes written (or -1 on error)
311 cebix 1.1 */
312    
313 cebix 1.5 ssize_t extfs_write(int fd, void *buffer, size_t length)
314 cebix 1.1 {
315     return write(fd, buffer, length);
316     }
317    
318    
319     /*
320 cebix 1.3 * 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 cebix 1.4 // Now remove file or directory (and helper directories in the directory)
334 cebix 1.3 if (remove(path) < 0) {
335 cebix 1.4 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 cebix 1.3 return rmdir(path) == 0;
345 cebix 1.4 } else
346 cebix 1.3 return false;
347     }
348     return true;
349 cebix 1.4 }
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 cebix 1.3 }
373    
374    
375     /*
376 cebix 1.1 * 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     }