joliet.c 27 KB

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