ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/extfs_unix.cpp
Revision: 1.12
Committed: 2000-04-10T18:53:02Z (24 years, 2 months ago) by cebix
Branch: MAIN
CVS Tags: snapshot-13072000
Changes since 1.11: +1 -1 lines
Log Message:
- updated copyright info: 1999->2000

File Contents

# User Rev Content
1 cebix 1.1 /*
2     * extfs_unix.cpp - MacOS file system for access native file system access, Unix specific stuff
3     *
4 cebix 1.12 * Basilisk II (C) 1997-2000 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 <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 cebix 1.3 * Add component to path name
61     */
62    
63 cebix 1.5 void add_path_component(char *path, const char *component)
64 cebix 1.3 {
65     int l = strlen(path);
66 cebix 1.5 if (l < MAX_PATH_LENGTH-1 && path[l-1] != '/') {
67 cebix 1.3 path[l] = '/';
68     path[l+1] = 0;
69     }
70 cebix 1.5 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    
83     // Layout of Finder info helper files (all fields big-endian)
84     struct finf_struct {
85     uint32 type;
86     uint32 creator;
87     uint16 flags;
88 cebix 1.11 uint8 pad0[22]; // total size: 32 bytes to match the size of FInfo+FXInfo
89 cebix 1.5 };
90    
91     static void make_helper_path(const char *src, char *dest, const char *add, bool only_dir = false)
92     {
93     dest[0] = 0;
94    
95     // Get pointer to last component of path
96     const char *last_part = strrchr(src, '/');
97     if (last_part)
98     last_part++;
99     else
100     last_part = src;
101    
102     // Copy everything before
103     strncpy(dest, src, last_part-src);
104     dest[last_part-src] = 0;
105    
106     // Add additional component
107     strncat(dest, add, MAX_PATH_LENGTH-1);
108    
109     // Add last component
110     if (!only_dir)
111     strncat(dest, last_part, MAX_PATH_LENGTH-1);
112     }
113    
114     static int create_helper_dir(const char *path, const char *add)
115     {
116     char helper_dir[MAX_PATH_LENGTH];
117     make_helper_path(path, helper_dir, add, true);
118 cebix 1.6 return mkdir(helper_dir, 0777);
119 cebix 1.5 }
120    
121     static int open_helper(const char *path, const char *add, int flag)
122     {
123     char helper_path[MAX_PATH_LENGTH];
124     make_helper_path(path, helper_path, add);
125    
126 cebix 1.7 if ((flag & O_ACCMODE) == O_RDWR || (flag & O_ACCMODE) == O_WRONLY)
127 cebix 1.5 flag |= O_CREAT;
128 cebix 1.6 int fd = open(helper_path, flag, 0666);
129 cebix 1.5 if (fd < 0) {
130     if (errno == ENOENT && (flag & O_CREAT)) {
131     // One path component was missing, probably the helper
132     // directory. Try to create it and re-open the file.
133     int ret = create_helper_dir(path, add);
134     if (ret < 0)
135     return ret;
136 cebix 1.6 fd = open(helper_path, flag, 0666);
137 cebix 1.5 }
138     }
139     return fd;
140     }
141    
142     static int open_finf(const char *path, int flag)
143     {
144     return open_helper(path, ".finf/", flag);
145     }
146    
147     static int open_rsrc(const char *path, int flag)
148     {
149     return open_helper(path, ".rsrc/", flag);
150 cebix 1.3 }
151    
152    
153     /*
154 cebix 1.1 * Get/set finder type/creator for file specified by full path
155     */
156    
157     struct ext2type {
158     const char *ext;
159     uint32 type;
160     uint32 creator;
161     };
162    
163     static const ext2type e2t_translation[] = {
164 cebix 1.2 {".Z", 'ZIVM', 'LZIV'},
165 cebix 1.1 {".gz", 'Gzip', 'Gzip'},
166     {".hqx", 'TEXT', 'SITx'},
167     {".pdf", 'PDF ', 'CARO'},
168     {".ps", 'TEXT', 'ttxt'},
169     {".sit", 'SIT!', 'SITx'},
170     {".tar", 'TARF', 'TAR '},
171     {".uu", 'TEXT', 'SITx'},
172     {".uue", 'TEXT', 'SITx'},
173     {".zip", 'ZIP ', 'ZIP '},
174     {".8svx", '8SVX', 'SNDM'},
175     {".aifc", 'AIFC', 'TVOD'},
176     {".aiff", 'AIFF', 'TVOD'},
177     {".au", 'ULAW', 'TVOD'},
178     {".mid", 'MIDI', 'TVOD'},
179     {".midi", 'MIDI', 'TVOD'},
180     {".mp2", 'MPG ', 'TVOD'},
181     {".mp3", 'MPG ', 'TVOD'},
182     {".wav", 'WAVE', 'TVOD'},
183     {".bmp", 'BMPf', 'ogle'},
184     {".gif", 'GIFf', 'ogle'},
185     {".lbm", 'ILBM', 'GKON'},
186     {".ilbm", 'ILBM', 'GKON'},
187     {".jpg", 'JPEG', 'ogle'},
188     {".jpeg", 'JPEG', 'ogle'},
189     {".pict", 'PICT', 'ogle'},
190     {".png", 'PNGf', 'ogle'},
191     {".sgi", '.SGI', 'ogle'},
192     {".tga", 'TPIC', 'ogle'},
193     {".tif", 'TIFF', 'ogle'},
194     {".tiff", 'TIFF', 'ogle'},
195     {".html", 'TEXT', 'MOSS'},
196     {".txt", 'TEXT', 'ttxt'},
197     {".rtf", 'TEXT', 'MSWD'},
198     {".c", 'TEXT', 'R*ch'},
199 cebix 1.2 {".C", 'TEXT', 'R*ch'},
200 cebix 1.1 {".cc", 'TEXT', 'R*ch'},
201     {".cpp", 'TEXT', 'R*ch'},
202     {".cxx", 'TEXT', 'R*ch'},
203     {".h", 'TEXT', 'R*ch'},
204     {".hh", 'TEXT', 'R*ch'},
205     {".hpp", 'TEXT', 'R*ch'},
206     {".hxx", 'TEXT', 'R*ch'},
207     {".s", 'TEXT', 'R*ch'},
208 cebix 1.2 {".S", 'TEXT', 'R*ch'},
209 cebix 1.1 {".i", 'TEXT', 'R*ch'},
210     {".mpg", 'MPEG', 'TVOD'},
211     {".mpeg", 'MPEG', 'TVOD'},
212     {".mov", 'MooV', 'TVOD'},
213     {".fli", 'FLI ', 'TVOD'},
214     {".avi", 'VfW ', 'TVOD'},
215     {NULL, 0, 0} // End marker
216     };
217    
218     void get_finder_type(const char *path, uint32 &type, uint32 &creator)
219     {
220     type = 0;
221     creator = 0;
222    
223 cebix 1.5 // Open Finder info file
224     int fd = open_finf(path, O_RDONLY);
225     if (fd >= 0) {
226    
227     // Read file
228     finf_struct finf;
229 cebix 1.11 if (read(fd, &finf, sizeof(finf_struct)) >= 8) {
230 cebix 1.5
231     // Type/creator are in Finder info file, return them
232     type = ntohl(finf.type);
233     creator = ntohl(finf.creator);
234     close(fd);
235     return;
236     }
237     close(fd);
238     }
239    
240     // No Finder info file, translate file name extension to MacOS type/creator
241 cebix 1.1 int path_len = strlen(path);
242     for (int i=0; e2t_translation[i].ext; i++) {
243     int ext_len = strlen(e2t_translation[i].ext);
244     if (path_len < ext_len)
245     continue;
246     if (!strcmp(path + path_len - ext_len, e2t_translation[i].ext)) {
247     type = e2t_translation[i].type;
248     creator = e2t_translation[i].creator;
249     break;
250     }
251     }
252     }
253    
254     void set_finder_type(const char *path, uint32 type, uint32 creator)
255     {
256 cebix 1.5 // Open Finder info file
257     int fd = open_finf(path, O_RDWR);
258     if (fd < 0)
259     return;
260    
261     // Read file
262 cebix 1.11 finf_struct finf;
263     finf.flags = DEFAULT_FINDER_FLAGS;
264     memset(&finf, 0, sizeof(finf_struct));
265 cebix 1.5 read(fd, &finf, sizeof(finf_struct));
266    
267     // Set Finder flags
268     finf.type = htonl(type);
269     finf.creator = htonl(creator);
270    
271     // Update file
272     lseek(fd, 0, SEEK_SET);
273     write(fd, &finf, sizeof(finf_struct));
274     close(fd);
275 cebix 1.1 }
276    
277    
278     /*
279 cebix 1.5 * Get/set finder flags for file/dir specified by full path
280 cebix 1.1 */
281    
282     void get_finder_flags(const char *path, uint16 &flags)
283     {
284     flags = DEFAULT_FINDER_FLAGS; // Default
285 cebix 1.5
286     // Open Finder info file
287     int fd = open_finf(path, O_RDONLY);
288     if (fd < 0)
289     return;
290    
291     // Read Finder flags
292     finf_struct finf;
293 cebix 1.11 if (read(fd, &finf, sizeof(finf_struct)) >= 10)
294 cebix 1.5 flags = ntohs(finf.flags);
295    
296     // Close file
297     close(fd);
298 cebix 1.1 }
299    
300     void set_finder_flags(const char *path, uint16 flags)
301     {
302 cebix 1.5 // Open Finder info file
303     int fd = open_finf(path, O_RDWR);
304     if (fd < 0)
305     return;
306    
307     // Read file
308 cebix 1.11 finf_struct finf;
309     memset(&finf, 0, sizeof(finf_struct));
310     finf.flags = DEFAULT_FINDER_FLAGS;
311 cebix 1.5 read(fd, &finf, sizeof(finf_struct));
312    
313     // Set Finder flags
314     finf.flags = htons(flags);
315    
316     // Update file
317     lseek(fd, 0, SEEK_SET);
318     write(fd, &finf, sizeof(finf_struct));
319     close(fd);
320 cebix 1.1 }
321    
322    
323     /*
324     * Resource fork emulation functions
325     */
326    
327     uint32 get_rfork_size(const char *path)
328     {
329 cebix 1.5 // Open resource file
330     int fd = open_rsrc(path, O_RDONLY);
331     if (fd < 0)
332     return 0;
333    
334     // Get size
335     off_t size = lseek(fd, 0, SEEK_END);
336    
337     // Close file and return size
338     close(fd);
339     return size < 0 ? 0 : size;
340 cebix 1.1 }
341    
342     int open_rfork(const char *path, int flag)
343     {
344 cebix 1.5 return open_rsrc(path, flag);
345 cebix 1.1 }
346    
347     void close_rfork(const char *path, int fd)
348     {
349 cebix 1.5 close(fd);
350 cebix 1.1 }
351    
352    
353     /*
354     * Read "length" bytes from file to "buffer",
355 cebix 1.10 * returns number of bytes read (or -1 on error)
356 cebix 1.1 */
357    
358 cebix 1.10 ssize_t extfs_read(int fd, void *buffer, size_t length)
359 cebix 1.1 {
360     return read(fd, buffer, length);
361     }
362    
363    
364     /*
365     * Write "length" bytes from "buffer" to file,
366 cebix 1.10 * returns number of bytes written (or -1 on error)
367 cebix 1.1 */
368    
369 cebix 1.10 ssize_t extfs_write(int fd, void *buffer, size_t length)
370 cebix 1.1 {
371     return write(fd, buffer, length);
372     }
373 cebix 1.8
374    
375     /*
376     * Remove file/directory (and associated helper files),
377     * returns false on error (and sets errno)
378     */
379    
380     bool extfs_remove(const char *path)
381     {
382     // Remove helpers first, don't complain if this fails
383     char helper_path[MAX_PATH_LENGTH];
384     make_helper_path(path, helper_path, ".finf/", false);
385     remove(helper_path);
386     make_helper_path(path, helper_path, ".rsrc/", false);
387     remove(helper_path);
388    
389 cebix 1.9 // Now remove file or directory (and helper directories in the directory)
390 cebix 1.8 if (remove(path) < 0) {
391 cebix 1.9 if (errno == EISDIR || errno == ENOTEMPTY) {
392     helper_path[0] = 0;
393     strncpy(helper_path, path, MAX_PATH_LENGTH-1);
394     add_path_component(helper_path, ".finf");
395     rmdir(helper_path);
396     helper_path[0] = 0;
397     strncpy(helper_path, path, MAX_PATH_LENGTH-1);
398     add_path_component(helper_path, ".rsrc");
399     rmdir(helper_path);
400 cebix 1.8 return rmdir(path) == 0;
401 cebix 1.9 } else
402 cebix 1.8 return false;
403     }
404     return true;
405 cebix 1.9 }
406    
407    
408     /*
409     * Rename/move file/directory (and associated helper files),
410     * returns false on error (and sets errno)
411     */
412    
413     bool extfs_rename(const char *old_path, const char *new_path)
414     {
415     // Rename helpers first, don't complain if this fails
416     char old_helper_path[MAX_PATH_LENGTH], new_helper_path[MAX_PATH_LENGTH];
417     make_helper_path(old_path, old_helper_path, ".finf/", false);
418     make_helper_path(new_path, new_helper_path, ".finf/", false);
419     create_helper_dir(new_path, ".finf/");
420     rename(old_helper_path, new_helper_path);
421     make_helper_path(old_path, old_helper_path, ".rsrc/", false);
422     make_helper_path(new_path, new_helper_path, ".rsrc/", false);
423     create_helper_dir(new_path, ".rsrc/");
424     rename(old_helper_path, new_helper_path);
425    
426     // Now rename file
427     return rename(old_path, new_path) == 0;
428 cebix 1.8 }