home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 6 / AACD06.ISO / AACD / Emulation / BasiliskII / src / Unix / extfs_unix.cpp < prev    next >
C/C++ Source or Header  |  2000-01-21  |  10KB  |  429 lines

  1. /*
  2.  *  extfs_unix.cpp - MacOS file system for access native file system access, Unix 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 "sysdeps.h"
  30. #include "extfs.h"
  31. #include "extfs_defs.h"
  32.  
  33. #define DEBUG 0
  34. #include "debug.h"
  35.  
  36.  
  37. // Default Finder flags
  38. const uint16 DEFAULT_FINDER_FLAGS = kHasBeenInited;
  39.  
  40.  
  41. /*
  42.  *  Initialization
  43.  */
  44.  
  45. void extfs_init(void)
  46. {
  47. }
  48.  
  49.  
  50. /*
  51.  *  Deinitialization
  52.  */
  53.  
  54. void extfs_exit(void)
  55. {
  56. }
  57.  
  58.  
  59. /*
  60.  *  Add component to path name
  61.  */
  62.  
  63. void add_path_component(char *path, const char *component)
  64. {
  65.     int l = strlen(path);
  66.     if (l < MAX_PATH_LENGTH-1 && path[l-1] != '/') {
  67.         path[l] = '/';
  68.         path[l+1] = 0;
  69.     }
  70.     strncat(path, component, MAX_PATH_LENGTH-1);
  71. }
  72.  
  73.  
  74. /*
  75.  *  Finder info and resource forks are kept in helper files
  76.  *
  77.  *  Finder info:
  78.  *    /path/.finf/file
  79.  *  Resource fork:
  80.  *    /path/.rsrc/file
  81.  */
  82.  
  83. // Layout of Finder info helper files (all fields big-endian)
  84. struct finf_struct {
  85.     uint32 type;
  86.     uint32 creator;
  87.     uint16 flags;
  88.     uint8 pad0[22];    // total size: 32 bytes to match the size of FInfo+FXInfo
  89. };
  90.  
  91. static void make_helper_path(const char *src, char *dest, const char *add, bool only_dir = false)
  92. {
  93.     dest[0] = 0;
  94.  
  95.     // Get pointer to last component of path
  96.     const char *last_part = strrchr(src, '/');
  97.     if (last_part)
  98.         last_part++;
  99.     else
  100.         last_part = src;
  101.  
  102.     // Copy everything before
  103.     strncpy(dest, src, last_part-src);
  104.     dest[last_part-src] = 0;
  105.  
  106.     // Add additional component
  107.     strncat(dest, add, MAX_PATH_LENGTH-1);
  108.  
  109.     // Add last component
  110.     if (!only_dir)
  111.         strncat(dest, last_part, MAX_PATH_LENGTH-1);
  112. }
  113.  
  114. static int create_helper_dir(const char *path, const char *add)
  115. {
  116.     char helper_dir[MAX_PATH_LENGTH];
  117.     make_helper_path(path, helper_dir, add, true);
  118.     return mkdir(helper_dir, 0777);
  119. }
  120.  
  121. static int open_helper(const char *path, const char *add, int flag)
  122. {
  123.     char helper_path[MAX_PATH_LENGTH];
  124.     make_helper_path(path, helper_path, add);
  125.  
  126.     if ((flag & O_ACCMODE) == O_RDWR || (flag & O_ACCMODE) == O_WRONLY)
  127.         flag |= O_CREAT;
  128.     int fd = open(helper_path, flag, 0666);
  129.     if (fd < 0) {
  130.         if (errno == ENOENT && (flag & O_CREAT)) {
  131.             // One path component was missing, probably the helper
  132.             // directory. Try to create it and re-open the file.
  133.             int ret = create_helper_dir(path, add);
  134.             if (ret < 0)
  135.                 return ret;
  136.             fd = open(helper_path, flag, 0666);
  137.         }
  138.     }
  139.     return fd;
  140. }
  141.  
  142. static int open_finf(const char *path, int flag)
  143. {
  144.     return open_helper(path, ".finf/", flag);
  145. }
  146.  
  147. static int open_rsrc(const char *path, int flag)
  148. {
  149.     return open_helper(path, ".rsrc/", flag);
  150. }
  151.  
  152.  
  153. /*
  154.  *  Get/set finder type/creator for file specified by full path
  155.  */
  156.  
  157. struct ext2type {
  158.     const char *ext;
  159.     uint32 type;
  160.     uint32 creator;
  161. };
  162.  
  163. static const ext2type e2t_translation[] = {
  164.     {".Z", 'ZIVM', 'LZIV'},
  165.     {".gz", 'Gzip', 'Gzip'},
  166.     {".hqx", 'TEXT', 'SITx'},
  167.     {".pdf", 'PDF ', 'CARO'},
  168.     {".ps", 'TEXT', 'ttxt'},
  169.     {".sit", 'SIT!', 'SITx'},
  170.     {".tar", 'TARF', 'TAR '},
  171.     {".uu", 'TEXT', 'SITx'},
  172.     {".uue", 'TEXT', 'SITx'},
  173.     {".zip", 'ZIP ', 'ZIP '},
  174.     {".8svx", '8SVX', 'SNDM'},
  175.     {".aifc", 'AIFC', 'TVOD'},
  176.     {".aiff", 'AIFF', 'TVOD'},
  177.     {".au", 'ULAW', 'TVOD'},
  178.     {".mid", 'MIDI', 'TVOD'},
  179.     {".midi", 'MIDI', 'TVOD'},
  180.     {".mp2", 'MPG ', 'TVOD'},
  181.     {".mp3", 'MPG ', 'TVOD'},
  182.     {".wav", 'WAVE', 'TVOD'},
  183.     {".bmp", 'BMPf', 'ogle'},
  184.     {".gif", 'GIFf', 'ogle'},
  185.     {".lbm", 'ILBM', 'GKON'},
  186.     {".ilbm", 'ILBM', 'GKON'},
  187.     {".jpg", 'JPEG', 'ogle'},
  188.     {".jpeg", 'JPEG', 'ogle'},
  189.     {".pict", 'PICT', 'ogle'},
  190.     {".png", 'PNGf', 'ogle'},
  191.     {".sgi", '.SGI', 'ogle'},
  192.     {".tga", 'TPIC', 'ogle'},
  193.     {".tif", 'TIFF', 'ogle'},
  194.     {".tiff", 'TIFF', 'ogle'},
  195.     {".html", 'TEXT', 'MOSS'},
  196.     {".txt", 'TEXT', 'ttxt'},
  197.     {".rtf", 'TEXT', 'MSWD'},
  198.     {".c", 'TEXT', 'R*ch'},
  199.     {".C", 'TEXT', 'R*ch'},
  200.     {".cc", 'TEXT', 'R*ch'},
  201.     {".cpp", 'TEXT', 'R*ch'},
  202.     {".cxx", 'TEXT', 'R*ch'},
  203.     {".h", 'TEXT', 'R*ch'},
  204.     {".hh", 'TEXT', 'R*ch'},
  205.     {".hpp", 'TEXT', 'R*ch'},
  206.     {".hxx", 'TEXT', 'R*ch'},
  207.     {".s", 'TEXT', 'R*ch'},
  208.     {".S", 'TEXT', 'R*ch'},
  209.     {".i", 'TEXT', 'R*ch'},
  210.     {".mpg", 'MPEG', 'TVOD'},
  211.     {".mpeg", 'MPEG', 'TVOD'},
  212.     {".mov", 'MooV', 'TVOD'},
  213.     {".fli", 'FLI ', 'TVOD'},
  214.     {".avi", 'VfW ', 'TVOD'},
  215.     {NULL, 0, 0}    // End marker
  216. };
  217.  
  218. void get_finder_type(const char *path, uint32 &type, uint32 &creator)
  219. {
  220.     type = 0;
  221.     creator = 0;
  222.  
  223.     // Open Finder info file
  224.     int fd = open_finf(path, O_RDONLY);
  225.     if (fd >= 0) {
  226.  
  227.         // Read file
  228.         finf_struct finf;
  229.         if (read(fd, &finf, sizeof(finf_struct)) >= 8) {
  230.  
  231.             // Type/creator are in Finder info file, return them
  232.             type = ntohl(finf.type);
  233.             creator = ntohl(finf.creator);
  234.             close(fd);
  235.             return;
  236.         }
  237.         close(fd);
  238.     }
  239.  
  240.     // No Finder info file, translate file name extension to MacOS type/creator
  241.     int path_len = strlen(path);
  242.     for (int i=0; e2t_translation[i].ext; i++) {
  243.         int ext_len = strlen(e2t_translation[i].ext);
  244.         if (path_len < ext_len)
  245.             continue;
  246.         if (!strcmp(path + path_len - ext_len, e2t_translation[i].ext)) {
  247.             type = e2t_translation[i].type;
  248.             creator = e2t_translation[i].creator;
  249.             break;
  250.         }
  251.     }
  252. }
  253.  
  254. void set_finder_type(const char *path, uint32 type, uint32 creator)
  255. {
  256.     // Open Finder info file
  257.     int fd = open_finf(path, O_RDWR);
  258.     if (fd < 0)
  259.         return;
  260.  
  261.     // Read file
  262.     finf_struct finf;
  263.     finf.flags = DEFAULT_FINDER_FLAGS;
  264.     memset(&finf, 0, sizeof(finf_struct));
  265.     read(fd, &finf, sizeof(finf_struct));
  266.  
  267.     // Set Finder flags
  268.     finf.type = htonl(type);
  269.     finf.creator = htonl(creator);
  270.  
  271.     // Update file
  272.     lseek(fd, 0, SEEK_SET);
  273.     write(fd, &finf, sizeof(finf_struct));
  274.     close(fd);
  275. }
  276.  
  277.  
  278. /*
  279.  *  Get/set finder flags for file/dir specified by full path
  280.  */
  281.  
  282. void get_finder_flags(const char *path, uint16 &flags)
  283. {
  284.     flags = DEFAULT_FINDER_FLAGS;    // Default
  285.  
  286.     // Open Finder info file
  287.     int fd = open_finf(path, O_RDONLY);
  288.     if (fd < 0)
  289.         return;
  290.  
  291.     // Read Finder flags
  292.     finf_struct finf;
  293.     if (read(fd, &finf, sizeof(finf_struct)) >= 10)
  294.         flags = ntohs(finf.flags);
  295.  
  296.     // Close file
  297.     close(fd);
  298. }
  299.  
  300. void set_finder_flags(const char *path, uint16 flags)
  301. {
  302.     // Open Finder info file
  303.     int fd = open_finf(path, O_RDWR);
  304.     if (fd < 0)
  305.         return;
  306.  
  307.     // Read file
  308.     finf_struct finf;
  309.     memset(&finf, 0, sizeof(finf_struct));
  310.     finf.flags = DEFAULT_FINDER_FLAGS;
  311.     read(fd, &finf, sizeof(finf_struct));
  312.  
  313.     // Set Finder flags
  314.     finf.flags = htons(flags);
  315.  
  316.     // Update file
  317.     lseek(fd, 0, SEEK_SET);
  318.     write(fd, &finf, sizeof(finf_struct));
  319.     close(fd);
  320. }
  321.  
  322.  
  323. /*
  324.  *  Resource fork emulation functions
  325.  */
  326.  
  327. uint32 get_rfork_size(const char *path)
  328. {
  329.     // Open resource file
  330.     int fd = open_rsrc(path, O_RDONLY);
  331.     if (fd < 0)
  332.         return 0;
  333.  
  334.     // Get size
  335.     off_t size = lseek(fd, 0, SEEK_END);
  336.     
  337.     // Close file and return size
  338.     close(fd);
  339.     return size < 0 ? 0 : size;
  340. }
  341.  
  342. int open_rfork(const char *path, int flag)
  343. {
  344.     return open_rsrc(path, flag);
  345. }
  346.  
  347. void close_rfork(const char *path, int fd)
  348. {
  349.     close(fd);
  350. }
  351.  
  352.  
  353. /*
  354.  *  Read "length" bytes from file to "buffer",
  355.  *  returns number of bytes read (or -1 on error)
  356.  */
  357.  
  358. ssize_t extfs_read(int fd, void *buffer, size_t length)
  359. {
  360.     return read(fd, buffer, length);
  361. }
  362.  
  363.  
  364. /*
  365.  *  Write "length" bytes from "buffer" to file,
  366.  *  returns number of bytes written (or -1 on error)
  367.  */
  368.  
  369. ssize_t extfs_write(int fd, void *buffer, size_t length)
  370. {
  371.     return write(fd, buffer, length);
  372. }
  373.  
  374.  
  375. /*
  376.  *  Remove file/directory (and associated helper files),
  377.  *  returns false on error (and sets errno)
  378.  */
  379.  
  380. bool extfs_remove(const char *path)
  381. {
  382.     // Remove helpers first, don't complain if this fails
  383.     char helper_path[MAX_PATH_LENGTH];
  384.     make_helper_path(path, helper_path, ".finf/", false);
  385.     remove(helper_path);
  386.     make_helper_path(path, helper_path, ".rsrc/", false);
  387.     remove(helper_path);
  388.  
  389.     // Now remove file or directory (and helper directories in the directory)
  390.     if (remove(path) < 0) {
  391.         if (errno == EISDIR || errno == ENOTEMPTY) {
  392.             helper_path[0] = 0;
  393.             strncpy(helper_path, path, MAX_PATH_LENGTH-1);
  394.             add_path_component(helper_path, ".finf");
  395.             rmdir(helper_path);
  396.             helper_path[0] = 0;
  397.             strncpy(helper_path, path, MAX_PATH_LENGTH-1);
  398.             add_path_component(helper_path, ".rsrc");
  399.             rmdir(helper_path);
  400.             return rmdir(path) == 0;
  401.         } else
  402.             return false;
  403.     }
  404.     return true;
  405. }
  406.  
  407.  
  408. /*
  409.  *  Rename/move file/directory (and associated helper files),
  410.  *  returns false on error (and sets errno)
  411.  */
  412.  
  413. bool extfs_rename(const char *old_path, const char *new_path)
  414. {
  415.     // Rename helpers first, don't complain if this fails
  416.     char old_helper_path[MAX_PATH_LENGTH], new_helper_path[MAX_PATH_LENGTH];
  417.     make_helper_path(old_path, old_helper_path, ".finf/", false);
  418.     make_helper_path(new_path, new_helper_path, ".finf/", false);
  419.     create_helper_dir(new_path, ".finf/");
  420.     rename(old_helper_path, new_helper_path);
  421.     make_helper_path(old_path, old_helper_path, ".rsrc/", false);
  422.     make_helper_path(new_path, new_helper_path, ".rsrc/", false);
  423.     create_helper_dir(new_path, ".rsrc/");
  424.     rename(old_helper_path, new_helper_path);
  425.  
  426.     // Now rename file
  427.     return rename(old_path, new_path) == 0;
  428. }
  429.