home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 18 / amigaformatcd18.iso / -in_the_mag- / emulation / emus / handlers / amicdfilesystem / src / rock.c < prev    next >
C/C++ Source or Header  |  1997-07-31  |  9KB  |  330 lines

  1. /* rock.c:
  2.  *
  3.  * Support for the Rock Ridge filing system.
  4.  *
  5.  * Modified by Nicola Salmoria.
  6.  *
  7.  * ----------------------------------------------------------------------
  8.  * This code is (C) Copyright 1993,1994 by Frank Munkert.
  9.  * All rights reserved.
  10.  * This software may be freely distributed and redistributed for
  11.  * non-commercial purposes, provided this notice is included.
  12.  * ----------------------------------------------------------------------
  13.  * [History removed]
  14.  */
  15.  
  16. #include <stdlib.h>
  17. #include <string.h>
  18.  
  19. #include <exec/memory.h>
  20. #include <proto/exec.h>
  21.  
  22. #include "rock.h"
  23.  
  24. #define VOL(vol,tag) (((t_iso_vol_info *)(vol->vol_info))->tag)
  25. #define OBJ(obj,tag) (((t_iso_obj_info *)(obj->obj_info))->tag)
  26.  
  27. /* Check whether the given volume uses the Rock Ridge Interchange Protocol.
  28.  * The protocol is identified by the sequence
  29.  *            'S' 'P' 7 1 0xbe 0xef
  30.  * in the system use field of the (00) directory in the root directory of
  31.  * the volume.
  32.  *
  33.  * Returns 1 iff the RR protocol is used; 0 otherwise.
  34.  * If the RR protocol is used, *p_skip will be set to the skip length
  35.  * specified in the SP system use field.
  36.  */
  37.  
  38. t_bool Uses_Rock_Ridge_Protocol (VOLUME *p_volume, int *p_skip)
  39. {
  40.   unsigned long loc = VOL(p_volume,pvd).root.extent_loc_m;
  41.   unsigned char buffer[256];
  42.   directory_record *dir = (directory_record *)buffer;
  43.   int system_use_pos;
  44.   unsigned char *sys;
  45.  
  46.   if (!Get_Directory_Record (p_volume, dir, loc, 0))
  47.     return 0;
  48.  
  49.   system_use_pos = 33 + dir->file_id_length;
  50.   if (system_use_pos & 1)
  51.     system_use_pos++;
  52.  
  53.   if (system_use_pos >= dir->length)
  54.     return 0;
  55.  
  56.   sys = (unsigned char *) dir + system_use_pos;
  57.   if (sys[0] == 'S' && sys[1] == 'P' && sys[2] == 7 &&
  58.       sys[3] == 1 && sys[4] == 0xbe && sys[5] == 0xef) {
  59.     *p_skip = sys[6];
  60.     return 1;
  61.   } else
  62.     return 0;
  63. }
  64.  
  65. /* Searches for the system use field with name p_name in the directory record
  66.  * p_dir and fills the buffer p_buf (with length p_buf_len) with the information
  67.  * contained in the system use field.
  68.  *
  69.  * p_index is the ordinal number of the system use field (if more than one
  70.  * system use field with the same name is recorded.) 0=first occurrence,
  71.  * 1=second occurrence, and so on.
  72.  *
  73.  * 1 is returned if the system use field has been found; otherwise 0
  74.  * is returned.
  75.  */
  76.  
  77. int Get_System_Use_Field (VOLUME *p_volume, directory_record *p_dir,
  78.               char *p_name, char *p_buf, int p_buf_len,
  79.               int p_index)
  80. {
  81.   int system_use_pos;
  82.   int slen, len;
  83.   unsigned long length = p_dir->length;
  84.   unsigned char *buf = (unsigned char *) p_dir;
  85.  
  86.   system_use_pos = 33 + p_dir->file_id_length;
  87.   if (system_use_pos & 1)
  88.     system_use_pos++;
  89.   system_use_pos += VOL(p_volume,skip);
  90.  
  91.   /* the system use field must be at least 4 bytes long */
  92.   while (system_use_pos + 3 < length) {
  93.     slen = buf[system_use_pos+2];
  94.     if (buf[system_use_pos] == p_name[0] &&
  95.         buf[system_use_pos+1] == p_name[1]) {
  96.       if (p_index)
  97.         p_index--;
  98.       else {
  99.         len = (slen < p_buf_len) ? slen : p_buf_len;
  100.         memcpy (p_buf, buf + system_use_pos, len);
  101.         return 1;
  102.       }
  103.     }
  104.     /* look for continuation area: */
  105.     if (buf[system_use_pos] == 'C' &&
  106.         buf[system_use_pos+1] == 'E') {
  107.       unsigned long newloc, offset;
  108.       memcpy (&newloc, buf + system_use_pos + 8, 4);
  109.       memcpy (&offset, buf + system_use_pos + 16, 4);
  110.       memcpy (&length, buf + system_use_pos + 24, 4);
  111.       if (!Read_Sector (p_volume->cd, newloc))
  112.         return 0;
  113.       buf = p_volume->cd->buffer;
  114.       system_use_pos = offset;
  115.       continue;
  116.     }
  117.  
  118.     /* look for system use field terminator: */
  119.     if (buf[system_use_pos] == 'S' &&
  120.         buf[system_use_pos+1] == 'T')
  121.       return 0;
  122.  
  123.     system_use_pos += slen;
  124.   }
  125.   return 0;
  126. }
  127.  
  128. /* Determines the Rock Ridge file name of the CDROM object p_obj.
  129.  * The file name will be stored in the buffer p_buf (with length p_buf_len).
  130.  * The file name will NOT be null-terminated. The number of characters in
  131.  * the file name is returned. If there is no Rock Ridge file name for
  132.  * p_obj, then -1 is returned.
  133.  */
  134.  
  135. int Get_RR_File_Name (VOLUME *p_volume, directory_record *p_dir,
  136.               char *p_buf, int p_buf_len)
  137. {
  138.   struct nm_system_use_field {
  139.     char      id[2];
  140.     unsigned char length;
  141.     unsigned char version;
  142.     unsigned char flags;
  143.     char          name[210];
  144.   } nm;
  145.   int len, slen;
  146.   int index = 0;
  147.   int total = 0;
  148.  
  149.   for (;;) {
  150.     if (!Get_System_Use_Field (p_volume, p_dir, "NM",
  151.                      (char *) &nm, sizeof (nm), index))
  152.       return -1;
  153.  
  154.     slen = nm.length-5;
  155.     len = (p_buf_len < slen) ? p_buf_len : slen;
  156.     if (len)
  157.       memcpy (p_buf, nm.name, len);
  158.  
  159.     total += len;
  160.     if (!(nm.flags & 1))
  161.       return total;
  162.  
  163.     p_buf += len;
  164.     p_buf_len -= len;
  165.     index++;
  166.   }
  167. }
  168.  
  169. /* Returns 1 if the PX system use field indicates a symbolic link.
  170.  */
  171.  
  172. int Is_A_Symbolic_Link (VOLUME *p_volume, directory_record *p_dir)
  173. {
  174.   struct px_system_use_field {
  175.     char      id[2];
  176.     unsigned char length;
  177.     unsigned char version;
  178.     unsigned long mode_i;
  179.     unsigned long mode_m;
  180.     unsigned long links_i;
  181.     unsigned long links_m;
  182.     unsigned long user_id_i;
  183.     unsigned long user_id_m;
  184.     unsigned long group_id_i;
  185.     unsigned long group_id_m;
  186.   } px;
  187.  
  188.   if (!Get_System_Use_Field (p_volume, p_dir, "PX", (char *) &px, sizeof (px), 0))
  189.     return 0;
  190.  
  191.   /* 0120000 is the POSIX code for symbolic links:
  192.    */
  193.   return (px.mode_m & 0770000) == 0120000;
  194. }
  195.  
  196. /* Read content of SL system use field.
  197.  * A full path name (starting with ":" or "sys:") will always be returned.
  198.  */
  199.  
  200. t_bool Get_Link_Name (VOLUME *p_volume,CDROM_OBJ *p_obj, char *p_buf, int p_buf_len)
  201. {
  202.   unsigned char buf[256];
  203.   char out[530];
  204.   int index = 0;
  205.   int len;
  206.   int offs;
  207.   char c;
  208.  
  209.   out[0] = 0;
  210.   for (;; ) {
  211.     if (!Get_System_Use_Field (p_volume, OBJ(p_obj,dir), "SL", (char *) buf,
  212.                      sizeof (buf), index)) {
  213.       return (index == 0) ? 0 : 1;
  214.     }
  215.  
  216.     offs = 5;
  217.     for (;;) {
  218.  
  219.       if (strlen (out) > 256)
  220.         return 0;
  221.  
  222.       if (index == 0 && offs == 5) {
  223.         /* handle the first component record: */
  224.  
  225.         if (buf[5] & 4) /* parent directory */ {
  226.           CDROM_OBJ *parent1 = Find_Parent (p_volume,p_obj);
  227.       CDROM_OBJ *parent2;
  228.       char fullpath[256];
  229.       if (!parent1)
  230.         return 0;
  231.           parent2 = Find_Parent (p_volume,parent1);
  232.       if (!parent2)
  233.         return 0;
  234.       if (!Full_Path_Name (p_volume,parent2, fullpath, sizeof (fullpath)))
  235.         return 0;
  236.       Close_Object (parent1);
  237.       Close_Object (parent2);
  238.       strcat (out, fullpath);
  239.       if (out[1] != 0)
  240.         strcat (out, "/");
  241.         } else if (buf[5] & 8) /* root */
  242.           strcat (out, "sys:");
  243.         else if (buf[5] & 16) /* volume root */
  244.           strcat (out, ":");
  245.         else { /* current directory */
  246.           CDROM_OBJ *parent = Find_Parent (p_volume,p_obj);
  247.       char fullpath[256];
  248.       if (!parent)
  249.         return 0;
  250.       if (!Full_Path_Name (p_volume,parent, fullpath, sizeof (fullpath)))
  251.         return 0;
  252.       Close_Object (parent);
  253.       strcat (out, fullpath);
  254.       if (out[1] != 0)
  255.         strcat (out, "/");
  256.         }
  257.       }
  258.  
  259.       if (out[0] && (c = out[strlen(out)-1]) != ':' && c != '/')
  260.         strcat (out, "/");
  261.  
  262.       if (buf[offs] & 32) /* host name */
  263.         strcat (out, "AMIGA");
  264.  
  265.       len = strlen (out);
  266.       memcpy (out + len, buf + offs + 2, buf[offs+1]);
  267.       out[len + buf[offs+1]] = 0;
  268.  
  269.       offs += 2 + buf[offs+1];
  270.       if (offs >= buf[2])
  271.         break;
  272.     }
  273.     if (!(buf[4] & 1)) /* continue flag */
  274.       break;
  275.     index++;
  276.   }
  277.  
  278.   strncpy (p_buf, out, p_buf_len - 1);
  279.   p_buf[p_buf_len-1] = 0;
  280.   return 1;
  281. }
  282.  
  283. /* Check whether a system use field is present: */
  284.  
  285. int Has_System_Use_Field (VOLUME *p_volume, directory_record *p_dir,
  286.               char *p_name)
  287. {
  288.   return Get_System_Use_Field (p_volume, p_dir, p_name, NULL, 0, 0);
  289. }
  290.  
  291. /* Return content of "CL" system use field, or -1, if no such system use field
  292.  * is present.
  293.  */
  294.  
  295. long RR_Child_Link (VOLUME *p_volume, directory_record *p_dir)
  296. {
  297.   struct cl {
  298.     char        name[2];
  299.     char        length[1];
  300.     char        version[1];
  301.     long    pos_i;
  302.     long    pos_m;
  303.   } buf;
  304.   if (!Get_System_Use_Field (p_volume, p_dir, "CL", (char*) &buf, sizeof (buf), 0))
  305.     return -1;
  306.   else
  307.     return buf.pos_m;
  308. }
  309.  
  310. /* Return content of "PL" system use field, or -1, if no such system use field
  311.  * is present.
  312.  */
  313.  
  314. long RR_Parent_Link (VOLUME *p_volume, directory_record *p_dir)
  315. {
  316.   struct pl {
  317.     char        name[2];
  318.     char        length[1];
  319.     char        version[1];
  320.     long    pos_i;
  321.     long    pos_m;
  322.   } buf;
  323.   if (!Get_System_Use_Field (p_volume, p_dir, "PL", (char*) &buf, sizeof (buf), 0))
  324.     return -1;
  325.   else
  326.     return buf.pos_m;
  327. }
  328.  
  329.  
  330.