ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/extfs_unix.cpp
Revision: 1.10
Committed: 1999-12-22T16:16:16Z (24 years, 6 months ago) by cebix
Branch: MAIN
CVS Tags: snapshot-22121999
Changes since 1.9: +4 -6 lines
Log Message:
- extfs_read() and extfs_write() return -1 on error and don't clear errno
- parent CNIDs of FSItems are exchanged in fs_rename() and fs_cat_move()

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     * Basilisk II (C) 1997-1999 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 <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.6 uint16 pad0;
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     if (read(fd, &finf, sizeof(finf_struct)) == sizeof(finf_struct)) {
230    
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.6 finf_struct finf = {0, 0, DEFAULT_FINDER_FLAGS, 0};
263 cebix 1.5 read(fd, &finf, sizeof(finf_struct));
264    
265     // Set Finder flags
266     finf.type = htonl(type);
267     finf.creator = htonl(creator);
268    
269     // Update file
270     lseek(fd, 0, SEEK_SET);
271     write(fd, &finf, sizeof(finf_struct));
272     close(fd);
273 cebix 1.1 }
274    
275    
276     /*
277 cebix 1.5 * Get/set finder flags for file/dir specified by full path
278 cebix 1.1 */
279    
280     void get_finder_flags(const char *path, uint16 &flags)
281     {
282     flags = DEFAULT_FINDER_FLAGS; // Default
283 cebix 1.5
284     // Open Finder info file
285     int fd = open_finf(path, O_RDONLY);
286     if (fd < 0)
287     return;
288    
289     // Read Finder flags
290     finf_struct finf;
291     if (read(fd, &finf, sizeof(finf_struct)) == sizeof(finf_struct))
292     flags = ntohs(finf.flags);
293    
294     // Close file
295     close(fd);
296 cebix 1.1 }
297    
298     void set_finder_flags(const char *path, uint16 flags)
299     {
300 cebix 1.5 // Open Finder info file
301     int fd = open_finf(path, O_RDWR);
302     if (fd < 0)
303     return;
304    
305     // Read file
306 cebix 1.6 finf_struct finf = {0, 0, DEFAULT_FINDER_FLAGS, 0};
307 cebix 1.5 read(fd, &finf, sizeof(finf_struct));
308    
309     // Set Finder flags
310     finf.flags = htons(flags);
311    
312     // Update file
313     lseek(fd, 0, SEEK_SET);
314     write(fd, &finf, sizeof(finf_struct));
315     close(fd);
316 cebix 1.1 }
317    
318    
319     /*
320     * Resource fork emulation functions
321     */
322    
323     uint32 get_rfork_size(const char *path)
324     {
325 cebix 1.5 // Open resource file
326     int fd = open_rsrc(path, O_RDONLY);
327     if (fd < 0)
328     return 0;
329    
330     // Get size
331     off_t size = lseek(fd, 0, SEEK_END);
332    
333     // Close file and return size
334     close(fd);
335     return size < 0 ? 0 : size;
336 cebix 1.1 }
337    
338     int open_rfork(const char *path, int flag)
339     {
340 cebix 1.5 return open_rsrc(path, flag);
341 cebix 1.1 }
342    
343     void close_rfork(const char *path, int fd)
344     {
345 cebix 1.5 close(fd);
346 cebix 1.1 }
347    
348    
349     /*
350     * Read "length" bytes from file to "buffer",
351 cebix 1.10 * returns number of bytes read (or -1 on error)
352 cebix 1.1 */
353    
354 cebix 1.10 ssize_t extfs_read(int fd, void *buffer, size_t length)
355 cebix 1.1 {
356     return read(fd, buffer, length);
357     }
358    
359    
360     /*
361     * Write "length" bytes from "buffer" to file,
362 cebix 1.10 * returns number of bytes written (or -1 on error)
363 cebix 1.1 */
364    
365 cebix 1.10 ssize_t extfs_write(int fd, void *buffer, size_t length)
366 cebix 1.1 {
367     return write(fd, buffer, length);
368     }
369 cebix 1.8
370    
371     /*
372     * Remove file/directory (and associated helper files),
373     * returns false on error (and sets errno)
374     */
375    
376     bool extfs_remove(const char *path)
377     {
378     // Remove helpers first, don't complain if this fails
379     char helper_path[MAX_PATH_LENGTH];
380     make_helper_path(path, helper_path, ".finf/", false);
381     remove(helper_path);
382     make_helper_path(path, helper_path, ".rsrc/", false);
383     remove(helper_path);
384    
385 cebix 1.9 // Now remove file or directory (and helper directories in the directory)
386 cebix 1.8 if (remove(path) < 0) {
387 cebix 1.9 if (errno == EISDIR || errno == ENOTEMPTY) {
388     helper_path[0] = 0;
389     strncpy(helper_path, path, MAX_PATH_LENGTH-1);
390     add_path_component(helper_path, ".finf");
391     rmdir(helper_path);
392     helper_path[0] = 0;
393     strncpy(helper_path, path, MAX_PATH_LENGTH-1);
394     add_path_component(helper_path, ".rsrc");
395     rmdir(helper_path);
396 cebix 1.8 return rmdir(path) == 0;
397 cebix 1.9 } else
398 cebix 1.8 return false;
399     }
400     return true;
401 cebix 1.9 }
402    
403    
404     /*
405     * Rename/move file/directory (and associated helper files),
406     * returns false on error (and sets errno)
407     */
408    
409     bool extfs_rename(const char *old_path, const char *new_path)
410     {
411     // Rename helpers first, don't complain if this fails
412     char old_helper_path[MAX_PATH_LENGTH], new_helper_path[MAX_PATH_LENGTH];
413     make_helper_path(old_path, old_helper_path, ".finf/", false);
414     make_helper_path(new_path, new_helper_path, ".finf/", false);
415     create_helper_dir(new_path, ".finf/");
416     rename(old_helper_path, new_helper_path);
417     make_helper_path(old_path, old_helper_path, ".rsrc/", false);
418     make_helper_path(new_path, new_helper_path, ".rsrc/", false);
419     create_helper_dir(new_path, ".rsrc/");
420     rename(old_helper_path, new_helper_path);
421    
422     // Now rename file
423     return rename(old_path, new_path) == 0;
424 cebix 1.8 }