ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Windows/extfs_windows.cpp
Revision: 1.3
Committed: 2007-01-22T17:14:06Z (17 years, 9 months ago) by asvitkine
Branch: MAIN
Changes since 1.2: +7 -0 lines
Log Message:
Since Guest and Host OS may use different text encodings for filenames,
I am adding functionality to support this. For the moment, I've only
added the platform-specific conversion for MacOSX (ie: UTF8 -> MacRoman),
but others can be added later.

File Contents

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