File: | src/gnu/usr.sbin/mkhybrid/mkhybrid/../src/volume.c |
Warning: | line 209, column 2 Value stored to 'vlen' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* |
2 | ** volume.c: prepare HFS volume for mkhybrid |
3 | ** |
4 | ** James Pearson 17/7/97 |
5 | ** modified JCP 29/7/97 to improve allocation sizes to cut |
6 | ** down on wasted space. Now uses the HFS "allocation" size rounded |
7 | ** up to the nearest 2048 bytes. Savings can be significant with |
8 | ** a large volume containing lots of smallish files. |
9 | ** |
10 | ** Updated for v1.12 - now uses the built in RELOCATED_DIRECTORY |
11 | ** flag for finding the real directory location JCP 8/1/97 |
12 | */ |
13 | |
14 | #ifdef APPLE_HYB1 |
15 | |
16 | #include "config.h" |
17 | #include "mkisofs.h" |
18 | #include "volume.h" |
19 | #include "write.h" |
20 | #include <errno(*__errno()).h> |
21 | |
22 | static hfsvol *vol_save = 0; /* used to "destroy" an HFS volume */ |
23 | |
24 | int DECL(copy_to_mac_vol, (hfsvol *, struct directory *))copy_to_mac_vol (hfsvol *, struct directory *); |
25 | |
26 | /* |
27 | ** AlcSiz: find allocation size for given volume size |
28 | */ |
29 | int |
30 | AlcSiz(int vlen) |
31 | { |
32 | int lpa, drAlBlkSiz; |
33 | |
34 | /* code extracted from hfs_format() */ |
35 | lpa = 1 + vlen / 65536; |
36 | drAlBlkSiz = lpa * HFS_BLOCKSZ512; |
37 | |
38 | /* now set our "allocation size" to the allocation block rounded |
39 | up to the nearest SECTOR_SIZE (2048 bytes) */ |
40 | drAlBlkSiz = V_ROUND_UP(drAlBlkSiz, SECTOR_SIZE)(((drAlBlkSiz + ((2048) - 1)) / (2048)) * (2048)); |
41 | |
42 | return(drAlBlkSiz); |
43 | } |
44 | |
45 | /* |
46 | ** XClpSiz: find the default size of the catalog/extent file |
47 | */ |
48 | int |
49 | XClpSiz(int vlen) |
50 | { |
51 | int olpa, lpa, drNmAlBlks, drAlBlkSiz; |
52 | int vbmsz, drXTClpSiz; |
53 | |
54 | /* code extracted from hfs_format() */ |
55 | |
56 | /* get the lpa from our calculated allocation block size */ |
57 | drAlBlkSiz = AlcSiz(vlen); |
58 | lpa = drAlBlkSiz/HFS_BLOCKSZ512; |
59 | |
60 | vbmsz = (vlen / lpa + 4095) / 4096; |
61 | drNmAlBlks = (vlen - 5 - vbmsz) / lpa; |
62 | drXTClpSiz = drNmAlBlks / 128 * drAlBlkSiz; |
63 | |
64 | /* make allowances because we have possibly rounded up the |
65 | allocation size */ |
66 | |
67 | /* get the "original" lpa " */ |
68 | olpa = 1 + vlen / 65536; |
69 | |
70 | /* adjust size upwards */ |
71 | drXTClpSiz = (drXTClpSiz*lpa)/olpa; |
72 | |
73 | /* round up to the nearest alloaction size */ |
74 | drXTClpSiz = V_ROUND_UP(drXTClpSiz, drAlBlkSiz)(((drXTClpSiz + (drAlBlkSiz - 1)) / drAlBlkSiz) * drAlBlkSiz); |
75 | |
76 | return(drXTClpSiz); |
77 | } |
78 | |
79 | /* |
80 | ** get_vol_size: get the size of the volume including the extent/catalog |
81 | */ |
82 | int |
83 | get_vol_size(int vblen) |
84 | { |
85 | int drXTClpSiz, drAlBlkSiz; |
86 | int new_vblen; |
87 | |
88 | /* try to estimate a "volume size" based on the code |
89 | in hfs_format - we need the size of the catalog/extents |
90 | and Desktop files included in the volume, as we add this |
91 | to the end of the ISO volume */ |
92 | |
93 | drXTClpSiz = XClpSiz(vblen); |
94 | drAlBlkSiz = AlcSiz(vblen); |
95 | |
96 | /* catalog file is set at CTC times (default twice) the extents file |
97 | size - hence the (ctc_size + 1) below. The Desktop starts of the |
98 | same size as the "clump size" == 4 x drAlBlkSiz, plus a spare |
99 | drAlBlkSiz for the alternative MDB */ |
100 | |
101 | new_vblen = vblen + ((hce->ctc_size + 1)*drXTClpSiz + 5*drAlBlkSiz)/HFS_BLOCKSZ512; |
102 | |
103 | return (new_vblen); |
104 | } |
105 | |
106 | /* |
107 | ** write_fork: "write" file data to the volume |
108 | ** |
109 | ** This is used to update the HFS file internal structures |
110 | ** but no data is actually written (it's trapped deep down in |
111 | ** libhfs). |
112 | */ |
113 | int |
114 | write_fork(hfsfile *hfp, long tot) |
115 | { |
116 | char blk[HFS_BLOCKSZ512]; |
117 | unsigned short start; |
118 | long len; |
119 | |
120 | len = tot; |
121 | /* we need to know where this fork starts */ |
122 | start = hfs_get_drAllocPtr(hfp); |
123 | |
124 | /* loop through the data a block at a time */ |
125 | while (len >= HFS_BLOCKSZ512) |
126 | { |
127 | if(hfs_write(hfp, blk, HFS_BLOCKSZ512) < 0) |
128 | return(-1); |
129 | len -= HFS_BLOCKSZ512; |
130 | } |
131 | /* write out anything left */ |
132 | if (len) |
133 | if(hfs_write(hfp, blk, len) < 0) |
134 | return(-1); |
135 | |
136 | /* set the start of the allocation search to be immediately |
137 | after this fork */ |
138 | hfs_set_drAllocPtr(hfp, start, tot); |
139 | |
140 | return(0); |
141 | } |
142 | |
143 | /* |
144 | ** make_mac_volume: "create" an HFS volume using the ISO data |
145 | ** |
146 | ** The HFS volume structures are set up (but no data is written yet). |
147 | ** |
148 | ** ISO volumes have a allocation size of 2048 bytes - regardless |
149 | ** of the size of the volume. HFS allocation size is depends on volume |
150 | ** size, so we may have to update the ISO structures to add in any |
151 | ** padding. |
152 | */ |
153 | int FDECL2(make_mac_volume, struct directory *, dpnt, int, start_extent)make_mac_volume(struct directory * dpnt, int start_extent) |
154 | { |
155 | char vol_name[HFS_MAX_VLEN27+1]; /* Mac volume name */ |
156 | hfsvol *vol; /* Mac volume */ |
157 | int vlen, vblen; /* vol length (bytes, blocks) */ |
158 | int Csize, lastCsize; /* allocation sizes */ |
159 | int ret = 0; /* return value */ |
160 | int loop = 1; |
161 | |
162 | /* umount volume if we have had a previous attempt */ |
163 | if (vol_save) |
164 | if (hfs_umount(vol_save, 0) < 0) |
165 | return (-1); |
166 | |
167 | /* set the default clump size to the ISO block size */ |
168 | lastCsize = SECTOR_SIZE(2048); |
169 | |
170 | if (verbose > 1) |
171 | fprintf(stderr(&__sF[2]), "Creating HFS Volume info\n"); |
172 | |
173 | /* name or copy ISO volume name to Mac Volume name */ |
174 | strncpy(vol_name, hfs_volume_id ? hfs_volume_id : volume_id, HFS_MAX_VLEN27); |
175 | vol_name[HFS_MAX_VLEN27] = '\0'; |
176 | |
177 | /* get initial size of HFS volume (size of ISO volume) */ |
178 | vblen = last_extent * BLK_CONV((2048)/512); |
179 | |
180 | /* add on size of extents/catalog file, but this may mean |
181 | the allocation size will change, so loop round until the allocation |
182 | size doesn't change */ |
183 | while (loop) { |
184 | hce->XTCsize = XClpSiz(vblen); |
185 | vblen = get_vol_size(vblen); |
186 | Csize = AlcSiz(vblen); |
187 | |
188 | if (Csize == lastCsize) { |
189 | /* allocation size hasn't changed, so carry on */ |
190 | loop = 0; |
191 | } |
192 | else { |
193 | /* allocation size has changed, so update ISO volume size */ |
194 | if ((vlen = get_adj_size(Csize)) < 0) { |
195 | snprintf(hce->error, ERROR_SIZE1024, |
196 | "too many files for HFS volume"); |
197 | return (-1); |
198 | } |
199 | vlen += V_ROUND_UP(start_extent * SECTOR_SIZE, Csize)(((start_extent * (2048) + (Csize - 1)) / Csize) * Csize); |
200 | vblen = vlen / HFS_BLOCKSZ512; |
201 | lastCsize = Csize; |
202 | } |
203 | } |
204 | |
205 | /* set vlen to size in bytes */ |
206 | /* vlen = hce->hfs_vol_size = vblen * HFS_BLOCKSZ; */ |
207 | /* take off the label/map size */ |
208 | vblen -= hce->hfs_map_size; |
209 | vlen = hce->hfs_vol_size = vblen * HFS_BLOCKSZ512; |
Value stored to 'vlen' is never read | |
210 | |
211 | /* set the default allocation size for libhfs */ |
212 | hce->Csize = Csize; |
213 | |
214 | /* format and mount the "volume" */ |
215 | if (hfs_format(hce, 0, vol_name) < 0) |
216 | { |
217 | snprintf(hce->error, ERROR_SIZE1024, "can't HFS format %s",vol_name); |
218 | return(-1); |
219 | } |
220 | |
221 | /* update the ISO structures with new start extents and any padding |
222 | required */ |
223 | if (Csize != SECTOR_SIZE(2048)) { |
224 | last_extent = adj_size(Csize, start_extent, hce->hfs_hdr_size + hce->hfs_map_size); |
225 | adj_size_other(dpnt); |
226 | } |
227 | |
228 | if ((vol = hfs_mount(hce, 0, 0)) == 0) |
229 | { |
230 | snprintf(hce->error, ERROR_SIZE1024, "can't HFS mount %s",vol_name); |
231 | return(-1); |
232 | } |
233 | |
234 | /* save the volume for possible later use */ |
235 | vol_save = vol; |
236 | |
237 | /* Recursively "copy" the files to the volume - we need to |
238 | know the first allocation block in the volume as starting blocks |
239 | of files are relative to this. |
240 | */ |
241 | ret = copy_to_mac_vol(vol, dpnt); |
242 | if (ret < 0) |
243 | return(ret); |
244 | |
245 | /* make the Desktop files - I *think* this stops the Mac |
246 | rebuilding the desktop when the CD is mounted on a Mac |
247 | These will be ignored if they already exist */ |
248 | if (create_dt) |
249 | ret = make_desktop(vol, last_extent*BLK_CONV((2048)/512)); |
250 | if (ret < 0) |
251 | return(ret); |
252 | |
253 | /* close the volume */ |
254 | if (hfs_flush(vol) < 0) |
255 | return(-1); |
256 | |
257 | /* unmount and set the start blocks for the catalog/extents files */ |
258 | if (hfs_umount(vol, last_extent*BLK_CONV((2048)/512)) < 0) |
259 | return(-1); |
260 | |
261 | return(Csize); |
262 | } |
263 | |
264 | #define TEN10 10 /* well, it is! */ |
265 | #define LCHAR"_" "_" |
266 | |
267 | /* copy_to_mac_vol: copy all files in a directory to corresponding |
268 | ** Mac folder. |
269 | ** |
270 | ** Files are copied recursively to corresponding folders on the Mac |
271 | ** volume. The caller routine needs to do a hfs_chdir before calling this |
272 | ** routine. |
273 | */ |
274 | int FDECL2(copy_to_mac_vol, hfsvol *, vol, struct directory *, node)copy_to_mac_vol(hfsvol * vol, struct directory * node) |
275 | { |
276 | struct directory_entry * s_entry; /* ISO directory entry */ |
277 | struct directory_entry * s_entry1; /* tmp ISO directory entry */ |
278 | struct directory *dpnt; /* ISO directory */ |
279 | |
280 | hfsfile *hfp; /* HFS file */ |
281 | hfsdirent *ent; /* HFS file entities */ |
282 | long id; /* current HFS folder */ |
283 | long dext, rext; /* real data/rsrc start blk */ |
284 | int ret; /* result code */ |
285 | int new_name; /* HFS file has modified name */ |
286 | |
287 | int tens; |
288 | int digits; |
289 | int i; |
290 | |
291 | /* store the current HFS directory ID */ |
292 | if ((id = hfs_getcwd(vol)) == 0) |
293 | return(-1); |
294 | |
295 | if (verbose > 1) |
296 | fprintf(stderr(&__sF[2]),"HFS scanning %s\n", node->whole_name); |
297 | |
298 | /* loop through the ISO directory entries and process files */ |
299 | for(s_entry = node->contents; s_entry; s_entry = s_entry->next) |
300 | { |
301 | /* ignore directory and associated (rsrc) files */ |
302 | if(s_entry->isorec.flags[0]) |
303 | continue; |
304 | |
305 | /* ignore any non-Mac type file */ |
306 | if(!s_entry->hfs_ent) |
307 | continue; |
308 | |
309 | #ifdef DEBUG |
310 | fprintf(stderr(&__sF[2])," Name = %s", s_entry->whole_name); |
311 | fprintf(stderr(&__sF[2])," Startb = %d\n", s_entry->starting_block); |
312 | #endif /* DEBUG */ |
313 | |
314 | ent = s_entry->hfs_ent; |
315 | |
316 | /* create file */ |
317 | i = HFS_MAX_FLEN31 - strlen(ent->name); |
318 | new_name = 0; |
319 | tens = TEN10; |
320 | digits = 1; |
321 | |
322 | while (1) |
323 | { |
324 | /* try to open file - if it exists, then append '_' to |
325 | the name and try again */ |
326 | errno(*__errno()) = 0; |
327 | if ((hfs_create(vol, ent->name, ent->type, ent->creator)) < 0) |
328 | { |
329 | if (errno(*__errno()) != EEXIST17 ) |
330 | { |
331 | /* not an "exist" error, or we can't append as |
332 | the filename is already HFS_MAX_FLEN chars */ |
333 | snprintf(hce->error, ERROR_SIZE1024, |
334 | "can't HFS create file %s", |
335 | s_entry->whole_name); |
336 | return(-1); |
337 | } |
338 | else if (i == 0) |
339 | { |
340 | /* File name at max HFS length - make unique name */ |
341 | if (!new_name) new_name++; |
342 | |
343 | sprintf(ent->name + HFS_MAX_FLEN31 - digits - 1, |
344 | "%s%d", LCHAR"_", new_name); |
345 | new_name++; |
346 | if (new_name == tens) { |
347 | tens *= TEN10; |
348 | digits++; |
349 | } |
350 | } |
351 | else |
352 | { |
353 | /* append '_' to get new name */ |
354 | strcat(ent->name, LCHAR"_"); |
355 | i--; |
356 | new_name = 1; |
357 | } |
358 | } |
359 | else |
360 | break; |
361 | } |
362 | |
363 | /* warn that we have a new name */ |
364 | if (new_name && verbose > 0) |
365 | { |
366 | fprintf(stderr(&__sF[2]), "Using HFS name: %s for %s\n", ent->name, |
367 | s_entry->whole_name); |
368 | } |
369 | |
370 | /* open file */ |
371 | if ((hfp = hfs_open(vol, ent->name)) == 0) |
372 | { |
373 | snprintf(hce->error, ERROR_SIZE1024, "can't HFS open %s", |
374 | s_entry->whole_name); |
375 | return(-1); |
376 | } |
377 | |
378 | /* if it has a data fork, then "write" it out */ |
379 | if (ent->dsize) |
380 | write_fork(hfp, ent->dsize); |
381 | |
382 | /* if it has a resource fork, set the fork and "write" it out */ |
383 | if (ent->rsize) |
384 | { |
385 | if ((hfs_setfork(hfp, 1)) < 0) |
386 | return(-1); |
387 | write_fork(hfp, ent->rsize); |
388 | } |
389 | |
390 | /* update any HFS file attributes */ |
391 | if ((hfs_fsetattr(hfp, ent)) < 0) |
392 | { |
393 | snprintf(hce->error, ERROR_SIZE1024, "can't HFS set attributes %s", |
394 | s_entry->whole_name); |
395 | return(-1); |
396 | } |
397 | |
398 | /* get the ISO starting block of data fork (may be zero) |
399 | and convert to the equivalent HFS block */ |
400 | if (ent->dsize) |
401 | dext = s_entry->starting_block * BLK_CONV((2048)/512); |
402 | else |
403 | dext = 0; |
404 | |
405 | /* if the file has a resource fork (associated file), get it's |
406 | ISO starting block and convert as above */ |
407 | if (s_entry->assoc && ent->rsize) |
408 | rext = s_entry->assoc->starting_block * BLK_CONV((2048)/512); |
409 | else |
410 | rext = 0; |
411 | |
412 | /* close the file and update the starting blocks */ |
413 | if (hfs_close(hfp, dext, rext) < 0) |
414 | { |
415 | snprintf(hce->error, ERROR_SIZE1024, "can't HFS close file %s", |
416 | s_entry->whole_name); |
417 | return(-1); |
418 | } |
419 | } |
420 | |
421 | /* process sub-directories - have a slight problem here, |
422 | if the directory had been relocated, then we need to find |
423 | the real directory - we do this by first finding the real |
424 | directory_entry, and then finding it's directory info */ |
425 | |
426 | /* following code taken from joliet.c */ |
427 | for(s_entry=node->contents;s_entry;s_entry=s_entry->next) |
428 | { |
429 | if((s_entry->de_flags & RELOCATED_DIRECTORY0x20) != 0) |
430 | { |
431 | /* if the directory has been reloacted, then search the |
432 | relocated directory for the real entry */ |
433 | for(s_entry1=reloc_dir->contents;s_entry1;s_entry1=s_entry1->next) |
434 | { |
435 | if(s_entry1->parent_rec == s_entry) |
436 | break; |
437 | } |
438 | |
439 | /* have a problem - can't find the real directory */ |
440 | if(s_entry1 == NULL((void *)0)) |
441 | { |
442 | snprintf(hce->error, ERROR_SIZE1024, |
443 | "can't locate relocated directory %s", |
444 | s_entry->whole_name); |
445 | return(-1); |
446 | } |
447 | } |
448 | else |
449 | s_entry1 = s_entry; |
450 | |
451 | /* now have the correct entry - now find the actual directory */ |
452 | if ((s_entry1->isorec.flags[0] & 2) && strcmp(s_entry1->name,".") && strcmp(s_entry1->name,"..")) |
453 | { |
454 | if((s_entry->de_flags & RELOCATED_DIRECTORY0x20) != 0) |
455 | dpnt = reloc_dir->subdir; |
456 | else |
457 | dpnt = node->subdir; |
458 | |
459 | while(1) |
460 | { |
461 | if (dpnt->self == s_entry1) |
462 | break; |
463 | dpnt = dpnt->next; |
464 | if(!dpnt) |
465 | { |
466 | snprintf(hce->error, ERROR_SIZE1024, |
467 | "can't find directory location %s", |
468 | s_entry1->whole_name); |
469 | return (-1); |
470 | } |
471 | } |
472 | /* now have the correct directory - so do the HFS stuff */ |
473 | ent = dpnt->hfs_ent; |
474 | |
475 | /* if we don't have hfs entries, then this is a "deep" |
476 | directory - this will be processed later */ |
477 | if (!ent) |
478 | continue; |
479 | |
480 | /* make sub-folder */ |
481 | i = HFS_MAX_FLEN31 - strlen(ent->name); |
482 | new_name = 0; |
483 | tens = TEN10; |
484 | digits = 1; |
485 | |
486 | while (1) |
487 | { |
488 | /* try to create new directory - if it exists, then |
489 | append '_' to the name and try again */ |
490 | errno(*__errno()) = 0; |
491 | if (hfs_mkdir(vol, ent->name) < 0) |
492 | { |
493 | if (errno(*__errno()) != EEXIST17) |
494 | { |
495 | /* not an "exist" error, or we can't append as |
496 | the filename is already HFS_MAX_FLEN chars */ |
497 | snprintf(hce->error, ERROR_SIZE1024, |
498 | "can't HFS create folder %s", |
499 | s_entry->whole_name); |
500 | return(-1); |
501 | } |
502 | else if (i == 0) |
503 | { |
504 | /* File name at max HFS length - make unique name */ |
505 | if (!new_name) new_name++; |
506 | |
507 | sprintf(ent->name + HFS_MAX_FLEN31 - digits - 1, |
508 | "%s%d", LCHAR"_", new_name); |
509 | new_name++; |
510 | if (new_name == tens) { |
511 | tens *= TEN10; |
512 | digits++; |
513 | } |
514 | } |
515 | else |
516 | { |
517 | /* append '_' to get new name */ |
518 | strcat(ent->name, LCHAR"_"); |
519 | i--; |
520 | new_name = 1; |
521 | } |
522 | } |
523 | else |
524 | break; |
525 | } |
526 | |
527 | /* warn that we have a new name */ |
528 | if (new_name && verbose > 0) |
529 | { |
530 | fprintf(stderr(&__sF[2]), "Using HFS name: %s for %s\n", ent->name, |
531 | s_entry->whole_name); |
532 | } |
533 | |
534 | /* see if we need to "bless" this folder */ |
535 | if (hfs_bless && strcmp(s_entry->whole_name, hfs_bless) == 0) { |
536 | hfs_stat(vol, ent->name, ent); |
537 | hfs_vsetbless(vol, ent->cnid); |
538 | if (verbose > 0) { |
539 | fprintf(stderr(&__sF[2]), "Blessing %s (%s)\n", |
540 | ent->name, s_entry->whole_name); |
541 | } |
542 | /* stop any further checks */ |
543 | hfs_bless = NULL((void *)0); |
544 | } |
545 | |
546 | /* change to sub-folder */ |
547 | if (hfs_chdir(vol, ent->name) < 0) |
548 | return(-1); |
549 | |
550 | /* recursively copy files ... */ |
551 | ret = copy_to_mac_vol(vol, dpnt); |
552 | if (ret < 0) |
553 | return(ret); |
554 | |
555 | /* change back to this folder */ |
556 | if (hfs_setcwd(vol, id) < 0) |
557 | return(-1); |
558 | } |
559 | } |
560 | |
561 | return(0); |
562 | } |
563 | #endif /* APPLE_HYB */ |
564 |