~darkmuggle-deactivatedaccount/ubuntu/quantal/grub2/fix-872244

« back to all changes in this revision

Viewing changes to util/mkisofs/write.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson
  • Date: 2010-01-11 11:12:55 UTC
  • mfrom: (17.3.7 squeeze)
  • Revision ID: james.westby@ubuntu.com-20100111111255-lr8ebkqw5x41gq6j
Tags: 1.98~20100101-1ubuntu1
* Resynchronise with Debian. Remaining changes:
  - Adjust for default Ubuntu boot options ("quiet splash").
  - Default to hiding the menu; holding down Shift at boot will show it.
  - Set a monochromatic theme for Ubuntu.
  - Apply Ubuntu GRUB Legacy changes to legacy update-grub script: title,
    recovery mode, quiet option, tweak how memtest86+ is displayed, and
    use UUIDs where appropriate.
  - Conflict with grub (<< 0.97-54) as well as grub-legacy.
  - Fix backslash-escaping in merge_debconf_into_conf.
  - Remove "GNU/Linux" from default distributor string.
  - Add crashkernel= options if kdump and makedumpfile are available.
  - If other operating systems are installed, then automatically unhide
    the menu. Otherwise, if GRUB_HIDDEN_TIMEOUT is 0, then use keystatus
    if available to check whether Shift is pressed. If it is, show the
    menu, otherwise boot immediately. If keystatus is not available, then
    fall back to a short delay interruptible with Escape.
  - Allow Shift to interrupt 'sleep --interruptible'.
  - Don't display introductory message about line editing unless we're
    actually offering a shell prompt. Don't clear the screen just before
    booting if we never drew the menu in the first place.
  - Remove some verbose messages printed before reading the configuration
    file.
  - If the environment variable "quiet" is set to something other than 0,
    suppress progress messages as the kernel and initrd load. Set this for
    non-recovery kernel menu entries.
  - Add GRUB_DEFAULT=saved, as well as grub-set-default and grub-reboot
    utilities. Provides functionality essentially equivalent to GRUB
    Legacy's savedefault.
  - Keep the loopback file open so that subsequent changes to the "root"
    environment variable don't affect it.
  - Change prepare_grub_to_access_device to handle filesystems
    loop-mounted on file images.
  - Ignore devices loop-mounted from files in 10_linux.
  - Show the boot menu if the previous boot failed, that is if it failed
    to get to the end of one of the normal runlevels.
  - Handle RAID devices containing virtio components.
* Update savedefault patch from current Bazaar branch, fixing grub-reboot
  to have distinct behaviour from grub-set-default (LP: #497326).
* Fix grub-mkisofs compilation error with FORTIFY_SOURCE.
* Convert recordfail boilerplate in each menu entry to use a function.

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
   along with this program; if not, see <http://www.gnu.org/licenses/>.
22
22
 */
23
23
 
 
24
#include "config.h"
 
25
 
24
26
#include <string.h>
25
27
#include <stdlib.h>
26
 
#include "config.h"
27
 
#include "mkisofs.h"
28
 
#include "iso9660.h"
29
28
#include <time.h>
30
29
#include <errno.h>
31
30
 
37
36
#ifdef HAVE_UNISTD_H
38
37
#include <unistd.h>
39
38
#endif
40
 
 
 
39
 
 
40
#include "mkisofs.h"
 
41
#include "iso9660.h"
 
42
#include "msdos_partition.h"
 
43
 
41
44
#ifdef __SVR4
42
45
extern char * strdup(const char *);
43
46
#endif
158
161
                  error (1, errno, _("Cannot open '%s'"), nbuf);
159
162
 
160
163
        }
161
 
     while(count) 
 
164
     while(count)
