home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / Emulation / BasiliskII / src / BeOS / extfs_beos.cpp < prev    next >
C/C++ Source or Header  |  1999-12-22  |  11KB  |  476 lines

  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 -1 on error)
  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. ssize_t extfs_read(int fd, void *buffer, size_t length)
  383. {
  384.     // Buffer in kernel space?
  385.     if ((uint32)buffer < 0x80000000) {
  386.  
  387.         // Yes, transfer via buffer
  388.         ssize_t actual = 0;
  389.         while (length) {
  390.             size_t transfer_size = (length > TMP_BUF_SIZE) ? TMP_BUF_SIZE : length;
  391.             ssize_t res = sread(fd, tmp_buf, transfer_size);
  392.             if (res < 0)
  393.                 return res;
  394.             memcpy(buffer, tmp_buf, res);
  395.             buffer = (void *)((uint8 *)buffer + res);
  396.             length -= res;
  397.             actual += res;
  398.             if (res != transfer_size)
  399.                 return actual;
  400.         }
  401.         return actual;
  402.  
  403.     } else {
  404.  
  405.         // No, transfer directly
  406.         return sread(fd, buffer, length);
  407.     }
  408. }
  409.  
  410.  
  411. /*
  412.  *  Write "length" bytes from "buffer" to file,
  413.  *  returns number of bytes written (or -1 on error)
  414.  */
  415.  
  416. static inline ssize_t swrite(int fd, void *buf, size_t count)
  417. {
  418.     ssize_t res;
  419.     while ((res = write(fd, buf, count)) == B_INTERRUPTED) ;
  420.     return res;
  421. }
  422.  
  423. ssize_t extfs_write(int fd, void *buffer, size_t length)
  424. {
  425.     // Buffer in kernel space?
  426.     if ((uint32)buffer < 0x80000000) {
  427.  
  428.         // Yes, transfer via buffer
  429.         ssize_t actual = 0;
  430.         while (length) {
  431.             size_t transfer_size = (length > TMP_BUF_SIZE) ? TMP_BUF_SIZE : length;
  432.             memcpy(tmp_buf, buffer, transfer_size);
  433.             ssize_t res = swrite(fd, tmp_buf, transfer_size);
  434.             if (res < 0)
  435.                 return res;
  436.             buffer = (void *)((uint8 *)buffer + res);
  437.             length -= res;
  438.             actual += res;
  439.             if (res != transfer_size)
  440.                 return actual;
  441.         }
  442.         return actual;
  443.  
  444.     } else {
  445.  
  446.         // No, transfer directly
  447.         return swrite(fd, buffer, length);
  448.     }
  449. }
  450.  
  451.  
  452. /*
  453.  *  Remove file/directory, returns false on error (and sets errno)
  454.  */
  455.  
  456. bool extfs_remove(const char *path)
  457. {
  458.     if (remove(path) < 0) {
  459.         if (errno == EISDIR)
  460.             return rmdir(path) == 0;
  461.         else
  462.             return false;
  463.     }
  464.     return true;
  465. }
  466.  
  467.  
  468. /*
  469.  *  Rename/move file/directory, returns false on error (and sets errno)
  470.  */
  471.  
  472. bool extfs_rename(const char *old_path, const char *new_path)
  473. {
  474.     return rename(old_path, new_path) == 0;
  475. }
  476.