ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/BeOS/extfs_beos.cpp
Revision: 1.7
Committed: 1999-11-08T17:00:12Z (24 years, 7 months ago) by cebix
Branch: MAIN
Changes since 1.6: +16 -0 lines
Log Message:
- fs_delete() will also delete helper files

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