162
165
     {
163
166
          size_t got = fwrite (buffer, size, count, file);
164
167
 
193
196
     struct directory * dpnt;
194
197
 
195
198
     dpnt = node;
196
 
     
 
199
    
197
200
     while (dpnt)
198
201
     {
199
202
          /* skip if it's hidden */
211
214
          {
212
215
               dpnt->extent = last_extent;
213
216
               dir_size = (dpnt->size + (SECTOR_SIZE - 1)) >> 11;
214
 
               
 
217
              
215
218
               last_extent += dir_size;
216
 
               
217
 
               /* 
 
219
              
 
220
               /*
218
221
                * Leave room for the CE entries for this directory.  Keep them
219
 
                * close to the reference directory so that access will be 
220
 
                * quick. 
 
222
                * close to the reference directory so that access will be
 
223
                * quick.
221
224
                */
222
225
               if(dpnt->ce_bytes)
223
226
               {
225
228
               }
226
229
          }
227
230
 
228
 
          if(dpnt->subdir) 
 
231
          if(dpnt->subdir)
229
232
          {
230
233
               assign_directory_addresses(dpnt->subdir);
231
234
          }
235
238
     return 0;
236
239
}
237
240
 
238
 
static void FDECL3(write_one_file, char *, filename, 
 
241
static void FDECL3(write_one_file, char *, filename,
239
242
                   uint64_t, size, FILE *, outfile)
240
243
{
241
244
     char                 buffer[SECTOR_SIZE * NSECT];
244
247
     size_t               use;
245
248
 
246
249
 
247
 
     if ((infile = fopen(filename, "rb")) == NULL) 
 
250
     if ((infile = fopen(filename, "rb")) == NULL)
248
251
       error (1, errno, _("cannot open %s\n"), filename);
249
252
     remain = size;
250
253
 
253
256
          use =  (remain >  SECTOR_SIZE * NSECT - 1 ? NSECT*SECTOR_SIZE : remain);
254
257
          use = ROUND_UP(use); /* Round up to nearest sector boundary */
255
258
          memset(buffer, 0, use);
256
 
          if (fread(buffer, 1, use, infile) == 0) 
257
 
            error (1, errno, _("cannot read %llu bytes from %s"), use, filename); 
 
259
          if (fread(buffer, 1, use, infile) == 0)
 
260
            error (1, errno, _("cannot read %llu bytes from %s"), use, filename);
258
261
          xfwrite(buffer, 1, use, outfile);
259
262
          last_extent_written += use/SECTOR_SIZE;
260
263
#if 0
261
 
          if((last_extent_written % 1000) < use/SECTOR_SIZE) 
 
264
          if((last_extent_written % 1000) < use/SECTOR_SIZE)
262
265
          {
263
266
               fprintf(stderr,"%d..", last_extent_written);
264
267
          }
268
271
               time_t now;
269
272
               time_t the_end;
270
273
               double frac;
271
 
               
 
274
              
272
275
               time(&now);
273
276
               frac = last_extent_written / (double)last_extent;
274
277
               the_end = begun + (now - begun) / frac;
287
290
     dwpnt = dw_head;
288
291
     while(dwpnt)
289
292
     {
290
 
          if(dwpnt->table) 
 
293
          if(dwpnt->table)
291
294
          {
292
295
            write_one_file (dwpnt->table, dwpnt->size, outfile);
293
296
            table_size += dwpnt->size;
294
297
            free (dwpnt->table);
295
298
          }
296
 
          else 
 
299
          else
297
300
          {
298
301
 
299
302
#ifdef VMS
324
327
}
325
328
#endif
326
329
 
327
 
static int FDECL2(compare_dirs, const void *, rr, const void *, ll) 
 
330
static int FDECL2(compare_dirs, const void *, rr, const void *, ll)
328
331
{
329
332
     char * rpnt, *lpnt;
330
333
     struct directory_entry ** r, **l;
331
 
     
 
334
    
332
335
     r = (struct directory_entry **) rr;
333
336
     l = (struct directory_entry **) ll;
334
337
     rpnt = (*r)->isorec.name;
341
344
       {
342
345
         sort_goof++;
343
346
       }
344
 
     
 
347
    
345
348
     /*
346
349
      *  Put the '.' and '..' entries on the head of the sorted list.
347
350
      *  For normal ASCII, this always happens to be the case, but out of
373
376
     if((*l)->isorec.name_len[0] == 1 && *lpnt == 1) return 1;
374
377
#endif
375
378
 
376
 
     while(*rpnt && *lpnt) 
 
379
     while(*rpnt && *lpnt)
377
380
     {
378
381
          if(*rpnt == ';' && *lpnt != ';') return -1;
379
382
          if(*rpnt != ';' && *lpnt == ';') return 1;
380
 
          
 
383
         
381
384
          if(*rpnt == ';' && *lpnt == ';') return 0;
382
 
          
 
385
         
383
386
          if(*rpnt == '.' && *lpnt != '.') return -1;
384
387
          if(*rpnt != '.' && *lpnt == '.') return 1;
385
 
          
 
388
         
386
389
          if((unsigned char)*rpnt < (unsigned char)*lpnt) return -1;
387
390
          if((unsigned char)*rpnt > (unsigned char)*lpnt) return 1;
388
391
          rpnt++;  lpnt++;
392
395
     return 0;
393
396
}
394
397
 
395
 
/* 
 
398
/*
396
399
 * Function:            sort_directory
397
400
 *
398
401
 * Purpose:             Sort the directory in the appropriate ISO9660
408
411
     int i, len;
409
412
     struct directory_entry * s_entry;
410
413
     struct directory_entry ** sortlist;
411
 
     
 
414
    
412
415
     /* need to keep a count of how many entries are hidden */
413
416
     s_entry = *sort_dir;
414
417
     while(s_entry)
425
428
     }
426
429
 
427
430
     /*
428
 
      * OK, now we know how many there are.  Build a vector for sorting. 
 
431
      * OK, now we know how many there are.  Build a vector for sorting.
429
432
      */
430
 
     sortlist =   (struct directory_entry **) 
 
433
     sortlist =   (struct directory_entry **)
431
434
          e_malloc(sizeof(struct directory_entry *) * dcount);
432
435
 
433
436
     j = dcount - 1;
449
452
         s_entry->isorec.name[len] = 0;
450
453
         s_entry = s_entry->next;
451
454
     }
452
 
  
 
455
 
453
456
     /*
454
457
      * Each directory is required to contain at least . and ..
455
458
      */
456
459
     if( dcount < 2 )
457
460
       {
458
461
         sort_goof = 1;
459
 
         
 
462
        
460
463
       }
461
464
     else
462
465
       {
463
466
         /* only sort the non-hidden entries */
464
467
         sort_goof = 0;
465
468
#ifdef __STDC__
466
 
         qsort(sortlist, dcount, sizeof(struct directory_entry *), 
 
469
         qsort(sortlist, dcount, sizeof(struct directory_entry *),
467
470
               (int (*)(const void *, const void *))compare_dirs);
468
471
#else
469
 
         qsort(sortlist, dcount, sizeof(struct directory_entry *), 
 
472
         qsort(sortlist, dcount, sizeof(struct directory_entry *),
470
473
               compare_dirs);
471
474
#endif
472
 
         
473
 
         /* 
474
 
          * Now reassemble the linked list in the proper sorted order 
 
475
        
 
476
         /*
 
477
          * Now reassemble the linked list in the proper sorted order
475
478
          * We still need the hidden entries, as they may be used in the
476
479
          * Joliet tree.
477
480
          */
479
482
           {
480
483
             sortlist[i]->next = sortlist[i+1];
481
484
           }
482
 
         
 
485
        
483
486
         sortlist[dcount+xcount-1]->next = NULL;
484
487
         *sort_dir = sortlist[0];
485
488
       }
491
494
static int root_gen()
492
495
{
493
496
     init_fstatbuf();
494
 
     
 
497
    
495
498
     root_record.length[0] = 1 + sizeof(struct iso_directory_record)
496
499
          - sizeof(root_record.name);
497
500
     root_record.ext_attr_length[0] = 0;
530
533
               {
531
534
                    continue;
532
535
               }
533
 
               
534
 
               /* 
535
 
                * This saves some space if there are symlinks present 
 
536
              
 
537
               /*
 
538
                * This saves some space if there are symlinks present
536
539
                */
537
540
               s_hash = find_hash(s_entry->dev, s_entry->inode);
538
541
               if(s_hash)
539
542
               {
540
543
                    if(verbose > 2)
541
544
                    {
542
 
                      fprintf (stderr, _("Cache hit for %s%s%s\n"), s_entry->filedir->de_name, 
 
545
                      fprintf (stderr, _("Cache hit for %s%s%s\n"), s_entry->filedir->de_name,
543
546
                               SPATH_SEPARATOR, s_entry->name);
544
547
                    }
545
548
                    set_733((char *) s_entry->isorec.extent, s_hash->starting_block);
548
551
               }
549
552
 
550
553
               /*
551
 
                * If this is for a directory that is not a . or a .. entry, 
 
554
                * If this is for a directory that is not a . or a .. entry,
552
555
                * then look up the information for the entry.  We have already
553
556
                * assigned extents for directories, so we just need to
554
557
                * fill in the blanks here.
555
558
                */
556
 
               if (strcmp(s_entry->name,".") && strcmp(s_entry->name,"..") && 
 
559
               if (strcmp(s_entry->name,".") && strcmp(s_entry->name,"..") &&
557
560
                   s_entry->isorec.flags[0] == 2)
558
561
               {
559
562
                    finddir = dpnt->subdir;
561
564
                    {
562
565
                         if(finddir->self == s_entry) break;
563
566
                         finddir = finddir->next;
564
 
                         if (!finddir) 
 
567
                         if (!finddir)
565
568
                           error (1, 0, _("Fatal goof\n"));
566
569
                    }
567
570
                    set_733((char *) s_entry->isorec.extent, finddir->extent);
578
581
                * If this is . or .., then look up the relevant info from the
579
582
                * tables.
580
583
                */
581
 
               if(strcmp(s_entry->name,".") == 0) 
 
584
               if(strcmp(s_entry->name,".") == 0)
582
585
               {
583
586
                    set_733((char *) s_entry->isorec.extent, dpnt->extent);
584
 
                    
585
 
                    /* 
 
587
                   
 
588
                    /*
586
589
                     * Set these so that the hash table has the
587
590
                     * correct information
588
591
                     */
589
592
                    s_entry->starting_block = dpnt->extent;
590
593
                    s_entry->size = ROUND_UP(dpnt->size);
591
 
                    
 
594
                   
592
595
                    add_hash(s_entry);
593
596
                    s_entry->starting_block = dpnt->extent;
594
597
                    set_733((char *) s_entry->isorec.size, ROUND_UP(dpnt->size));
595
598
                    continue;
596
599
               }
597
600
 
598
 
               if(strcmp(s_entry->name,"..") == 0) 
 
601
               if(strcmp(s_entry->name,"..") == 0)
599
602
               {
600
603
                    if(dpnt == root)
601
 
                    { 
 
604
                    {
602
605
                         total_dir_size += root->size;
603
606
                    }
604
607
                    set_733((char *) s_entry->isorec.extent, dpnt->parent->extent);
605
 
                    
606
 
                    /* 
 
608
                   
 
609
                    /*
607
610
                     * Set these so that the hash table has the
608
611
                     * correct information
609
612
                     */
610
613
                    s_entry->starting_block = dpnt->parent->extent;
611
614
                    s_entry->size = ROUND_UP(dpnt->parent->size);
612
 
                    
 
615
                   
613
616
                    add_hash(s_entry);
614
617
                    s_entry->starting_block = dpnt->parent->extent;
615
618
                    set_733((char *) s_entry->isorec.size, ROUND_UP(dpnt->parent->size));
616
619
                    continue;
617
620
               }
618
621
 
619
 
               /* 
 
622
               /*
620
623
                * Some ordinary non-directory file.  Just schedule the
621
624
                * file to be written.  This is all quite
622
625
                * straightforward, just make a list and assign extents
624
627
                * directories, we should be ready write out these
625
628
                * files
626
629
                */
627
 
               if(s_entry->size) 
 
630
               if(s_entry->size)
628
631
               {
629
 
                    dwpnt = (struct deferred_write *) 
 
632
                    dwpnt = (struct deferred_write *)
630
633
                         e_malloc(sizeof(struct deferred_write));
631
634
                    if(dw_tail)
632
635
                    {
633
636
                         dw_tail->next = dwpnt;
634
637
                         dw_tail = dwpnt;
635
 
                    } 
636
 
                    else 
 
638
                    }
 
639
                    else
637
640
                    {
638
641
                         dw_head = dwpnt;
639
642
                         dw_tail = dwpnt;
640
643
                    }
641
 
                    if(s_entry->inode  ==  TABLE_INODE) 
 
644
                    if(s_entry->inode  ==  TABLE_INODE)
642
645
                    {
643
646
                         dwpnt->table = s_entry->table;
644
647
                         dwpnt->name = NULL;
645
648
                         sprintf(whole_path,"%s%sTRANS.TBL",
646
649
                                 s_entry->filedir->whole_name, SPATH_SEPARATOR);
647
 
                    } 
648
 
                    else 
 
650
                    }
 
651
                    else
649
652
                    {
650
653
                         dwpnt->table = NULL;
651
654
                         strcpy(whole_path, s_entry->whole_name);
669
672
                         fprintf (stderr, "Warning: large file %s\n", whole_path);
670
673
                         fprintf (stderr, "Starting block is %d\n", s_entry->starting_block);
671
674
                         fprintf (stderr, "Reported file size is %d extents\n", s_entry->size);
672
 
                         
 
675
                        
673
676
                    }
674
677
#endif
675
678
#ifdef  NOT_NEEDED      /* Never use this code if you like to create a DVD */
676
679
 
677
 
                    if(last_extent > (800000000 >> 11)) 
678
 
                    { 
 
680
                    if(last_extent > (800000000 >> 11))
 
681
                    {
679
682
                         /*
680
 
                          * More than 800Mb? Punt 
 
683
                          * More than 800Mb? Punt
681
684
                          */
682
685
                         fprintf(stderr,"Extent overflow processing file %s\n", whole_path);
683
686
                         fprintf(stderr,"Starting block is %d\n", s_entry->starting_block);
696
699
                */
697
700
               set_733((char *) s_entry->isorec.extent, last_extent);
698
701
          }
699
 
          if(dpnt->subdir) 
 
702
          if(dpnt->subdir)
700
703
          {
701
704
               assign_file_addresses(dpnt->subdir);
702
705
          }
708
711
{
709
712
     struct directory_entry             * s_entry;
710
713
     struct directory_entry             * s_entry_d;
711
 
     
 
714
    
712
715
     s_entry = dpnt->contents;
713
 
     while(s_entry) 
 
716
     while(s_entry)
714
717
     {
715
718
         s_entry_d = s_entry;
716
719
         s_entry = s_entry->next;
717
 
         
 
720
        
718
721
         if( s_entry_d->name != NULL )
719
722
         {
720
723
             free (s_entry_d->name);
750
753
     struct directory_entry             * s_entry;
751
754
     struct directory_entry             * s_entry_d;
752
755
     unsigned int                         total_size;
753
 
     
 
756
    
754
757
     total_size = (dpnt->size + (SECTOR_SIZE - 1)) &  ~(SECTOR_SIZE - 1);
755
758
     directory_buffer = (char *) e_malloc(total_size);
756
759
     memset(directory_buffer, 0, total_size);
757
760
     dir_index = 0;
758
 
     
 
761
    
759
762
     ce_size = (dpnt->ce_bytes + (SECTOR_SIZE - 1)) &  ~(SECTOR_SIZE - 1);
760
763
     ce_buffer = NULL;
761
 
     
762
 
     if(ce_size) 
 
764
    
 
765
     if(ce_size)
763
766
     {
764
767
          ce_buffer = (char *) e_malloc(ce_size);
765
768
          memset(ce_buffer, 0, ce_size);
766
 
          
 
769
         
767
770
          ce_index = 0;
768
 
          
 
771
         
769
772
          /*
770
 
           * Absolute byte address of CE entries for this directory 
 
773
           * Absolute byte address of CE entries for this directory
771
774
           */
772
775
          ce_address = last_extent_written + (total_size >> 11);
773
776
          ce_address = ce_address << 11;
774
777
     }
775
 
     
 
778
    
776
779
     s_entry = dpnt->contents;
777
 
     while(s_entry) 
 
780
     while(s_entry)
778
781
     {
779
782
          /* skip if it's hidden */
780
783
          if(s_entry->de_flags & INHIBIT_ISO9660_ENTRY) {
782
785
            continue;
783
786
          }
784
787
 
785
 
          /* 
786
 
           * We do not allow directory entries to cross sector boundaries.  
787
 
           * Simply pad, and then start the next entry at the next sector 
 
788
          /*
 
789
           * We do not allow directory entries to cross sector boundaries. 
 
790
           * Simply pad, and then start the next entry at the next sector
788
791
           */
789
792
          new_reclen = s_entry->isorec.length[0];
790
793
          if( (dir_index & (SECTOR_SIZE - 1)) + new_reclen >= SECTOR_SIZE )
791
794
          {
792
 
               dir_index = (dir_index + (SECTOR_SIZE - 1)) & 
 
795
               dir_index = (dir_index + (SECTOR_SIZE - 1)) &
793
796
                    ~(SECTOR_SIZE - 1);
794
797
          }
795
798
 
796
 
          memcpy(directory_buffer + dir_index, &s_entry->isorec, 
 
799
          memcpy(directory_buffer + dir_index, &s_entry->isorec,
797
800
                 sizeof(struct iso_directory_record) -
798
801
                 sizeof(s_entry->isorec.name) + s_entry->isorec.name_len[0]);
799
 
          dir_index += sizeof(struct iso_directory_record) - 
 
802
          dir_index += sizeof(struct iso_directory_record) -
800
803
               sizeof (s_entry->isorec.name)+ s_entry->isorec.name_len[0];
801
804
 
802
805
          /*
803
 
           * Add the Rock Ridge attributes, if present 
 
806
           * Add the Rock Ridge attributes, if present
804
807
           */
805
808
          if(s_entry->rr_attr_size)
806
809
          {
809
812
                    directory_buffer[dir_index++] = 0;
810
813
               }
811
814
 
812
 
               /* 
 
815
               /*
813
816
                * If the RR attributes were too long, then write the
814
817
                * CE records, as required.
815
818
                */
816
 
               if(s_entry->rr_attr_size != s_entry->total_rr_attr_size) 
 
819
               if(s_entry->rr_attr_size != s_entry->total_rr_attr_size)
817
820
               {
818
821
                    unsigned char * pnt;
819
822
                    int len, nbytes;
820
 
                    
821
 
                    /* 
 
823
                   
 
824
                    /*
822
825
                     * Go through the entire record and fix up the CE entries
823
 
                     * so that the extent and offset are correct 
 
826
                     * so that the extent and offset are correct
824
827
                     */
825
 
                    
 
828
                   
826
829
                    pnt = s_entry->rr_attributes;
827
830
                    len = s_entry->total_rr_attr_size;
828
831
                    while(len > 3)
834
837
                                      ce_index, ce_address);
835
838
                         }
836
839
#endif
837
 
                         
838
 
                         if(pnt[0] == 'C' && pnt[1] == 'E') 
 
840
                        
 
841
                         if(pnt[0] == 'C' && pnt[1] == 'E')
839
842
                         {
840
843
                              nbytes = get_733( (char *) pnt+20);
841
 
                              
 
844
                             
842
845
                              if((ce_index & (SECTOR_SIZE - 1)) + nbytes >=
843
 
                                 SECTOR_SIZE) 
 
846
                                 SECTOR_SIZE)
844
847
                              {
845
848
                                   ce_index = ROUND_UP(ce_index);
846
849
                              }
847
 
                              
848
 
                              set_733( (char *) pnt+4, 
 
850
                             
 
851
                              set_733( (char *) pnt+4,
849
852
                                       (ce_address + ce_index) >> 11);
850
 
                              set_733( (char *) pnt+12, 
 
853
                              set_733( (char *) pnt+12,
851
854
                                       (ce_address + ce_index) & (SECTOR_SIZE - 1));
852
 
                              
853
 
                              
854
 
                              /* 
855
 
                               * Now store the block in the ce buffer 
 
855
                             
 
856
                             
 
857
                              /*
 
858
                               * Now store the block in the ce buffer
856
859
                               */
857
 
                              memcpy(ce_buffer + ce_index, 
 
860
                              memcpy(ce_buffer + ce_index,
858
861
                                     pnt + pnt[2], nbytes);
859
862
                              ce_index += nbytes;
860
 
                              if(ce_index & 1) 
 
863
                              if(ce_index & 1)
861
864
                              {
862
865
                                   ce_index++;
863
866
                              }
865
868
                         len -= pnt[2];
866
869
                         pnt += pnt[2];
867
870
                    }
868
 
                    
 
871
                   
869
872
               }
870
873
 
871
874
               rockridge_size += s_entry->total_rr_attr_size;
872
 
               memcpy(directory_buffer + dir_index, s_entry->rr_attributes, 
 
875
               memcpy(directory_buffer + dir_index, s_entry->rr_attributes,
873
876
                      s_entry->rr_attr_size);
874
877
               dir_index += s_entry->rr_attr_size;
875
878
          }
877
880
          {
878
881
               directory_buffer[dir_index++] = 0;
879
882
          }
880
 
          
 
883
         
881
884
          s_entry_d = s_entry;
882
885
          s_entry = s_entry->next;
883
 
          
 
886
         
884
887
          /*
885
888
           * Joliet doesn't use the Rock Ridge attributes, so we free it here.
886
889
           */
887
 
          if (s_entry_d->rr_attributes) 
 
890
          if (s_entry_d->rr_attributes)
888
891
            {
889
892
              free(s_entry_d->rr_attributes);
890
893
              s_entry_d->rr_attributes = NULL;
912
915
          last_extent_written += ce_size >> 11;
913
916
          free(ce_buffer);
914
917
     }
915
 
     
 
918
    
916
919
} /* generate_one_directory(... */
917
920
 
918
 
static 
 
921
static
919
922
void FDECL1(build_pathlist, struct directory *, node)
920
923
{
921
924
     struct directory * dpnt;
922
 
     
 
925
    
923
926
     dpnt = node;
924
 
     
 
927
    
925
928
     while (dpnt)
926
929
     {
927
930
        /* skip if it's hidden */
933
936
     }
934
937
} /* build_pathlist(... */
935
938
 
936
 
static int FDECL2(compare_paths, void const *, r, void const *, l) 
 
939
static int FDECL2(compare_paths, void const *, r, void const *, l)
937
940
{
938
941
  struct directory const *ll = *(struct directory * const *)l;
939
942
  struct directory const *rr = *(struct directory * const *)r;
943
946
       return -1;
944
947
  }
945
948
 
946
 
  if (rr->parent->path_index > ll->parent->path_index) 
 
949
  if (rr->parent->path_index > ll->parent->path_index)
947
950
  {
948
951
       return 1;
949
952
  }
950
953
 
951
954
  return strcmp(rr->self->isorec.name, ll->self->isorec.name);
952
 
  
 
955
 
953
956
} /* compare_paths(... */
954
957
 
955
958
static int generate_path_tables()
965
968
  int                      tablesize;
966
969
 
967
970
  /*
968
 
   * First allocate memory for the tables and initialize the memory 
 
971
   * First allocate memory for the tables and initialize the memory
969
972
   */
970
973
  tablesize = path_blocks << 11;
971
974
  path_table_m = (char *) e_malloc(tablesize);
974
977
  memset(path_table_m, 0, tablesize);
975
978
 
976
979
  /*
977
 
   * Now start filling in the path tables.  Start with root directory 
 
980
   * Now start filling in the path tables.  Start with root directory
978
981
   */
979
982
  if( next_path_index > 0xffff )
980
983
  {
983
986
  }
984
987
 
985
988
  path_table_index = 0;
986
 
  pathlist = (struct directory **) e_malloc(sizeof(struct directory *) 
 
989
  pathlist = (struct directory **) e_malloc(sizeof(struct directory *)
987
990
                                            * next_path_index);
988
991
  memset(pathlist, 0, sizeof(struct directory *) * next_path_index);
989
992
  build_pathlist(root);
992
995
  {
993
996
       fix = 0;
994
997
#ifdef __STDC__
995
 
       qsort(&pathlist[1], next_path_index-1, sizeof(struct directory *), 
 
998
       qsort(&pathlist[1], next_path_index-1, sizeof(struct directory *),
996
999
             (int (*)(const void *, const void *))compare_paths);
997
1000
#else
998
 
       qsort(&pathlist[1], next_path_index-1, sizeof(struct directory *), 
 
1001
       qsort(&pathlist[1], next_path_index-1, sizeof(struct directory *),
999
1002
             compare_paths);
1000
1003
#endif
1001
1004
 
1017
1020
         error (1, 0, _("Entry %d not in path tables\n"), j);
1018
1021
       }
1019
1022
       npnt = dpnt->de_name;
1020
 
       
1021
 
       /* 
1022
 
        * So the root comes out OK 
 
1023
      
 
1024
       /*
 
1025
        * So the root comes out OK
1023
1026
        */
1024
 
       if( (*npnt == 0) || (dpnt == root) ) 
 
1027
       if( (*npnt == 0) || (dpnt == root) )
1025
1028
       {
1026
 
            npnt = ".";  
 
1029
            npnt = "."; 
1027
1030
       }
1028
1031
       npnt1 = strrchr(npnt, PATH_SEPARATOR);
1029
 
       if(npnt1) 
1030
 
       { 
 
1032
       if(npnt1)
 
1033
       {
1031
1034
            npnt = npnt1 + 1;
1032
1035
       }
1033
 
       
 
1036
      
1034
1037
       de = dpnt->self;
1035
 
       if(!de) 
 
1038
       if(!de)
1036
1039
       {
1037
1040
         error (1, 0, _("Fatal goof\n"));
1038
1041
       }
1039
 
       
1040
 
       
 
1042
      
 
1043
      
1041
1044
       namelen = de->isorec.name_len[0];
1042
 
       
 
1045
      
1043
1046
       path_table_l[path_table_index] = namelen;
1044
1047
       path_table_m[path_table_index] = namelen;
1045
1048
       path_table_index += 2;
1046
 
       
1047
 
       set_731(path_table_l + path_table_index, dpnt->extent); 
1048
 
       set_732(path_table_m + path_table_index, dpnt->extent); 
 
1049
      
 
1050
       set_731(path_table_l + path_table_index, dpnt->extent);
 
1051
       set_732(path_table_m + path_table_index, dpnt->extent);
1049
1052
       path_table_index += 4;
1050
 
       
1051
 
       set_721(path_table_l + path_table_index, 
1052
 
               dpnt->parent->path_index); 
1053
 
       set_722(path_table_m + path_table_index, 
1054
 
               dpnt->parent->path_index); 
 
1053
      
 
1054
       set_721(path_table_l + path_table_index,
 
1055
               dpnt->parent->path_index);
 
1056
       set_722(path_table_m + path_table_index,
 
1057
               dpnt->parent->path_index);
1055
1058
       path_table_index += 2;
1056
 
       
 
1059
      
1057
1060
       for(i =0; i<namelen; i++)
1058
1061
       {
1059
1062
            path_table_l[path_table_index] = de->isorec.name[i];
1060
1063
            path_table_m[path_table_index] = de->isorec.name[i];
1061
1064
            path_table_index++;
1062
1065
       }
1063
 
       if(path_table_index & 1) 
 
1066
       if(path_table_index & 1)
1064
1067
       {
1065
1068
            path_table_index++;  /* For odd lengths we pad */
1066
1069
       }
1067
1070
  }
1068
 
  
 
1071
 
1069
1072
  free(pathlist);
1070
1073
  if(path_table_index != path_table_size)
1071
1074
  {
1108
1111
  /*
1109
1112
   * OK, all done with that crap.  Now write out the directories.
1110
1113
   * This is where the fur starts to fly, because we need to keep track of
1111
 
   * each file as we find it and keep track of where we put it. 
 
1114
   * each file as we find it and keep track of where we put it.
1112
1115
   */
1113
1116
 
1114
1117
  should_write = last_extent - session_start;
1124
1127
#ifdef DBG_ISO
1125
1128
      fprintf(stderr,"Total directory extents being written = %llu\n", last_extent);
1126
1129
#endif
1127
 
      
1128
 
      fprintf (stderr, _("Total extents scheduled to be written = %llu\n"), 
 
1130
     
 
1131
      fprintf (stderr, _("Total extents scheduled to be written = %llu\n"),
1129
1132
               last_extent - session_start);
1130
1133
    }
1131
1134
 
1132
 
  /* 
1133
 
   * Now write all of the files that we need. 
 
1135
  /*
 
1136
   * Now write all of the files that we need.
1134
1137
   */
1135
1138
  write_files(outfile);
1136
 
  
 
1139
 
1137
1140
  /*
1138
1141
   * The rest is just fluff.
1139
1142
   */
1145
1148
  fprintf (stderr, _("Total extents actually written = %llu\n"),
1146
1149
           last_extent_written - session_start);
1147
1150
 
1148
 
  /* 
1149
 
   * Hard links throw us off here 
 
1151
  /*
 
1152
   * Hard links throw us off here
1150
1153
   */
1151
1154
  assert (last_extent > session_start);
1152
1155
  if(should_write + session_start != last_extent)
1192
1195
 
1193
1196
  /*
1194
1197
   * This will break  in the year  2000, I supose, but there is no good way
1195
 
   * to get the top two digits of the year. 
 
1198
   * to get the top two digits of the year.
1196
1199
   */
1197
1200
  sprintf(iso_time, "%4.4d%2.2d%2.2d%2.2d%2.2d%2.2d00", 1900 + local.tm_year,
1198
1201
          local.tm_mon+1, local.tm_mday,
1204
1207
  iso_time[16] = (local.tm_min + 60*(local.tm_hour + 24*local.tm_yday)) / 15;
1205
1208
 
1206
1209
  /*
1207
 
   * Next we write out the primary descriptor for the disc 
 
1210
   * Next we write out the primary descriptor for the disc
1208
1211
   */
1209
1212
  memset(&vol_desc, 0, sizeof(vol_desc));
1210
1213
  vol_desc.type[0] = ISO_VD_PRIMARY;
1211
1214
  memcpy(vol_desc.id, ISO_STANDARD_ID, sizeof(ISO_STANDARD_ID));
1212
1215
  vol_desc.version[0] = 1;
1213
 
  
 
1216
 
1214
1217
  memset(vol_desc.system_id, ' ', sizeof(vol_desc.system_id));
1215
1218
  memcpy_max(vol_desc.system_id, system_id, strlen(system_id));
1216
 
  
 
1219
 
1217
1220
  memset(vol_desc.volume_id, ' ', sizeof(vol_desc.volume_id));
1218
1221
  memcpy_max(vol_desc.volume_id, volume_id, strlen(volume_id));
1219
 
  
 
1222
 
1220
1223
  should_write = last_extent - session_start;
1221
1224
  set_733((char *) vol_desc.volume_space_size, should_write);
1222
1225
  set_723(vol_desc.volume_set_size, volume_set_size);
1223
1226
  set_723(vol_desc.volume_sequence_number, volume_sequence_number);
1224
1227
  set_723(vol_desc.logical_block_size, 2048);
1225
 
  
 
1228
 
1226
1229
  /*
1227
1230
   * The path tables are used by DOS based machines to cache directory
1228
 
   * locations 
 
1231
   * locations
1229
1232
   */
1230
1233
 
1231
1234
  set_733((char *) vol_desc.path_table_size, path_table_size);
1235
1238
  set_732(vol_desc.opt_type_m_path_table, path_table[3]);
1236
1239
 
1237
1240
  /*
1238
 
   * Now we copy the actual root directory record 
 
1241
   * Now we copy the actual root directory record
1239
1242
   */
1240
 
  memcpy(vol_desc.root_directory_record, &root_record, 
 
1243
  memcpy(vol_desc.root_directory_record, &root_record,
1241
1244
         sizeof(struct iso_directory_record) + 1);
1242
1245
 
1243
1246
  /*
1257
1260
  if(appid) memcpy_max(vol_desc.application_id, appid, strlen(appid));
1258
1261
 
1259
1262
  FILL_SPACE(copyright_file_id);
1260
 
  if(copyright) memcpy_max(vol_desc.copyright_file_id, copyright, 
 
1263
  if(copyright) memcpy_max(vol_desc.copyright_file_id, copyright,
1261
1264
                       strlen(copyright));
1262
1265
 
1263
1266
  FILL_SPACE(abstract_file_id);
1264
 
  if(abstract) memcpy_max(vol_desc.abstract_file_id, abstract, 
 
1267
  if(abstract) memcpy_max(vol_desc.abstract_file_id, abstract,
1265
1268
                          strlen(abstract));
1266
1269
 
1267
1270
  FILL_SPACE(bibliographic_file_id);
1268
 
  if(biblio) memcpy_max(vol_desc.bibliographic_file_id, biblio, 
 
1271
  if(biblio) memcpy_max(vol_desc.bibliographic_file_id, biblio,
1269
1272
                       strlen(biblio));
1270
1273
 
1271
1274
  FILL_SPACE(creation_date);
1281
1284
  memcpy(vol_desc.effective_date, effective_date ? effective_date : iso_time, 17);
1282
1285
 
1283
1286
  /*
1284
 
   * if not a bootable cd do it the old way 
 
1287
   * if not a bootable cd do it the old way
1285
1288
   */
1286
1289
  xfwrite(&vol_desc, 1, 2048, outfile);
1287
1290
  last_extent_written++;
1296
1299
  struct iso_primary_descriptor evol_desc;
1297
1300
 
1298
1301
  /*
1299
 
   * Now write the end volume descriptor.  Much simpler than the other one 
 
1302
   * Now write the end volume descriptor.  Much simpler than the other one
1300
1303
   */
1301
1304
  memset(&evol_desc, 0, sizeof(evol_desc));
1302
1305
  evol_desc.type[0] = ISO_VD_END;
1313
1316
static int FDECL1(pathtab_write, FILE *, outfile)
1314
1317
{
1315
1318
  /*
1316
 
   * Next we write the path tables 
 
1319
   * Next we write the path tables
1317
1320
   */
1318
1321
  xfwrite(path_table_l, 1, path_blocks << 11, outfile);
1319
1322
  xfwrite(path_table_m, 1, path_blocks << 11, outfile);
1344
1347
/*
1345
1348
 * Functions to describe padding block at the start of the disc.
1346
1349
 */
 
1350
 
 
1351
#define PADBLOCK_SIZE   16
 
1352
 
1347
1353
static int FDECL1(pathtab_size, int, starting_extent)
1348
1354
{
1349
1355
  path_table[0] = starting_extent;
1357
1363
 
1358
1364
static int FDECL1(padblock_size, int, starting_extent)
1359
1365
{
1360
 
  last_extent += 16;
 
1366
  last_extent += PADBLOCK_SIZE;
1361
1367
  return 0;
1362
1368
}
1363
1369
 
1420
1426
 
1421
1427
static int FDECL1(padblock_write, FILE *, outfile)
1422
1428
{
1423
 
  char                          buffer[2048];
1424
 
  int                           i;
1425
 
 
1426
 
  memset(buffer, 0, sizeof(buffer));
1427
 
 
1428
 
  for(i=0; i<16; i++)
1429
 
    {
1430
 
      xfwrite(buffer, 1, sizeof(buffer), outfile);
1431
 
    }
1432
 
 
1433
 
  last_extent_written += 16;
 
1429
  char *buffer;
 
1430
 
 
1431
  buffer = e_malloc (2048 * PADBLOCK_SIZE);
 
1432
  memset (buffer, 0, 2048 * PADBLOCK_SIZE);
 
1433
 
 
1434
  if (use_embedded_boot)
 
1435
    {
 
1436
      FILE *fp = fopen (boot_image_embed, "rb");
 
1437
      if (! fp)
 
1438
        error (1, errno, _("Unable to open %s"), boot_image_embed);
 
1439
 
 
1440
      fread (buffer, 2048 * PADBLOCK_SIZE, 1, fp);
 
1441
      if (fgetc (fp) != EOF)
 
1442
        error (1, 0, _("%s is too big for embed area"), boot_image_embed);
 
1443
    }
 
1444
 
 
1445
  if (use_protective_msdos_label)
 
1446
    {
 
1447
      struct msdos_partition_mbr *mbr = (void *) buffer;
 
1448
 
 
1449
      memset (mbr->entries, 0, sizeof(mbr->entries));
 
1450
 
 
1451
      /* Some idiotic BIOSes refuse to boot if they don't find at least
 
1452
         one partition with active bit set.  */
 
1453
      mbr->entries[0].flag = 0x80;
 
1454
 
 
1455
      /* Doesn't really matter, as long as it's non-zero.  It seems that
 
1456
         0xCD is used elsewhere, so we follow suit.  */
 
1457
      mbr->entries[0].type = 0xcd;
 
1458
 
 
1459
      /* Start immediately (sector 1).  */
 
1460
      mbr->entries[0].start = 1;
 
1461
 
 
1462
      /* We don't know yet.  Let's keep it safe.  */
 
1463
      mbr->entries[0].length = UINT32_MAX;
 
1464
 
 
1465
      mbr->signature = MSDOS_PARTITION_SIGNATURE;
 
1466
    }
 
1467
 
 
1468
  xfwrite (buffer, 1, 2048 * PADBLOCK_SIZE, outfile);
 
1469
  last_extent_written += PADBLOCK_SIZE;
 
1470
 
1434
1471
  return 0;
1435
1472
}
1436
1473