ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/BeOS/extfs_beos.cpp
Revision: 1.1
Committed: 1999-10-19T17:41:28Z (25 years, 1 month ago) by cebix
Branch: MAIN
Log Message:
- added external file system
- moved most init/deinit code to InitAll()/ExitAll() in main.cpp

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