1 1.1 tsutsui /* 2 1.1 tsutsui * File joliet.c - handle Win95/WinNT long file/unicode extensions for iso9660. 3 1.1 tsutsui 4 1.1 tsutsui Copyright 1997 Eric Youngdale. 5 1.1 tsutsui 6 1.1 tsutsui This program is free software; you can redistribute it and/or modify 7 1.1 tsutsui it under the terms of the GNU General Public License as published by 8 1.1 tsutsui the Free Software Foundation; either version 2, or (at your option) 9 1.1 tsutsui any later version. 10 1.1 tsutsui 11 1.1 tsutsui This program is distributed in the hope that it will be useful, 12 1.1 tsutsui but WITHOUT ANY WARRANTY; without even the implied warranty of 13 1.1 tsutsui MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 1.1 tsutsui GNU General Public License for more details. 15 1.1 tsutsui 16 1.1 tsutsui You should have received a copy of the GNU General Public License 17 1.1 tsutsui along with this program; if not, write to the Free Software 18 1.1 tsutsui Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 19 1.1 tsutsui 20 1.1 tsutsui /* APPLE_HYB James Pearson j.pearson (at) ge.ucl.ac.uk 12/3/99 */ 21 1.1 tsutsui 22 1.1 tsutsui /* 23 1.1 tsutsui * Joliet extensions for ISO9660. These are spottily documented by 24 1.1 tsutsui * Microsoft. In their infinite stupidity, they completely ignored 25 1.1 tsutsui * the possibility of using an SUSP record with the long filename 26 1.1 tsutsui * in it, and instead wrote out a duplicate directory tree with the 27 1.1 tsutsui * long filenames in it. 28 1.1 tsutsui * 29 1.1 tsutsui * I am not sure why they did this. One reason is that they get the path 30 1.1 tsutsui * tables with the long filenames in them. 31 1.1 tsutsui * 32 1.1 tsutsui * There are two basic principles to Joliet, and the non-Unicode variant 33 1.1 tsutsui * known as Romeo. Long filenames seem to be the main one, and the second 34 1.1 tsutsui * is that the character set and a few other things is substantially relaxed. 35 1.1 tsutsui * 36 1.1 tsutsui * The SVD is identical to the PVD, except: 37 1.1 tsutsui * 38 1.1 tsutsui * Id is 2, not 1 (indicates SVD). 39 1.1 tsutsui * escape_sequences contains UCS-2 indicator (levels 1, 2 or 3). 40 1.1 tsutsui * The root directory record points to a different extent (with different 41 1.1 tsutsui * size). 42 1.1 tsutsui * There are different path tables for the two sets of directory trees. 43 1.1 tsutsui * 44 1.1 tsutsui * The following fields are recorded in Unicode: 45 1.1 tsutsui * system_id 46 1.1 tsutsui * volume_id 47 1.1 tsutsui * volume_set_id 48 1.1 tsutsui * publisher_id 49 1.1 tsutsui * preparer_id 50 1.1 tsutsui * application_id 51 1.1 tsutsui * copyright_file_id 52 1.1 tsutsui * abstract_file_id 53 1.1 tsutsui * bibliographic_file_id 54 1.1 tsutsui * 55 1.1 tsutsui * Unicode strings are always encoded in big-endian format. 56 1.1 tsutsui * 57 1.1 tsutsui * In a directory record, everything is the same as with iso9660, except 58 1.1 tsutsui * that the name is recorded in unicode. The name length is specified in 59 1.1 tsutsui * total bytes, not in number of unicode characters. 60 1.1 tsutsui * 61 1.1 tsutsui * The character set used for the names is different with UCS - the 62 1.1 tsutsui * restrictions are that the following are not allowed: 63 1.1 tsutsui * 64 1.1 tsutsui * Characters (00)(00) through (00)(1f) (control chars) 65 1.1 tsutsui * (00)(2a) '*' 66 1.1 tsutsui * (00)(2f) '/' 67 1.1 tsutsui * (00)(3a) ':' 68 1.1 tsutsui * (00)(3b) ';' 69 1.1 tsutsui * (00)(3f) '?' 70 1.1 tsutsui * (00)(5c) '\' 71 1.1 tsutsui */ 72 1.1 tsutsui #include "config.h" 73 1.1 tsutsui #include "mkisofs.h" 74 1.1 tsutsui #include "iso9660.h" 75 1.1 tsutsui 76 1.1 tsutsui 77 1.1 tsutsui #include <stdlib.h> 78 1.1 tsutsui #include <time.h> 79 1.1 tsutsui 80 1.1 tsutsui static int jpath_table_index; 81 1.1 tsutsui static struct directory ** jpathlist; 82 1.1 tsutsui static int next_jpath_index = 1; 83 1.1 tsutsui static int sort_goof; 84 1.1 tsutsui 85 1.1 tsutsui static int generate_joliet_path_tables __PR((void)); 86 1.1 tsutsui static int DECL(joliet_sort_directory, (struct directory_entry ** sort_dir)); 87 1.1 tsutsui static void DECL(assign_joliet_directory_addresses, (struct directory * node)); 88 1.1 tsutsui static int jroot_gen __PR((void)); 89 1.1 tsutsui 90 1.1 tsutsui /* 91 1.1 tsutsui * Function: convert_to_unicode 92 1.1 tsutsui * 93 1.1 tsutsui * Purpose: Perform a 1/2 assed unicode conversion on a text 94 1.1 tsutsui * string. 95 1.1 tsutsui * 96 1.1 tsutsui * Notes: 97 1.1 tsutsui */ 98 1.1 tsutsui static void FDECL3(convert_to_unicode, unsigned char *, buffer, int, size, char *, source ) 99 1.1 tsutsui { 100 1.1 tsutsui unsigned char * tmpbuf; 101 1.1 tsutsui int i; 102 1.1 tsutsui int j; 103 1.1 tsutsui 104 1.1 tsutsui /* 105 1.1 tsutsui * If we get a NULL pointer for the source, it means we have an inplace 106 1.1 tsutsui * copy, and we need to make a temporary working copy first. 107 1.1 tsutsui */ 108 1.1 tsutsui if( source == NULL ) 109 1.1 tsutsui { 110 1.1 tsutsui tmpbuf = (u_char *) e_malloc(size); 111 1.1 tsutsui memcpy( tmpbuf, buffer, size); 112 1.1 tsutsui } 113 1.1 tsutsui else 114 1.1 tsutsui { 115 1.1 tsutsui tmpbuf = (u_char *)source; 116 1.1 tsutsui } 117 1.1 tsutsui 118 1.1 tsutsui /* 119 1.1 tsutsui * Now start copying characters. If the size was specified to be 0, then 120 1.1 tsutsui * assume the input was 0 terminated. 121 1.1 tsutsui */ 122 1.1 tsutsui j = 0; 123 1.1 tsutsui for(i=0; i < size ; i += 2, j++) 124 1.1 tsutsui { 125 1.1 tsutsui buffer[i] = 0; 126 1.1 tsutsui /* 127 1.1 tsutsui * JS integrated from: Achim_Kaiser (at) t-online.de 128 1.1 tsutsui * 129 1.1 tsutsui * Let all valid unicode characters pass through (assuming ISO-8859-1). 130 1.1 tsutsui * Others are set to '_' . 131 1.1 tsutsui */ 132 1.1 tsutsui if( tmpbuf[j] != 0 && 133 1.1 tsutsui (tmpbuf[j] <= 0x1f || (tmpbuf[j] >= 0x7F && tmpbuf[j] <= 0xA0)) ) 134 1.1 tsutsui { 135 1.1 tsutsui buffer[i+1] = '_'; 136 1.1 tsutsui } 137 1.1 tsutsui else 138 1.1 tsutsui { 139 1.1 tsutsui switch(tmpbuf[j]) 140 1.1 tsutsui { 141 1.1 tsutsui case '*': 142 1.1 tsutsui case '/': 143 1.1 tsutsui case ':': 144 1.1 tsutsui case ';': 145 1.1 tsutsui case '?': 146 1.1 tsutsui case '\\': 147 1.1 tsutsui /* 148 1.1 tsutsui * Even Joliet has some standards as to what is allowed in a pathname. 149 1.1 tsutsui * Pretty tame in comparison to what DOS restricts you to. 150 1.1 tsutsui */ 151 1.1 tsutsui buffer[i+1] = '_'; 152 1.1 tsutsui break; 153 1.1 tsutsui default: 154 1.1 tsutsui buffer[i+1] = tmpbuf[j]; 155 1.1 tsutsui break; 156 1.1 tsutsui } 157 1.1 tsutsui } 158 1.1 tsutsui } 159 1.1 tsutsui 160 1.1 tsutsui if( source == NULL ) 161 1.1 tsutsui { 162 1.1 tsutsui free(tmpbuf); 163 1.1 tsutsui } 164 1.1 tsutsui } 165 1.1 tsutsui 166 1.1 tsutsui /* 167 1.1 tsutsui * Function: joliet_strlen 168 1.1 tsutsui * 169 1.1 tsutsui * Purpose: Return length in bytes of string after conversion to unicode. 170 1.1 tsutsui * 171 1.1 tsutsui * Notes: This is provided mainly as a convenience so that when more intelligent 172 1.1 tsutsui * Unicode conversion for either Multibyte or 8-bit codes is available that 173 1.1 tsutsui * we can easily adapt. 174 1.1 tsutsui */ 175 1.1 tsutsui static int FDECL1(joliet_strlen, const char *, string) 176 1.1 tsutsui { 177 1.1 tsutsui int rtn; 178 1.1 tsutsui 179 1.1 tsutsui rtn = strlen(string) << 1; 180 1.1 tsutsui 181 1.1 tsutsui /* 182 1.1 tsutsui * We do clamp the maximum length of a Joliet string to be the 183 1.1 tsutsui * maximum path size. This helps to ensure that we don't completely 184 1.1 tsutsui * bolix things up with very long paths. The Joliet specs say 185 1.1 tsutsui * that the maximum length is 128 bytes, or 64 unicode characters. 186 1.1 tsutsui */ 187 1.1 tsutsui if( rtn > 0x80) 188 1.1 tsutsui { 189 1.1 tsutsui rtn = 0x80; 190 1.1 tsutsui } 191 1.1 tsutsui return rtn; 192 1.1 tsutsui } 193 1.1 tsutsui 194 1.1 tsutsui /* 195 1.1 tsutsui * Function: get_joliet_vol_desc 196 1.1 tsutsui * 197 1.1 tsutsui * Purpose: generate a Joliet compatible volume desc. 198 1.1 tsutsui * 199 1.1 tsutsui * Notes: Assume that we have the non-joliet vol desc 200 1.1 tsutsui * already present in the buffer. Just modifiy the 201 1.1 tsutsui * appropriate fields. 202 1.1 tsutsui */ 203 1.1 tsutsui static void FDECL1(get_joliet_vol_desc, struct iso_primary_descriptor *, jvol_desc) 204 1.1 tsutsui { 205 1.1 tsutsui jvol_desc->type[0] = ISO_VD_SUPPLEMENTARY; 206 1.1 tsutsui 207 1.1 tsutsui /* 208 1.1 tsutsui * For now, always do Unicode level 3. I don't really know what 1 and 2 209 1.1 tsutsui * are - perhaps a more limited Unicode set. 210 1.1 tsutsui * 211 1.1 tsutsui * FIXME(eric) - how does Romeo fit in here? As mkisofs just 212 1.1 tsutsui * "expands" 8 bit character codes to 16 bits and does nothing 213 1.1 tsutsui * special with the Unicode characters, therefore shouldn't mkisofs 214 1.1 tsutsui * really be stating that it's using UCS-2 Level 1, not Level 3 for 215 1.1 tsutsui * the Joliet directory tree. 216 1.1 tsutsui */ 217 1.1 tsutsui strcpy(jvol_desc->escape_sequences, "%/@"); 218 1.1 tsutsui 219 1.1 tsutsui /* 220 1.1 tsutsui * Until we have Unicode path tables, leave these unset. 221 1.1 tsutsui */ 222 1.1 tsutsui set_733((char *) jvol_desc->path_table_size, jpath_table_size); 223 1.1 tsutsui set_731(jvol_desc->type_l_path_table, jpath_table[0]); 224 1.1 tsutsui set_731(jvol_desc->opt_type_l_path_table, jpath_table[1]); 225 1.1 tsutsui set_732(jvol_desc->type_m_path_table, jpath_table[2]); 226 1.1 tsutsui set_732(jvol_desc->opt_type_m_path_table, jpath_table[3]); 227 1.1 tsutsui 228 1.1 tsutsui /* 229 1.1 tsutsui * Set this one up. 230 1.1 tsutsui */ 231 1.1 tsutsui memcpy(jvol_desc->root_directory_record, &jroot_record, 232 1.1 tsutsui sizeof(jvol_desc->root_directory_record)); 233 1.1 tsutsui 234 1.1 tsutsui /* 235 1.1 tsutsui * Finally, we have a bunch of strings to convert to Unicode. 236 1.1 tsutsui * FIXME(eric) - I don't know how to do this in general, so we will 237 1.1 tsutsui * just be really lazy and do a char -> short conversion. We probably 238 1.1 tsutsui * will want to filter any characters >= 0x80. 239 1.1 tsutsui */ 240 1.1 tsutsui convert_to_unicode((u_char *)jvol_desc->system_id, sizeof(jvol_desc->system_id), NULL); 241 1.1 tsutsui convert_to_unicode((u_char *)jvol_desc->volume_id, sizeof(jvol_desc->volume_id), NULL); 242 1.1 tsutsui convert_to_unicode((u_char *)jvol_desc->volume_set_id, sizeof(jvol_desc->volume_set_id), NULL); 243 1.1 tsutsui convert_to_unicode((u_char *)jvol_desc->publisher_id, sizeof(jvol_desc->publisher_id), NULL); 244 1.1 tsutsui convert_to_unicode((u_char *)jvol_desc->preparer_id, sizeof(jvol_desc->preparer_id), NULL); 245 1.1 tsutsui convert_to_unicode((u_char *)jvol_desc->application_id, sizeof(jvol_desc->application_id), NULL); 246 1.1 tsutsui convert_to_unicode((u_char *)jvol_desc->copyright_file_id, sizeof(jvol_desc->copyright_file_id), NULL); 247 1.1 tsutsui convert_to_unicode((u_char *)jvol_desc->abstract_file_id, sizeof(jvol_desc->abstract_file_id), NULL); 248 1.1 tsutsui convert_to_unicode((u_char *)jvol_desc->bibliographic_file_id, sizeof(jvol_desc->bibliographic_file_id), NULL); 249 1.1 tsutsui 250 1.1 tsutsui 251 1.1 tsutsui } 252 1.1 tsutsui 253 1.1 tsutsui static void FDECL1(assign_joliet_directory_addresses, struct directory *, node) 254 1.1 tsutsui { 255 1.1 tsutsui int dir_size; 256 1.1 tsutsui struct directory * dpnt; 257 1.1 tsutsui 258 1.1 tsutsui dpnt = node; 259 1.1 tsutsui 260 1.1 tsutsui while (dpnt) 261 1.1 tsutsui { 262 1.1 tsutsui if( (dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) == 0 ) 263 1.1 tsutsui { 264 1.1 tsutsui /* 265 1.1 tsutsui * If we already have an extent for this (i.e. it came from 266 1.1 tsutsui * a multisession disc), then don't reassign a new extent. 267 1.1 tsutsui */ 268 1.1 tsutsui dpnt->jpath_index = next_jpath_index++; 269 1.1 tsutsui if( dpnt->jextent == 0 ) 270 1.1 tsutsui { 271 1.1 tsutsui dpnt->jextent = last_extent; 272 1.1 tsutsui dir_size = (dpnt->jsize + (SECTOR_SIZE - 1)) >> 11; 273 1.1 tsutsui last_extent += dir_size; 274 1.1 tsutsui } 275 1.1 tsutsui } 276 1.1 tsutsui 277 1.1 tsutsui /* skip if hidden - but not for the rr_moved dir */ 278 1.1 tsutsui if(dpnt->subdir && (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) || dpnt == reloc_dir)) 279 1.1 tsutsui { 280 1.1 tsutsui assign_joliet_directory_addresses(dpnt->subdir); 281 1.1 tsutsui } 282 1.1 tsutsui dpnt = dpnt->next; 283 1.1 tsutsui } 284 1.1 tsutsui } 285 1.1 tsutsui 286 1.1 tsutsui static 287 1.1 tsutsui void FDECL1(build_jpathlist, struct directory *, node) 288 1.1 tsutsui { 289 1.1 tsutsui struct directory * dpnt; 290 1.1 tsutsui 291 1.1 tsutsui dpnt = node; 292 1.1 tsutsui 293 1.1 tsutsui while (dpnt) 294 1.1 tsutsui 295 1.1 tsutsui { 296 1.1 tsutsui if( (dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) == 0 ) 297 1.1 tsutsui { 298 1.1 tsutsui jpathlist[dpnt->jpath_index] = dpnt; 299 1.1 tsutsui } 300 1.1 tsutsui if(dpnt->subdir) build_jpathlist(dpnt->subdir); 301 1.1 tsutsui dpnt = dpnt->next; 302 1.1 tsutsui } 303 1.1 tsutsui } /* build_jpathlist(... */ 304 1.1 tsutsui 305 1.1 tsutsui static int FDECL2(joliet_compare_paths, void const *, r, void const *, l) 306 1.1 tsutsui { 307 1.1 tsutsui struct directory const *ll = *(struct directory * const *)l; 308 1.1 tsutsui struct directory const *rr = *(struct directory * const *)r; 309 1.1 tsutsui int rparent, lparent; 310 1.1 tsutsui 311 1.1 tsutsui rparent = rr->parent->jpath_index; 312 1.1 tsutsui lparent = ll->parent->jpath_index; 313 1.1 tsutsui if( rr->parent == reloc_dir ) 314 1.1 tsutsui { 315 1.1 tsutsui rparent = rr->self->parent_rec->filedir->jpath_index; 316 1.1 tsutsui } 317 1.1 tsutsui 318 1.1 tsutsui if( ll->parent == reloc_dir ) 319 1.1 tsutsui { 320 1.1 tsutsui lparent = ll->self->parent_rec->filedir->jpath_index; 321 1.1 tsutsui } 322 1.1 tsutsui 323 1.1 tsutsui if (rparent < lparent) 324 1.1 tsutsui { 325 1.1 tsutsui return -1; 326 1.1 tsutsui } 327 1.1 tsutsui 328 1.1 tsutsui if (rparent > lparent) 329 1.1 tsutsui { 330 1.1 tsutsui return 1; 331 1.1 tsutsui } 332 1.1 tsutsui #ifdef APPLE_HYB 333 1.1 tsutsui /* use Mac name for Joliet name */ 334 1.1 tsutsui if (USE_MAC_NAME(mac_name, rr->self) && USE_MAC_NAME(mac_name, ll->self)) 335 1.1 tsutsui return strcmp(rr->self->hfs_ent->name, ll->self->hfs_ent->name); 336 1.1 tsutsui else 337 1.1 tsutsui #endif /* APPLE_HYB */ 338 1.1 tsutsui return strcmp(rr->self->name, ll->self->name); 339 1.1 tsutsui 340 1.1 tsutsui } /* compare_paths(... */ 341 1.1 tsutsui 342 1.1 tsutsui static int generate_joliet_path_tables() 343 1.1 tsutsui { 344 1.1 tsutsui struct directory_entry * de; 345 1.1 tsutsui struct directory * dpnt; 346 1.1 tsutsui int fix; 347 1.1 tsutsui int j; 348 1.1 tsutsui int namelen; 349 1.1 tsutsui char * npnt; 350 1.1 tsutsui char * npnt1; 351 1.1 tsutsui int tablesize; 352 1.1 tsutsui 353 1.1 tsutsui /* 354 1.1 tsutsui * First allocate memory for the tables and initialize the memory 355 1.1 tsutsui */ 356 1.1 tsutsui tablesize = jpath_blocks << 11; 357 1.1 tsutsui jpath_table_m = (char *) e_malloc(tablesize); 358 1.1 tsutsui jpath_table_l = (char *) e_malloc(tablesize); 359 1.1 tsutsui memset(jpath_table_l, 0, tablesize); 360 1.1 tsutsui memset(jpath_table_m, 0, tablesize); 361 1.1 tsutsui 362 1.1 tsutsui if( next_jpath_index > 0xffff ) 363 1.1 tsutsui { 364 1.1 tsutsui fprintf(stderr, "Unable to generate sane path tables - too many directories (%d)\n", 365 1.1 tsutsui next_jpath_index); 366 1.1 tsutsui exit(1); 367 1.1 tsutsui } 368 1.1 tsutsui /* 369 1.1 tsutsui * Now start filling in the path tables. Start with root directory 370 1.1 tsutsui */ 371 1.1 tsutsui jpath_table_index = 0; 372 1.1 tsutsui jpathlist = (struct directory **) e_malloc(sizeof(struct directory *) 373 1.1 tsutsui * next_jpath_index); 374 1.1 tsutsui memset(jpathlist, 0, sizeof(struct directory *) * next_jpath_index); 375 1.1 tsutsui build_jpathlist(root); 376 1.1 tsutsui 377 1.1 tsutsui do 378 1.1 tsutsui { 379 1.1 tsutsui fix = 0; 380 1.1 tsutsui #ifdef __STDC__ 381 1.1 tsutsui qsort(&jpathlist[1], next_jpath_index-1, sizeof(struct directory *), 382 1.1 tsutsui (int (*)(const void *, const void *))joliet_compare_paths); 383 1.1 tsutsui #else 384 1.1 tsutsui qsort(&jpathlist[1], next_jpath_index-1, sizeof(struct directory *), 385 1.1 tsutsui joliet_compare_paths); 386 1.1 tsutsui #endif 387 1.1 tsutsui 388 1.1 tsutsui for(j=1; j<next_jpath_index; j++) 389 1.1 tsutsui { 390 1.1 tsutsui if(jpathlist[j]->jpath_index != j) 391 1.1 tsutsui { 392 1.1 tsutsui jpathlist[j]->jpath_index = j; 393 1.1 tsutsui fix++; 394 1.1 tsutsui } 395 1.1 tsutsui } 396 1.1 tsutsui } while(fix); 397 1.1 tsutsui 398 1.1 tsutsui for(j=1; j<next_jpath_index; j++) 399 1.1 tsutsui { 400 1.1 tsutsui dpnt = jpathlist[j]; 401 1.1 tsutsui if(!dpnt) 402 1.1 tsutsui { 403 1.1 tsutsui fprintf(stderr,"Entry %d not in path tables\n", j); 404 1.1 tsutsui exit(1); 405 1.1 tsutsui } 406 1.1 tsutsui npnt = dpnt->de_name; 407 1.1 tsutsui 408 1.1 tsutsui npnt1 = strrchr(npnt, PATH_SEPARATOR); 409 1.1 tsutsui if(npnt1) 410 1.1 tsutsui { 411 1.1 tsutsui npnt = npnt1 + 1; 412 1.1 tsutsui } 413 1.1 tsutsui 414 1.1 tsutsui de = dpnt->self; 415 1.1 tsutsui if(!de) 416 1.1 tsutsui { 417 1.1 tsutsui fprintf(stderr,"Fatal goof - directory has amnesia\n"); 418 1.1 tsutsui exit(1); 419 1.1 tsutsui } 420 1.1 tsutsui 421 1.1 tsutsui #ifdef APPLE_HYB 422 1.1 tsutsui if (USE_MAC_NAME(mac_name, de)) 423 1.1 tsutsui namelen = joliet_strlen(de->hfs_ent->name); 424 1.1 tsutsui else 425 1.1 tsutsui #endif /* APPLE_HYB */ 426 1.1 tsutsui namelen = joliet_strlen(de->name); 427 1.1 tsutsui 428 1.1 tsutsui if( dpnt == root ) 429 1.1 tsutsui { 430 1.1 tsutsui jpath_table_l[jpath_table_index] = 1; 431 1.1 tsutsui jpath_table_m[jpath_table_index] = 1; 432 1.1 tsutsui } 433 1.1 tsutsui else 434 1.1 tsutsui { 435 1.1 tsutsui jpath_table_l[jpath_table_index] = namelen; 436 1.1 tsutsui jpath_table_m[jpath_table_index] = namelen; 437 1.1 tsutsui } 438 1.1 tsutsui jpath_table_index += 2; 439 1.1 tsutsui 440 1.1 tsutsui set_731(jpath_table_l + jpath_table_index, dpnt->jextent); 441 1.1 tsutsui set_732(jpath_table_m + jpath_table_index, dpnt->jextent); 442 1.1 tsutsui jpath_table_index += 4; 443 1.1 tsutsui 444 1.1 tsutsui if( dpnt->parent != reloc_dir ) 445 1.1 tsutsui { 446 1.1 tsutsui set_721(jpath_table_l + jpath_table_index, 447 1.1 tsutsui dpnt->parent->jpath_index); 448 1.1 tsutsui set_722(jpath_table_m + jpath_table_index, 449 1.1 tsutsui dpnt->parent->jpath_index); 450 1.1 tsutsui } 451 1.1 tsutsui else 452 1.1 tsutsui { 453 1.1 tsutsui set_721(jpath_table_l + jpath_table_index, 454 1.1 tsutsui dpnt->self->parent_rec->filedir->jpath_index); 455 1.1 tsutsui set_722(jpath_table_m + jpath_table_index, 456 1.1 tsutsui dpnt->self->parent_rec->filedir->jpath_index); 457 1.1 tsutsui } 458 1.1 tsutsui 459 1.1 tsutsui jpath_table_index += 2; 460 1.1 tsutsui 461 1.1 tsutsui /* 462 1.1 tsutsui * The root directory is still represented in non-unicode fashion. 463 1.1 tsutsui */ 464 1.1 tsutsui if( dpnt == root ) 465 1.1 tsutsui { 466 1.1 tsutsui jpath_table_l[jpath_table_index] = 0; 467 1.1 tsutsui jpath_table_m[jpath_table_index] = 0; 468 1.1 tsutsui jpath_table_index ++; 469 1.1 tsutsui } 470 1.1 tsutsui else 471 1.1 tsutsui { 472 1.1 tsutsui #ifdef APPLE_HYB 473 1.1 tsutsui if (USE_MAC_NAME(mac_name , de)) { 474 1.1 tsutsui convert_to_unicode((u_char *)jpath_table_l + jpath_table_index, 475 1.1 tsutsui namelen, de->hfs_ent->name); 476 1.1 tsutsui convert_to_unicode((u_char *)jpath_table_m + jpath_table_index, 477 1.1 tsutsui namelen, de->hfs_ent->name); 478 1.1 tsutsui } 479 1.1 tsutsui else { 480 1.1 tsutsui #endif /* APPLE_HYB */ 481 1.1 tsutsui convert_to_unicode((u_char *)jpath_table_l + jpath_table_index, 482 1.1 tsutsui namelen, de->name); 483 1.1 tsutsui convert_to_unicode((u_char *)jpath_table_m + jpath_table_index, 484 1.1 tsutsui namelen, de->name); 485 1.1 tsutsui #ifdef APPLE_HYB 486 1.1 tsutsui } 487 1.1 tsutsui #endif /* APPLE_HYB */ 488 1.1 tsutsui 489 1.1 tsutsui jpath_table_index += namelen; 490 1.1 tsutsui } 491 1.1 tsutsui 492 1.1 tsutsui if(jpath_table_index & 1) 493 1.1 tsutsui { 494 1.1 tsutsui jpath_table_index++; /* For odd lengths we pad */ 495 1.1 tsutsui } 496 1.1 tsutsui } 497 1.1 tsutsui 498 1.1 tsutsui free(jpathlist); 499 1.1 tsutsui if(jpath_table_index != jpath_table_size) 500 1.1 tsutsui { 501 1.1 tsutsui fprintf(stderr,"Joliet path table lengths do not match %d %d\n", 502 1.1 tsutsui jpath_table_index, 503 1.1 tsutsui jpath_table_size); 504 1.1 tsutsui } 505 1.1 tsutsui return 0; 506 1.1 tsutsui } /* generate_path_tables(... */ 507 1.1 tsutsui 508 1.1 tsutsui static void FDECL2(generate_one_joliet_directory, struct directory *, dpnt, FILE *, outfile) 509 1.1 tsutsui { 510 1.1 tsutsui unsigned int dir_index; 511 1.1 tsutsui char * directory_buffer; 512 1.1 tsutsui int new_reclen; 513 1.1 tsutsui struct directory_entry * s_entry; 514 1.1 tsutsui struct directory_entry * s_entry1; 515 1.1 tsutsui struct iso_directory_record jrec; 516 1.1 tsutsui unsigned int total_size; 517 1.1 tsutsui int cvt_len; 518 1.1 tsutsui struct directory * finddir; 519 1.1 tsutsui 520 1.1 tsutsui total_size = (dpnt->jsize + (SECTOR_SIZE - 1)) & ~(SECTOR_SIZE - 1); 521 1.1 tsutsui directory_buffer = (char *) e_malloc(total_size); 522 1.1 tsutsui memset(directory_buffer, 0, total_size); 523 1.1 tsutsui dir_index = 0; 524 1.1 tsutsui 525 1.1 tsutsui s_entry = dpnt->jcontents; 526 1.1 tsutsui while(s_entry) 527 1.1 tsutsui { 528 1.1 tsutsui if(s_entry->de_flags & INHIBIT_JOLIET_ENTRY) { 529 1.1 tsutsui s_entry = s_entry->jnext; 530 1.1 tsutsui continue; 531 1.1 tsutsui } 532 1.1 tsutsui 533 1.1 tsutsui /* 534 1.1 tsutsui * If this entry was a directory that was relocated, we have a bit 535 1.1 tsutsui * of trouble here. We need to dig out the real thing and put it 536 1.1 tsutsui * back here. In the Joliet tree, there is no relocated rock 537 1.1 tsutsui * ridge, as there are no depth limits to a directory tree. 538 1.1 tsutsui */ 539 1.1 tsutsui if( (s_entry->de_flags & RELOCATED_DIRECTORY) != 0 ) 540 1.1 tsutsui { 541 1.1 tsutsui for(s_entry1 = reloc_dir->contents; s_entry1; s_entry1 = s_entry1->next) 542 1.1 tsutsui { 543 1.1 tsutsui if( s_entry1->parent_rec == s_entry ) 544 1.1 tsutsui { 545 1.1 tsutsui break; 546 1.1 tsutsui } 547 1.1 tsutsui } 548 1.1 tsutsui if( s_entry1 == NULL ) 549 1.1 tsutsui { 550 1.1 tsutsui /* 551 1.1 tsutsui * We got trouble. 552 1.1 tsutsui */ 553 1.1 tsutsui fprintf(stderr, "Unable to locate relocated directory\n"); 554 1.1 tsutsui exit(1); 555 1.1 tsutsui } 556 1.1 tsutsui } 557 1.1 tsutsui else 558 1.1 tsutsui { 559 1.1 tsutsui s_entry1 = s_entry; 560 1.1 tsutsui } 561 1.1 tsutsui 562 1.1 tsutsui /* 563 1.1 tsutsui * We do not allow directory entries to cross sector boundaries. 564 1.1 tsutsui * Simply pad, and then start the next entry at the next sector 565 1.1 tsutsui */ 566 1.1 tsutsui new_reclen = s_entry1->jreclen; 567 1.1 tsutsui if( (dir_index & (SECTOR_SIZE - 1)) + new_reclen >= SECTOR_SIZE ) 568 1.1 tsutsui { 569 1.1 tsutsui dir_index = (dir_index + (SECTOR_SIZE - 1)) & 570 1.1 tsutsui ~(SECTOR_SIZE - 1); 571 1.1 tsutsui } 572 1.1 tsutsui 573 1.1 tsutsui memcpy(&jrec, &s_entry1->isorec, sizeof(struct iso_directory_record) - 574 1.1 tsutsui sizeof(s_entry1->isorec.name)); 575 1.1 tsutsui 576 1.1 tsutsui #ifdef APPLE_HYB 577 1.1 tsutsui /* Use the HFS name if it exists */ 578 1.1 tsutsui if (USE_MAC_NAME(mac_name, s_entry1)) 579 1.1 tsutsui cvt_len = joliet_strlen(s_entry1->hfs_ent->name); 580 1.1 tsutsui else 581 1.1 tsutsui #endif /* APPLE_HYB */ 582 1.1 tsutsui cvt_len = joliet_strlen(s_entry1->name); 583 1.1 tsutsui 584 1.1 tsutsui /* 585 1.1 tsutsui * Fix the record length - this was the non-Joliet version we 586 1.1 tsutsui * were seeing. 587 1.1 tsutsui */ 588 1.1 tsutsui jrec.name_len[0] = cvt_len; 589 1.1 tsutsui jrec.length[0] = s_entry1->jreclen; 590 1.1 tsutsui 591 1.1 tsutsui /* 592 1.1 tsutsui * If this is a directory, fix the correct size and extent 593 1.1 tsutsui * number. 594 1.1 tsutsui */ 595 1.1 tsutsui if( (jrec.flags[0] & 2) != 0 ) 596 1.1 tsutsui { 597 1.1 tsutsui if(strcmp(s_entry1->name,".") == 0) 598 1.1 tsutsui { 599 1.1 tsutsui jrec.name_len[0] = 1; 600 1.1 tsutsui set_733((char *) jrec.extent, dpnt->jextent); 601 1.1 tsutsui set_733((char *) jrec.size, ROUND_UP(dpnt->jsize)); 602 1.1 tsutsui } 603 1.1 tsutsui else if(strcmp(s_entry1->name,"..") == 0) 604 1.1 tsutsui { 605 1.1 tsutsui jrec.name_len[0] = 1; 606 1.1 tsutsui if( dpnt->parent == reloc_dir ) 607 1.1 tsutsui { 608 1.1 tsutsui set_733((char *) jrec.extent, dpnt->self->parent_rec->filedir->jextent); 609 1.1 tsutsui set_733((char *) jrec.size, ROUND_UP(dpnt->self->parent_rec->filedir->jsize)); 610 1.1 tsutsui } 611 1.1 tsutsui else 612 1.1 tsutsui 613 1.1 tsutsui { 614 1.1 tsutsui set_733((char *) jrec.extent, dpnt->parent->jextent); 615 1.1 tsutsui set_733((char *) jrec.size, ROUND_UP(dpnt->parent->jsize)); 616 1.1 tsutsui } 617 1.1 tsutsui } 618 1.1 tsutsui else 619 1.1 tsutsui { 620 1.1 tsutsui if( (s_entry->de_flags & RELOCATED_DIRECTORY) != 0 ) 621 1.1 tsutsui { 622 1.1 tsutsui finddir = reloc_dir->subdir; 623 1.1 tsutsui } 624 1.1 tsutsui else 625 1.1 tsutsui { 626 1.1 tsutsui finddir = dpnt->subdir; 627 1.1 tsutsui } 628 1.1 tsutsui while(1==1) 629 1.1 tsutsui { 630 1.1 tsutsui if(finddir->self == s_entry1) break; 631 1.1 tsutsui finddir = finddir->next; 632 1.1 tsutsui if(!finddir) 633 1.1 tsutsui { 634 1.1 tsutsui fprintf(stderr,"Fatal goof - unable to find directory location\n"); exit(1); 635 1.1 tsutsui } 636 1.1 tsutsui } 637 1.1 tsutsui set_733((char *) jrec.extent, finddir->jextent); 638 1.1 tsutsui set_733((char *) jrec.size, ROUND_UP(finddir->jsize)); 639 1.1 tsutsui } 640 1.1 tsutsui } 641 1.1 tsutsui 642 1.1 tsutsui memcpy(directory_buffer + dir_index, &jrec, 643 1.1 tsutsui sizeof(struct iso_directory_record) - 644 1.1 tsutsui sizeof(s_entry1->isorec.name)); 645 1.1 tsutsui 646 1.1 tsutsui 647 1.1 tsutsui dir_index += sizeof(struct iso_directory_record) - 648 1.1 tsutsui sizeof (s_entry1->isorec.name); 649 1.1 tsutsui 650 1.1 tsutsui /* 651 1.1 tsutsui * Finally dump the Unicode version of the filename. 652 1.1 tsutsui * Note - . and .. are the same as with non-Joliet discs. 653 1.1 tsutsui */ 654 1.1 tsutsui if( (jrec.flags[0] & 2) != 0 655 1.1 tsutsui && strcmp(s_entry1->name, ".") == 0 ) 656 1.1 tsutsui { 657 1.1 tsutsui directory_buffer[dir_index++] = 0; 658 1.1 tsutsui } 659 1.1 tsutsui else if( (jrec.flags[0] & 2) != 0 660 1.1 tsutsui && strcmp(s_entry1->name, "..") == 0 ) 661 1.1 tsutsui { 662 1.1 tsutsui directory_buffer[dir_index++] = 1; 663 1.1 tsutsui } 664 1.1 tsutsui else 665 1.1 tsutsui { 666 1.1 tsutsui #ifdef APPLE_HYB 667 1.1 tsutsui if (USE_MAC_NAME(mac_name, s_entry1)) 668 1.1 tsutsui /* Use the HFS name if it exists */ 669 1.1 tsutsui convert_to_unicode((u_char *)directory_buffer + dir_index, 670 1.1 tsutsui cvt_len, 671 1.1 tsutsui s_entry1->hfs_ent->name); 672 1.1 tsutsui else 673 1.1 tsutsui #endif /* APPLE_HYB */ 674 1.1 tsutsui convert_to_unicode((u_char *)directory_buffer + dir_index, 675 1.1 tsutsui cvt_len, 676 1.1 tsutsui s_entry1->name); 677 1.1 tsutsui dir_index += cvt_len; 678 1.1 tsutsui } 679 1.1 tsutsui 680 1.1 tsutsui if(dir_index & 1) 681 1.1 tsutsui { 682 1.1 tsutsui directory_buffer[dir_index++] = 0; 683 1.1 tsutsui } 684 1.1 tsutsui 685 1.1 tsutsui s_entry = s_entry->jnext; 686 1.1 tsutsui } 687 1.1 tsutsui 688 1.1 tsutsui if(dpnt->jsize != dir_index) 689 1.1 tsutsui { 690 1.1 tsutsui fprintf(stderr,"Unexpected joliet directory length %d %d %s\n",dpnt->jsize, 691 1.1 tsutsui dir_index, dpnt->de_name); 692 1.1 tsutsui } 693 1.1 tsutsui 694 1.1 tsutsui xfwrite(directory_buffer, 1, total_size, outfile); 695 1.1 tsutsui last_extent_written += total_size >> 11; 696 1.1 tsutsui free(directory_buffer); 697 1.1 tsutsui } /* generate_one_joliet_directory(... */ 698 1.1 tsutsui 699 1.1 tsutsui static int FDECL1(joliet_sort_n_finish, struct directory *, this_dir) 700 1.1 tsutsui { 701 1.1 tsutsui struct directory_entry * s_entry; 702 1.1 tsutsui int status = 0; 703 1.1 tsutsui 704 1.1 tsutsui /* don't want to skip this directory if it's the reloc_dir at the moment */ 705 1.1 tsutsui if(this_dir != reloc_dir && this_dir->dir_flags & INHIBIT_JOLIET_ENTRY) 706 1.1 tsutsui { 707 1.1 tsutsui return 0; 708 1.1 tsutsui } 709 1.1 tsutsui 710 1.1 tsutsui for(s_entry = this_dir->contents; s_entry; s_entry = s_entry->next) 711 1.1 tsutsui { 712 1.1 tsutsui /* skip hidden entries */ 713 1.1 tsutsui if( (s_entry->de_flags & INHIBIT_JOLIET_ENTRY) != 0 ) 714 1.1 tsutsui { 715 1.1 tsutsui continue; 716 1.1 tsutsui } 717 1.1 tsutsui 718 1.1 tsutsui /* 719 1.1 tsutsui * First update the path table sizes for directories. 720 1.1 tsutsui * 721 1.1 tsutsui * Finally, set the length of the directory entry if Joliet is used. 722 1.1 tsutsui * The name is longer, but no Rock Ridge is ever used here, so 723 1.1 tsutsui * depending upon the options the entry size might turn out to be about 724 1.1 tsutsui * the same. The Unicode name is always a multiple of 2 bytes, so 725 1.1 tsutsui * we always add 1 to make it an even number. 726 1.1 tsutsui */ 727 1.1 tsutsui if(s_entry->isorec.flags[0] == 2) 728 1.1 tsutsui { 729 1.1 tsutsui if (strcmp(s_entry->name,".") && strcmp(s_entry->name,"..")) 730 1.1 tsutsui { 731 1.1 tsutsui #ifdef APPLE_HYB 732 1.1 tsutsui if (USE_MAC_NAME(mac_name, s_entry)) 733 1.1 tsutsui /* Use the HFS name if it exists */ 734 1.1 tsutsui jpath_table_size += joliet_strlen(s_entry->hfs_ent->name) + sizeof(struct iso_path_table) - 1; 735 1.1 tsutsui else 736 1.1 tsutsui #endif /* APPLE_HYB */ 737 1.1 tsutsui jpath_table_size += joliet_strlen(s_entry->name) + sizeof(struct iso_path_table) - 1; 738 1.1 tsutsui if (jpath_table_size & 1) 739 1.1 tsutsui { 740 1.1 tsutsui jpath_table_size++; 741 1.1 tsutsui } 742 1.1 tsutsui } 743 1.1 tsutsui else 744 1.1 tsutsui { 745 1.1 tsutsui if (this_dir == root && strlen(s_entry->name) == 1) 746 1.1 tsutsui { 747 1.1 tsutsui jpath_table_size += sizeof(struct iso_path_table); 748 1.1 tsutsui if (jpath_table_size & 1) jpath_table_size++; 749 1.1 tsutsui } 750 1.1 tsutsui } 751 1.1 tsutsui } 752 1.1 tsutsui 753 1.1 tsutsui if (strcmp(s_entry->name,".") && strcmp(s_entry->name,"..")) 754 1.1 tsutsui { 755 1.1 tsutsui #ifdef APPLE_HYB 756 1.1 tsutsui if (USE_MAC_NAME(mac_name, s_entry)) 757 1.1 tsutsui /* Use the HFS name if it exists */ 758 1.1 tsutsui s_entry->jreclen = sizeof(struct iso_directory_record) 759 1.1 tsutsui - sizeof(s_entry->isorec.name) 760 1.1 tsutsui + joliet_strlen(s_entry->hfs_ent->name) 761 1.1 tsutsui + 1; 762 1.1 tsutsui else 763 1.1 tsutsui #endif /* APPLE_HYB */ 764 1.1 tsutsui s_entry->jreclen = sizeof(struct iso_directory_record) 765 1.1 tsutsui - sizeof(s_entry->isorec.name) 766 1.1 tsutsui + joliet_strlen(s_entry->name) 767 1.1 tsutsui + 1; 768 1.1 tsutsui } 769 1.1 tsutsui else 770 1.1 tsutsui { 771 1.1 tsutsui /* 772 1.1 tsutsui * Special - for '.' and '..' we generate the same records we 773 1.1 tsutsui * did for non-Joliet discs. 774 1.1 tsutsui */ 775 1.1 tsutsui s_entry->jreclen = sizeof(struct iso_directory_record) 776 1.1 tsutsui - sizeof(s_entry->isorec.name) 777 1.1 tsutsui + 1; 778 1.1 tsutsui } 779 1.1 tsutsui 780 1.1 tsutsui 781 1.1 tsutsui } 782 1.1 tsutsui 783 1.1 tsutsui if( (this_dir->dir_flags & INHIBIT_JOLIET_ENTRY) != 0 ) 784 1.1 tsutsui { 785 1.1 tsutsui return 0; 786 1.1 tsutsui } 787 1.1 tsutsui 788 1.1 tsutsui this_dir->jcontents = this_dir->contents; 789 1.1 tsutsui status = joliet_sort_directory(&this_dir->jcontents); 790 1.1 tsutsui 791 1.1 tsutsui /* 792 1.1 tsutsui * Now go through the directory and figure out how large this one will be. 793 1.1 tsutsui * Do not split a directory entry across a sector boundary 794 1.1 tsutsui */ 795 1.1 tsutsui s_entry = this_dir->jcontents; 796 1.1 tsutsui /* 797 1.1 tsutsui * XXX Is it ok to comment this out? 798 1.1 tsutsui */ 799 1.1 tsutsui /*XXX JS this_dir->ce_bytes = 0;*/ 800 1.1 tsutsui for(s_entry = this_dir->jcontents; s_entry; s_entry = s_entry->jnext) 801 1.1 tsutsui { 802 1.1 tsutsui int jreclen; 803 1.1 tsutsui 804 1.1 tsutsui if( (s_entry->de_flags & INHIBIT_JOLIET_ENTRY) != 0 ) 805 1.1 tsutsui { 806 1.1 tsutsui continue; 807 1.1 tsutsui } 808 1.1 tsutsui 809 1.1 tsutsui jreclen = s_entry->jreclen; 810 1.1 tsutsui 811 1.1 tsutsui if ((this_dir->jsize & (SECTOR_SIZE - 1)) + jreclen >= SECTOR_SIZE) 812 1.1 tsutsui { 813 1.1 tsutsui this_dir->jsize = (this_dir->jsize + (SECTOR_SIZE - 1)) & 814 1.1 tsutsui ~(SECTOR_SIZE - 1); 815 1.1 tsutsui } 816 1.1 tsutsui this_dir->jsize += jreclen; 817 1.1 tsutsui } 818 1.1 tsutsui return status; 819 1.1 tsutsui } 820 1.1 tsutsui 821 1.1 tsutsui /* 822 1.1 tsutsui * Similar to the iso9660 case, except here we perform a full sort based upon the 823 1.1 tsutsui * regular name of the file, not the 8.3 version. 824 1.1 tsutsui */ 825 1.1 tsutsui static int FDECL2(joliet_compare_dirs, const void *, rr, const void *, ll) 826 1.1 tsutsui { 827 1.1 tsutsui char * rpnt, *lpnt; 828 1.1 tsutsui struct directory_entry ** r, **l; 829 1.1 tsutsui 830 1.1 tsutsui r = (struct directory_entry **) rr; 831 1.1 tsutsui l = (struct directory_entry **) ll; 832 1.1 tsutsui rpnt = (*r)->name; 833 1.1 tsutsui lpnt = (*l)->name; 834 1.1 tsutsui 835 1.1 tsutsui /* 836 1.1 tsutsui * If the entries are the same, this is an error. 837 1.1 tsutsui */ 838 1.1 tsutsui if( strcmp(rpnt, lpnt) == 0 ) 839 1.1 tsutsui { 840 1.1 tsutsui sort_goof++; 841 1.1 tsutsui } 842 1.1 tsutsui 843 1.1 tsutsui /* 844 1.1 tsutsui * Put the '.' and '..' entries on the head of the sorted list. 845 1.1 tsutsui * For normal ASCII, this always happens to be the case, but out of 846 1.1 tsutsui * band characters cause this not to be the case sometimes. 847 1.1 tsutsui */ 848 1.1 tsutsui if( strcmp(rpnt, ".") == 0 ) return -1; 849 1.1 tsutsui if( strcmp(lpnt, ".") == 0 ) return 1; 850 1.1 tsutsui 851 1.1 tsutsui if( strcmp(rpnt, "..") == 0 ) return -1; 852 1.1 tsutsui if( strcmp(lpnt, "..") == 0 ) return 1; 853 1.1 tsutsui 854 1.1 tsutsui while(*rpnt && *lpnt) 855 1.1 tsutsui { 856 1.1 tsutsui if(*rpnt == ';' && *lpnt != ';') return -1; 857 1.1 tsutsui if(*rpnt != ';' && *lpnt == ';') return 1; 858 1.1 tsutsui 859 1.1 tsutsui if(*rpnt == ';' && *lpnt == ';') return 0; 860 1.1 tsutsui 861 1.1 tsutsui /* 862 1.1 tsutsui * Extensions are not special here. Don't treat the dot as something that 863 1.1 tsutsui * must be bumped to the start of the list. 864 1.1 tsutsui */ 865 1.1 tsutsui #if 0 866 1.1 tsutsui if(*rpnt == '.' && *lpnt != '.') return -1; 867 1.1 tsutsui if(*rpnt != '.' && *lpnt == '.') return 1; 868 1.1 tsutsui #endif 869 1.1 tsutsui 870 1.1 tsutsui if(*rpnt < *lpnt) return -1; 871 1.1 tsutsui if(*rpnt > *lpnt) return 1; 872 1.1 tsutsui rpnt++; lpnt++; 873 1.1 tsutsui } 874 1.1 tsutsui if(*rpnt) return 1; 875 1.1 tsutsui if(*lpnt) return -1; 876 1.1 tsutsui return 0; 877 1.1 tsutsui } 878 1.1 tsutsui 879 1.1 tsutsui 880 1.1 tsutsui /* 881 1.1 tsutsui * Function: sort_directory 882 1.1 tsutsui * 883 1.1 tsutsui * Purpose: Sort the directory in the appropriate ISO9660 884 1.1 tsutsui * order. 885 1.1 tsutsui * 886 1.1 tsutsui * Notes: Returns 0 if OK, returns > 0 if an error occurred. 887 1.1 tsutsui */ 888 1.1 tsutsui static int FDECL1(joliet_sort_directory, struct directory_entry **, sort_dir) 889 1.1 tsutsui { 890 1.1 tsutsui int dcount = 0; 891 1.1 tsutsui int i; 892 1.1 tsutsui struct directory_entry * s_entry; 893 1.1 tsutsui struct directory_entry ** sortlist; 894 1.1 tsutsui 895 1.1 tsutsui s_entry = *sort_dir; 896 1.1 tsutsui while(s_entry) 897 1.1 tsutsui { 898 1.1 tsutsui /* skip hidden entries */ 899 1.1 tsutsui if (!(s_entry->de_flags & INHIBIT_JOLIET_ENTRY)) 900 1.1 tsutsui dcount++; 901 1.1 tsutsui s_entry = s_entry->next; 902 1.1 tsutsui } 903 1.1 tsutsui 904 1.1 tsutsui /* 905 1.1 tsutsui * OK, now we know how many there are. Build a vector for sorting. 906 1.1 tsutsui */ 907 1.1 tsutsui sortlist = (struct directory_entry **) 908 1.1 tsutsui e_malloc(sizeof(struct directory_entry *) * dcount); 909 1.1 tsutsui 910 1.1 tsutsui dcount = 0; 911 1.1 tsutsui s_entry = *sort_dir; 912 1.1 tsutsui while(s_entry) 913 1.1 tsutsui { 914 1.1 tsutsui /* skip hidden entries */ 915 1.1 tsutsui if (!(s_entry->de_flags & INHIBIT_JOLIET_ENTRY)) { 916 1.1 tsutsui sortlist[dcount] = s_entry; 917 1.1 tsutsui dcount++; 918 1.1 tsutsui } 919 1.1 tsutsui s_entry = s_entry->next; 920 1.1 tsutsui } 921 1.1 tsutsui 922 1.1 tsutsui sort_goof = 0; 923 1.1 tsutsui #ifdef __STDC__ 924 1.1 tsutsui qsort(sortlist, dcount, sizeof(struct directory_entry *), 925 1.1 tsutsui (int (*)(const void *, const void *))joliet_compare_dirs); 926 1.1 tsutsui #else 927 1.1 tsutsui qsort(sortlist, dcount, sizeof(struct directory_entry *), 928 1.1 tsutsui joliet_compare_dirs); 929 1.1 tsutsui #endif 930 1.1 tsutsui 931 1.1 tsutsui /* 932 1.1 tsutsui * Now reassemble the linked list in the proper sorted order 933 1.1 tsutsui */ 934 1.1 tsutsui for(i=0; i<dcount-1; i++) 935 1.1 tsutsui { 936 1.1 tsutsui sortlist[i]->jnext = sortlist[i+1]; 937 1.1 tsutsui } 938 1.1 tsutsui 939 1.1 tsutsui sortlist[dcount-1]->jnext = NULL; 940 1.1 tsutsui *sort_dir = sortlist[0]; 941 1.1 tsutsui 942 1.1 tsutsui free(sortlist); 943 1.1 tsutsui return sort_goof; 944 1.1 tsutsui } 945 1.1 tsutsui 946 1.1 tsutsui int FDECL1(joliet_sort_tree, struct directory *, node) 947 1.1 tsutsui { 948 1.1 tsutsui struct directory * dpnt; 949 1.1 tsutsui int ret = 0; 950 1.1 tsutsui 951 1.1 tsutsui dpnt = node; 952 1.1 tsutsui 953 1.1 tsutsui while (dpnt){ 954 1.1 tsutsui ret = joliet_sort_n_finish(dpnt); 955 1.1 tsutsui if( ret ) 956 1.1 tsutsui { 957 1.1 tsutsui break; 958 1.1 tsutsui } 959 1.1 tsutsui if(dpnt->subdir) ret = joliet_sort_tree(dpnt->subdir); 960 1.1 tsutsui if( ret ) 961 1.1 tsutsui { 962 1.1 tsutsui break; 963 1.1 tsutsui } 964 1.1 tsutsui dpnt = dpnt->next; 965 1.1 tsutsui } 966 1.1 tsutsui return ret; 967 1.1 tsutsui } 968 1.1 tsutsui 969 1.1 tsutsui static void FDECL2(generate_joliet_directories, struct directory *, node, FILE*, outfile){ 970 1.1 tsutsui struct directory * dpnt; 971 1.1 tsutsui 972 1.1 tsutsui dpnt = node; 973 1.1 tsutsui 974 1.1 tsutsui while (dpnt) 975 1.1 tsutsui { 976 1.1 tsutsui if( (dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) == 0 ) 977 1.1 tsutsui { 978 1.1 tsutsui /* 979 1.1 tsutsui * In theory we should never reuse a directory, so this doesn't 980 1.1 tsutsui * make much sense. 981 1.1 tsutsui */ 982 1.1 tsutsui if( dpnt->jextent > session_start ) 983 1.1 tsutsui { 984 1.1 tsutsui generate_one_joliet_directory(dpnt, outfile); 985 1.1 tsutsui } 986 1.1 tsutsui } 987 1.1 tsutsui /* skip if hidden - but not for the rr_moved dir */ 988 1.1 tsutsui if(dpnt->subdir && (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) || dpnt == reloc_dir)) 989 1.1 tsutsui generate_joliet_directories(dpnt->subdir, outfile); 990 1.1 tsutsui dpnt = dpnt->next; 991 1.1 tsutsui } 992 1.1 tsutsui } 993 1.1 tsutsui 994 1.1 tsutsui 995 1.1 tsutsui /* 996 1.1 tsutsui * Function to write the EVD for the disc. 997 1.1 tsutsui */ 998 1.1 tsutsui static int FDECL1(jpathtab_write, FILE *, outfile) 999 1.1 tsutsui { 1000 1.1 tsutsui /* 1001 1.1 tsutsui * Next we write the path tables 1002 1.1 tsutsui */ 1003 1.1 tsutsui xfwrite(jpath_table_l, 1, jpath_blocks << 11, outfile); 1004 1.1 tsutsui xfwrite(jpath_table_m, 1, jpath_blocks << 11, outfile); 1005 1.1 tsutsui last_extent_written += 2*jpath_blocks; 1006 1.1 tsutsui free(jpath_table_l); 1007 1.1 tsutsui free(jpath_table_m); 1008 1.1 tsutsui jpath_table_l = NULL; 1009 1.1 tsutsui jpath_table_m = NULL; 1010 1.1 tsutsui return 0; 1011 1.1 tsutsui } 1012 1.1 tsutsui 1013 1.1 tsutsui static int FDECL1(jdirtree_size, int, starting_extent) 1014 1.1 tsutsui { 1015 1.1 tsutsui assign_joliet_directory_addresses(root); 1016 1.1 tsutsui return 0; 1017 1.1 tsutsui } 1018 1.1 tsutsui 1019 1.1 tsutsui static int jroot_gen() 1020 1.1 tsutsui { 1021 1.1 tsutsui jroot_record.length[0] = 1 + sizeof(struct iso_directory_record) 1022 1.1 tsutsui - sizeof(jroot_record.name); 1023 1.1 tsutsui jroot_record.ext_attr_length[0] = 0; 1024 1.1 tsutsui set_733((char *) jroot_record.extent, root->jextent); 1025 1.1 tsutsui set_733((char *) jroot_record.size, ROUND_UP(root->jsize)); 1026 1.1 tsutsui iso9660_date(jroot_record.date, root_statbuf.st_mtime); 1027 1.1 tsutsui jroot_record.flags[0] = 2; 1028 1.1 tsutsui jroot_record.file_unit_size[0] = 0; 1029 1.1 tsutsui jroot_record.interleave[0] = 0; 1030 1.1 tsutsui set_723(jroot_record.volume_sequence_number, volume_sequence_number); 1031 1.1 tsutsui jroot_record.name_len[0] = 1; 1032 1.1 tsutsui return 0; 1033 1.1 tsutsui } 1034 1.1 tsutsui 1035 1.1 tsutsui static int FDECL1(jdirtree_write, FILE *, outfile) 1036 1.1 tsutsui { 1037 1.1 tsutsui generate_joliet_directories(root, outfile); 1038 1.1 tsutsui return 0; 1039 1.1 tsutsui } 1040 1.1 tsutsui 1041 1.1 tsutsui /* 1042 1.1 tsutsui * Function to write the EVD for the disc. 1043 1.1 tsutsui */ 1044 1.1 tsutsui static int FDECL1(jvd_write, FILE *, outfile) 1045 1.1 tsutsui { 1046 1.1 tsutsui struct iso_primary_descriptor jvol_desc; 1047 1.1 tsutsui 1048 1.1 tsutsui /* 1049 1.1 tsutsui * Next we write out the boot volume descriptor for the disc 1050 1.1 tsutsui */ 1051 1.1 tsutsui jvol_desc = vol_desc; 1052 1.1 tsutsui get_joliet_vol_desc(&jvol_desc); 1053 1.1 tsutsui xfwrite(&jvol_desc, 1, 2048, outfile); 1054 1.1 tsutsui last_extent_written ++; 1055 1.1 tsutsui return 0; 1056 1.1 tsutsui } 1057 1.1 tsutsui 1058 1.1 tsutsui /* 1059 1.1 tsutsui * Functions to describe padding block at the start of the disc. 1060 1.1 tsutsui */ 1061 1.1 tsutsui static int FDECL1(jpathtab_size, int, starting_extent) 1062 1.1 tsutsui { 1063 1.1 tsutsui jpath_table[0] = starting_extent; 1064 1.1 tsutsui jpath_table[1] = 0; 1065 1.1 tsutsui jpath_table[2] = jpath_table[0] + jpath_blocks; 1066 1.1 tsutsui jpath_table[3] = 0; 1067 1.1 tsutsui 1068 1.1 tsutsui last_extent += 2*jpath_blocks; 1069 1.1 tsutsui return 0; 1070 1.1 tsutsui } 1071 1.1 tsutsui 1072 1.1 tsutsui struct output_fragment joliet_desc = {NULL, oneblock_size, jroot_gen,jvd_write}; 1073 1.1 tsutsui struct output_fragment jpathtable_desc= {NULL, jpathtab_size, generate_joliet_path_tables, jpathtab_write}; 1074 1.1 tsutsui struct output_fragment jdirtree_desc = {NULL, jdirtree_size, NULL, jdirtree_write}; 1075