ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/BeOS/extfs_beos.cpp
Revision: 1.18
Committed: 2008-01-01T09:40:32Z (16 years, 5 months ago) by gbeauche
Branch: MAIN
CVS Tags: HEAD
Changes since 1.17: +1 -1 lines
Log Message:
Happy New Year!

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-2008 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, bool is_dir)
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 if (!is_dir) {
155
156 // Read BeOS MIME type
157 ssize_t actual = fs_read_attr(fd, "BEOS:TYPE", B_MIME_STRING_TYPE, 0, tmp_buf, 256);
158 tmp_buf[255] = 0;
159
160 if (actual > 0) {
161
162 // Translate MIME type to MacOS type/creator
163 uint8 mactype[4];
164 if (sscanf((char *)tmp_buf, "application/x-MacOS-%c%c%c%c", mactype, mactype+1, mactype+2, mactype+3) == 4) {
165
166 // MacOS style type
167 WriteMacInt32(finfo + fdType, (mactype[0] << 24) | (mactype[1] << 16) | (mactype[2] << 8) | mactype[3]);
168
169 } else {
170
171 // MIME string, look in table
172 for (int i=0; m2t_translation[i].mime; i++) {
173 if (!strcmp((char *)tmp_buf, m2t_translation[i].mime)) {
174 WriteMacInt32(finfo + fdType, m2t_translation[i].type);
175 WriteMacInt32(finfo + fdCreator, m2t_translation[i].creator);
176 break;
177 }
178 }
179 }
180 }
181
182 // Override file type with MACOS:CREATOR attribute
183 if (fs_read_attr(fd, "MACOS:CREATOR", B_UINT32_TYPE, 0, tmp_buf, 4) == 4)
184 WriteMacInt32(finfo + fdCreator, (tmp_buf[0] << 24) | (tmp_buf[1] << 16) | (tmp_buf[2] << 8) | tmp_buf[3]);
185 }
186
187 // Read MACOS:HFS_FLAGS attribute
188 if (fs_read_attr(fd, "MACOS:HFS_FLAGS", B_UINT16_TYPE, 0, tmp_buf, 2) == 2)
189 WriteMacInt16(finfo + fdFlags, (tmp_buf[0] << 8) | tmp_buf[1]);
190
191 // Close file
192 close(fd);
193 }
194
195 void set_finfo(const char *path, uint32 finfo, uint32 fxinfo, bool is_dir)
196 {
197 // Open file
198 int fd = open(path, O_WRONLY);
199 if (fd < 0)
200 return;
201
202 if (!is_dir) {
203
204 // Set BEOS:TYPE attribute
205 uint32 type = ReadMacInt32(finfo + fdType);
206 if (type) {
207 for (int i=0; m2t_translation[i].mime; i++) {
208 if (m2t_translation[i].type == type && m2t_translation[i].reversible) {
209 fs_write_attr(fd, "BEOS:TYPE", B_MIME_STRING_TYPE, 0, m2t_translation[i].mime, strlen(m2t_translation[i].mime) + 1);
210 break;
211 }
212 }
213 }
214
215 // Set MACOS:CREATOR attribute
216 uint32 creator = ReadMacInt32(finfo + fdCreator);
217 if (creator) {
218 tmp_buf[0] = creator >> 24;
219 tmp_buf[1] = creator >> 16;
220 tmp_buf[2] = creator >> 8;
221 tmp_buf[3] = creator;
222 fs_write_attr(fd, "MACOS:CREATOR", B_UINT32_TYPE, 0, tmp_buf, 4);
223 }
224 }
225
226 // Write MACOS:HFS_FLAGS attribute
227 uint16 flags = ReadMacInt16(finfo + fdFlags);
228 if (flags != DEFAULT_FINDER_FLAGS) {
229 tmp_buf[0] = flags >> 8;
230 tmp_buf[1] = flags;
231 fs_write_attr(fd, "MACOS:HFS_FLAGS", B_UINT16_TYPE, 0, tmp_buf, 2);
232 } else
233 fs_remove_attr(fd, "MACOS:HFS_FLAGS");
234
235 // Close file
236 close(fd);
237 }
238
239
240 /*
241 * Resource fork emulation functions
242 */
243
244 uint32 get_rfork_size(const char *path)
245 {
246 // Open file
247 int fd = open(path, O_RDONLY);
248 if (fd < 0)
249 return 0;
250
251 // Get size of MACOS:RFORK attribute
252 struct attr_info info;
253 if (fs_stat_attr(fd, "MACOS:RFORK", &info) < 0)
254 info.size = 0;
255
256 // Close file and return size
257 close(fd);
258 return info.size;
259 }
260
261 int open_rfork(const char *path, int flag)
262 {
263 // Open original file
264 int fd = open(path, flag);
265 if (fd < 0)
266 return -1;
267
268 // Open temporary file for resource fork
269 char rname[L_tmpnam];
270 tmpnam(rname);
271 int rfd = open(rname, O_RDWR | O_CREAT | O_TRUNC, 0666);
272 if (rfd < 0) {
273 close(fd);
274 return -1;
275 }
276 unlink(rname); // File will be deleted when closed
277
278 // Get size of MACOS:RFORK attribute
279 struct attr_info info;
280 if (fs_stat_attr(fd, "MACOS:RFORK", &info) < 0)
281 info.size = 0;
282
283 // Copy resource data from attribute to temporary file
284 if (info.size > 0) {
285
286 // Allocate buffer
287 void *buf = malloc(info.size);
288 if (buf == NULL) {
289 close(rfd);
290 close(fd);
291 return -1;
292 }
293
294 // Copy data
295 fs_read_attr(fd, "MACOS:RFORK", B_RAW_TYPE, 0, buf, info.size);
296 write(rfd, buf, info.size);
297 lseek(rfd, 0, SEEK_SET);
298
299 // Free buffer
300 if (buf)
301 free(buf);
302 }
303
304 // Close original file
305 close(fd);
306 return rfd;
307 }
308
309 void close_rfork(const char *path, int fd)
310 {
311 if (fd < 0)
312 return;
313
314 // Get size of temporary file
315 struct stat st;
316 if (fstat(fd, &st) < 0)
317 st.st_size = 0;
318
319 // Open original file
320 int ofd = open(path, O_WRONLY);
321 if (ofd > 0) {
322
323 // Copy resource data to MACOS:RFORK attribute
324 if (st.st_size > 0) {
325
326 // Allocate buffer
327 void *buf = malloc(st.st_size);
328 if (buf == NULL) {
329 close(ofd);
330 close(fd);
331 return;
332 }
333
334 // Copy data
335 lseek(fd, 0, SEEK_SET);
336 read(fd, buf, st.st_size);
337 fs_write_attr(ofd, "MACOS:RFORK", B_RAW_TYPE, 0, buf, st.st_size);
338
339 // Free buffer
340 if (buf)
341 free(buf);
342
343 } else
344 fs_remove_attr(ofd, "MACOS:RFORK");
345
346 // Close original file
347 close(ofd);
348 }
349
350 // Close temporary file
351 close(fd);
352 }
353
354
355 /*
356 * Read "length" bytes from file to "buffer",
357 * returns number of bytes read (or -1 on error)
358 */
359
360 static inline ssize_t sread(int fd, void *buf, size_t count)
361 {
362 ssize_t res;
363 while ((res = read(fd, buf, count)) == B_INTERRUPTED) ;
364 return res;
365 }
366
367 ssize_t extfs_read(int fd, void *buffer, size_t length)
368 {
369 // Buffer in kernel space?
370 if ((uint32)buffer < 0x80000000) {
371
372 // Yes, transfer via buffer
373 ssize_t actual = 0;
374 while (length) {
375 size_t transfer_size = (length > TMP_BUF_SIZE) ? TMP_BUF_SIZE : length;
376 ssize_t res = sread(fd, tmp_buf, transfer_size);
377 if (res < 0)
378 return res;
379 memcpy(buffer, tmp_buf, res);
380 buffer = (void *)((uint8 *)buffer + res);
381 length -= res;
382 actual += res;
383 if (res != transfer_size)
384 return actual;
385 }
386 return actual;
387
388 } else {
389
390 // No, transfer directly
391 return sread(fd, buffer, length);
392 }
393 }
394
395
396 /*
397 * Write "length" bytes from "buffer" to file,
398 * returns number of bytes written (or -1 on error)
399 */
400
401 static inline ssize_t swrite(int fd, void *buf, size_t count)
402 {
403 ssize_t res;
404 while ((res = write(fd, buf, count)) == B_INTERRUPTED) ;
405 return res;
406 }
407
408 ssize_t extfs_write(int fd, void *buffer, size_t length)
409 {
410 // Buffer in kernel space?
411 if ((uint32)buffer < 0x80000000) {
412
413 // Yes, transfer via buffer
414 ssize_t actual = 0;
415 while (length) {
416 size_t transfer_size = (length > TMP_BUF_SIZE) ? TMP_BUF_SIZE : length;
417 memcpy(tmp_buf, buffer, transfer_size);
418 ssize_t res = swrite(fd, tmp_buf, transfer_size);
419 if (res < 0)
420 return res;
421 buffer = (void *)((uint8 *)buffer + res);
422 length -= res;
423 actual += res;
424 if (res != transfer_size)
425 return actual;
426 }
427 return actual;
428
429 } else {
430
431 // No, transfer directly
432 return swrite(fd, buffer, length);
433 }
434 }
435
436
437 /*
438 * Remove file/directory, returns false on error (and sets errno)
439 */
440
441 bool extfs_remove(const char *path)
442 {
443 if (remove(path) < 0) {
444 if (errno == EISDIR)
445 return rmdir(path) == 0;
446 else
447 return false;
448 }
449 return true;
450 }
451
452
453 /*
454 * Rename/move file/directory, returns false on error (and sets errno)
455 */
456
457 bool extfs_rename(const char *old_path, const char *new_path)
458 {
459 return rename(old_path, new_path) == 0;
460 }