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