home *** CD-ROM | disk | FTP | other *** search
- /*
- * extfs_beos.cpp - MacOS file system for access native file system access, BeOS specific stuff
- *
- * Basilisk II (C) 1997-2001 Christian Bauer
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
- #include "sysdeps.h"
-
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <string.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <dirent.h>
- #include <errno.h>
-
- #include <fs_attr.h>
- #include <support/TypeConstants.h>
- #include <storage/Mime.h>
-
- #include "extfs.h"
- #include "extfs_defs.h"
-
- #define DEBUG 0
- #include "debug.h"
-
-
- // Default Finder flags
- const uint16 DEFAULT_FINDER_FLAGS = kHasBeenInited;
-
- // Temporary buffer for transfers from/to kernel space
- const int TMP_BUF_SIZE = 0x10000;
- static uint8 *tmp_buf = NULL;
-
-
- /*
- * Initialization
- */
-
- void extfs_init(void)
- {
- // Allocate temporary buffer
- tmp_buf = new uint8[TMP_BUF_SIZE];
- }
-
-
- /*
- * Deinitialization
- */
-
- void extfs_exit(void)
- {
- // Delete temporary buffer
- delete[] tmp_buf;
- }
-
-
- /*
- * Add component to path name
- */
-
- void add_path_component(char *path, const char *component)
- {
- int l = strlen(path);
- if (l < MAX_PATH_LENGTH-1 && path[l-1] != '/') {
- path[l] = '/';
- path[l+1] = 0;
- }
- strncat(path, component, MAX_PATH_LENGTH-1);
- }
-
-
- /*
- * Get/set finder info for file/directory specified by full path
- */
-
- struct mime2type {
- const char *mime;
- uint32 type;
- uint32 creator;
- bool reversible; // type -> mime translation possible
- };
-
- static const mime2type m2t_translation[] = {
- {"application/x-compress", 'ZIVM', 'LZIV', true},
- {"application/x-gzip", 'Gzip', 'Gzip', true},
- {"application/x-macbinary", 'BINA', '????', false},
- {"application/mac-binhex40", 'TEXT', 'SITx', false},
- {"application/pdf", 'PDF ', 'CARO', true},
- {"application/postscript", 'TEXT', 'ttxt', false},
- {"application/x-stuffit", 'SIT!', 'SITx', true},
- {"application/x-tar", 'TARF', 'TAR ', true},
- {"application/x-uuencode", 'TEXT', 'SITx', false},
- {"application/zip", 'ZIP ', 'ZIP ', true},
- {"audio/x-8svx", '8SVX', 'SNDM', true},
- {"audio/x-aifc", 'AIFC', 'TVOD', true},
- {"audio/x-aiff", 'AIFF', 'TVOD', true},
- {"audio/basic", 'ULAW', 'TVOD', true},
- {"audio/x-midi", 'MIDI', 'TVOD', true},
- {"audio/x-mpeg", 'MPG ', 'TVOD', true},
- {"audio/x-wav", 'WAVE', 'TVOD', true},
- {"image/x-bmp", 'BMPf', 'ogle', true},
- {"image/gif", 'GIFf', 'ogle', true},
- {"image/x-ilbm", 'ILBM', 'GKON', true},
- {"image/jpeg", 'JPEG', 'ogle', true},
- {"image/jpeg", 'JFIF', 'ogle', true},
- {"image/x-photoshop", '8BPS', '8BIM', true},
- {"image/pict", 'PICT', 'ogle', true},
- {"image/png", 'PNGf', 'ogle', true},
- {"image/x-sgi", '.SGI', 'ogle', true},
- {"image/x-targa", 'TPIC', 'ogle', true},
- {"image/tiff", 'TIFF', 'ogle', true},
- {"text/html", 'TEXT', 'MOSS', false},
- {"text/plain", 'TEXT', 'ttxt', true},
- {"text/rtf", 'TEXT', 'MSWD', false},
- {"text/x-source-code", 'TEXT', 'R*ch', false},
- {"video/mpeg", 'MPEG', 'TVOD', true},
- {"video/quicktime", 'MooV', 'TVOD', true},
- {"video/x-flc", 'FLI ', 'TVOD', true},
- {"video/x-msvideo", 'VfW ', 'TVOD', true},
- {NULL, 0, 0, false} // End marker
- };
-
- void get_finfo(const char *path, uint32 finfo, uint32 fxinfo, bool is_dir)
- {
- // Set default finder info
- Mac_memset(finfo, 0, SIZEOF_FInfo);
- if (fxinfo)
- Mac_memset(fxinfo, 0, SIZEOF_FXInfo);
- WriteMacInt16(finfo + fdFlags, DEFAULT_FINDER_FLAGS);
- WriteMacInt32(finfo + fdLocation, (uint32)-1);
-
- // Open file
- int fd = open(path, O_RDONLY);
- if (fd < 0)
- return;
-
- if (!is_dir) {
-
- // Read BeOS MIME type
- ssize_t actual = fs_read_attr(fd, "BEOS:TYPE", B_MIME_STRING_TYPE, 0, tmp_buf, 256);
- tmp_buf[255] = 0;
-
- if (actual > 0) {
-
- // Translate MIME type to MacOS type/creator
- uint8 mactype[4];
- if (sscanf((char *)tmp_buf, "application/x-MacOS-%c%c%c%c", mactype, mactype+1, mactype+2, mactype+3) == 4) {
-
- // MacOS style type
- WriteMacInt32(finfo + fdType, (mactype[0] << 24) | (mactype[1] << 16) | (mactype[2] << 8) | mactype[3]);
-
- } else {
-
- // MIME string, look in table
- for (int i=0; m2t_translation[i].mime; i++) {
- if (!strcmp((char *)tmp_buf, m2t_translation[i].mime)) {
- WriteMacInt32(finfo + fdType, m2t_translation[i].type);
- WriteMacInt32(finfo + fdCreator, m2t_translation[i].creator);
- break;
- }
- }
- }
- }
-
- // Override file type with MACOS:CREATOR attribute
- if (fs_read_attr(fd, "MACOS:CREATOR", B_UINT32_TYPE, 0, tmp_buf, 4) == 4)
- WriteMacInt32(finfo + fdCreator, (tmp_buf[0] << 24) | (tmp_buf[1] << 16) | (tmp_buf[2] << 8) | tmp_buf[3]);
- }
-
- // Read MACOS:HFS_FLAGS attribute
- if (fs_read_attr(fd, "MACOS:HFS_FLAGS", B_UINT16_TYPE, 0, tmp_buf, 2) == 2)
- WriteMacInt16(finfo + fdFlags, (tmp_buf[0] << 8) | tmp_buf[1]);
-
- // Close file
- close(fd);
- }
-
- void set_finfo(const char *path, uint32 finfo, uint32 fxinfo, bool is_dir)
- {
- // Open file
- int fd = open(path, O_WRONLY);
- if (fd < 0)
- return;
-
- if (!is_dir) {
-
- // Set BEOS:TYPE attribute
- uint32 type = ReadMacInt32(finfo + fdType);
- if (type) {
- for (int i=0; m2t_translation[i].mime; i++) {
- if (m2t_translation[i].type == type && m2t_translation[i].reversible) {
- fs_write_attr(fd, "BEOS:TYPE", B_MIME_STRING_TYPE, 0, m2t_translation[i].mime, strlen(m2t_translation[i].mime) + 1);
- break;
- }
- }
- }
-
- // Set MACOS:CREATOR attribute
- uint32 creator = ReadMacInt32(finfo + fdCreator);
- if (creator) {
- tmp_buf[0] = creator >> 24;
- tmp_buf[1] = creator >> 16;
- tmp_buf[2] = creator >> 8;
- tmp_buf[3] = creator;
- fs_write_attr(fd, "MACOS:CREATOR", B_UINT32_TYPE, 0, tmp_buf, 4);
- }
- }
-
- // Write MACOS:HFS_FLAGS attribute
- uint16 flags = ReadMacInt16(finfo + fdFlags);
- if (flags != DEFAULT_FINDER_FLAGS) {
- tmp_buf[0] = flags >> 8;
- tmp_buf[1] = flags;
- fs_write_attr(fd, "MACOS:HFS_FLAGS", B_UINT16_TYPE, 0, tmp_buf, 2);
- } else
- fs_remove_attr(fd, "MACOS:HFS_FLAGS");
-
- // Close file
- close(fd);
- }
-
-
- /*
- * Resource fork emulation functions
- */
-
- uint32 get_rfork_size(const char *path)
- {
- // Open file
- int fd = open(path, O_RDONLY);
- if (fd < 0)
- return 0;
-
- // Get size of MACOS:RFORK attribute
- struct attr_info info;
- if (fs_stat_attr(fd, "MACOS:RFORK", &info) < 0)
- info.size = 0;
-
- // Close file and return size
- close(fd);
- return info.size;
- }
-
- int open_rfork(const char *path, int flag)
- {
- // Open original file
- int fd = open(path, flag);
- if (fd < 0)
- return -1;
-
- // Open temporary file for resource fork
- char rname[L_tmpnam];
- tmpnam(rname);
- int rfd = open(rname, O_RDWR | O_CREAT | O_TRUNC, 0666);
- if (rfd < 0) {
- close(fd);
- return -1;
- }
- unlink(rname); // File will be deleted when closed
-
- // Get size of MACOS:RFORK attribute
- struct attr_info info;
- if (fs_stat_attr(fd, "MACOS:RFORK", &info) < 0)
- info.size = 0;
-
- // Copy resource data from attribute to temporary file
- if (info.size > 0) {
-
- // Allocate buffer
- void *buf = malloc(info.size);
- if (buf == NULL) {
- close(rfd);
- close(fd);
- return -1;
- }
-
- // Copy data
- fs_read_attr(fd, "MACOS:RFORK", B_RAW_TYPE, 0, buf, info.size);
- write(rfd, buf, info.size);
- lseek(rfd, 0, SEEK_SET);
-
- // Free buffer
- if (buf)
- free(buf);
- }
-
- // Close original file
- close(fd);
- return rfd;
- }
-
- void close_rfork(const char *path, int fd)
- {
- if (fd < 0)
- return;
-
- // Get size of temporary file
- struct stat st;
- if (fstat(fd, &st) < 0)
- st.st_size = 0;
-
- // Open original file
- int ofd = open(path, O_WRONLY);
- if (ofd > 0) {
-
- // Copy resource data to MACOS:RFORK attribute
- if (st.st_size > 0) {
-
- // Allocate buffer
- void *buf = malloc(st.st_size);
- if (buf == NULL) {
- close(ofd);
- close(fd);
- return;
- }
-
- // Copy data
- lseek(fd, 0, SEEK_SET);
- read(fd, buf, st.st_size);
- fs_write_attr(ofd, "MACOS:RFORK", B_RAW_TYPE, 0, buf, st.st_size);
-
- // Free buffer
- if (buf)
- free(buf);
-
- } else
- fs_remove_attr(ofd, "MACOS:RFORK");
-
- // Close original file
- close(ofd);
- }
-
- // Close temporary file
- close(fd);
- }
-
-
- /*
- * Read "length" bytes from file to "buffer",
- * returns number of bytes read (or -1 on error)
- */
-
- static inline ssize_t sread(int fd, void *buf, size_t count)
- {
- ssize_t res;
- while ((res = read(fd, buf, count)) == B_INTERRUPTED) ;
- return res;
- }
-
- ssize_t extfs_read(int fd, void *buffer, size_t length)
- {
- // Buffer in kernel space?
- if ((uint32)buffer < 0x80000000) {
-
- // Yes, transfer via buffer
- ssize_t actual = 0;
- while (length) {
- size_t transfer_size = (length > TMP_BUF_SIZE) ? TMP_BUF_SIZE : length;
- ssize_t res = sread(fd, tmp_buf, transfer_size);
- if (res < 0)
- return res;
- memcpy(buffer, tmp_buf, res);
- buffer = (void *)((uint8 *)buffer + res);
- length -= res;
- actual += res;
- if (res != transfer_size)
- return actual;
- }
- return actual;
-
- } else {
-
- // No, transfer directly
- return sread(fd, buffer, length);
- }
- }
-
-
- /*
- * Write "length" bytes from "buffer" to file,
- * returns number of bytes written (or -1 on error)
- */
-
- static inline ssize_t swrite(int fd, void *buf, size_t count)
- {
- ssize_t res;
- while ((res = write(fd, buf, count)) == B_INTERRUPTED) ;
- return res;
- }
-
- ssize_t extfs_write(int fd, void *buffer, size_t length)
- {
- // Buffer in kernel space?
- if ((uint32)buffer < 0x80000000) {
-
- // Yes, transfer via buffer
- ssize_t actual = 0;
- while (length) {
- size_t transfer_size = (length > TMP_BUF_SIZE) ? TMP_BUF_SIZE : length;
- memcpy(tmp_buf, buffer, transfer_size);
- ssize_t res = swrite(fd, tmp_buf, transfer_size);
- if (res < 0)
- return res;
- buffer = (void *)((uint8 *)buffer + res);
- length -= res;
- actual += res;
- if (res != transfer_size)
- return actual;
- }
- return actual;
-
- } else {
-
- // No, transfer directly
- return swrite(fd, buffer, length);
- }
- }
-
-
- /*
- * Remove file/directory, returns false on error (and sets errno)
- */
-
- bool extfs_remove(const char *path)
- {
- if (remove(path) < 0) {
- if (errno == EISDIR)
- return rmdir(path) == 0;
- else
- return false;
- }
- return true;
- }
-
-
- /*
- * Rename/move file/directory, returns false on error (and sets errno)
- */
-
- bool extfs_rename(const char *old_path, const char *new_path)
- {
- return rename(old_path, new_path) == 0;
- }
-