home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 8 / FreshFishVol8-CD1.bin / useful / disk / cdrom / mkisofs / rock.c < prev    next >
C/C++ Source or Header  |  1994-05-29  |  8KB  |  336 lines

  1. /*
  2.  * File rock.c - generate RRIP  records for iso9660 filesystems.
  3.  
  4.    Written by Eric Youngdale (1993).
  5.  
  6.    Copyright 1993 Yggdrasil Computing, Incorporated
  7.  
  8.    This program is free software; you can redistribute it and/or modify
  9.    it under the terms of the GNU General Public License as published by
  10.    the Free Software Foundation; either version 2, or (at your option)
  11.    any later version.
  12.  
  13.    This program is distributed in the hope that it will be useful,
  14.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.    GNU General Public License for more details.
  17.  
  18.    You should have received a copy of the GNU General Public License
  19.    along with this program; if not, write to the Free Software
  20.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  21.  
  22. #include <stdlib.h>
  23.  
  24. #ifndef AMIGA
  25. #ifndef VMS
  26. #ifndef __QNX__
  27. #include <sys/sysmacros.h>
  28. #endif
  29. #include <unistd.h>
  30. #endif
  31. #endif
  32.  
  33. #include "mkisofs.h"
  34. #include "iso9660.h"
  35. #include <string.h>
  36.  
  37. #ifdef VMS
  38. #define S_ISLNK(m)    (0)
  39. #else
  40. #ifndef S_ISLNK
  41. #define S_ISLNK(m)    (((m) & S_IFMT) == S_IFLNK)
  42. #endif
  43. #endif
  44.  
  45. #define SU_VERSION 1
  46.  
  47. #define SL_ROOT    8
  48. #define SL_PARENT  4
  49. #define SL_CURRENT 2
  50. #define SL_CONTINUE 1
  51.  
  52. /*
  53.  * Buffer to build RR attributes
  54.  */
  55.  
  56. static unsigned char Rock[16384];
  57. static unsigned char symlink_buff[256];
  58.  
  59. #ifdef __STDC__
  60. int generate_rock_ridge_attributes (char * whole_name, char * name,
  61.                     struct directory_entry * s_entry,
  62.                     struct stat * statbuf,
  63.                     struct stat * lstatbuf,
  64.                     int deep_opt)
  65. #else
  66. int generate_rock_ridge_attributes (whole_name, name,
  67.                     s_entry,
  68.                     statbuf,
  69.                     lstatbuf,
  70.                     deep_opt)
  71. char * whole_name; char * name; struct directory_entry * s_entry;
  72. struct stat * statbuf, *lstatbuf;
  73. int deep_opt;
  74. #endif
  75. {
  76.   int ipnt = 0;
  77.   int flagpos, flagval;
  78.  
  79.   statbuf = statbuf;        /* this shuts up unreferenced compiler warnings */
  80.  
  81.   /* Identify that we are using the SUSP protocol */
  82.   if(deep_opt & NEED_SP){
  83.       Rock[ipnt++] ='S';
  84.       Rock[ipnt++] ='P';
  85.       Rock[ipnt++] = 7;
  86.       Rock[ipnt++] = SU_VERSION;
  87.       Rock[ipnt++] = 0xbe;
  88.       Rock[ipnt++] = 0xef;
  89.       Rock[ipnt++] = 0;
  90.   };
  91.  
  92.   /* First build the posix name field */
  93.   Rock[ipnt++] ='R';
  94.   Rock[ipnt++] ='R';
  95.   Rock[ipnt++] = 5;
  96.   Rock[ipnt++] = SU_VERSION;
  97.   flagpos = ipnt;
  98.   flagval = 0;
  99.   Rock[ipnt++] = 0;   /* We go back and fix this later */
  100.  
  101.   if(strcmp(name,".")  && strcmp(name,"..")){
  102.       /* First build the posix name field */
  103.       Rock[ipnt++] ='N';
  104.       Rock[ipnt++] ='M';
  105.       Rock[ipnt++] = 5 + strlen(name);
  106.       Rock[ipnt++] = SU_VERSION;
  107.       Rock[ipnt++] = 0;
  108.       flagval |= (1<<3);
  109.       strcpy((char *)&Rock[ipnt], name);
  110.       ipnt += strlen(name);
  111.   };
  112.  
  113.   /*
  114.    * Add the posix modes 
  115.    */
  116.   Rock[ipnt++] ='P';
  117.   Rock[ipnt++] ='X';
  118.   Rock[ipnt++] = 36;
  119.   Rock[ipnt++] = SU_VERSION;  
  120.   flagval |= (1<<0);
  121.   set_733((char*)Rock + ipnt, lstatbuf->st_mode);
  122.   ipnt += 8;
  123.   set_733((char*)Rock + ipnt, lstatbuf->st_nlink);
  124.   ipnt += 8;
  125.   set_733((char*)Rock + ipnt, lstatbuf->st_uid);
  126.   ipnt += 8;
  127.   set_733((char*)Rock + ipnt, lstatbuf->st_gid);
  128.   ipnt += 8;
  129.  
  130. #ifndef AMIGA
  131.  
  132.   /*
  133.    * Check for special devices
  134.    */
  135.   if (S_ISCHR(lstatbuf->st_mode) || S_ISBLK(lstatbuf->st_mode)) {
  136.     Rock[ipnt++] ='P';
  137.     Rock[ipnt++] ='N';
  138.     Rock[ipnt++] = 20;
  139.     Rock[ipnt++] = SU_VERSION;  
  140.     flagval |= (1<<1);
  141.     set_733((char*)Rock + ipnt, major(lstatbuf->st_rdev));
  142.     ipnt += 8;
  143.     set_733((char*)Rock + ipnt, minor(lstatbuf->st_rdev));
  144.     ipnt += 8;
  145.   };
  146.  
  147.   /*
  148.    * Check for and symbolic links.  VMS does not have these.
  149.    */
  150.   if (S_ISLNK(lstatbuf->st_mode)){
  151.     int lenpos, lenval, j0;
  152.     int cflag, nchar;
  153.     unsigned char * cpnt, *cpnt1;
  154.     nchar = readlink(whole_name, symlink_buff, sizeof(symlink_buff));
  155.     symlink_buff[nchar] = 0;
  156.     set_733(s_entry->isorec.size, 0);
  157.     Rock[ipnt++] ='S';
  158.     Rock[ipnt++] ='L';
  159.     lenpos = ipnt;
  160.     Rock[ipnt++] = 20;
  161.     Rock[ipnt++] = SU_VERSION;  
  162.     Rock[ipnt++] = 0;
  163.     flagval |= (1<<2);
  164.     lenval = 5;
  165.     cpnt = &symlink_buff[0];
  166.     while(*cpnt){
  167.       cpnt1 = (unsigned char *) strchr((char *) cpnt, '/');
  168.       cflag = 0;
  169.       if(cpnt1) {
  170.     *cpnt1 = 0;
  171.       };
  172.  
  173.       /* We treat certain components in a special way.  */
  174.       if(cpnt[0] == '.' && cpnt[1] == '.' && cpnt[2] == 0){
  175.     Rock[ipnt++] = SL_PARENT | cflag;
  176.     Rock[ipnt++] = 0;  /* length is zero */
  177.     lenval += 2;
  178.       } else if(cpnt[0] == '.' && cpnt[1] == 0){
  179.     Rock[ipnt++] = SL_CURRENT | cflag;
  180.     Rock[ipnt++] = 0;  /* length is zero */
  181.     lenval += 2;
  182.       } else if(cpnt[0] == 0){
  183.     Rock[ipnt++] = SL_ROOT | cflag;
  184.     Rock[ipnt++] = 0;  /* length is zero */
  185.     lenval += 2;
  186.       } else {
  187.     Rock[ipnt++] = cflag;
  188.     j0 = strlen((char *) cpnt);
  189.     Rock[ipnt++] = j0;
  190.     strcpy((char *) Rock + ipnt, (char *) cpnt);
  191.     ipnt += j0;
  192.     lenval += j0 + 2;
  193.       };
  194.       if(cpnt1)
  195.     cpnt = cpnt1 + 1;
  196.       else
  197.     break;
  198.     };
  199.     Rock[lenpos] = lenval;
  200.   };
  201.  
  202. #endif
  203.  
  204.   /* 
  205.    * Add in the Rock Ridge TF time field
  206.    */
  207.   Rock[ipnt++] ='T';
  208.   Rock[ipnt++] ='F';
  209. #ifdef __QNX__
  210.   Rock[ipnt++] = 5 + 4 * 7;
  211.   Rock[ipnt++] = SU_VERSION;
  212.   Rock[ipnt++] = 0x0f;
  213. #else
  214.   Rock[ipnt++] = 5 + 3 * 7;
  215.   Rock[ipnt++] = SU_VERSION;
  216.   Rock[ipnt++] = 0x0e;
  217. #endif
  218.   flagval |= (1<<7);
  219. #ifdef __QNX__
  220.   iso9660_date((char *) &Rock[ipnt], lstatbuf->st_ftime);
  221.   ipnt += 7;
  222. #endif
  223.   iso9660_date((char *) &Rock[ipnt], lstatbuf->st_mtime);
  224.   ipnt += 7;
  225.   iso9660_date((char *) &Rock[ipnt], lstatbuf->st_atime);
  226.   ipnt += 7;
  227.   iso9660_date((char *) &Rock[ipnt], lstatbuf->st_ctime);
  228.   ipnt += 7;
  229.  
  230.   /* 
  231.    * Add in the Rock Ridge RE time field
  232.    */
  233.   if(deep_opt & NEED_RE){
  234.       Rock[ipnt++] ='R';
  235.       Rock[ipnt++] ='E';
  236.       Rock[ipnt++] = 4;
  237.       Rock[ipnt++] = SU_VERSION;
  238.       flagval |= (1<<6);
  239.   };
  240.   /* 
  241.    * Add in the Rock Ridge PL record, if required.
  242.    */
  243.   if(deep_opt & NEED_PL){
  244.       Rock[ipnt++] ='P';
  245.       Rock[ipnt++] ='L';
  246.       Rock[ipnt++] = 12;
  247.       Rock[ipnt++] = SU_VERSION;
  248.       set_733((char*)Rock + ipnt, 0);
  249.       ipnt += 8;
  250.       flagval |= (1<<5);
  251.   };
  252.  
  253.   /* 
  254.    * Add in the Rock Ridge CL field, if required.
  255.    */
  256.   if(deep_opt & NEED_CL){
  257.       Rock[ipnt++] ='C';
  258.       Rock[ipnt++] ='L';
  259.       Rock[ipnt++] = 12;
  260.       Rock[ipnt++] = SU_VERSION;
  261.       set_733((char*)Rock + ipnt, 0);
  262.       ipnt += 8;
  263.       flagval |= (1<<4);
  264.   };
  265.  
  266.   /* 
  267.    * Add in the Rock Ridge CE field, if required.  We use  this for the
  268.    * extension record that is stored in the root directory.
  269.    */
  270.   if(deep_opt & NEED_CE){
  271.       Rock[ipnt++] ='C';
  272.       Rock[ipnt++] ='E';
  273.       Rock[ipnt++] = 28;
  274.       Rock[ipnt++] = SU_VERSION;
  275.       set_733((char*)Rock + ipnt, 0);
  276.       ipnt += 8;
  277.       set_733((char*)Rock + ipnt, 0);
  278.       ipnt += 8;
  279.       set_733((char*)Rock + ipnt, 0);
  280.       ipnt += 8;
  281.   };
  282.  
  283.   /*
  284.    * Done filling in all of the fields.  Now copy it back to a buffer for the
  285.    * file in question.
  286.    */
  287.  
  288.   /* Now copy this back to the buffer for the file */
  289.   Rock[flagpos] = flagval;
  290.  
  291.   s_entry->rr_attributes = (char *) malloc(ipnt);
  292.   s_entry->rr_attr_size = ipnt;
  293.   memcpy(s_entry->rr_attributes, Rock, ipnt);
  294.   return ipnt;
  295. }
  296.  
  297. /* Guaranteed to  return a single sector with the relevant info */
  298.  
  299. char * FDECL4(generate_rr_extension_record, char *, id,  char  *, descriptor,
  300.                     char *, source, int  *, size){
  301.   int ipnt = 0;
  302.   char * pnt;
  303.   int len_id, len_des, len_src;
  304.  
  305.   len_id = strlen(id);
  306.   len_des =  strlen(descriptor);
  307.   len_src = strlen(source);
  308.   Rock[ipnt++] ='E';
  309.   Rock[ipnt++] ='R';
  310.   Rock[ipnt++] = 8 + len_id + len_des + len_src;
  311.   Rock[ipnt++] = 1;
  312.   Rock[ipnt++] = len_id;
  313.   Rock[ipnt++] = len_des;
  314.   Rock[ipnt++] = len_src;
  315.   Rock[ipnt++] = 1;
  316.  
  317.   memcpy(Rock  + ipnt, id, len_id);
  318.   ipnt += len_id;
  319.  
  320.   memcpy(Rock  + ipnt, descriptor, len_des);
  321.   ipnt += len_des;
  322.  
  323.   memcpy(Rock  + ipnt, source, len_src);
  324.   ipnt += len_src;
  325.  
  326.   if(ipnt  > SECTOR_SIZE) {
  327.       fprintf(stderr,"Extension record too  long\n");
  328.       exit(1);
  329.   };
  330.   pnt = (char *) malloc(SECTOR_SIZE);
  331.   memset(pnt, 0,  SECTOR_SIZE);
  332.   memcpy(pnt, Rock, ipnt);
  333.   *size = ipnt;
  334.   return pnt;
  335. }
  336.