File: | src/gnu/usr.sbin/mkhybrid/mkhybrid/../src/multi.c |
Warning: | line 913, column 11 Null pointer passed as 1st argument to string comparison function |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* | ||||
2 | * File multi.c - scan existing iso9660 image and merge into | ||||
3 | * iso9660 filesystem. Used for multisession support. | ||||
4 | * | ||||
5 | * Written by Eric Youngdale (1996). | ||||
6 | * | ||||
7 | * This program is free software; you can redistribute it and/or modify | ||||
8 | * it under the terms of the GNU General Public License as published by | ||||
9 | * the Free Software Foundation; either version 2, or (at your option) | ||||
10 | * any later version. | ||||
11 | * | ||||
12 | * This program is distributed in the hope that it will be useful, | ||||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
15 | * GNU General Public License for more details. | ||||
16 | * | ||||
17 | * You should have received a copy of the GNU General Public License | ||||
18 | * along with this program; if not, write to the Free Software | ||||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||||
20 | */ | ||||
21 | |||||
22 | #include <stdlib.h> | ||||
23 | #include <string.h> | ||||
24 | #include <time.h> | ||||
25 | #include <errno(*__errno()).h> | ||||
26 | #include <sys/types.h> | ||||
27 | #include <sys/stat.h> | ||||
28 | |||||
29 | #include "config.h" | ||||
30 | |||||
31 | #ifndef VMS | ||||
32 | |||||
33 | #ifdef HAVE_UNISTD_H1 | ||||
34 | #include <unistd.h> | ||||
35 | #endif | ||||
36 | |||||
37 | #else | ||||
38 | #include <sys/file.h> | ||||
39 | #include <vms/fabdef.h> | ||||
40 | #include "vms.h" | ||||
41 | extern char * strdup(const char *); | ||||
42 | #endif | ||||
43 | |||||
44 | #include "mkisofs.h" | ||||
45 | #include "iso9660.h" | ||||
46 | |||||
47 | #define TF_CREATE1 1 | ||||
48 | #define TF_MODIFY2 2 | ||||
49 | #define TF_ACCESS4 4 | ||||
50 | #define TF_ATTRIBUTES8 8 | ||||
51 | |||||
52 | static int isonum_711 __PR((unsigned char * p))(unsigned char * p); | ||||
53 | static int isonum_721 __PR((unsigned char * p))(unsigned char * p); | ||||
54 | static int isonum_723 __PR((unsigned char * p))(unsigned char * p); | ||||
55 | static int isonum_731 __PR((unsigned char * p))(unsigned char * p); | ||||
56 | |||||
57 | static int DECL(merge_old_directory_into_tree, (struct directory_entry *,merge_old_directory_into_tree (struct directory_entry *, struct directory *) | ||||
58 | struct directory *))merge_old_directory_into_tree (struct directory_entry *, struct directory *); | ||||
59 | |||||
60 | #ifdef __STDC__1 | ||||
61 | static int | ||||
62 | isonum_711 (unsigned char * p) | ||||
63 | #else | ||||
64 | static int | ||||
65 | isonum_711 (p) | ||||
66 | unsigned char * p; | ||||
67 | #endif | ||||
68 | { | ||||
69 | return (*p & 0xff); | ||||
70 | } | ||||
71 | |||||
72 | #ifdef __STDC__1 | ||||
73 | static int | ||||
74 | isonum_721 (unsigned char * p) | ||||
75 | #else | ||||
76 | static int | ||||
77 | isonum_721 (p) | ||||
78 | unsigned char * p; | ||||
79 | #endif | ||||
80 | { | ||||
81 | return ((p[0] & 0xff) | ((p[1] & 0xff) << 8)); | ||||
82 | } | ||||
83 | |||||
84 | #ifdef __STDC__1 | ||||
85 | static int | ||||
86 | isonum_723 (unsigned char * p) | ||||
87 | #else | ||||
88 | static int | ||||
89 | isonum_723 (p) | ||||
90 | unsigned char * p; | ||||
91 | #endif | ||||
92 | { | ||||
93 | #if 0 | ||||
94 | if (p[0] != p[3] || p[1] != p[2]) { | ||||
95 | fprintf (stderr(&__sF[2]), "invalid format 7.2.3 number\n"); | ||||
96 | exit (1); | ||||
97 | } | ||||
98 | #endif | ||||
99 | return (isonum_721 (p)); | ||||
100 | } | ||||
101 | |||||
102 | #ifdef __STDC__1 | ||||
103 | static int | ||||
104 | isonum_731 (unsigned char * p) | ||||
105 | #else | ||||
106 | static int | ||||
107 | isonum_731 (p) | ||||
108 | unsigned char * p; | ||||
109 | #endif | ||||
110 | { | ||||
111 | return ((p[0] & 0xff) | ||||
112 | | ((p[1] & 0xff) << 8) | ||||
113 | | ((p[2] & 0xff) << 16) | ||||
114 | | ((p[3] & 0xff) << 24)); | ||||
115 | } | ||||
116 | |||||
117 | #ifdef __STDC__1 | ||||
118 | int | ||||
119 | isonum_733 (unsigned char * p) | ||||
120 | #else | ||||
121 | int | ||||
122 | isonum_733 (p) | ||||
123 | unsigned char * p; | ||||
124 | #endif | ||||
125 | { | ||||
126 | return (isonum_731 (p)); | ||||
127 | } | ||||
128 | |||||
129 | FILE * in_image = NULL((void *)0); | ||||
130 | |||||
131 | #ifndef USE_SCG | ||||
132 | /* | ||||
133 | * Don't define readsecs if mkisofs is linked with | ||||
134 | * the SCSI library. | ||||
135 | * readsecs() will be implemented as SCSI command in this case. | ||||
136 | * | ||||
137 | * Use global var in_image directly in readsecs() | ||||
138 | * the SCSI equivalent will not use a FILE* for I/O. | ||||
139 | * | ||||
140 | * The main point of this pointless abstraction is that Solaris won't let | ||||
141 | * you read 2K sectors from the cdrom driver. The fact that 99.9% of the | ||||
142 | * discs out there have a 2K sectorsize doesn't seem to matter that much. | ||||
143 | * Anyways, this allows the use of a scsi-generics type of interface on | ||||
144 | * Solaris. | ||||
145 | */ | ||||
146 | #ifdef __STDC__1 | ||||
147 | static int | ||||
148 | readsecs(int startsecno, void *buffer, int sectorcount) | ||||
149 | #else | ||||
150 | static int | ||||
151 | readsecs(startsecno, buffer, sectorcount) | ||||
152 | int startsecno; | ||||
153 | void *buffer; | ||||
154 | int sectorcount; | ||||
155 | #endif | ||||
156 | { | ||||
157 | int f = fileno(in_image)(!__isthreaded ? ((in_image)->_file) : (fileno)(in_image)); | ||||
158 | |||||
159 | if (lseek(f, (off_t)startsecno * SECTOR_SIZE(2048), 0) == (off_t)-1) { | ||||
160 | fprintf(stderr(&__sF[2])," Seek error on old image\n"); | ||||
161 | exit(10); | ||||
162 | } | ||||
163 | return (read(f, buffer, sectorcount * SECTOR_SIZE(2048))); | ||||
164 | } | ||||
165 | #endif | ||||
166 | |||||
167 | /* | ||||
168 | * Parse the RR attributes so we can find the file name. | ||||
169 | */ | ||||
170 | static int | ||||
171 | FDECL3(parse_rr, unsigned char *, pnt, int, len, struct directory_entry *,dpnt)parse_rr(unsigned char * pnt, int len, struct directory_entry * dpnt) | ||||
172 | { | ||||
173 | int cont_extent, cont_offset, cont_size; | ||||
174 | char name_buf[256]; | ||||
175 | |||||
176 | cont_extent = cont_offset = cont_size = 0; | ||||
177 | |||||
178 | while(len >= 4){ | ||||
179 | if(pnt[3] != 1) { | ||||
180 | fprintf(stderr(&__sF[2]),"**BAD RRVERSION"); | ||||
181 | return -1; | ||||
182 | }; | ||||
183 | if(strncmp((char *) pnt, "NM", 2) == 0) { | ||||
184 | strncpy(name_buf, (char *) pnt+5, pnt[2] - 5); | ||||
185 | name_buf[pnt[2] - 5] = 0; | ||||
186 | dpnt->name = strdup(name_buf); | ||||
187 | dpnt->got_rr_name = 1; | ||||
188 | return 0; | ||||
189 | } | ||||
190 | |||||
191 | if(strncmp((char *) pnt, "CE", 2) == 0) { | ||||
192 | cont_extent = isonum_733(pnt+4); | ||||
193 | cont_offset = isonum_733(pnt+12); | ||||
194 | cont_size = isonum_733(pnt+20); | ||||
195 | }; | ||||
196 | |||||
197 | len -= pnt[2]; | ||||
198 | pnt += pnt[2]; | ||||
199 | if(len <= 3 && cont_extent) { | ||||
200 | unsigned char sector[SECTOR_SIZE(2048)]; | ||||
201 | readsecs(cont_extent, sector, 1); | ||||
202 | parse_rr(§or[cont_offset], cont_size, dpnt); | ||||
203 | }; | ||||
204 | }; | ||||
205 | |||||
206 | /* Fall back to the iso name if no RR name found */ | ||||
207 | if (dpnt->name == NULL((void *)0)) { | ||||
208 | char *cp; | ||||
209 | |||||
210 | strcpy(name_buf, dpnt->isorec.name); | ||||
211 | cp = strchr(name_buf, ';'); | ||||
212 | if (cp != NULL((void *)0)) { | ||||
213 | *cp = '\0'; | ||||
214 | } | ||||
215 | |||||
216 | dpnt->name = strdup(name_buf); | ||||
217 | } | ||||
218 | |||||
219 | return 0; | ||||
220 | } /* parse_rr */ | ||||
221 | |||||
222 | |||||
223 | static int | ||||
224 | FDECL4(check_rr_dates, struct directory_entry *, dpnt,check_rr_dates(struct directory_entry * dpnt, struct directory_entry * current, struct stat * statbuf, struct stat * lstatbuf) | ||||
225 | struct directory_entry *, current,check_rr_dates(struct directory_entry * dpnt, struct directory_entry * current, struct stat * statbuf, struct stat * lstatbuf) | ||||
226 | struct stat *, statbuf,check_rr_dates(struct directory_entry * dpnt, struct directory_entry * current, struct stat * statbuf, struct stat * lstatbuf) | ||||
227 | struct stat *,lstatbuf)check_rr_dates(struct directory_entry * dpnt, struct directory_entry * current, struct stat * statbuf, struct stat * lstatbuf) | ||||
228 | { | ||||
229 | int cont_extent, cont_offset, cont_size; | ||||
230 | int offset; | ||||
231 | unsigned char * pnt; | ||||
232 | int len; | ||||
233 | int same_file; | ||||
234 | int same_file_type; | ||||
235 | mode_t mode; | ||||
236 | char time_buf[7]; | ||||
237 | |||||
238 | |||||
239 | cont_extent = cont_offset = cont_size = 0; | ||||
240 | same_file = 1; | ||||
241 | same_file_type = 1; | ||||
242 | |||||
243 | pnt = dpnt->rr_attributes; | ||||
244 | len = dpnt->rr_attr_size; | ||||
245 | /* | ||||
246 | * We basically need to parse the rr attributes again, and | ||||
247 | * dig out the dates and file types. | ||||
248 | */ | ||||
249 | while(len >= 4){ | ||||
250 | if(pnt[3] != 1) { | ||||
251 | fprintf(stderr(&__sF[2]),"**BAD RRVERSION"); | ||||
252 | return -1; | ||||
253 | }; | ||||
254 | |||||
255 | /* | ||||
256 | * If we have POSIX file modes, make sure that the file type | ||||
257 | * is the same. If it isn't, then we must always | ||||
258 | * write the new file. | ||||
259 | */ | ||||
260 | if(strncmp((char *) pnt, "PX", 2) == 0) { | ||||
261 | mode = isonum_733(pnt + 4); | ||||
262 | if( (lstatbuf->st_mode & S_IFMT0170000) != (mode & S_IFMT0170000) ) | ||||
263 | { | ||||
264 | same_file_type = 0; | ||||
265 | same_file = 0; | ||||
266 | } | ||||
267 | } | ||||
268 | |||||
269 | if(strncmp((char *) pnt, "TF", 2) == 0) { | ||||
270 | offset = 5; | ||||
271 | if( pnt[4] & TF_CREATE1 ) | ||||
272 | { | ||||
273 | iso9660_date((char *) time_buf, lstatbuf->st_ctimest_ctim.tv_sec); | ||||
274 | if(memcmp(time_buf, pnt+offset, 7) == 0) | ||||
275 | same_file = 0; | ||||
276 | offset += 7; | ||||
277 | } | ||||
278 | if( pnt[4] & TF_MODIFY2 ) | ||||
279 | { | ||||
280 | iso9660_date((char *) time_buf, lstatbuf->st_mtimest_mtim.tv_sec); | ||||
281 | if(memcmp(time_buf, pnt+offset, 7) == 0) | ||||
282 | same_file = 0; | ||||
283 | offset += 7; | ||||
284 | } | ||||
285 | } | ||||
286 | |||||
287 | if(strncmp((char *) pnt, "CE", 2) == 0) { | ||||
288 | cont_extent = isonum_733(pnt+4); | ||||
289 | cont_offset = isonum_733(pnt+12); | ||||
290 | cont_size = isonum_733(pnt+20); | ||||
291 | }; | ||||
292 | |||||
293 | len -= pnt[2]; | ||||
294 | pnt += pnt[2]; | ||||
295 | if(len <= 3 && cont_extent) { | ||||
296 | unsigned char sector[SECTOR_SIZE(2048)]; | ||||
297 | |||||
298 | readsecs(cont_extent, sector, 1); | ||||
299 | parse_rr(§or[cont_offset], cont_size, dpnt); | ||||
300 | }; | ||||
301 | }; | ||||
302 | |||||
303 | /* | ||||
304 | * If we have the same fundamental file type, then it is clearly | ||||
305 | * safe to reuse the TRANS.TBL entry. | ||||
306 | */ | ||||
307 | if( same_file_type ) | ||||
308 | { | ||||
309 | current->de_flags |= SAFE_TO_REUSE_TABLE_ENTRY0x01; | ||||
310 | } | ||||
311 | |||||
312 | return same_file; | ||||
313 | } | ||||
314 | |||||
315 | struct directory_entry ** | ||||
316 | FDECL2(read_merging_directory, struct iso_directory_record *, mrootp,read_merging_directory(struct iso_directory_record * mrootp, int * nent) | ||||
317 | int *, nent)read_merging_directory(struct iso_directory_record * mrootp, int * nent) | ||||
318 | { | ||||
319 | unsigned char * cpnt; | ||||
320 | unsigned char * cpnt1; | ||||
321 | char * dirbuff; | ||||
322 | int i; | ||||
323 | struct iso_directory_record * idr; | ||||
324 | int len; | ||||
325 | struct directory_entry **pnt; | ||||
326 | int rlen; | ||||
327 | struct directory_entry **rtn; | ||||
328 | int seen_rockridge; | ||||
329 | unsigned char * tt_buf; | ||||
330 | int tt_extent; | ||||
331 | int tt_size; | ||||
332 | |||||
333 | static int warning_given = 0; | ||||
334 | |||||
335 | /* | ||||
336 | * First, allocate a buffer large enough to read in the entire | ||||
337 | * directory. | ||||
338 | */ | ||||
339 | dirbuff = (char *) e_malloc(isonum_733((unsigned char *)mrootp->size)); | ||||
340 | |||||
341 | readsecs(isonum_733((unsigned char *)mrootp->extent), dirbuff, | ||||
342 | isonum_733((unsigned char *)mrootp->size)/SECTOR_SIZE(2048)); | ||||
343 | |||||
344 | /* | ||||
345 | * Next look over the directory, and count up how many entries we | ||||
346 | * have. | ||||
347 | */ | ||||
348 | len = isonum_733((unsigned char *)mrootp->size); | ||||
349 | i = 0; | ||||
350 | *nent = 0; | ||||
351 | while(i < len ) | ||||
352 | { | ||||
353 | idr = (struct iso_directory_record *) &dirbuff[i]; | ||||
354 | if(idr->length[0] == 0) | ||||
355 | { | ||||
356 | i = (i + SECTOR_SIZE(2048) - 1) & ~(SECTOR_SIZE(2048) - 1); | ||||
357 | continue; | ||||
358 | } | ||||
359 | (*nent)++; | ||||
360 | i += idr->length[0]; | ||||
361 | } | ||||
362 | |||||
363 | /* | ||||
364 | * Now allocate the buffer which will hold the array we are | ||||
365 | * about to return. | ||||
366 | */ | ||||
367 | rtn = (struct directory_entry **) e_malloc(*nent * sizeof(*rtn)); | ||||
368 | |||||
369 | /* | ||||
370 | * Finally, scan the directory one last time, and pick out the | ||||
371 | * relevant bits of information, and store it in the relevant | ||||
372 | * bits of the structure. | ||||
373 | */ | ||||
374 | i = 0; | ||||
375 | pnt = rtn; | ||||
376 | tt_extent = 0; | ||||
377 | seen_rockridge = 0; | ||||
378 | tt_size = 0; | ||||
379 | while(i < len ) | ||||
380 | { | ||||
381 | idr = (struct iso_directory_record *) &dirbuff[i]; | ||||
382 | if(idr->length[0] == 0) | ||||
383 | { | ||||
384 | i = (i + SECTOR_SIZE(2048) - 1) & ~(SECTOR_SIZE(2048) - 1); | ||||
385 | continue; | ||||
386 | } | ||||
387 | *pnt = (struct directory_entry *) e_malloc(sizeof(**rtn)); | ||||
388 | (*pnt)->next = NULL((void *)0); | ||||
389 | (*pnt)->isorec = *idr; | ||||
390 | (*pnt)->starting_block = isonum_733((unsigned char *)idr->extent); | ||||
391 | (*pnt)->size = isonum_733((unsigned char *)idr->size); | ||||
392 | (*pnt)->priority = 0; | ||||
393 | (*pnt)->name = NULL((void *)0); | ||||
394 | (*pnt)->got_rr_name = 0; | ||||
395 | (*pnt)->table = NULL((void *)0); | ||||
396 | (*pnt)->whole_name = NULL((void *)0); | ||||
397 | (*pnt)->filedir = NULL((void *)0); | ||||
398 | (*pnt)->parent_rec = NULL((void *)0); | ||||
399 | /* | ||||
400 | * Set this information so that we correctly cache previous | ||||
401 | * session bits of information. | ||||
402 | */ | ||||
403 | (*pnt)->inode = (*pnt)->starting_block; | ||||
404 | (*pnt)->dev = PREV_SESS_DEV(sizeof(dev_t) >= 4 ? 0x7ffffffd : 0x7ffd); | ||||
405 | (*pnt)->rr_attributes = NULL((void *)0); | ||||
406 | (*pnt)->rr_attr_size = 0; | ||||
407 | (*pnt)->total_rr_attr_size = 0; | ||||
408 | (*pnt)->de_flags = SAFE_TO_REUSE_TABLE_ENTRY0x01; | ||||
409 | |||||
410 | /* | ||||
411 | * Check for and parse any RR attributes for the file. | ||||
412 | * All we are really looking for here is the original name | ||||
413 | * of the file. | ||||
414 | */ | ||||
415 | rlen = idr->length[0] & 0xff; | ||||
416 | cpnt = (unsigned char *) idr; | ||||
417 | |||||
418 | rlen -= sizeof(struct iso_directory_record); | ||||
419 | cpnt += sizeof(struct iso_directory_record); | ||||
420 | |||||
421 | rlen += sizeof(idr->name); | ||||
422 | cpnt -= sizeof(idr->name); | ||||
423 | |||||
424 | rlen -= idr->name_len[0]; | ||||
425 | cpnt += idr->name_len[0]; | ||||
426 | |||||
427 | if((idr->name_len[0] & 1) == 0){ | ||||
428 | cpnt++; | ||||
429 | rlen--; | ||||
430 | }; | ||||
431 | |||||
432 | if( rlen != 0 ) | ||||
433 | { | ||||
434 | (*pnt)->total_rr_attr_size = (*pnt)->rr_attr_size = rlen; | ||||
435 | (*pnt)->rr_attributes = e_malloc(rlen); | ||||
436 | memcpy((*pnt)->rr_attributes, cpnt, rlen); | ||||
437 | seen_rockridge = 1; | ||||
438 | } | ||||
439 | |||||
440 | /* | ||||
441 | * Now zero out the remainder of the name field. | ||||
442 | */ | ||||
443 | cpnt = (unsigned char *) &(*pnt)->isorec.name; | ||||
444 | cpnt += idr->name_len[0]; | ||||
445 | memset(cpnt, 0, sizeof((*pnt)->isorec.name) - idr->name_len[0]); | ||||
446 | |||||
447 | parse_rr((*pnt)->rr_attributes, rlen, *pnt); | ||||
448 | |||||
449 | if( ((*pnt)->isorec.name_len[0] == 1) | ||||
450 | && ( ((*pnt)->isorec.name[0] == 0) | ||||
451 | || ((*pnt)->isorec.name[0] == 1)) ) | ||||
452 | { | ||||
453 | if( (*pnt)->name != NULL((void *)0) ) | ||||
454 | { | ||||
455 | free((*pnt)->name); | ||||
456 | } | ||||
457 | if( (*pnt)->whole_name != NULL((void *)0) ) | ||||
458 | { | ||||
459 | free((*pnt)->whole_name); | ||||
460 | } | ||||
461 | if( (*pnt)->isorec.name[0] == 0 ) | ||||
462 | { | ||||
463 | (*pnt)->name = strdup("."); | ||||
464 | } | ||||
465 | else | ||||
466 | { | ||||
467 | (*pnt)->name = strdup(".."); | ||||
468 | } | ||||
469 | } | ||||
470 | |||||
471 | #ifdef DEBUG | ||||
472 | fprintf(stderr(&__sF[2]), "got DE name: %s\n", (*pnt)->name); | ||||
473 | #endif | ||||
474 | |||||
475 | #ifdef APPLE_HYB1 | ||||
476 | if( strncmp(idr->name, trans_tbl, strlen(trans_tbl)) == 0) | ||||
477 | #else | ||||
478 | if( strncmp(idr->name, "TRANS.TBL", 9) == 0) | ||||
479 | #endif /* APPLE_HYB */ | ||||
480 | { | ||||
481 | if( (*pnt)->name != NULL((void *)0) ) | ||||
482 | { | ||||
483 | free((*pnt)->name); | ||||
484 | } | ||||
485 | if( (*pnt)->whole_name != NULL((void *)0) ) | ||||
486 | { | ||||
487 | free((*pnt)->whole_name); | ||||
488 | } | ||||
489 | (*pnt)->name = strdup("<translation table>"); | ||||
490 | tt_extent = isonum_733((unsigned char *)idr->extent); | ||||
491 | tt_size = isonum_733((unsigned char *)idr->size); | ||||
492 | } | ||||
493 | |||||
494 | pnt++; | ||||
495 | i += idr->length[0]; | ||||
496 | } | ||||
497 | |||||
498 | /* | ||||
499 | * If there was a TRANS.TBL;1 entry, then grab it, read it, and use it | ||||
500 | * to get the filenames of the files. Also, save the table info, just | ||||
501 | * in case we need to use it. | ||||
502 | */ | ||||
503 | if( tt_extent != 0 && tt_size != 0 ) | ||||
504 | { | ||||
505 | tt_buf = (unsigned char *) e_malloc(tt_size); | ||||
506 | readsecs(tt_extent, tt_buf, tt_size/SECTOR_SIZE(2048)); | ||||
507 | |||||
508 | /* | ||||
509 | * Loop through the file, examine each entry, and attempt to | ||||
510 | * attach it to the correct entry. | ||||
511 | */ | ||||
512 | cpnt = tt_buf; | ||||
513 | cpnt1 = tt_buf; | ||||
514 | while( cpnt - tt_buf < tt_size ) | ||||
515 | { | ||||
516 | while(*cpnt1 != '\n' && *cpnt1 != '\0') cpnt1++; | ||||
517 | *cpnt1 = '\0'; | ||||
518 | |||||
519 | for(pnt = rtn, i = 0; i <*nent; i++, pnt++) | ||||
520 | { | ||||
521 | rlen = isonum_711((*pnt)->isorec.name_len); | ||||
522 | if( strncmp((char *) cpnt + 2, (*pnt)->isorec.name, | ||||
523 | rlen) == 0 | ||||
524 | && cpnt[2+rlen] == ' ') | ||||
525 | { | ||||
526 | (*pnt)->table = e_malloc(strlen((char*)cpnt) - 33); | ||||
527 | sprintf((*pnt)->table, "%c\t%s\n", | ||||
528 | *cpnt, cpnt+37); | ||||
529 | if( !(*pnt)->got_rr_name ) | ||||
530 | { | ||||
531 | if ((*pnt)->name != NULL((void *)0)) { | ||||
532 | free((*pnt)->name); | ||||
533 | } | ||||
534 | (*pnt)->name = strdup((char *) cpnt+37); | ||||
535 | } | ||||
536 | break; | ||||
537 | } | ||||
538 | } | ||||
539 | cpnt = cpnt1 + 1; | ||||
540 | cpnt1 = cpnt; | ||||
541 | } | ||||
542 | |||||
543 | free(tt_buf); | ||||
544 | } | ||||
545 | else if( !seen_rockridge && !warning_given ) | ||||
546 | { | ||||
547 | /* | ||||
548 | * Warn the user that iso (8.3) names were used because neither | ||||
549 | * Rock Ridge (-R) nor TRANS.TBL (-T) name translations were found. | ||||
550 | */ | ||||
551 | fprintf(stderr(&__sF[2]),"Warning: Neither Rock Ridge (-R) nor TRANS.TBL (-T) \n"); | ||||
552 | fprintf(stderr(&__sF[2]),"name translations were found on previous session.\n"); | ||||
553 | fprintf(stderr(&__sF[2]),"ISO (8.3) file names have been used instead.\n"); | ||||
554 | warning_given = 1; | ||||
555 | } | ||||
556 | |||||
557 | if( dirbuff != NULL((void *)0) ) | ||||
558 | { | ||||
559 | free(dirbuff); | ||||
560 | } | ||||
561 | |||||
562 | return rtn; | ||||
563 | } /* read_merging_directory */ | ||||
564 | |||||
565 | /* | ||||
566 | * Free any associated data related to the structures. | ||||
567 | */ | ||||
568 | int | ||||
569 | FDECL2(free_mdinfo, struct directory_entry ** , ptr, int, len )free_mdinfo(struct directory_entry ** ptr, int len) | ||||
570 | { | ||||
571 | int i; | ||||
572 | struct directory_entry **p; | ||||
573 | |||||
574 | p = ptr; | ||||
575 | for(i=0; i<len; i++, p++) | ||||
576 | { | ||||
577 | /* | ||||
578 | * If the tree-handling code decided that it needed an entry, | ||||
579 | * it will have removed it from the list. Thus we must allow | ||||
580 | * for null pointers here. | ||||
581 | */ | ||||
582 | if( *p == NULL((void *)0) ) | ||||
583 | { | ||||
584 | continue; | ||||
585 | } | ||||
586 | |||||
587 | if( (*p)->name != NULL((void *)0) ) | ||||
588 | { | ||||
589 | free((*p)->name); | ||||
590 | } | ||||
591 | |||||
592 | if( (*p)->whole_name != NULL((void *)0) ) | ||||
593 | { | ||||
594 | free((*p)->whole_name); | ||||
595 | } | ||||
596 | |||||
597 | if( (*p)->rr_attributes != NULL((void *)0) ) | ||||
598 | { | ||||
599 | free((*p)->rr_attributes); | ||||
600 | } | ||||
601 | |||||
602 | if( (*p)->table != NULL((void *)0) ) | ||||
603 | { | ||||
604 | free((*p)->table); | ||||
605 | } | ||||
606 | |||||
607 | free(*p); | ||||
608 | |||||
609 | } | ||||
610 | |||||
611 | free(ptr); | ||||
612 | return 0; | ||||
613 | } | ||||
614 | |||||
615 | /* | ||||
616 | * Search the list to see if we have any entries from the previous | ||||
617 | * session that match this entry. If so, copy the extent number | ||||
618 | * over so we don't bother to write it out to the new session. | ||||
619 | */ | ||||
620 | |||||
621 | int | ||||
622 | FDECL6(check_prev_session, struct directory_entry ** , ptr, int, len,check_prev_session(struct directory_entry ** ptr, int len, struct directory_entry * curr_entry, struct stat * statbuf, struct stat * lstatbuf, struct directory_entry ** odpnt) | ||||
623 | struct directory_entry *, curr_entry,check_prev_session(struct directory_entry ** ptr, int len, struct directory_entry * curr_entry, struct stat * statbuf, struct stat * lstatbuf, struct directory_entry ** odpnt) | ||||
624 | struct stat *, statbuf, struct stat *, lstatbuf,check_prev_session(struct directory_entry ** ptr, int len, struct directory_entry * curr_entry, struct stat * statbuf, struct stat * lstatbuf, struct directory_entry ** odpnt) | ||||
625 | struct directory_entry **, odpnt)check_prev_session(struct directory_entry ** ptr, int len, struct directory_entry * curr_entry, struct stat * statbuf, struct stat * lstatbuf, struct directory_entry ** odpnt) | ||||
626 | { | ||||
627 | int i; | ||||
628 | |||||
629 | for( i=0; i < len; i++ ) | ||||
630 | { | ||||
631 | if( ptr[i] == NULL((void *)0) ) | ||||
632 | { | ||||
633 | continue; | ||||
634 | } | ||||
635 | |||||
636 | #if 0 | ||||
637 | if( ptr[i]->name != NULL((void *)0) && ptr[i]->isorec.name_len[0] == 1 | ||||
638 | && ptr[i]->name[0] == '\0' ) | ||||
639 | { | ||||
640 | continue; | ||||
641 | } | ||||
642 | if( ptr[i]->name != NULL((void *)0) && ptr[i]->isorec.name_len[0] == 1 | ||||
643 | && ptr[i]->name[0] == 1) | ||||
644 | { | ||||
645 | continue; | ||||
646 | } | ||||
647 | #else | ||||
648 | if( ptr[i]->name != NULL((void *)0) && strcmp(ptr[i]->name, ".") == 0 ) | ||||
649 | { | ||||
650 | continue; | ||||
651 | } | ||||
652 | if( ptr[i]->name != NULL((void *)0) && strcmp(ptr[i]->name, "..") == 0 ) | ||||
653 | { | ||||
654 | continue; | ||||
655 | } | ||||
656 | #endif | ||||
657 | |||||
658 | if( ptr[i]->name != NULL((void *)0) | ||||
659 | && strcmp(ptr[i]->name, curr_entry->name) != 0 ) | ||||
660 | { | ||||
661 | continue; | ||||
662 | } | ||||
663 | |||||
664 | /* | ||||
665 | * We know that the files have the same name. If they also have | ||||
666 | * the same file type (i.e. file, dir, block, etc), then we | ||||
667 | * can safely reuse the TRANS.TBL entry for this file. | ||||
668 | * The check_rr_dates function will do this for us. | ||||
669 | * | ||||
670 | * Verify that the file type and dates are consistent. | ||||
671 | * If not, we probably have a different file, and we need | ||||
672 | * to write it out again. | ||||
673 | */ | ||||
674 | if( (ptr[i]->rr_attributes != NULL((void *)0)) | ||||
675 | && (check_rr_dates(ptr[i], curr_entry, statbuf, lstatbuf)) ) | ||||
676 | { | ||||
677 | goto found_it; | ||||
678 | } | ||||
679 | |||||
680 | |||||
681 | /* | ||||
682 | * Verify size and timestamp. If rock ridge is in use, we need | ||||
683 | * to compare dates from RR too. Directories are special, we | ||||
684 | * calculate their size later. | ||||
685 | */ | ||||
686 | if( (curr_entry->isorec.flags[0] & 2) == 0 | ||||
687 | && ptr[i]->size != curr_entry->size ) | ||||
688 | { | ||||
689 | goto found_it; | ||||
690 | } | ||||
691 | |||||
692 | if( memcmp(ptr[i]->isorec.date, curr_entry->isorec.date,7) != 0 ) | ||||
693 | { | ||||
694 | goto found_it; | ||||
695 | } | ||||
696 | |||||
697 | /* | ||||
698 | * Never ever reuse directory extents. See comments in | ||||
699 | * tree.c for an explaination of why this must be the case. | ||||
700 | */ | ||||
701 | if( (curr_entry->isorec.flags[0] & 2) != 0 ) | ||||
702 | { | ||||
703 | goto found_it; | ||||
704 | } | ||||
705 | |||||
706 | memcpy(curr_entry->isorec.extent, ptr[i]->isorec.extent, 8); | ||||
707 | curr_entry->de_flags |= SAFE_TO_REUSE_TABLE_ENTRY0x01; | ||||
708 | goto found_it; | ||||
709 | } | ||||
710 | return 0; | ||||
711 | |||||
712 | found_it: | ||||
713 | if( odpnt != NULL((void *)0) ) | ||||
714 | { | ||||
715 | *odpnt = ptr[i]; | ||||
716 | } | ||||
717 | else | ||||
718 | { | ||||
719 | free(ptr[i]); | ||||
720 | } | ||||
721 | ptr[i] = NULL((void *)0); | ||||
722 | return 0; | ||||
723 | } | ||||
724 | |||||
725 | /* | ||||
726 | * merge_isofs: Scan an existing image, and return a pointer | ||||
727 | * to the root directory for this image. | ||||
728 | */ | ||||
729 | struct iso_directory_record * FDECL1(merge_isofs, char *, path)merge_isofs(char * path) | ||||
730 | { | ||||
731 | char buffer[SECTOR_SIZE(2048)]; | ||||
732 | int file_addr; | ||||
733 | int i; | ||||
734 | struct iso_primary_descriptor * pri = NULL((void *)0); | ||||
735 | struct iso_directory_record * rootp; | ||||
736 | struct iso_volume_descriptor * vdp; | ||||
737 | |||||
738 | /* | ||||
739 | * Start by opening up the image and searching for the volume header. | ||||
740 | * Ultimately, we need to search for volume headers in multiple places | ||||
741 | * because we might be starting with a multisession image. | ||||
742 | * FIXME(eric). | ||||
743 | */ | ||||
744 | |||||
745 | #ifndef USE_SCG | ||||
746 | in_image = fopen(path, "rb"); | ||||
747 | if( in_image == NULL((void *)0) ) | ||||
748 | { | ||||
749 | return NULL((void *)0); | ||||
750 | } | ||||
751 | #else | ||||
752 | if (strchr(path, '/')) { | ||||
753 | in_image = fopen(path, "rb"); | ||||
754 | if( in_image == NULL((void *)0) ) { | ||||
755 | return NULL((void *)0); | ||||
756 | } | ||||
757 | } else { | ||||
758 | if (scsidev_open(path) < 0) | ||||
759 | return NULL((void *)0); | ||||
760 | } | ||||
761 | #endif | ||||
762 | |||||
763 | get_session_start(&file_addr); | ||||
764 | |||||
765 | for(i = 0; i< 100; i++) | ||||
766 | { | ||||
767 | if (readsecs(file_addr/SECTOR_SIZE(2048), &buffer, | ||||
768 | sizeof(buffer)/SECTOR_SIZE(2048)) != sizeof(buffer)) | ||||
769 | { | ||||
770 | fprintf(stderr(&__sF[2])," Read error on old image %s\n", path); | ||||
771 | exit(10); | ||||
772 | } | ||||
773 | |||||
774 | vdp = (struct iso_volume_descriptor *)buffer; | ||||
775 | |||||
776 | if( (strncmp(vdp->id, ISO_STANDARD_ID"CD001", sizeof vdp->id) == 0) | ||||
777 | && (isonum_711((unsigned char *) vdp->type) == ISO_VD_PRIMARY1) ) | ||||
778 | { | ||||
779 | break; | ||||
780 | } | ||||
781 | file_addr += SECTOR_SIZE(2048); | ||||
782 | } | ||||
783 | |||||
784 | if( i == 100 ) | ||||
785 | { | ||||
786 | return NULL((void *)0); | ||||
787 | } | ||||
788 | |||||
789 | pri = (struct iso_primary_descriptor *)vdp; | ||||
790 | |||||
791 | /* | ||||
792 | * Check the blocksize of the image to make sure it is compatible. | ||||
793 | */ | ||||
794 | if( (isonum_723 ((unsigned char *) pri->logical_block_size) != SECTOR_SIZE(2048)) | ||||
795 | || (isonum_723 ((unsigned char *) pri->volume_set_size) != 1) ) | ||||
796 | { | ||||
797 | return NULL((void *)0); | ||||
798 | } | ||||
799 | |||||
800 | /* | ||||
801 | * Get the location and size of the root directory. | ||||
802 | */ | ||||
803 | rootp = calloc(1, sizeof(struct iso_directory_record)); | ||||
804 | |||||
805 | memcpy(rootp, pri->root_directory_record, sizeof(pri->root_directory_record)); | ||||
806 | |||||
807 | return rootp; | ||||
808 | } | ||||
809 | |||||
810 | void FDECL3(merge_remaining_entries, struct directory *, this_dir,merge_remaining_entries(struct directory * this_dir, struct directory_entry ** pnt, int n_orig) | ||||
811 | struct directory_entry **, pnt,merge_remaining_entries(struct directory * this_dir, struct directory_entry ** pnt, int n_orig) | ||||
812 | int, n_orig)merge_remaining_entries(struct directory * this_dir, struct directory_entry ** pnt, int n_orig) | ||||
813 | { | ||||
814 | int i; | ||||
815 | struct directory_entry * s_entry; | ||||
816 | unsigned int ttbl_extent = 0; | ||||
817 | unsigned int ttbl_index = 0; | ||||
818 | char whole_path[1024]; | ||||
819 | |||||
820 | /* | ||||
821 | * Whatever is leftover in the list needs to get merged back | ||||
822 | * into the directory. | ||||
823 | */ | ||||
824 | for( i=0; i < n_orig; i++ ) | ||||
825 | { | ||||
826 | if( pnt[i] == NULL((void *)0) ) | ||||
827 | { | ||||
828 | continue; | ||||
829 | } | ||||
830 | |||||
831 | if( pnt[i]->name != NULL((void *)0) && pnt[i]->whole_name == NULL((void *)0)) | ||||
832 | { | ||||
833 | /* | ||||
834 | * Set the name for this directory. | ||||
835 | */ | ||||
836 | strcpy(whole_path, this_dir->de_name); | ||||
837 | strcat(whole_path, SPATH_SEPARATOR"/"); | ||||
838 | strcat(whole_path, pnt[i]->name); | ||||
839 | |||||
840 | pnt[i]->whole_name = strdup(whole_path); | ||||
841 | } | ||||
842 | |||||
843 | if( pnt[i]->name
| ||||
844 | && strcmp(pnt[i]->name, "<translation table>") == 0 ) | ||||
845 | { | ||||
846 | ttbl_extent = isonum_733((unsigned char *) pnt[i]->isorec.extent); | ||||
847 | ttbl_index = i; | ||||
848 | continue; | ||||
849 | } | ||||
850 | /* | ||||
851 | * Skip directories for now - these need to be treated | ||||
852 | * differently. | ||||
853 | */ | ||||
854 | if( (pnt[i]->isorec.flags[0] & 2) != 0 ) | ||||
855 | { | ||||
856 | /* | ||||
857 | * FIXME - we need to insert this directory into the | ||||
858 | * tree, so that the path tables we generate will | ||||
859 | * be correct. | ||||
860 | */ | ||||
861 | if( (strcmp(pnt[i]->name, ".") == 0) | ||||
862 | || (strcmp(pnt[i]->name, "..") == 0) ) | ||||
863 | { | ||||
864 | free(pnt[i]); | ||||
865 | pnt[i] = NULL((void *)0); | ||||
866 | continue; | ||||
867 | } | ||||
868 | else | ||||
869 | { | ||||
870 | merge_old_directory_into_tree(pnt[i], this_dir); | ||||
871 | } | ||||
872 | } | ||||
873 | pnt[i]->next = this_dir->contents; | ||||
874 | pnt[i]->filedir = this_dir; | ||||
875 | this_dir->contents = pnt[i]; | ||||
876 | pnt[i] = NULL((void *)0); | ||||
877 | } | ||||
878 | |||||
879 | |||||
880 | /* | ||||
881 | * If we don't have an entry for the translation table, then | ||||
882 | * don't bother trying to copy the starting extent over. | ||||
883 | * Note that it is possible that if we are copying the entire | ||||
884 | * directory, the entry for the translation table will have already | ||||
885 | * been inserted into the linked list and removed from the old | ||||
886 | * entries list, in which case we want to leave the extent number | ||||
887 | * as it was before. | ||||
888 | */ | ||||
889 | if( ttbl_extent == 0 ) | ||||
890 | { | ||||
891 | return; | ||||
892 | } | ||||
893 | |||||
894 | /* | ||||
895 | * Finally, check the directory we are creating to see whether | ||||
896 | * there are any new entries in it. If there are not, we can | ||||
897 | * reuse the same translation table. | ||||
898 | */ | ||||
899 | for(s_entry = this_dir->contents; s_entry; s_entry = s_entry->next) | ||||
900 | { | ||||
901 | /* | ||||
902 | * Don't care about '.' or '..'. They are never in the table | ||||
903 | * anyways. | ||||
904 | */ | ||||
905 | if( s_entry->name
| ||||
906 | { | ||||
907 | continue; | ||||
908 | } | ||||
909 | if( s_entry->name
| ||||
910 | { | ||||
911 | continue; | ||||
912 | } | ||||
913 | if( strcmp(s_entry->name, "<translation table>") == 0) | ||||
| |||||
914 | { | ||||
915 | continue; | ||||
916 | } | ||||
917 | if( (s_entry->de_flags & SAFE_TO_REUSE_TABLE_ENTRY0x01) == 0 ) | ||||
918 | { | ||||
919 | return; | ||||
920 | } | ||||
921 | } | ||||
922 | |||||
923 | /* | ||||
924 | * Locate the translation table, and re-use the same extent. | ||||
925 | * It isn't clear that there should ever be one in there already | ||||
926 | * so for now we try and muddle through the best we can. | ||||
927 | */ | ||||
928 | for(s_entry = this_dir->contents; s_entry; s_entry = s_entry->next) | ||||
929 | { | ||||
930 | if( strcmp(s_entry->name, "<translation table>") == 0) | ||||
931 | { | ||||
932 | fprintf(stderr(&__sF[2]),"Should never get here\n"); | ||||
933 | set_733(s_entry->isorec.extent, ttbl_extent); | ||||
934 | return; | ||||
935 | } | ||||
936 | } | ||||
937 | |||||
938 | pnt[ttbl_index]->next = this_dir->contents; | ||||
939 | pnt[ttbl_index]->filedir = this_dir; | ||||
940 | this_dir->contents = pnt[ttbl_index]; | ||||
941 | pnt[ttbl_index] = NULL((void *)0); | ||||
942 | } | ||||
943 | |||||
944 | |||||
945 | /* | ||||
946 | * Here we have a case of a directory that has completely disappeared from | ||||
947 | * the face of the earth on the tree we are mastering from. Go through and | ||||
948 | * merge it into the tree, as well as everything beneath it. | ||||
949 | * | ||||
950 | * Note that if a directory has been moved for some reason, this will | ||||
951 | * incorrectly pick it up and attempt to merge it back into the old | ||||
952 | * location. FIXME(eric). | ||||
953 | */ | ||||
954 | static int | ||||
955 | FDECL2(merge_old_directory_into_tree, struct directory_entry *, dpnt,merge_old_directory_into_tree(struct directory_entry * dpnt, struct directory * parent) | ||||
956 | struct directory *, parent)merge_old_directory_into_tree(struct directory_entry * dpnt, struct directory * parent) | ||||
957 | { | ||||
958 | struct directory_entry **contents = NULL((void *)0); | ||||
959 | int i; | ||||
960 | int n_orig; | ||||
961 | struct directory * this_dir, *next_brother; | ||||
962 | char whole_path[1024]; | ||||
963 | |||||
964 | this_dir = (struct directory *) e_malloc(sizeof(struct directory)); | ||||
965 | memset(this_dir, 0, sizeof(struct directory)); | ||||
966 | this_dir->next = NULL((void *)0); | ||||
967 | this_dir->subdir = NULL((void *)0); | ||||
968 | this_dir->self = dpnt; | ||||
969 | this_dir->contents = NULL((void *)0); | ||||
970 | this_dir->size = 0; | ||||
971 | this_dir->extent = 0; | ||||
972 | this_dir->depth = parent->depth + 1; | ||||
973 | this_dir->parent = parent; | ||||
974 | if(!parent->subdir) | ||||
975 | parent->subdir = this_dir; | ||||
976 | else { | ||||
977 | next_brother = parent->subdir; | ||||
978 | while(next_brother->next) next_brother = next_brother->next; | ||||
979 | next_brother->next = this_dir; | ||||
980 | } | ||||
981 | |||||
982 | /* | ||||
983 | * Set the name for this directory. | ||||
984 | */ | ||||
985 | strcpy(whole_path, parent->de_name); | ||||
986 | strcat(whole_path, SPATH_SEPARATOR"/"); | ||||
987 | strcat(whole_path, dpnt->name); | ||||
988 | this_dir->de_name = strdup(whole_path); | ||||
989 | this_dir->whole_name = strdup(whole_path); | ||||
990 | |||||
991 | /* | ||||
992 | * Now fill this directory using information from the previous | ||||
993 | * session. | ||||
994 | */ | ||||
995 | contents = read_merging_directory(&dpnt->isorec, &n_orig); | ||||
996 | /* | ||||
997 | * Start by simply copying the '.', '..' and non-directory | ||||
998 | * entries to this directory. Technically we could let | ||||
999 | * merge_remaining_entries handle this, but it gets rather confused | ||||
1000 | * by the '.' and '..' entries. | ||||
1001 | */ | ||||
1002 | for(i=0; i < n_orig; i ++ ) | ||||
1003 | { | ||||
1004 | /* | ||||
1005 | * We can always reuse the TRANS.TBL in this particular case. | ||||
1006 | */ | ||||
1007 | contents[i]->de_flags |= SAFE_TO_REUSE_TABLE_ENTRY0x01; | ||||
1008 | |||||
1009 | if( ((contents[i]->isorec.flags[0] & 2) != 0) | ||||
1010 | && (i >= 2) ) | ||||
1011 | { | ||||
1012 | continue; | ||||
1013 | } | ||||
1014 | |||||
1015 | /* | ||||
1016 | * If we have a directory, don't reuse the extent number. | ||||
1017 | */ | ||||
1018 | if( (contents[i]->isorec.flags[0] & 2) != 0 ) | ||||
1019 | { | ||||
1020 | memset(contents[i]->isorec.extent, 0, 8); | ||||
1021 | |||||
1022 | if( strcmp(contents[i]->name, ".") == 0 ) | ||||
1023 | this_dir->dir_flags |= DIR_HAS_DOT0x02; | ||||
1024 | |||||
1025 | if( strcmp(contents[i]->name, "..") == 0 ) | ||||
1026 | this_dir->dir_flags |= DIR_HAS_DOTDOT0x04; | ||||
1027 | } | ||||
1028 | |||||
1029 | /* | ||||
1030 | * Set the whole name for this file. | ||||
1031 | */ | ||||
1032 | strcpy(whole_path, this_dir->whole_name); | ||||
1033 | strcat(whole_path, SPATH_SEPARATOR"/"); | ||||
1034 | strcat(whole_path, contents[i]->name); | ||||
1035 | |||||
1036 | contents[i]->whole_name = strdup(whole_path); | ||||
1037 | |||||
1038 | contents[i]->next = this_dir->contents; | ||||
1039 | contents[i]->filedir = this_dir; | ||||
1040 | this_dir->contents = contents[i]; | ||||
1041 | contents[i] = NULL((void *)0); | ||||
1042 | } | ||||
1043 | |||||
1044 | /* | ||||
1045 | * Zero the extent number for ourselves. | ||||
1046 | */ | ||||
1047 | memset(dpnt->isorec.extent, 0, 8); | ||||
1048 | |||||
1049 | /* | ||||
1050 | * Anything that is left are other subdirectories that need to be merged. | ||||
1051 | */ | ||||
1052 | merge_remaining_entries(this_dir, contents, n_orig); | ||||
1053 | free_mdinfo(contents, n_orig); | ||||
1054 | #if 0 | ||||
1055 | /* | ||||
1056 | * This is no longer required. The post-scan sort will handle | ||||
1057 | * all of this for us. | ||||
1058 | */ | ||||
1059 | sort_n_finish(this_dir); | ||||
1060 | #endif | ||||
1061 | |||||
1062 | return 0; | ||||
1063 | } | ||||
1064 | |||||
1065 | |||||
1066 | char * cdwrite_data = NULL((void *)0); | ||||
1067 | |||||
1068 | int | ||||
1069 | FDECL1(get_session_start, int *, file_addr)get_session_start(int * file_addr) | ||||
1070 | { | ||||
1071 | char * pnt; | ||||
1072 | |||||
1073 | #ifdef CDWRITE_DETERMINES_FIRST_WRITABLE_ADDRESS | ||||
1074 | /* | ||||
1075 | * FIXME(eric). We need to coordinate with cdwrite to obtain | ||||
1076 | * the parameters. For now, we assume we are writing the 2nd session, | ||||
1077 | * so we start from the session that starts at 0. | ||||
1078 | */ | ||||
1079 | |||||
1080 | *file_addr = (16 << 11); | ||||
1081 | |||||
1082 | /* | ||||
1083 | * We need to coordinate with cdwrite to get the next writable address | ||||
1084 | * from the device. Here is where we use it. | ||||
1085 | */ | ||||
1086 | session_start = last_extent = last_extent_written = cdwrite_result(); | ||||
1087 | |||||
1088 | #else | ||||
1089 | |||||
1090 | if( cdwrite_data == NULL((void *)0) ) | ||||
1091 | { | ||||
1092 | fprintf(stderr(&__sF[2]),"Special parameters for cdwrite not specified with -C\n"); | ||||
1093 | exit(1); | ||||
1094 | } | ||||
1095 | |||||
1096 | /* | ||||
1097 | * Next try and find the ',' in there which delimits the two numbers. | ||||
1098 | */ | ||||
1099 | pnt = strchr(cdwrite_data, ','); | ||||
1100 | if( pnt == NULL((void *)0) ) | ||||
1101 | { | ||||
1102 | fprintf(stderr(&__sF[2]), "Malformed cdwrite parameters\n"); | ||||
1103 | exit(1); | ||||
1104 | } | ||||
1105 | |||||
1106 | *pnt = '\0'; | ||||
1107 | if (file_addr != NULL((void *)0)) { | ||||
1108 | *file_addr = atol(cdwrite_data) * SECTOR_SIZE(2048); | ||||
1109 | } | ||||
1110 | pnt++; | ||||
1111 | |||||
1112 | session_start = last_extent = last_extent_written = atol(pnt); | ||||
1113 | |||||
1114 | pnt--; | ||||
1115 | *pnt = ','; | ||||
1116 | |||||
1117 | #endif | ||||
1118 | return 0; | ||||
1119 | } | ||||
1120 | |||||
1121 | /* | ||||
1122 | * This function scans the directory tree, looking for files, and it makes | ||||
1123 | * note of everything that is found. We also begin to construct the ISO9660 | ||||
1124 | * directory entries, so that we can determine how large each directory is. | ||||
1125 | */ | ||||
1126 | |||||
1127 | int | ||||
1128 | FDECL2(merge_previous_session,struct directory *, this_dir,merge_previous_session(struct directory * this_dir, struct iso_directory_record * mrootp) | ||||
1129 | struct iso_directory_record *, mrootp)merge_previous_session(struct directory * this_dir, struct iso_directory_record * mrootp) | ||||
1130 | { | ||||
1131 | struct directory_entry **orig_contents = NULL((void *)0); | ||||
1132 | struct directory_entry * odpnt = NULL((void *)0); | ||||
1133 | int n_orig; | ||||
1134 | struct directory_entry * s_entry; | ||||
1135 | int status, lstatus; | ||||
1136 | struct stat statbuf, lstatbuf; | ||||
1137 | |||||
1138 | /* | ||||
1139 | * Parse the same directory in the image that we are merging | ||||
1140 | * for multisession stuff. | ||||
1141 | */ | ||||
1142 | orig_contents = read_merging_directory(mrootp, &n_orig); | ||||
1143 | if( orig_contents
| ||||
| |||||
1144 | { | ||||
1145 | return 0; | ||||
1146 | } | ||||
1147 | |||||
1148 | |||||
1149 | /* Now we scan the directory itself, and look at what is inside of it. */ | ||||
1150 | |||||
1151 | for(s_entry = this_dir->contents; s_entry; s_entry = s_entry->next) | ||||
1152 | { | ||||
1153 | status = stat_filter(s_entry->whole_name, &statbuf); | ||||
1154 | lstatus = lstat_filter(s_entry->whole_name, &lstatbuf); | ||||
1155 | |||||
1156 | /* | ||||
1157 | * We always should create an entirely new directory tree whenever | ||||
1158 | * we generate a new session, unless there were *no* changes whatsoever | ||||
1159 | * to any of the directories, in which case it would be kind of pointless | ||||
1160 | * to generate a new session. | ||||
1161 | * | ||||
1162 | * I believe it is possible to rigorously prove that any change anywhere | ||||
1163 | * in the filesystem will force the entire tree to be regenerated | ||||
1164 | * because the modified directory will get a new extent number. Since | ||||
1165 | * each subdirectory of the changed directory has a '..' entry, all of | ||||
1166 | * them will need to be rewritten too, and since the parent directory | ||||
1167 | * of the modified directory will have an extent pointer to the directory | ||||
1168 | * it too will need to be rewritten. Thus we will never be able to reuse | ||||
1169 | * any directory information when writing new sessions. | ||||
1170 | * | ||||
1171 | * We still check the previous session so we can mark off the equivalent | ||||
1172 | * entry in the list we got from the original disc, however. | ||||
1173 | */ | ||||
1174 | |||||
1175 | /* | ||||
1176 | * The check_prev_session function looks for an identical entry in | ||||
1177 | * the previous session. If we see it, then we copy the extent | ||||
1178 | * number to s_entry, and cross it off the list. | ||||
1179 | */ | ||||
1180 | check_prev_session(orig_contents, n_orig, s_entry, | ||||
1181 | &statbuf, &lstatbuf, &odpnt); | ||||
1182 | |||||
1183 | if(S_ISDIR(statbuf.st_mode)((statbuf.st_mode & 0170000) == 0040000) && odpnt
| ||||
1184 | { | ||||
1185 | int dflag; | ||||
1186 | |||||
1187 | if (strcmp(s_entry->name,".") && strcmp(s_entry->name,"..")) | ||||
1188 | { | ||||
1189 | struct directory * child; | ||||
1190 | |||||
1191 | child = find_or_create_directory(this_dir, | ||||
1192 | s_entry->whole_name, | ||||
1193 | s_entry, 1); | ||||
1194 | dflag = merge_previous_session(child, | ||||
1195 | &odpnt->isorec); | ||||
1196 | /* If unable to scan directory, mark this as a non-directory */ | ||||
1197 | if(!dflag) | ||||
1198 | lstatbuf.st_mode = (lstatbuf.st_mode & ~S_IFMT0170000) | S_IFREG0100000; | ||||
1199 | free(odpnt); | ||||
1200 | odpnt = NULL((void *)0); | ||||
1201 | } | ||||
1202 | } | ||||
1203 | } | ||||
1204 | |||||
1205 | /* | ||||
1206 | * Whatever is left over, are things which are no longer in the tree | ||||
1207 | * on disk. We need to also merge these into the tree. | ||||
1208 | */ | ||||
1209 | merge_remaining_entries(this_dir, orig_contents, n_orig); | ||||
1210 | free_mdinfo(orig_contents, n_orig); | ||||
1211 | |||||
1212 | return 1; | ||||
1213 | } | ||||
1214 |