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

# User Rev Content
1 cebix 1.1 /*
2     * extfs_beos.cpp - MacOS file system for access native file system access, BeOS specific stuff
3     *
4 cebix 1.12 * Basilisk II (C) 1997-2001 Christian Bauer
5 cebix 1.1 *
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 cebix 1.2 #include "sysdeps.h"
22    
23 cebix 1.1 #include <sys/types.h>
24     #include <sys/stat.h>
25 cebix 1.2 #include <string.h>
26 cebix 1.1 #include <stdio.h>
27     #include <stdlib.h>
28     #include <unistd.h>
29 cebix 1.2 #include <fcntl.h>
30 cebix 1.1 #include <dirent.h>
31     #include <errno.h>
32    
33     #include <fs_attr.h>
34 cebix 1.2 #include <support/TypeConstants.h>
35     #include <storage/Mime.h>
36 cebix 1.1
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 cebix 1.3 * Add component to path name
76     */
77    
78 cebix 1.5 void add_path_component(char *path, const char *component)
79 cebix 1.3 {
80     int l = strlen(path);
81 cebix 1.5 if (l < MAX_PATH_LENGTH-1 && path[l-1] != '/') {
82 cebix 1.3 path[l] = '/';
83     path[l+1] = 0;
84     }
85 cebix 1.5 strncat(path, component, MAX_PATH_LENGTH-1);
86 cebix 1.3 }
87    
88    
89     /*
90 cebix 1.11 * Get/set finder info for file/directory specified by full path
91 cebix 1.1 */
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 cebix 1.11 void get_finfo(const char *path, uint32 finfo, uint32 fxinfo)
141 cebix 1.1 {
142 cebix 1.11 // 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 cebix 1.1
149     // Open file
150     int fd = open(path, O_RDONLY);
151     if (fd < 0)
152     return;
153    
154 cebix 1.11 // Read BeOS MIME type
155 cebix 1.1 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 cebix 1.11 WriteMacInt32(finfo + fdType, mactype);
167 cebix 1.1
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 cebix 1.11 WriteMacInt32(finfo + fdType, m2t_translation[i].type);
174     WriteMacInt32(finfo + fdCreator, m2t_translation[i].creator);
175 cebix 1.1 break;
176     }
177     }
178     }
179     }
180    
181     // Override file type with MACOS:CREATOR attribute
182 cebix 1.11 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 cebix 1.1
189     // Close file
190     close(fd);
191     }
192    
193 cebix 1.11 void set_finfo(const char *path, uint32 finfo, uint32 fxinfo)
194 cebix 1.1 {
195 cebix 1.11 char mime[256];
196    
197 cebix 1.1 // Open file
198     int fd = open(path, O_WRONLY);
199     if (fd < 0)
200     return;
201    
202     // Set BEOS:TYPE attribute
203 cebix 1.11 uint32 type = ReadMacInt32(finfo + fdType);
204 cebix 1.1 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 cebix 1.11 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 cebix 1.1
229     // Write MACOS:HFS_FLAGS attribute
230 cebix 1.11 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 cebix 1.1 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 cebix 1.6 int rfd = open(rname, O_RDWR | O_CREAT | O_TRUNC, 0666);
275 cebix 1.1 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 cebix 1.9 * returns number of bytes read (or -1 on error)
361 cebix 1.1 */
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 cebix 1.9 ssize_t extfs_read(int fd, void *buffer, size_t length)
371 cebix 1.1 {
372     // Buffer in kernel space?
373     if ((uint32)buffer < 0x80000000) {
374    
375     // Yes, transfer via buffer
376 cebix 1.9 ssize_t actual = 0;
377 cebix 1.1 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 cebix 1.9 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 cebix 1.1 if (res != transfer_size)
387     return actual;
388     }
389 cebix 1.9 return actual;
390 cebix 1.1
391     } else {
392    
393     // No, transfer directly
394 cebix 1.9 return sread(fd, buffer, length);
395 cebix 1.1 }
396     }
397    
398    
399     /*
400     * Write "length" bytes from "buffer" to file,
401 cebix 1.9 * returns number of bytes written (or -1 on error)
402 cebix 1.1 */
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 cebix 1.9 ssize_t extfs_write(int fd, void *buffer, size_t length)
412 cebix 1.1 {
413     // Buffer in kernel space?
414     if ((uint32)buffer < 0x80000000) {
415    
416     // Yes, transfer via buffer
417 cebix 1.9 ssize_t actual = 0;
418 cebix 1.1 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 cebix 1.9 if (res < 0)
423     return res;
424     buffer = (void *)((uint8 *)buffer + res);
425     length -= res;
426     actual += res;
427 cebix 1.1 if (res != transfer_size)
428     return actual;
429     }
430 cebix 1.9 return actual;
431 cebix 1.1
432     } else {
433    
434     // No, transfer directly
435 cebix 1.9 return swrite(fd, buffer, length);
436 cebix 1.1 }
437     }
438 cebix 1.7
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 cebix 1.8
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     }