joliet.c revision 1.1 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