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

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