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