ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Windows/extfs_windows.cpp
Revision: 1.1
Committed: 2004-12-03T22:03:12Z (19 years, 11 months ago) by gbeauche
Branch: MAIN
Log Message:
Merge and upgrade native filesystem support from B2/Win. The nice
"My Computer" icon is now back. Adapt from recent extfs_unix.cpp.

File Contents

# Content
1 /*
2 * extfs_windows.cpp - MacOS file system for access native file system access, Windows specific stuff
3 *
4 * Basilisk II (C) 1997-2004 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 <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 }