ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/BeOS/extfs_beos.cpp
Revision: 1.12
Committed: 2001-02-02T20:52:57Z (23 years, 9 months ago) by cebix
Branch: MAIN
Changes since 1.11: +1 -1 lines
Log Message:
- bumped version number to 0.9
- updated copyright dates

File Contents

# Content
1 /*
2 * extfs_beos.cpp - MacOS file system for access native file system access, BeOS specific stuff
3 *
4 * Basilisk II (C) 1997-2001 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 "sysdeps.h"
22
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <string.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <unistd.h>
29 #include <fcntl.h>
30 #include <dirent.h>
31 #include <errno.h>
32
33 #include <fs_attr.h>
34 #include <support/TypeConstants.h>
35 #include <storage/Mime.h>
36
37 #include "extfs.h"
38 #include "extfs_defs.h"
39
40 #define DEBUG 0
41 #include "debug.h"
42
43
44 // Default Finder flags
45 const uint16 DEFAULT_FINDER_FLAGS = kHasBeenInited;
46
47 // Temporary buffer for transfers from/to kernel space
48 const int TMP_BUF_SIZE = 0x10000;
49 static uint8 *tmp_buf = NULL;
50
51
52 /*
53 * Initialization
54 */
55
56 void extfs_init(void)
57 {
58 // Allocate temporary buffer
59 tmp_buf = new uint8[TMP_BUF_SIZE];
60 }
61
62
63 /*
64 * Deinitialization
65 */
66
67 void extfs_exit(void)
68 {
69 // Delete temporary buffer
70 delete[] tmp_buf;
71 }
72
73
74 /*
75 * Add component to path name
76 */
77
78 void add_path_component(char *path, const char *component)
79 {
80 int l = strlen(path);
81 if (l < MAX_PATH_LENGTH-1 && path[l-1] != '/') {
82 path[l] = '/';
83 path[l+1] = 0;
84 }
85 strncat(path, component, MAX_PATH_LENGTH-1);
86 }
87
88
89 /*
90 * Get/set finder info for file/directory specified by full path
91 */
92
93 struct mime2type {
94 const char *mime;
95 uint32 type;
96 uint32 creator;
97 bool reversible; // type -> mime translation possible
98 };
99
100 static const mime2type m2t_translation[] = {
101 {"application/x-compress", 'ZIVM', 'LZIV', true},
102 {"application/x-gzip", 'Gzip', 'Gzip', true},
103 {"application/x-macbinary", 'BINA', '????', false},
104 {"application/mac-binhex40", 'TEXT', 'SITx', false},
105 {"application/pdf", 'PDF ', 'CARO', true},
106 {"application/postscript", 'TEXT', 'ttxt', false},
107 {"application/x-stuffit", 'SIT!', 'SITx', true},
108 {"application/x-tar", 'TARF', 'TAR ', true},
109 {"application/x-uuencode", 'TEXT', 'SITx', false},
110 {"application/zip", 'ZIP ', 'ZIP ', true},
111 {"audio/x-8svx", '8SVX', 'SNDM', true},
112 {"audio/x-aifc", 'AIFC', 'TVOD', true},
113 {"audio/x-aiff", 'AIFF', 'TVOD', true},
114 {"audio/basic", 'ULAW', 'TVOD', true},
115 {"audio/x-midi", 'MIDI', 'TVOD', true},
116 {"audio/x-mpeg", 'MPG ', 'TVOD', true},
117 {"audio/x-wav", 'WAVE', 'TVOD', true},
118 {"image/x-bmp", 'BMPf', 'ogle', true},
119 {"image/gif", 'GIFf', 'ogle', true},
120 {"image/x-ilbm", 'ILBM', 'GKON', true},
121 {"image/jpeg", 'JPEG', 'ogle', true},
122 {"image/jpeg", 'JFIF', 'ogle', true},
123 {"image/x-photoshop", '8BPS', '8BIM', true},
124 {"image/pict", 'PICT', 'ogle', true},
125 {"image/png", 'PNGf', 'ogle', true},
126 {"image/x-sgi", '.SGI', 'ogle', true},
127 {"image/x-targa", 'TPIC', 'ogle', true},
128 {"image/tiff", 'TIFF', 'ogle', true},
129 {"text/html", 'TEXT', 'MOSS', false},
130 {"text/plain", 'TEXT', 'ttxt', true},
131 {"text/rtf", 'TEXT', 'MSWD', false},
132 {"text/x-source-code", 'TEXT', 'R*ch', false},
133 {"video/mpeg", 'MPEG', 'TVOD', true},
134 {"video/quicktime", 'MooV', 'TVOD', true},
135 {"video/x-flc", 'FLI ', 'TVOD', true},
136 {"video/x-msvideo", 'VfW ', 'TVOD', true},
137 {NULL, 0, 0, false} // End marker
138 };
139
140 void get_finfo(const char *path, uint32 finfo, uint32 fxinfo)
141 {
142 // Set default finder info
143 Mac_memset(finfo, 0, SIZEOF_FInfo);
144 if (fxinfo)
145 Mac_memset(fxinfo, 0, SIZEOF_FXInfo);
146 WriteMacInt16(finfo + fdFlags, DEFAULT_FINDER_FLAGS);
147 WriteMacInt32(finfo + fdLocation, (uint32)-1);
148
149 // Open file
150 int fd = open(path, O_RDONLY);
151 if (fd < 0)
152 return;
153
154 // Read BeOS MIME type
155 char mime[256];
156 ssize_t actual = fs_read_attr(fd, "BEOS:TYPE", B_MIME_STRING_TYPE, 0, mime, 256);
157 mime[255] = 0;
158
159 if (actual > 0) {
160
161 // Translate MIME type to MacOS type/creator
162 char mactype[4];
163 if (sscanf(mime, "application/x-MacOS-%c%c%c%c", mactype, mactype+1, mactype+2, mactype+3) == 4) {
164
165 // MacOS style type
166 WriteMacInt32(finfo + fdType, mactype);
167
168 } else {
169
170 // MIME string, look in table
171 for (int i=0; m2t_translation[i].mime; i++) {
172 if (!strcmp(mime, m2t_translation[i].mime)) {
173 WriteMacInt32(finfo + fdType, m2t_translation[i].type);
174 WriteMacInt32(finfo + fdCreator, m2t_translation[i].creator);
175 break;
176 }
177 }
178 }
179 }
180
181 // Override file type with MACOS:CREATOR attribute
182 if (fs_read_attr(fd, "MACOS:CREATOR", B_UINT32_TYPE, 0, &mime, 4) == 4)
183 WriteMacInt32(finfo + fdCreator, (mime[0] << 24) | (mime[1] << 16) | (mime[2] << 8) | mime[3]);
184
185 // Read MACOS:HFS_FLAGS attribute
186 if (fs_read_attr(fd, "MACOS:HFS_FLAGS", B_UINT16_TYPE, 0, &mime, 2) == 2)
187 WriteMacInt16(finfo + fdFlags, (mime[0] << 8) | mime[1]);
188
189 // Close file
190 close(fd);
191 }
192
193 void set_finfo(const char *path, uint32 finfo, uint32 fxinfo)
194 {
195 char mime[256];
196
197 // Open file
198 int fd = open(path, O_WRONLY);
199 if (fd < 0)
200 return;
201
202 // Set BEOS:TYPE attribute
203 uint32 type = ReadMacInt32(finfo + fdType);
204 if (type) {
205 bool written = false;
206 for (int i=0; m2t_translation[i].mime; i++) {
207 if (m2t_translation[i].type == type && m2t_translation[i].reversible) {
208 fs_write_attr(fd, "BEOS:TYPE", B_MIME_STRING_TYPE, 0, m2t_translation[i].mime, strlen(m2t_translation[i].mime) + 1);
209 written = true;
210 break;
211 }
212 }
213 if (!written) {
214 sprintf(mime, "application/x-MacOS-%c%c%c%c", type >> 24, type >> 16, type >> 8, type);
215 fs_write_attr(fd, "BEOS:TYPE", B_MIME_STRING_TYPE, 0, mime, strlen(mime) + 1);
216 }
217 }
218
219 // Set MACOS:CREATOR attribute
220 uint32 creator = ReadMacInt32(finfo + fdType);
221 if (creator) {
222 mime[0] = creator >> 24;
223 mime[1] = creator >> 16;
224 mime[2] = creator >> 8;
225 mime[3] = creator;
226 fs_write_attr(fd, "MACOS:CREATOR", B_UINT32_TYPE, 0, &mime, 4);
227 }
228
229 // Write MACOS:HFS_FLAGS attribute
230 uint16 flags = ReadMacInt16(finfo + fdFlags);
231 if (flags != DEFAULT_FINDER_FLAGS) {
232 mime[0] = flags >> 8;
233 mime[1] = flags;
234 fs_write_attr(fd, "MACOS:HFS_FLAGS", B_UINT16_TYPE, 0, &mime, 2);
235 } else
236 fs_remove_attr(fd, "MACOS:HFS_FLAGS");
237
238 // Close file
239 close(fd);
240 }
241
242
243 /*
244 * Resource fork emulation functions
245 */
246
247 uint32 get_rfork_size(const char *path)
248 {
249 // Open file
250 int fd = open(path, O_RDONLY);
251 if (fd < 0)
252 return 0;
253
254 // Get size of MACOS:RFORK attribute
255 struct attr_info info;
256 if (fs_stat_attr(fd, "MACOS:RFORK", &info) < 0)
257 info.size = 0;
258
259 // Close file and return size
260 close(fd);
261 return info.size;
262 }
263
264 int open_rfork(const char *path, int flag)
265 {
266 // Open original file
267 int fd = open(path, flag);
268 if (fd < 0)
269 return -1;
270
271 // Open temporary file for resource fork
272 char rname[L_tmpnam];
273 tmpnam(rname);
274 int rfd = open(rname, O_RDWR | O_CREAT | O_TRUNC, 0666);
275 if (rfd < 0) {
276 close(fd);
277 return -1;
278 }
279 unlink(rname); // File will be deleted when closed
280
281 // Get size of MACOS:RFORK attribute
282 struct attr_info info;
283 if (fs_stat_attr(fd, "MACOS:RFORK", &info) < 0)
284 info.size = 0;
285
286 // Copy resource data from attribute to temporary file
287 if (info.size > 0) {
288
289 // Allocate buffer
290 void *buf = malloc(info.size);
291 if (buf == NULL) {
292 close(rfd);
293 close(fd);
294 return -1;
295 }
296
297 // Copy data
298 fs_read_attr(fd, "MACOS:RFORK", B_RAW_TYPE, 0, buf, info.size);
299 write(rfd, buf, info.size);
300 lseek(rfd, 0, SEEK_SET);
301
302 // Free buffer
303 if (buf)
304 free(buf);
305 }
306
307 // Close original file
308 close(fd);
309 return rfd;
310 }
311
312 void close_rfork(const char *path, int fd)
313 {
314 if (fd < 0)
315 return;
316
317 // Get size of temporary file
318 struct stat st;
319 if (fstat(fd, &st) < 0)
320 st.st_size = 0;
321
322 // Open original file
323 int ofd = open(path, O_WRONLY);
324 if (ofd > 0) {
325
326 // Copy resource data to MACOS:RFORK attribute
327 if (st.st_size > 0) {
328
329 // Allocate buffer
330 void *buf = malloc(st.st_size);
331 if (buf == NULL) {
332 close(ofd);
333 close(fd);
334 return;
335 }
336
337 // Copy data
338 lseek(fd, 0, SEEK_SET);
339 read(fd, buf, st.st_size);
340 fs_write_attr(ofd, "MACOS:RFORK", B_RAW_TYPE, 0, buf, st.st_size);
341
342 // Free buffer
343 if (buf)
344 free(buf);
345
346 } else
347 fs_remove_attr(ofd, "MACOS:RFORK");
348
349 // Close original file
350 close(ofd);
351 }
352
353 // Close temporary file
354 close(fd);
355 }
356
357
358 /*
359 * Read "length" bytes from file to "buffer",
360 * returns number of bytes read (or -1 on error)
361 */
362
363 static inline ssize_t sread(int fd, void *buf, size_t count)
364 {
365 ssize_t res;
366 while ((res = read(fd, buf, count)) == B_INTERRUPTED) ;
367 return res;
368 }
369
370 ssize_t extfs_read(int fd, void *buffer, size_t length)
371 {
372 // Buffer in kernel space?
373 if ((uint32)buffer < 0x80000000) {
374
375 // Yes, transfer via buffer
376 ssize_t actual = 0;
377 while (length) {
378 size_t transfer_size = (length > TMP_BUF_SIZE) ? TMP_BUF_SIZE : length;
379 ssize_t res = sread(fd, tmp_buf, transfer_size);
380 if (res < 0)
381 return res;
382 memcpy(buffer, tmp_buf, res);
383 buffer = (void *)((uint8 *)buffer + res);
384 length -= res;
385 actual += res;
386 if (res != transfer_size)
387 return actual;
388 }
389 return actual;
390
391 } else {
392
393 // No, transfer directly
394 return sread(fd, buffer, length);
395 }
396 }
397
398
399 /*
400 * Write "length" bytes from "buffer" to file,
401 * returns number of bytes written (or -1 on error)
402 */
403
404 static inline ssize_t swrite(int fd, void *buf, size_t count)
405 {
406 ssize_t res;
407 while ((res = write(fd, buf, count)) == B_INTERRUPTED) ;
408 return res;
409 }
410
411 ssize_t extfs_write(int fd, void *buffer, size_t length)
412 {
413 // Buffer in kernel space?
414 if ((uint32)buffer < 0x80000000) {
415
416 // Yes, transfer via buffer
417 ssize_t actual = 0;
418 while (length) {
419 size_t transfer_size = (length > TMP_BUF_SIZE) ? TMP_BUF_SIZE : length;
420 memcpy(tmp_buf, buffer, transfer_size);
421 ssize_t res = swrite(fd, tmp_buf, transfer_size);
422 if (res < 0)
423 return res;
424 buffer = (void *)((uint8 *)buffer + res);
425 length -= res;
426 actual += res;
427 if (res != transfer_size)
428 return actual;
429 }
430 return actual;
431
432 } else {
433
434 // No, transfer directly
435 return swrite(fd, buffer, length);
436 }
437 }
438
439
440 /*
441 * Remove file/directory, returns false on error (and sets errno)
442 */
443
444 bool extfs_remove(const char *path)
445 {
446 if (remove(path) < 0) {
447 if (errno == EISDIR)
448 return rmdir(path) == 0;
449 else
450 return false;
451 }
452 return true;
453 }
454
455
456 /*
457 * Rename/move file/directory, returns false on error (and sets errno)
458 */
459
460 bool extfs_rename(const char *old_path, const char *new_path)
461 {
462 return rename(old_path, new_path) == 0;
463 }