~ubuntu-branches/ubuntu/wily/brasero/wily

« back to all changes in this revision

Viewing changes to src/burn-iso9660.c

  • Committer: Bazaar Package Importer
  • Author(s): Pedro Fragoso
  • Date: 2008-11-18 11:30:50 UTC
  • mfrom: (1.1.13 upstream)
  • Revision ID: james.westby@ubuntu.com-20081118113050-hoy0pi04uv7ww9d8
Tags: 0.8.3-0ubuntu1
* New upstream release (LP: #299411)
  - allow use of remote files
  - drives are now probed asynchronously and may not popup immediatly
    but brasero starts faster
  - some parts of GUI were revisited (in particular the burn
    option dialogs)
  - command line option for video projects (LP: #273140)
  - brasero crashed with SIGSEGV in g_main_context_dispatch()
    (LP: #281599)
  - Brasero main GUI appears after closing the dialog
    when opening an ISO file using Nautilus (LP: #242022)
  - brasero delete original files in VIDEO_TS folder (LP: #280835)
  - brasero crashed with SIGSEGV in 
    brasero_mkisofs_base_write_to_files() (LP: #275312)
  - brasero crashed with SIGSEGV in 
    brasero_project_save_project_as() (LP: #275086)
  - brasero crashed with SIGSEGV in 
    IA__g_sequence_iter_get_sequence() (LP: #282622)
  - brasero crashed with SIGSEGV in brasero_medium_get_drive()
    (LP: #283197)
  - Dialog contains a lot of empty space (LP: #190192)
 * debian/patches/008-add-gettext-domain-to-desktop-file.patch:
   - Dropped, we don't need this anymore
 * debian/control:
  - Add Build-deps on libeel2-dev and libnautilus-extension-dev
 * debian/brasero.install:
  - Install nautilus extension

Show diffs side-by-side

added added

removed removed

Lines of Context:
126
126
 
127
127
#define ISO9660_BYTES_TO_BLOCKS(size)                   BRASERO_SIZE_TO_SECTORS ((size), ISO9660_BLOCK_SIZE)
128
128
 
129
 
static BraseroVolFile *
130
 
brasero_iso9660_read_directory_records (BraseroIsoCtx *ctx, gint address);
 
129
static GList *
 
130
brasero_iso9660_load_directory_records (BraseroIsoCtx *ctx,
 
131
                                        BraseroVolFile *parent,
 
132
                                        BraseroIsoDirRec *record,
 
133
                                        gboolean recursive);
131
134
 
132
135
static BraseroVolFile *
133
136
brasero_iso9660_lookup_directory_records (BraseroIsoCtx *ctx,
394
397
        return BRASERO_ISO_ERROR;
395
398
}
396
399
 
 
400
static BraseroIsoResult
 
401
brasero_iso9660_get_first_directory_record (BraseroIsoCtx *ctx,
 
402
                                            BraseroIsoDirRec **record,
 
403
                                            gint address)
 
404
{
 
405
        BraseroIsoResult result;
 
406
 
 
407
        BRASERO_BURN_LOG ("Reading directory record");
 
408
 
 
409
        result = brasero_iso9660_seek (ctx, address);
 
410
        if (result != BRASERO_ISO_OK)
 
411
                return BRASERO_ISO_ERROR;
 
412
 
 
413
        /* load "." */
 
414
        result = brasero_iso9660_next_record (ctx, record);
 
415
        if (result != BRASERO_ISO_OK)
 
416
                return BRASERO_ISO_ERROR;
 
417
 
 
418
        return BRASERO_ISO_OK;
 
419
}
 
420
 
397
421
static BraseroVolFile *
398
422
brasero_iso9660_read_file_record (BraseroIsoCtx *ctx,
399
423
                                  BraseroIsoDirRec *record,
441
465
 
442
466
static BraseroVolFile *
443
467
brasero_iso9660_read_directory_record (BraseroIsoCtx *ctx,
444
 
                                       BraseroIsoDirRec *record)
 
468
                                       BraseroIsoDirRec *record,
 
469
                                       gboolean recursive)
445
470
{
446
471
        gchar *susp;
447
472
        gint address;
456
481
                return NULL;
457
482
        }
458
483
 
 
484
        /* create the directory and set information */
 
485
        directory = g_new0 (BraseroVolFile, 1);
 
486
        directory->isdir = TRUE;
 
487
        directory->isdir_loaded = FALSE;
 
488
        directory->name = g_new0 (gchar, record->id_size + 1);
 
489
        memcpy (directory->name, record->id, record->id_size);
 
490
 
459
491
        if (ctx->has_susp && ctx->has_RR) {
460
492
                /* See if we've got a susp area. Do it now to see if it has a CL
461
493
                 * entry. The rest will be checked later after reading contents.
463
495
                susp = brasero_iso9660_get_susp (ctx, record, &susp_len);
464
496
                if (!brasero_iso9660_read_susp (ctx, &susp_ctx, susp, susp_len)) {
465
497
                        BRASERO_BURN_LOG ("Could not read susp area");
 
498
                        brasero_volume_file_free (directory);
466
499
                        return NULL;
467
500
                }
468
501
 
473
506
                }
474
507
                else
475
508
                        address = brasero_iso9660_get_733_val (record->address);
 
509
 
 
510
                BRASERO_BURN_LOG ("New directory %s with susp area", directory->name);
 
511
 
 
512
                /* if this directory has a "RE" susp entry then drop it; it's 
 
513
                 * not at the right place in the Rock Ridge file hierarchy. It
 
514
                 * will probably be skipped */
 
515
                if (susp_ctx.has_RE) {
 
516
                        BRASERO_BURN_LOG ("Rock Ridge relocated directory. Skipping entry.");
 
517
                        directory->relocated = TRUE;
 
518
                }
 
519
 
 
520
                if (susp_ctx.rr_name) {
 
521
                        BRASERO_BURN_LOG ("Got a susp (RR) %s", susp_ctx.rr_name);
 
522
                        directory->rr_name = susp_ctx.rr_name;
 
523
                        susp_ctx.rr_name = NULL;
 
524
                }
 
525
 
 
526
                brasero_susp_ctx_clean (&susp_ctx);
476
527
        }
477
528
        else
478
529
                address = brasero_iso9660_get_733_val (record->address);
479
530
 
480
 
        directory = brasero_iso9660_read_directory_records (ctx, address);
481
 
        if (!directory) {
482
 
                if (ctx->has_susp && ctx->has_RR)
483
 
                        brasero_susp_ctx_clean (&susp_ctx);
484
 
 
485
 
                return NULL;
486
 
        }
487
 
 
488
 
        directory->name = g_new0 (gchar, record->id_size + 1);
489
 
        memcpy (directory->name, record->id, record->id_size);
490
 
 
491
 
        if (!ctx->has_susp || !ctx->has_RR) {
492
 
                BRASERO_BURN_LOG ("New directory %s", directory->name);
493
 
                return directory;
494
 
        }
495
 
 
496
 
        BRASERO_BURN_LOG ("New directory %s with susp area", directory->name);
497
 
 
498
 
        /* if this directory has a "RE" susp entry then drop it; it's not at the
499
 
         * right place in the Rock Ridge file hierarchy. */
500
 
        if (susp_ctx.has_RE) {
501
 
                BRASERO_BURN_LOG ("Rock Ridge relocated directory. Skipping entry.");
502
 
                directory->relocated = TRUE;
503
 
        }
504
 
 
505
 
        if (susp_ctx.rr_name) {
506
 
                BRASERO_BURN_LOG ("Got a susp (RR) %s", susp_ctx.rr_name);
507
 
                directory->rr_name = susp_ctx.rr_name;
508
 
                susp_ctx.rr_name = NULL;
509
 
        }
510
 
 
511
 
        brasero_susp_ctx_clean (&susp_ctx);
 
531
        /* load contents if recursive */
 
532
        if (recursive) {
 
533
                GList *children;
 
534
 
 
535
                brasero_iso9660_get_first_directory_record (ctx,
 
536
                                                            &record,
 
537
                                                            address);
 
538
                children = brasero_iso9660_load_directory_records (ctx,
 
539
                                                                   directory,
 
540
                                                                   record,
 
541
                                                                   TRUE);
 
542
                if (!children && ctx->error) {
 
543
                        brasero_volume_file_free (directory);
 
544
                        if (ctx->has_susp && ctx->has_RR)
 
545
                                brasero_susp_ctx_clean (&susp_ctx);
 
546
 
 
547
                        return NULL;
 
548
                }
 
549
 
 
550
                directory->isdir_loaded = TRUE;
 
551
                directory->specific.dir.children = children;
 
552
        }
 
553
        else    /* store the address of contents for later use */
 
554
                directory->specific.dir.address = address;
 
555
 
 
556
        BRASERO_BURN_LOG ("New directory %s", directory->name);
512
557
        return directory;
513
558
}
514
559
 
515
 
static BraseroVolFile *
516
 
brasero_iso9660_read_directory_records (BraseroIsoCtx *ctx, gint address)
 
560
static GList *
 
561
brasero_iso9660_load_directory_records (BraseroIsoCtx *ctx,
 
562
                                        BraseroVolFile *parent,
 
563
                                        BraseroIsoDirRec *record,
 
564
                                        gboolean recursive)
517
565
{
518
566
        GSList *iter;
519
567
        gint max_block;
520
568
        gint max_record_size;
521
569
        BraseroVolFile *entry;
 
570
        GList *children = NULL;
522
571
        BraseroIsoResult result;
523
 
        BraseroIsoDirRec *record;
524
572
        GSList *directories = NULL;
525
 
        BraseroVolFile *parent = NULL;
526
 
 
527
 
        BRASERO_BURN_LOG ("Reading directory record");
528
 
 
529
 
        result = brasero_iso9660_seek (ctx, address);
530
 
        if (result != BRASERO_ISO_OK)
531
 
                return NULL;
532
 
 
533
 
        /* "." */
534
 
        result = brasero_iso9660_next_record (ctx, &record);
535
 
        if (result != BRASERO_ISO_OK)
536
 
                return NULL;
537
 
 
538
 
        /* look for "SP" SUSP if it's root directory */
539
 
        if (ctx->is_root) {
540
 
                BraseroSuspCtx susp_ctx;
541
 
                guint susp_len = 0;
542
 
                gchar *susp;
543
 
 
544
 
                susp = brasero_iso9660_get_susp (ctx, record, &susp_len);
545
 
                brasero_iso9660_read_susp (ctx, &susp_ctx, susp, susp_len);
546
 
 
547
 
                ctx->has_susp = susp_ctx.has_SP;
548
 
                ctx->has_RR = susp_ctx.has_RockRidge;
549
 
                ctx->susp_skip = susp_ctx.skip;
550
 
                ctx->is_root = FALSE;
551
 
 
552
 
                if (ctx->has_susp)
553
 
                        BRASERO_BURN_LOG ("File system supports system use sharing protocol");
554
 
 
555
 
                if (ctx->has_RR)
556
 
                        BRASERO_BURN_LOG ("File system has Rock Ridge extension");
557
 
 
558
 
                brasero_susp_ctx_clean (&susp_ctx);
559
 
        }
560
573
 
561
574
        max_record_size = brasero_iso9660_get_733_val (record->file_size);
562
575
        max_block = ISO9660_BYTES_TO_BLOCKS (max_record_size);
568
581
                return NULL;
569
582
 
570
583
        BRASERO_BURN_LOG ("Skipped '.' and '..'");
571
 
        parent = g_new0 (BraseroVolFile, 1);
572
 
        parent->isdir = 1;
573
584
 
574
585
        while (1) {
575
586
                BraseroIsoResult result;
647
658
                /* check that we don't have another file record for the
648
659
                 * same file (usually files > 4G). It always follows
649
660
                 * its sibling */
650
 
                if (parent->specific.dir.children) {
 
661
                if (children) {
651
662
                        BraseroVolFile *last;
652
663
 
653
 
                        last = parent->specific.dir.children->data;
 
664
                        last = children->data;
654
665
                        if (!last->isdir && !strcmp (BRASERO_VOLUME_FILE_NAME (last), BRASERO_VOLUME_FILE_NAME (entry))) {
655
666
                                /* add size and addresses */
656
667
                                ctx->data_blocks += ISO9660_BYTES_TO_BLOCKS (entry->specific.file.size_bytes);
660
671
                        }
661
672
                }
662
673
 
663
 
                parent->specific.dir.children = g_list_prepend (parent->specific.dir.children, entry);
 
674
                children = g_list_prepend (children, entry);
664
675
                ctx->data_blocks += ISO9660_BYTES_TO_BLOCKS (entry->specific.file.size_bytes);
665
676
        }
666
677
 
669
680
        for (iter = directories; iter; iter = iter->next) {
670
681
                record = iter->data;
671
682
 
672
 
                entry = brasero_iso9660_read_directory_record (ctx, record);
 
683
                entry = brasero_iso9660_read_directory_record (ctx, record, recursive);
673
684
                if (!entry)
674
685
                        goto error;
675
686
 
679
690
                }
680
691
 
681
692
                entry->parent = parent;
682
 
                parent->specific.dir.children = g_list_prepend (parent->specific.dir.children, entry);
 
693
                children = g_list_prepend (children, entry);
683
694
        }
684
695
        g_slist_foreach (directories, (GFunc) g_free, NULL);
685
696
        g_slist_free (directories);
686
697
 
687
 
        return parent;
 
698
        return children;
688
699
 
689
700
error:
690
701
 
 
702
        g_list_foreach (children, (GFunc) brasero_volume_file_free, NULL);
 
703
        g_list_free (children);
 
704
 
691
705
        g_slist_foreach (directories, (GFunc) g_free, NULL);
692
706
        g_slist_free (directories);
693
707
 
694
 
        brasero_volume_file_free (parent);
695
708
        return NULL;
696
709
}
697
710
 
 
711
static gboolean
 
712
brasero_iso9660_check_SUSP_RR_use (BraseroIsoCtx *ctx,
 
713
                                   BraseroIsoDirRec *record)
 
714
{
 
715
        BraseroSuspCtx susp_ctx;
 
716
        guint susp_len = 0;
 
717
        gchar *susp;
 
718
 
 
719
        susp = brasero_iso9660_get_susp (ctx, record, &susp_len);
 
720
        brasero_iso9660_read_susp (ctx, &susp_ctx, susp, susp_len);
 
721
 
 
722
        ctx->has_susp = susp_ctx.has_SP;
 
723
        ctx->has_RR = susp_ctx.has_RockRidge;
 
724
        ctx->susp_skip = susp_ctx.skip;
 
725
        ctx->is_root = FALSE;
 
726
 
 
727
        if (ctx->has_susp)
 
728
                BRASERO_BURN_LOG ("File system supports system use sharing protocol");
 
729
 
 
730
        if (ctx->has_RR)
 
731
                BRASERO_BURN_LOG ("File system has Rock Ridge extension");
 
732
 
 
733
        brasero_susp_ctx_clean (&susp_ctx);
 
734
        return TRUE;
 
735
}
 
736
 
698
737
static void
699
738
brasero_iso9660_ctx_init (BraseroIsoCtx *ctx, BraseroVolSrc *vol)
700
739
{
703
742
        ctx->is_root = TRUE;
704
743
        ctx->vol = vol;
705
744
        ctx->offset = 0;
 
745
 
 
746
        /* to fully initialize the context we need the root directory record */
706
747
}
707
748
 
708
749
BraseroVolFile *
712
753
                              GError **error)
713
754
{
714
755
        BraseroIsoPrimary *primary;
 
756
        BraseroIsoDirRec *record;
715
757
        BraseroVolFile *volfile;
716
758
        BraseroIsoDirRec *root;
717
759
        BraseroIsoCtx ctx;
 
760
        GList *children;
718
761
        gint address;
719
762
 
720
763
        primary = (BraseroIsoPrimary *) block;
721
764
        root = primary->root_rec;
722
765
 
 
766
        /* check settings */
 
767
        address = brasero_iso9660_get_733_val (root->address);
723
768
        brasero_iso9660_ctx_init (&ctx, vol);
724
 
 
725
 
        address = brasero_iso9660_get_733_val (root->address);
726
 
 
727
 
        BRASERO_BURN_LOG ("Reading root directory record at %i", address);
728
 
        volfile = brasero_iso9660_read_directory_records (&ctx, address);
 
769
        brasero_iso9660_get_first_directory_record (&ctx, &record, address);
 
770
        brasero_iso9660_check_SUSP_RR_use (&ctx, record);
 
771
 
 
772
        /* create volume file */
 
773
        volfile = g_new0 (BraseroVolFile, 1);
 
774
        volfile->isdir = TRUE;
 
775
        volfile->isdir_loaded = FALSE;
 
776
 
 
777
        children = brasero_iso9660_load_directory_records (&ctx,
 
778
                                                           volfile,
 
779
                                                           record,
 
780
                                                           TRUE);
 
781
        volfile->specific.dir.children = children;
729
782
 
730
783
        if (ctx.spare_record)
731
784
                g_free (ctx.spare_record);
733
786
        if (data_blocks)
734
787
                *data_blocks = ctx.data_blocks;
735
788
 
736
 
        if (error && ctx.error)
737
 
                g_propagate_error (error, ctx.error);
 
789
        if (!children && ctx.error) {
 
790
                if (error)
 
791
                        g_propagate_error (error, ctx.error);
 
792
 
 
793
                brasero_volume_file_free (volfile);
 
794
                volfile = NULL;
 
795
        }
738
796
 
739
797
        return volfile;
740
798
}
835
893
 
836
894
static BraseroVolFile *
837
895
brasero_iso9660_lookup_directory_records (BraseroIsoCtx *ctx,
838
 
                                         const gchar *path,
839
 
                                         gint address)
 
896
                                          const gchar *path,
 
897
                                          gint address)
840
898
{
841
899
        guint len;
842
900
        gchar *end;
970
1028
 
971
1029
        primary = (BraseroIsoPrimary *) block;
972
1030
        root = primary->root_rec;
 
1031
 
973
1032
        address = brasero_iso9660_get_733_val (root->address);
974
 
 
975
1033
        brasero_iso9660_ctx_init (&ctx, vol);
976
1034
 
977
1035
        /* now that we have root block address, skip first "/" and go. */
978
1036
        path ++;
979
 
        entry = brasero_iso9660_lookup_directory_records (&ctx, path, address);
 
1037
        entry = brasero_iso9660_lookup_directory_records (&ctx,
 
1038
                                                          path,
 
1039
                                                          address);
980
1040
 
981
1041
        /* clean context */
982
1042
        if (ctx.spare_record)
987
1047
 
988
1048
        return entry;
989
1049
}
 
1050
 
 
1051
GList *
 
1052
brasero_iso9660_get_directory_contents (BraseroVolSrc *vol,
 
1053
                                        const gchar *vol_desc,
 
1054
                                        gint address,
 
1055
                                        GError **error)
 
1056
{
 
1057
        BraseroIsoDirRec *record = NULL;
 
1058
        BraseroIsoPrimary *primary;
 
1059
        BraseroIsoDirRec *root;
 
1060
        BraseroIsoCtx ctx;
 
1061
        GList *children;
 
1062
 
 
1063
        /* Check root "." for use of RR and things like that */
 
1064
        primary = (BraseroIsoPrimary *) vol_desc;
 
1065
        root = primary->root_rec;
 
1066
 
 
1067
        brasero_iso9660_ctx_init (&ctx, vol);
 
1068
        brasero_iso9660_get_first_directory_record (&ctx,
 
1069
                                                    &record,
 
1070
                                                    brasero_iso9660_get_733_val (root->address));
 
1071
        brasero_iso9660_check_SUSP_RR_use (&ctx, record);
 
1072
 
 
1073
        /* Seek up to the contents of the directory */
 
1074
        if (address > 0)
 
1075
                brasero_iso9660_get_first_directory_record (&ctx,
 
1076
                                                            &record,
 
1077
                                                            address);
 
1078
 
 
1079
        /* load */
 
1080
        children = brasero_iso9660_load_directory_records (&ctx,
 
1081
                                                           NULL,
 
1082
                                                           record,
 
1083
                                                           FALSE);
 
1084
        if (ctx.error && error)
 
1085
                g_propagate_error (error, ctx.error);
 
1086
 
 
1087
        return children;
 
1088
}