Home | History | Annotate | Line # | Download | only in dist
      1  1.1  tsutsui /*
      2  1.1  tsutsui  * File rock.c - generate RRIP  records for iso9660 filesystems.
      3  1.1  tsutsui 
      4  1.1  tsutsui    Written by Eric Youngdale (1993).
      5  1.1  tsutsui 
      6  1.1  tsutsui    Copyright 1993 Yggdrasil Computing, Incorporated
      7  1.1  tsutsui 
      8  1.1  tsutsui    This program is free software; you can redistribute it and/or modify
      9  1.1  tsutsui    it under the terms of the GNU General Public License as published by
     10  1.1  tsutsui    the Free Software Foundation; either version 2, or (at your option)
     11  1.1  tsutsui    any later version.
     12  1.1  tsutsui 
     13  1.1  tsutsui    This program is distributed in the hope that it will be useful,
     14  1.1  tsutsui    but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  1.1  tsutsui    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16  1.1  tsutsui    GNU General Public License for more details.
     17  1.1  tsutsui 
     18  1.1  tsutsui    You should have received a copy of the GNU General Public License
     19  1.1  tsutsui    along with this program; if not, write to the Free Software
     20  1.1  tsutsui    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
     21  1.1  tsutsui 
     22  1.1  tsutsui #include <stdlib.h>
     23  1.1  tsutsui 
     24  1.1  tsutsui #include "config.h"
     25  1.1  tsutsui 
     26  1.1  tsutsui #ifndef VMS
     27  1.1  tsutsui #if defined(MAJOR_IN_SYSMACROS)
     28  1.1  tsutsui #include <sys/sysmacros.h>
     29  1.1  tsutsui #endif
     30  1.1  tsutsui 
     31  1.1  tsutsui #ifdef HAVE_UNISTD_H
     32  1.1  tsutsui #include <unistd.h>
     33  1.1  tsutsui #endif
     34  1.1  tsutsui 
     35  1.1  tsutsui #endif
     36  1.1  tsutsui #if defined(MAJOR_IN_MKDEV)
     37  1.1  tsutsui #include <sys/types.h>
     38  1.1  tsutsui #include <sys/mkdev.h>
     39  1.1  tsutsui #endif
     40  1.1  tsutsui 
     41  1.1  tsutsui #include "mkisofs.h"
     42  1.1  tsutsui #include "iso9660.h"
     43  1.1  tsutsui #include <string.h>
     44  1.1  tsutsui 
     45  1.1  tsutsui #ifdef	DOESNT_WORK
     46  1.1  tsutsui 
     47  1.1  tsutsui #ifdef NON_UNIXFS
     48  1.1  tsutsui #define S_ISLNK(m)	(0)
     49  1.1  tsutsui #else
     50  1.1  tsutsui #ifndef S_ISLNK
     51  1.1  tsutsui #define S_ISLNK(m)	(((m) & S_IFMT) == S_IFLNK)
     52  1.1  tsutsui #endif
     53  1.1  tsutsui #endif
     54  1.1  tsutsui 
     55  1.1  tsutsui #else
     56  1.1  tsutsui #include <statdefs.h>
     57  1.1  tsutsui #endif
     58  1.1  tsutsui 
     59  1.1  tsutsui #define SU_VERSION 1
     60  1.1  tsutsui 
     61  1.1  tsutsui #define SL_ROOT    8
     62  1.1  tsutsui #define SL_PARENT  4
     63  1.1  tsutsui #define SL_CURRENT 2
     64  1.1  tsutsui #define SL_CONTINUE 1
     65  1.1  tsutsui 
     66  1.1  tsutsui #define CE_SIZE 28
     67  1.1  tsutsui #define CL_SIZE 12
     68  1.1  tsutsui #define ER_SIZE 8
     69  1.1  tsutsui #define NM_SIZE 5
     70  1.1  tsutsui #define PL_SIZE 12
     71  1.1  tsutsui #define PN_SIZE 20
     72  1.1  tsutsui #define PX_SIZE 36
     73  1.1  tsutsui #define RE_SIZE 4
     74  1.1  tsutsui #define SL_SIZE 20
     75  1.1  tsutsui #define ZZ_SIZE 15
     76  1.1  tsutsui #ifdef APPLE_HYB
     77  1.1  tsutsui #define AA_SIZE 14		/* size of Apple extension */
     78  1.1  tsutsui #endif /* APPLE_HYB */
     79  1.1  tsutsui #ifdef __QNX__
     80  1.1  tsutsui #define TF_SIZE (5 + 4 * 7)
     81  1.1  tsutsui #else
     82  1.1  tsutsui #define TF_SIZE (5 + 3 * 7)
     83  1.1  tsutsui #endif
     84  1.1  tsutsui 
     85  1.1  tsutsui /* If we need to store this number of bytes, make sure we
     86  1.1  tsutsui    do not box ourselves in so that we do not have room for
     87  1.1  tsutsui    a CE entry for the continuation record */
     88  1.1  tsutsui 
     89  1.1  tsutsui #define MAYBE_ADD_CE_ENTRY(BYTES) \
     90  1.1  tsutsui     (BYTES + CE_SIZE + currlen + (ipnt - recstart) > reclimit ? 1 : 0)
     91  1.1  tsutsui 
     92  1.1  tsutsui /*
     93  1.1  tsutsui  * Buffer to build RR attributes
     94  1.1  tsutsui  */
     95  1.1  tsutsui 
     96  1.1  tsutsui static unsigned char Rock[16384];
     97  1.1  tsutsui static unsigned char symlink_buff[256];
     98  1.1  tsutsui static int ipnt = 0;
     99  1.1  tsutsui static int recstart = 0;
    100  1.1  tsutsui static int currlen = 0;
    101  1.1  tsutsui static int mainrec = 0;
    102  1.1  tsutsui static int reclimit;
    103  1.1  tsutsui 
    104  1.1  tsutsui #ifdef APPLE_HYB
    105  1.1  tsutsui /* if we are using the HFS name, we don't want the '/' character */
    106  1.1  tsutsui static void
    107  1.1  tsutsui rstrncpy(char *t, char *f, int c)
    108  1.1  tsutsui {
    109  1.1  tsutsui 	while (c-- && *f) {
    110  1.1  tsutsui 	    switch (*f) {
    111  1.1  tsutsui 		case '/':
    112  1.1  tsutsui 		    *t = '_';
    113  1.1  tsutsui 		    break;
    114  1.1  tsutsui 		default:
    115  1.1  tsutsui 		    *t = *f;
    116  1.1  tsutsui 		    break;
    117  1.1  tsutsui 	    }
    118  1.1  tsutsui 	    t++; f++;
    119  1.1  tsutsui 	}
    120  1.1  tsutsui }
    121  1.1  tsutsui #endif /* APPLE HYB */
    122  1.1  tsutsui 
    123  1.1  tsutsui static void add_CE_entry	__PR((void));
    124  1.1  tsutsui 
    125  1.1  tsutsui static void add_CE_entry(){
    126  1.1  tsutsui           if(recstart)
    127  1.1  tsutsui 	    set_733((char*)Rock + recstart - 8, ipnt + 28 - recstart);
    128  1.1  tsutsui 	  Rock[ipnt++] ='C';
    129  1.1  tsutsui 	  Rock[ipnt++] ='E';
    130  1.1  tsutsui 	  Rock[ipnt++] = CE_SIZE;
    131  1.1  tsutsui 	  Rock[ipnt++] = SU_VERSION;
    132  1.1  tsutsui 	  set_733((char*)Rock + ipnt, 0);
    133  1.1  tsutsui 	  ipnt += 8;
    134  1.1  tsutsui 	  set_733((char*)Rock + ipnt, 0);
    135  1.1  tsutsui 	  ipnt += 8;
    136  1.1  tsutsui 	  set_733((char*)Rock + ipnt, 0);
    137  1.1  tsutsui 	  ipnt += 8;
    138  1.1  tsutsui 	  recstart = ipnt;
    139  1.1  tsutsui 	  currlen = 0;
    140  1.1  tsutsui 	  if(!mainrec) mainrec = ipnt;
    141  1.1  tsutsui 	  reclimit = SECTOR_SIZE - 8; /* Limit to one sector */
    142  1.1  tsutsui }
    143  1.1  tsutsui 
    144  1.1  tsutsui #ifdef __STDC__
    145  1.1  tsutsui int generate_rock_ridge_attributes (char * whole_name, char * name,
    146  1.1  tsutsui 				    struct directory_entry * s_entry,
    147  1.1  tsutsui 				    struct stat * statbuf,
    148  1.1  tsutsui 				    struct stat * lstatbuf,
    149  1.1  tsutsui 				    int deep_opt)
    150  1.1  tsutsui #else
    151  1.1  tsutsui int generate_rock_ridge_attributes (whole_name, name,
    152  1.1  tsutsui 				    s_entry,
    153  1.1  tsutsui 				    statbuf,
    154  1.1  tsutsui 				    lstatbuf,
    155  1.1  tsutsui 				    deep_opt)
    156  1.1  tsutsui char * whole_name; char * name; struct directory_entry * s_entry;
    157  1.1  tsutsui struct stat * statbuf, *lstatbuf;
    158  1.1  tsutsui int deep_opt;
    159  1.1  tsutsui #endif
    160  1.1  tsutsui {
    161  1.1  tsutsui   int flagpos, flagval;
    162  1.1  tsutsui   int need_ce;
    163  1.1  tsutsui 
    164  1.1  tsutsui   statbuf = statbuf;        /* this shuts up unreferenced compiler warnings */
    165  1.1  tsutsui   mainrec = recstart = ipnt = 0;
    166  1.1  tsutsui   reclimit = 0xf8;
    167  1.1  tsutsui 
    168  1.1  tsutsui   /* no need to fill in the RR stuff if we won't see the file */
    169  1.1  tsutsui   if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY)
    170  1.1  tsutsui     return 0;
    171  1.1  tsutsui 
    172  1.1  tsutsui   /* Obtain the amount of space that is currently used for the directory
    173  1.1  tsutsui      record.  Assume max for name, since name conflicts may cause us
    174  1.1  tsutsui      to rename the file later on */
    175  1.1  tsutsui   currlen = sizeof(s_entry->isorec);
    176  1.1  tsutsui 
    177  1.1  tsutsui #ifdef APPLE_HYB
    178  1.1  tsutsui   /* if we have regular file, then add Apple extensions */
    179  1.1  tsutsui   if (S_ISREG(lstatbuf->st_mode) && apple_ext && s_entry->hfs_ent) {
    180  1.1  tsutsui     Rock[ipnt++] ='A';		/* AppleSignature */
    181  1.1  tsutsui     Rock[ipnt++] ='A';
    182  1.1  tsutsui     Rock[ipnt++] = AA_SIZE;	/* includes AppleSignature bytes */
    183  1.1  tsutsui     Rock[ipnt++] = 0x02;	/* SystemUseID */
    184  1.1  tsutsui     Rock[ipnt++] = s_entry->hfs_ent->type[0];
    185  1.1  tsutsui     Rock[ipnt++] = s_entry->hfs_ent->type[1];
    186  1.1  tsutsui     Rock[ipnt++] = s_entry->hfs_ent->type[2];
    187  1.1  tsutsui     Rock[ipnt++] = s_entry->hfs_ent->type[3];
    188  1.1  tsutsui     Rock[ipnt++] = s_entry->hfs_ent->creator[0];
    189  1.1  tsutsui     Rock[ipnt++] = s_entry->hfs_ent->creator[1];
    190  1.1  tsutsui     Rock[ipnt++] = s_entry->hfs_ent->creator[2];
    191  1.1  tsutsui     Rock[ipnt++] = s_entry->hfs_ent->creator[3];
    192  1.1  tsutsui     Rock[ipnt++] = (s_entry->hfs_ent->fdflags >> 8) & 0xff;
    193  1.1  tsutsui     Rock[ipnt++] = s_entry->hfs_ent->fdflags & 0xff;
    194  1.1  tsutsui   }
    195  1.1  tsutsui #endif /* APPLE_HYB */
    196  1.1  tsutsui 
    197  1.1  tsutsui   /* Identify that we are using the SUSP protocol */
    198  1.1  tsutsui   if(deep_opt & NEED_SP){
    199  1.1  tsutsui 	  Rock[ipnt++] ='S';
    200  1.1  tsutsui 	  Rock[ipnt++] ='P';
    201  1.1  tsutsui 	  Rock[ipnt++] = 7;
    202  1.1  tsutsui 	  Rock[ipnt++] = SU_VERSION;
    203  1.1  tsutsui 	  Rock[ipnt++] = 0xbe;
    204  1.1  tsutsui 	  Rock[ipnt++] = 0xef;
    205  1.1  tsutsui 	  Rock[ipnt++] = 0;
    206  1.1  tsutsui   };
    207  1.1  tsutsui 
    208  1.1  tsutsui   /* First build the posix name field */
    209  1.1  tsutsui   Rock[ipnt++] ='R';
    210  1.1  tsutsui   Rock[ipnt++] ='R';
    211  1.1  tsutsui   Rock[ipnt++] = 5;
    212  1.1  tsutsui   Rock[ipnt++] = SU_VERSION;
    213  1.1  tsutsui   flagpos = ipnt;
    214  1.1  tsutsui   flagval = 0;
    215  1.1  tsutsui   Rock[ipnt++] = 0;   /* We go back and fix this later */
    216  1.1  tsutsui 
    217  1.1  tsutsui   if(strcmp(name,".")  && strcmp(name,"..")){
    218  1.1  tsutsui     char * npnt;
    219  1.1  tsutsui     int remain, use;
    220  1.1  tsutsui 
    221  1.1  tsutsui #ifdef APPLE_HYB
    222  1.1  tsutsui     /* use the HFS name if it exists */
    223  1.1  tsutsui     if (USE_MAC_NAME(mac_name, s_entry)) {
    224  1.1  tsutsui 	remain = strlen(s_entry->hfs_ent->name);
    225  1.1  tsutsui 	npnt = s_entry->hfs_ent->name;
    226  1.1  tsutsui     }
    227  1.1  tsutsui     else {
    228  1.1  tsutsui #endif
    229  1.1  tsutsui 
    230  1.1  tsutsui 	remain = strlen(name);
    231  1.1  tsutsui 	npnt = name;
    232  1.1  tsutsui #ifdef APPLE_HYB
    233  1.1  tsutsui     }
    234  1.1  tsutsui #endif /* APPLE_HYB */
    235  1.1  tsutsui 
    236  1.1  tsutsui     while(remain){
    237  1.1  tsutsui           use = remain;
    238  1.1  tsutsui 	  need_ce = 0;
    239  1.1  tsutsui 	  /* Can we fit this SUSP and a CE entry? */
    240  1.1  tsutsui 	  if(use + currlen + CE_SIZE + (ipnt - recstart) > reclimit) {
    241  1.1  tsutsui 	    use = reclimit - currlen - CE_SIZE - (ipnt - recstart);
    242  1.1  tsutsui 	    need_ce++;
    243  1.1  tsutsui 	  }
    244  1.1  tsutsui 
    245  1.1  tsutsui 	  /* Only room for 256 per SUSP field */
    246  1.1  tsutsui 	  if(use > 0xf8) use = 0xf8;
    247  1.1  tsutsui 
    248  1.1  tsutsui 	  /* First build the posix name field */
    249  1.1  tsutsui 	  Rock[ipnt++] ='N';
    250  1.1  tsutsui 	  Rock[ipnt++] ='M';
    251  1.1  tsutsui 	  Rock[ipnt++] = NM_SIZE + use;
    252  1.1  tsutsui 	  Rock[ipnt++] = SU_VERSION;
    253  1.1  tsutsui 	  Rock[ipnt++] = (remain != use ? 1 : 0);
    254  1.1  tsutsui 	  flagval |= (1<<3);
    255  1.1  tsutsui #ifdef APPLE_HYB
    256  1.1  tsutsui 	  /* filter out any '/' character in HFS filename */
    257  1.1  tsutsui 	  if (USE_MAC_NAME(mac_name, s_entry))
    258  1.1  tsutsui 	    rstrncpy((char *)&Rock[ipnt], npnt, use);
    259  1.1  tsutsui 	  else
    260  1.1  tsutsui #endif /* APPLE_HYB */
    261  1.1  tsutsui 	    strncpy((char *)&Rock[ipnt], npnt, use);
    262  1.1  tsutsui 	  npnt += use;
    263  1.1  tsutsui 	  ipnt += use;
    264  1.1  tsutsui 	  remain -= use;
    265  1.1  tsutsui 	  if(remain && need_ce) add_CE_entry();
    266  1.1  tsutsui 	};
    267  1.1  tsutsui   };
    268  1.1  tsutsui 
    269  1.1  tsutsui   /*
    270  1.1  tsutsui    * Add the posix modes
    271  1.1  tsutsui    */
    272  1.1  tsutsui   if(MAYBE_ADD_CE_ENTRY(PX_SIZE)) add_CE_entry();
    273  1.1  tsutsui   Rock[ipnt++] ='P';
    274  1.1  tsutsui   Rock[ipnt++] ='X';
    275  1.1  tsutsui   Rock[ipnt++] = PX_SIZE;
    276  1.1  tsutsui   Rock[ipnt++] = SU_VERSION;
    277  1.1  tsutsui   flagval |= (1<<0);
    278  1.1  tsutsui   set_733((char*)Rock + ipnt, lstatbuf->st_mode);
    279  1.1  tsutsui   ipnt += 8;
    280  1.1  tsutsui   set_733((char*)Rock + ipnt, lstatbuf->st_nlink);
    281  1.1  tsutsui   ipnt += 8;
    282  1.1  tsutsui   set_733((char*)Rock + ipnt, lstatbuf->st_uid);
    283  1.1  tsutsui   ipnt += 8;
    284  1.1  tsutsui   set_733((char*)Rock + ipnt, lstatbuf->st_gid);
    285  1.1  tsutsui   ipnt += 8;
    286  1.1  tsutsui 
    287  1.1  tsutsui   /*
    288  1.1  tsutsui    * Check for special devices
    289  1.1  tsutsui    */
    290  1.1  tsutsui #ifndef NON_UNIXFS
    291  1.1  tsutsui   if (S_ISCHR(lstatbuf->st_mode) || S_ISBLK(lstatbuf->st_mode)) {
    292  1.1  tsutsui     if(MAYBE_ADD_CE_ENTRY(PN_SIZE)) add_CE_entry();
    293  1.1  tsutsui     Rock[ipnt++] ='P';
    294  1.1  tsutsui     Rock[ipnt++] ='N';
    295  1.1  tsutsui     Rock[ipnt++] = PN_SIZE;
    296  1.1  tsutsui     Rock[ipnt++] = SU_VERSION;
    297  1.1  tsutsui     flagval |= (1<<1);
    298  1.1  tsutsui #if defined(MAJOR_IN_SYSMACROS) || defined(MAJOR_IN_MKDEV)
    299  1.1  tsutsui     set_733((char*)Rock + ipnt, major(lstatbuf->st_rdev ));
    300  1.1  tsutsui     ipnt += 8;
    301  1.1  tsutsui     set_733((char*)Rock + ipnt, minor(lstatbuf->st_rdev));
    302  1.1  tsutsui     ipnt += 8;
    303  1.1  tsutsui #else
    304  1.1  tsutsui     /*
    305  1.1  tsutsui      * If we don't have sysmacros.h, then we have to guess as to how
    306  1.1  tsutsui      * best to pick apart the device number for major/minor.
    307  1.1  tsutsui      * Note: this may very well be wrong for many systems, so
    308  1.1  tsutsui      * it is always best to use the major/minor macros if the
    309  1.1  tsutsui      * system supports it.
    310  1.1  tsutsui      */
    311  1.1  tsutsui     if(sizeof(dev_t) <= 2) {
    312  1.1  tsutsui         set_733((char*)Rock + ipnt, (lstatbuf->st_rdev >> 8));
    313  1.1  tsutsui         ipnt += 8;
    314  1.1  tsutsui         set_733((char*)Rock + ipnt, lstatbuf->st_rdev & 0xff);
    315  1.1  tsutsui         ipnt += 8;
    316  1.1  tsutsui     }
    317  1.1  tsutsui     else if(sizeof(dev_t) <= 4) {
    318  1.1  tsutsui         set_733((char*)Rock + ipnt, (lstatbuf->st_rdev >> 8) >> 8);
    319  1.1  tsutsui         ipnt += 8;
    320  1.1  tsutsui         set_733((char*)Rock + ipnt, lstatbuf->st_rdev & 0xffff);
    321  1.1  tsutsui         ipnt += 8;
    322  1.1  tsutsui     }
    323  1.1  tsutsui     else {
    324  1.1  tsutsui         set_733((char*)Rock + ipnt, (lstatbuf->st_rdev >> 16) >> 16);
    325  1.1  tsutsui         ipnt += 8;
    326  1.1  tsutsui         set_733((char*)Rock + ipnt, lstatbuf->st_rdev);
    327  1.1  tsutsui         ipnt += 8;
    328  1.1  tsutsui     }
    329  1.1  tsutsui #endif
    330  1.1  tsutsui   };
    331  1.1  tsutsui #endif
    332  1.1  tsutsui   /*
    333  1.1  tsutsui    * Check for and symbolic links.  VMS does not have these.
    334  1.1  tsutsui    */
    335  1.1  tsutsui   if (S_ISLNK(lstatbuf->st_mode)){
    336  1.1  tsutsui     int lenpos, lenval, j0, j1;
    337  1.1  tsutsui     int nchar;
    338  1.1  tsutsui     unsigned char * cpnt, *cpnt1;
    339  1.1  tsutsui     nchar = readlink(whole_name, (char *)symlink_buff, sizeof(symlink_buff)-1);
    340  1.1  tsutsui     symlink_buff[nchar < 0 ? 0 : nchar] = 0;
    341  1.1  tsutsui     nchar = strlen((char *) symlink_buff);
    342  1.1  tsutsui     set_733(s_entry->isorec.size, 0);
    343  1.1  tsutsui     cpnt = &symlink_buff[0];
    344  1.1  tsutsui     flagval |= (1<<2);
    345  1.1  tsutsui 
    346  1.1  tsutsui     if (! split_SL_field)
    347  1.1  tsutsui       {
    348  1.1  tsutsui 	int sl_bytes = 0;
    349  1.1  tsutsui 	for (cpnt1 = cpnt; *cpnt1 != '\0'; cpnt1++)
    350  1.1  tsutsui 	  {
    351  1.1  tsutsui 	    if (*cpnt1 == '/')
    352  1.1  tsutsui 	      {
    353  1.1  tsutsui 		sl_bytes += 4;
    354  1.1  tsutsui 	      }
    355  1.1  tsutsui 	    else
    356  1.1  tsutsui 	      {
    357  1.1  tsutsui 		sl_bytes += 1;
    358  1.1  tsutsui 	      }
    359  1.1  tsutsui 	  }
    360  1.1  tsutsui 	if (sl_bytes > 250)
    361  1.1  tsutsui 	  {
    362  1.1  tsutsui 	    /*
    363  1.1  tsutsui 	     * the symbolic link won't fit into one SL System Use Field
    364  1.1  tsutsui 	     * print an error message and continue with splited one
    365  1.1  tsutsui 	     */
    366  1.1  tsutsui 	    fprintf(stderr,"symbolic link ``%s'' to long for one SL System Use Field, splitting", cpnt);
    367  1.1  tsutsui 	  }
    368  1.1  tsutsui        if(MAYBE_ADD_CE_ENTRY(SL_SIZE + sl_bytes)) add_CE_entry();
    369  1.1  tsutsui      }
    370  1.1  tsutsui 
    371  1.1  tsutsui     while(nchar){
    372  1.1  tsutsui       if(MAYBE_ADD_CE_ENTRY(SL_SIZE)) add_CE_entry();
    373  1.1  tsutsui       Rock[ipnt++] ='S';
    374  1.1  tsutsui       Rock[ipnt++] ='L';
    375  1.1  tsutsui       lenpos = ipnt;
    376  1.1  tsutsui       Rock[ipnt++] = SL_SIZE;
    377  1.1  tsutsui       Rock[ipnt++] = SU_VERSION;
    378  1.1  tsutsui       Rock[ipnt++] = 0; /* Flags */
    379  1.1  tsutsui       lenval = 5;
    380  1.1  tsutsui       while(*cpnt){
    381  1.1  tsutsui 	cpnt1 = (unsigned char *) strchr((char *) cpnt, '/');
    382  1.1  tsutsui 	if(cpnt1) {
    383  1.1  tsutsui 	  nchar--;
    384  1.1  tsutsui 	  *cpnt1 = 0;
    385  1.1  tsutsui 	};
    386  1.1  tsutsui 
    387  1.1  tsutsui 	/* We treat certain components in a special way.  */
    388  1.1  tsutsui 	if(cpnt[0] == '.' && cpnt[1] == '.' && cpnt[2] == 0){
    389  1.1  tsutsui 	  if(MAYBE_ADD_CE_ENTRY(2)) add_CE_entry();
    390  1.1  tsutsui 	  Rock[ipnt++] = SL_PARENT;
    391  1.1  tsutsui 	  Rock[ipnt++] = 0;  /* length is zero */
    392  1.1  tsutsui 	  lenval += 2;
    393  1.1  tsutsui 	  nchar -= 2;
    394  1.1  tsutsui 	} else if(cpnt[0] == '.' && cpnt[1] == 0){
    395  1.1  tsutsui 	  if(MAYBE_ADD_CE_ENTRY(2)) add_CE_entry();
    396  1.1  tsutsui 	  Rock[ipnt++] = SL_CURRENT;
    397  1.1  tsutsui 	  Rock[ipnt++] = 0;  /* length is zero */
    398  1.1  tsutsui 	  lenval += 2;
    399  1.1  tsutsui 	  nchar -= 1;
    400  1.1  tsutsui 	} else if(cpnt[0] == 0){
    401  1.1  tsutsui 	  if(MAYBE_ADD_CE_ENTRY(2)) add_CE_entry();
    402  1.1  tsutsui 	  Rock[ipnt++] = SL_ROOT;
    403  1.1  tsutsui 	  Rock[ipnt++] = 0;  /* length is zero */
    404  1.1  tsutsui 	  lenval += 2;
    405  1.1  tsutsui 	} else {
    406  1.1  tsutsui 	  /* If we do not have enough room for a component, start
    407  1.1  tsutsui 	     a new continuations segment now */
    408  1.1  tsutsui          if(split_SL_component ? MAYBE_ADD_CE_ENTRY(6) :
    409  1.1  tsutsui                                  MAYBE_ADD_CE_ENTRY(6 + strlen ((char *) cpnt)))
    410  1.1  tsutsui 	   {
    411  1.1  tsutsui 	     add_CE_entry();
    412  1.1  tsutsui 	     if(cpnt1)
    413  1.1  tsutsui 	       {
    414  1.1  tsutsui 		 *cpnt1 = '/';
    415  1.1  tsutsui 		 nchar++;
    416  1.1  tsutsui 		 cpnt1 = NULL; /* A kluge so that we can restart properly */
    417  1.1  tsutsui 	       }
    418  1.1  tsutsui 	     break;
    419  1.1  tsutsui 	   }
    420  1.1  tsutsui 	  j0 = strlen((char *) cpnt);
    421  1.1  tsutsui 	  while(j0) {
    422  1.1  tsutsui 	    j1 = j0;
    423  1.1  tsutsui 	    if(j1 > 0xf8) j1 = 0xf8;
    424  1.1  tsutsui 	    need_ce = 0;
    425  1.1  tsutsui 	    if(j1 + currlen + CE_SIZE + (ipnt - recstart) > reclimit) {
    426  1.1  tsutsui 	      j1 = reclimit - currlen - CE_SIZE - (ipnt - recstart);
    427  1.1  tsutsui 	      need_ce++;
    428  1.1  tsutsui 	    }
    429  1.1  tsutsui 	    Rock[ipnt++] = (j1 != j0 ? SL_CONTINUE : 0);
    430  1.1  tsutsui 	    Rock[ipnt++] = j1;
    431  1.1  tsutsui 	    strncpy((char *) Rock + ipnt, (char *) cpnt, j1);
    432  1.1  tsutsui 	    ipnt += j1;
    433  1.1  tsutsui 	    lenval += j1 + 2;
    434  1.1  tsutsui 	    cpnt += j1;
    435  1.1  tsutsui 	    nchar -= j1;  /* Number we processed this time */
    436  1.1  tsutsui 	    j0 -= j1;
    437  1.1  tsutsui 	    if(need_ce) {
    438  1.1  tsutsui 	      add_CE_entry();
    439  1.1  tsutsui 	      if(cpnt1) {
    440  1.1  tsutsui 		*cpnt1 = '/';
    441  1.1  tsutsui                 nchar++;
    442  1.1  tsutsui 		cpnt1 = NULL; /* A kluge so that we can restart properly */
    443  1.1  tsutsui 	      }
    444  1.1  tsutsui 	      break;
    445  1.1  tsutsui 	    }
    446  1.1  tsutsui 	  }
    447  1.1  tsutsui 	};
    448  1.1  tsutsui 	if(cpnt1) {
    449  1.1  tsutsui 	  cpnt = cpnt1 + 1;
    450  1.1  tsutsui 	} else
    451  1.1  tsutsui 	  break;
    452  1.1  tsutsui       }
    453  1.1  tsutsui       Rock[lenpos] = lenval;
    454  1.1  tsutsui       if(nchar) Rock[lenpos + 2] = SL_CONTINUE; /* We need another SL entry */
    455  1.1  tsutsui     } /* while nchar */
    456  1.1  tsutsui   } /* Is a symbolic link */
    457  1.1  tsutsui   /*
    458  1.1  tsutsui    * Add in the Rock Ridge TF time field
    459  1.1  tsutsui    */
    460  1.1  tsutsui   if(MAYBE_ADD_CE_ENTRY(TF_SIZE)) add_CE_entry();
    461  1.1  tsutsui   Rock[ipnt++] ='T';
    462  1.1  tsutsui   Rock[ipnt++] ='F';
    463  1.1  tsutsui   Rock[ipnt++] = TF_SIZE;
    464  1.1  tsutsui   Rock[ipnt++] = SU_VERSION;
    465  1.1  tsutsui #ifdef __QNX__
    466  1.1  tsutsui   Rock[ipnt++] = 0x0f;
    467  1.1  tsutsui #else
    468  1.1  tsutsui   Rock[ipnt++] = 0x0e;
    469  1.1  tsutsui #endif
    470  1.1  tsutsui   flagval |= (1<<7);
    471  1.1  tsutsui #ifdef __QNX__
    472  1.1  tsutsui   iso9660_date((char *) &Rock[ipnt], lstatbuf->st_ftime);
    473  1.1  tsutsui   ipnt += 7;
    474  1.1  tsutsui #endif
    475  1.1  tsutsui   iso9660_date((char *) &Rock[ipnt], lstatbuf->st_mtime);
    476  1.1  tsutsui   ipnt += 7;
    477  1.1  tsutsui   iso9660_date((char *) &Rock[ipnt], lstatbuf->st_atime);
    478  1.1  tsutsui   ipnt += 7;
    479  1.1  tsutsui   iso9660_date((char *) &Rock[ipnt], lstatbuf->st_ctime);
    480  1.1  tsutsui   ipnt += 7;
    481  1.1  tsutsui 
    482  1.1  tsutsui   /*
    483  1.1  tsutsui    * Add in the Rock Ridge RE time field
    484  1.1  tsutsui    */
    485  1.1  tsutsui   if(deep_opt & NEED_RE){
    486  1.1  tsutsui           if(MAYBE_ADD_CE_ENTRY(RE_SIZE)) add_CE_entry();
    487  1.1  tsutsui 	  Rock[ipnt++] ='R';
    488  1.1  tsutsui 	  Rock[ipnt++] ='E';
    489  1.1  tsutsui 	  Rock[ipnt++] = RE_SIZE;
    490  1.1  tsutsui 	  Rock[ipnt++] = SU_VERSION;
    491  1.1  tsutsui 	  flagval |= (1<<6);
    492  1.1  tsutsui   };
    493  1.1  tsutsui   /*
    494  1.1  tsutsui    * Add in the Rock Ridge PL record, if required.
    495  1.1  tsutsui    */
    496  1.1  tsutsui   if(deep_opt & NEED_PL){
    497  1.1  tsutsui           if(MAYBE_ADD_CE_ENTRY(PL_SIZE)) add_CE_entry();
    498  1.1  tsutsui 	  Rock[ipnt++] ='P';
    499  1.1  tsutsui 	  Rock[ipnt++] ='L';
    500  1.1  tsutsui 	  Rock[ipnt++] = PL_SIZE;
    501  1.1  tsutsui 	  Rock[ipnt++] = SU_VERSION;
    502  1.1  tsutsui 	  set_733((char*)Rock + ipnt, 0);
    503  1.1  tsutsui 	  ipnt += 8;
    504  1.1  tsutsui 	  flagval |= (1<<5);
    505  1.1  tsutsui   };
    506  1.1  tsutsui 
    507  1.1  tsutsui   /*
    508  1.1  tsutsui    * Add in the Rock Ridge CL field, if required.
    509  1.1  tsutsui    */
    510  1.1  tsutsui   if(deep_opt & NEED_CL){
    511  1.1  tsutsui           if(MAYBE_ADD_CE_ENTRY(CL_SIZE)) add_CE_entry();
    512  1.1  tsutsui 	  Rock[ipnt++] ='C';
    513  1.1  tsutsui 	  Rock[ipnt++] ='L';
    514  1.1  tsutsui 	  Rock[ipnt++] = CL_SIZE;
    515  1.1  tsutsui 	  Rock[ipnt++] = SU_VERSION;
    516  1.1  tsutsui 	  set_733((char*)Rock + ipnt, 0);
    517  1.1  tsutsui 	  ipnt += 8;
    518  1.1  tsutsui 	  flagval |= (1<<4);
    519  1.1  tsutsui   };
    520  1.1  tsutsui 
    521  1.1  tsutsui #ifndef VMS
    522  1.1  tsutsui   /* If transparent compression was requested, fill in the correct
    523  1.1  tsutsui      field for this file */
    524  1.1  tsutsui   if(transparent_compression &&
    525  1.1  tsutsui      S_ISREG(lstatbuf->st_mode) &&
    526  1.1  tsutsui      strlen(name) > 3 &&
    527  1.1  tsutsui      strcmp(name + strlen(name) - 3,".gZ") == 0){
    528  1.1  tsutsui     FILE * zipfile;
    529  1.1  tsutsui     char * checkname;
    530  1.1  tsutsui     unsigned int file_size;
    531  1.1  tsutsui     unsigned char header[8];
    532  1.1  tsutsui     int OK_flag;
    533  1.1  tsutsui 
    534  1.1  tsutsui     /* First open file and verify that the correct algorithm was used */
    535  1.1  tsutsui     file_size = 0;
    536  1.1  tsutsui     OK_flag = 1;
    537  1.1  tsutsui 
    538  1.1  tsutsui     zipfile = fopen(whole_name, "rb");
    539  1.1  tsutsui     fread(header, 1, sizeof(header), zipfile);
    540  1.1  tsutsui 
    541  1.1  tsutsui     /* Check some magic numbers from gzip. */
    542  1.1  tsutsui     if(header[0] != 0x1f || header[1] != 0x8b || header[2] != 8) OK_flag = 0;
    543  1.1  tsutsui     /* Make sure file was blocksized. */
    544  1.1  tsutsui     if(((header[3] & 0x40) == 0)) OK_flag = 0;
    545  1.1  tsutsui     /* OK, now go to the end of the file and get some more info */
    546  1.1  tsutsui     if(OK_flag){
    547  1.1  tsutsui       int status;
    548  1.1  tsutsui       status = (long)lseek(fileno(zipfile), (off_t)(-8), SEEK_END);
    549  1.1  tsutsui       if(status == -1) OK_flag = 0;
    550  1.1  tsutsui     }
    551  1.1  tsutsui     if(OK_flag){
    552  1.1  tsutsui       if(read(fileno(zipfile), (char*)header, sizeof(header)) != sizeof(header))
    553  1.1  tsutsui 	OK_flag = 0;
    554  1.1  tsutsui       else {
    555  1.1  tsutsui 	int blocksize;
    556  1.1  tsutsui 	blocksize = (header[3] << 8) | header[2];
    557  1.1  tsutsui 	file_size = ((unsigned int)header[7] << 24) |
    558  1.1  tsutsui 		    ((unsigned int)header[6] << 16) |
    559  1.1  tsutsui 		    ((unsigned int)header[5] << 8)  | header[4];
    560  1.1  tsutsui #if 0
    561  1.1  tsutsui 	fprintf(stderr,"Blocksize = %d %d\n", blocksize, file_size);
    562  1.1  tsutsui #endif
    563  1.1  tsutsui 	if(blocksize != SECTOR_SIZE) OK_flag = 0;
    564  1.1  tsutsui       }
    565  1.1  tsutsui     }
    566  1.1  tsutsui     fclose(zipfile);
    567  1.1  tsutsui 
    568  1.1  tsutsui     checkname = strdup(whole_name);
    569  1.1  tsutsui     checkname[strlen(whole_name)-3] = 0;
    570  1.1  tsutsui     zipfile = fopen(checkname, "rb");
    571  1.1  tsutsui     if(zipfile) {
    572  1.1  tsutsui       OK_flag = 0;
    573  1.1  tsutsui       fprintf(stderr,"Unable to insert transparent compressed file - name conflict\n");
    574  1.1  tsutsui       fclose(zipfile);
    575  1.1  tsutsui     }
    576  1.1  tsutsui 
    577  1.1  tsutsui     free(checkname);
    578  1.1  tsutsui 
    579  1.1  tsutsui     if(OK_flag){
    580  1.1  tsutsui       if(MAYBE_ADD_CE_ENTRY(ZZ_SIZE)) add_CE_entry();
    581  1.1  tsutsui       Rock[ipnt++] ='Z';
    582  1.1  tsutsui       Rock[ipnt++] ='Z';
    583  1.1  tsutsui       Rock[ipnt++] = ZZ_SIZE;
    584  1.1  tsutsui       Rock[ipnt++] = SU_VERSION;
    585  1.1  tsutsui       Rock[ipnt++] = 'g'; /* Identify compression technique used */
    586  1.1  tsutsui       Rock[ipnt++] = 'z';
    587  1.1  tsutsui       Rock[ipnt++] = 3;
    588  1.1  tsutsui       set_733((char*)Rock + ipnt, file_size); /* Real file size */
    589  1.1  tsutsui       ipnt += 8;
    590  1.1  tsutsui     };
    591  1.1  tsutsui   }
    592  1.1  tsutsui #endif
    593  1.1  tsutsui   /*
    594  1.1  tsutsui    * Add in the Rock Ridge CE field, if required.  We use  this for the
    595  1.1  tsutsui    * extension record that is stored in the root directory.
    596  1.1  tsutsui    */
    597  1.1  tsutsui   if(deep_opt & NEED_CE) add_CE_entry();
    598  1.1  tsutsui   /*
    599  1.1  tsutsui    * Done filling in all of the fields.  Now copy it back to a buffer for the
    600  1.1  tsutsui    * file in question.
    601  1.1  tsutsui    */
    602  1.1  tsutsui 
    603  1.1  tsutsui   /* Now copy this back to the buffer for the file */
    604  1.1  tsutsui   Rock[flagpos] = flagval;
    605  1.1  tsutsui 
    606  1.1  tsutsui   /* If there was a CE, fill in the size field */
    607  1.1  tsutsui   if(recstart)
    608  1.1  tsutsui     set_733((char*)Rock + recstart - 8, ipnt - recstart);
    609  1.1  tsutsui 
    610  1.1  tsutsui   s_entry->rr_attributes = (unsigned char *) e_malloc(ipnt);
    611  1.1  tsutsui   s_entry->total_rr_attr_size = ipnt;
    612  1.1  tsutsui   s_entry->rr_attr_size = (mainrec ? mainrec : ipnt);
    613  1.1  tsutsui   memcpy(s_entry->rr_attributes, Rock, ipnt);
    614  1.1  tsutsui   return ipnt;
    615  1.1  tsutsui }
    616  1.1  tsutsui 
    617  1.1  tsutsui /* Guaranteed to  return a single sector with the relevant info */
    618  1.1  tsutsui 
    619  1.1  tsutsui char * FDECL4(generate_rr_extension_record, char *, id,  char  *, descriptor,
    620  1.1  tsutsui 				    char *, source, int  *, size){
    621  1.1  tsutsui   int lipnt = 0;
    622  1.1  tsutsui   char * pnt;
    623  1.1  tsutsui   int len_id, len_des, len_src;
    624  1.1  tsutsui 
    625  1.1  tsutsui   len_id = strlen(id);
    626  1.1  tsutsui   len_des =  strlen(descriptor);
    627  1.1  tsutsui   len_src = strlen(source);
    628  1.1  tsutsui   Rock[lipnt++] ='E';
    629  1.1  tsutsui   Rock[lipnt++] ='R';
    630  1.1  tsutsui   Rock[lipnt++] = ER_SIZE + len_id + len_des + len_src;
    631  1.1  tsutsui   Rock[lipnt++] = 1;
    632  1.1  tsutsui   Rock[lipnt++] = len_id;
    633  1.1  tsutsui   Rock[lipnt++] = len_des;
    634  1.1  tsutsui   Rock[lipnt++] = len_src;
    635  1.1  tsutsui   Rock[lipnt++] = 1;
    636  1.1  tsutsui 
    637  1.1  tsutsui   memcpy(Rock  + lipnt, id, len_id);
    638  1.1  tsutsui   lipnt += len_id;
    639  1.1  tsutsui 
    640  1.1  tsutsui   memcpy(Rock  + lipnt, descriptor, len_des);
    641  1.1  tsutsui   lipnt += len_des;
    642  1.1  tsutsui 
    643  1.1  tsutsui   memcpy(Rock  + lipnt, source, len_src);
    644  1.1  tsutsui   lipnt += len_src;
    645  1.1  tsutsui 
    646  1.1  tsutsui   if(lipnt  > SECTOR_SIZE) {
    647  1.1  tsutsui 	  fprintf(stderr,"Extension record too  long\n");
    648  1.1  tsutsui 	  exit(1);
    649  1.1  tsutsui   };
    650  1.1  tsutsui   pnt = (char *) e_malloc(SECTOR_SIZE);
    651  1.1  tsutsui   memset(pnt, 0,  SECTOR_SIZE);
    652  1.1  tsutsui   memcpy(pnt, Rock, lipnt);
    653  1.1  tsutsui   *size = lipnt;
    654  1.1  tsutsui   return pnt;
    655  1.1  tsutsui }
    656