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, 1 month 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

# Content
1 /*
2 * extfs_unix.cpp - MacOS file system for access native file system access, Unix specific stuff
3 *
4 * Basilisk II (C) 1997-2000 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 * Add component to path name
61 */
62
63 void add_path_component(char *path, const char *component)
64 {
65 int l = strlen(path);
66 if (l < MAX_PATH_LENGTH-1 && path[l-1] != '/') {
67 path[l] = '/';
68 path[l+1] = 0;
69 }
70 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 uint8 pad0[22]; // total size: 32 bytes to match the size of FInfo+FXInfo
89 };
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 return mkdir(helper_dir, 0777);
119 }
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 if ((flag & O_ACCMODE) == O_RDWR || (flag & O_ACCMODE) == O_WRONLY)
127 flag |= O_CREAT;
128 int fd = open(helper_path, flag, 0666);
129 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 fd = open(helper_path, flag, 0666);
137 }
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 }
151
152
153 /*
154 * 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 {".Z", 'ZIVM', 'LZIV'},
165 {".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 {".C", 'TEXT', 'R*ch'},
200 {".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 {".S", 'TEXT', 'R*ch'},
209 {".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 // 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)) >= 8) {
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 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 // Open Finder info file
257 int fd = open_finf(path, O_RDWR);
258 if (fd < 0)
259 return;
260
261 // Read file
262 finf_struct finf;
263 finf.flags = DEFAULT_FINDER_FLAGS;
264 memset(&finf, 0, sizeof(finf_struct));
265 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 }
276
277
278 /*
279 * Get/set finder flags for file/dir specified by full path
280 */
281
282 void get_finder_flags(const char *path, uint16 &flags)
283 {
284 flags = DEFAULT_FINDER_FLAGS; // Default
285
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 if (read(fd, &finf, sizeof(finf_struct)) >= 10)
294 flags = ntohs(finf.flags);
295
296 // Close file
297 close(fd);
298 }
299
300 void set_finder_flags(const char *path, uint16 flags)
301 {
302 // Open Finder info file
303 int fd = open_finf(path, O_RDWR);
304 if (fd < 0)
305 return;
306
307 // Read file
308 finf_struct finf;
309 memset(&finf, 0, sizeof(finf_struct));
310 finf.flags = DEFAULT_FINDER_FLAGS;
311 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 }
321
322
323 /*
324 * Resource fork emulation functions
325 */
326
327 uint32 get_rfork_size(const char *path)
328 {
329 // 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 }
341
342 int open_rfork(const char *path, int flag)
343 {
344 return open_rsrc(path, flag);
345 }
346
347 void close_rfork(const char *path, int fd)
348 {
349 close(fd);
350 }
351
352
353 /*
354 * Read "length" bytes from file to "buffer",
355 * returns number of bytes read (or -1 on error)
356 */
357
358 ssize_t extfs_read(int fd, void *buffer, size_t length)
359 {
360 return read(fd, buffer, length);
361 }
362
363
364 /*
365 * Write "length" bytes from "buffer" to file,
366 * returns number of bytes written (or -1 on error)
367 */
368
369 ssize_t extfs_write(int fd, void *buffer, size_t length)
370 {
371 return write(fd, buffer, length);
372 }
373
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 // Now remove file or directory (and helper directories in the directory)
390 if (remove(path) < 0) {
391 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 return rmdir(path) == 0;
401 } else
402 return false;
403 }
404 return true;
405 }
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 }