Bug Summary

File:src/gnu/usr.sbin/mkhybrid/mkhybrid/../src/multi.c
Warning:line 1154, column 7
Value stored to 'lstatus' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name multi.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/gnu/usr.sbin/mkhybrid/mkhybrid/obj -resource-dir /usr/local/lib/clang/13.0.0 -D SYSTEM_ID_DEFAULT="OpenBSD" -D APPLE_HYB -D VANILLA_AUTOCONF -I /usr/src/gnu/usr.sbin/mkhybrid/mkhybrid/../src -I /usr/src/gnu/usr.sbin/mkhybrid/mkhybrid/../src/include -I /usr/src/gnu/usr.sbin/mkhybrid/mkhybrid/../src/libhfs_iso -I /usr/src/gnu/usr.sbin/mkhybrid/mkhybrid/../src/libfile -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/gnu/usr.sbin/mkhybrid/mkhybrid/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/gnu/usr.sbin/mkhybrid/mkhybrid/../src/multi.c
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"
41extern 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
52static int isonum_711 __PR((unsigned char * p))(unsigned char * p);
53static int isonum_721 __PR((unsigned char * p))(unsigned char * p);
54static int isonum_723 __PR((unsigned char * p))(unsigned char * p);
55static int isonum_731 __PR((unsigned char * p))(unsigned char * p);
56
57static 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
61static int
62isonum_711 (unsigned char * p)
63#else
64static int
65isonum_711 (p)
66 unsigned char * p;
67#endif
68{
69 return (*p & 0xff);
70}
71
72#ifdef __STDC__1
73static int
74isonum_721 (unsigned char * p)
75#else
76static int
77isonum_721 (p)
78 unsigned char * p;
79#endif
80{
81 return ((p[0] & 0xff) | ((p[1] & 0xff) << 8));
82}
83
84#ifdef __STDC__1
85static int
86isonum_723 (unsigned char * p)
87#else
88static int
89isonum_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
103static int
104isonum_731 (unsigned char * p)
105#else
106static int
107isonum_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
118int
119isonum_733 (unsigned char * p)
120#else
121int
122isonum_733 (p)
123 unsigned char * p;
124#endif
125{
126 return (isonum_731 (p));
127}
128
129FILE * 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
147static int
148readsecs(int startsecno, void *buffer, int sectorcount)
149#else
150static int
151readsecs(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 */
170static int
171FDECL3(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(&sector[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
223static int
224FDECL4(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(&sector[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
315struct directory_entry **
316FDECL2(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 */
568int
569FDECL2(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
621int
622FDECL6(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
712found_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 */
729struct 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
810void 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 != NULL((void *)0)
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 != NULL((void *)0) && strcmp(s_entry->name, ".") == 0 )
906 {
907 continue;
908 }
909 if( s_entry->name != NULL((void *)0) && strcmp(s_entry->name, "..") == 0 )
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 */
954static int
955FDECL2(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
1066char * cdwrite_data = NULL((void *)0);
1067
1068int
1069FDECL1(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
1127int
1128FDECL2(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 == NULL((void *)0) )
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);
Value stored to 'lstatus' is never read
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 != NULL((void *)0))
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