Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12-SP4:GA
wodim
genisoimage-multi-extent.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File genisoimage-multi-extent.patch of Package wodim
--- genisoimage/diag/isoinfo.c +++ genisoimage/diag/isoinfo.c @@ -11,6 +11,7 @@ */ /* @(#)isoinfo.c 1.50 05/05/15 joerg */ +/* Parts from @(#)isoinfo.c 1.63 08/08/25 joerg */ /* * File isodump.c - dump iso9660 directory information. * @@ -618,7 +619,7 @@ sprintf(outline+48, "%4d", date_buf[0]+1900); sprintf(outline+53, "[%7d", extent); /* XXX up to 20 GB */ - sprintf(outline+61, " %02X]", idr->flags[0]); + sprintf(outline+61, " %02X]", idr->flags[0] & 0xFF); for (i = 0; i < 66; i++) { if (outline[i] == 0) outline[i] = ' '; @@ -663,6 +664,9 @@ int i; struct iso_directory_record * idr; unsigned char uh, ul, uc, *up; + unsigned char flags = 0; + Llong size = 0; + int sextent = 0; if (do_listing) @@ -776,8 +780,27 @@ strcat(testname, name_buf); printf("%s\n", testname); } - if (do_listing) - dump_stat(idr, isonum_733((unsigned char *)idr->extent)); + if (do_listing) { + if ((idr->flags[0] & ISO_MULTIEXTENT) && size == 0) + sextent = isonum_733((unsigned char *)idr->extent); + if (debug || + ((idr->flags[0] & ISO_MULTIEXTENT) == 0 && size == 0)) { + dump_stat(idr, isonum_733((unsigned char *)idr->extent)); + } + size += fstat_buf.st_size; + if ((flags & ISO_MULTIEXTENT) && + (idr->flags[0] & ISO_MULTIEXTENT) == 0) { + fstat_buf.st_size = size; + if (!debug) + idr->flags[0] |= ISO_MULTIEXTENT; + dump_stat(idr, sextent); + if (!debug) + idr->flags[0] &= ~ISO_MULTIEXTENT; + } + flags = idr->flags[0]; + if ((idr->flags[0] & ISO_MULTIEXTENT) == 0) + size = 0; + } i += buffer[i]; if (i > 2048 - offsetof(struct iso_directory_record, name[0])) break; } --- genisoimage/genisoimage.1 +++ genisoimage/genisoimage.1 @@ -189,12 +189,14 @@ file. .TP .B \-allow\-limited\-size -When processing files larger than 2GiB which cannot be easily represented in -ISO9660, add them with a shrunk visible file size to ISO9660 and with the +When processing files larger than 2GiB which cannot be represented in +ISO9660 level 1 or 2, add them with a shrunk visible file size to ISO9660 and with the correct visible file size to the UDF system. The result is an inconsistent filesystem and users need to make sure that they really use UDF rather than ISO9660 driver to read a such disk. Implies enabling .BR \-udf. +See also +.BR \-iso\-level\ 3 .TP .B \-allow\-leading\-dots .TP @@ -685,6 +687,8 @@ With level 2, files may only consist of one section. .IP With level 3, no restrictions (other than ISO-9660:1988) do apply. +Starting with this level, genisoimage also allows files to be larger than 4 GB +by implementing ISO-9660 multi-extent files. .IP With all ISO9660 levels from 1 to 3, all filenames are restricted to uppercase letters, numbers and underscores (_). Filenames are @@ -2792,7 +2796,7 @@ Copyright 1996-1997 by Robert Leslie Copyright 1997-2001 by James Pearson Copyright 1999-2006 by J\(:org Schilling -Copyright 2007 by J\(:org Schilling (originating few updates) +Copyright 2007-2008 by J\(:org Schilling (originating few updates) Copyright 2002-2003 by Jungshik Shin Copyright 2003 by Jaakko Heinonen Copyright 2006 by the Cdrkit maintainers --- genisoimage/genisoimage.c +++ genisoimage/genisoimage.c @@ -19,6 +19,7 @@ */ /* @(#)mkisofs.c 1.167 06/01/30 joerg */ /* Parts from @(#)mkisofs.c 1.206 07/02/26 joerg */ +/* Parts from @(#)mkisofs.c 1.238 08/06/13 joerg */ /* * Program genisoimage.c - generate iso9660 filesystem based upon directory * tree on hard disk. @@ -189,6 +190,8 @@ int no_rr = 0; /* Do not use RR attributes from old session */ int force_rr = 0; /* Force to use RR attributes from old session */ Uint RR_relocation_depth = 6; /* Violates iso9660, but most systems work */ +int do_largefiles = 0; /* Whether to allow multi-extent files */ +off_t maxnonlarge = (off_t)0xFFFFFFFF; int iso9660_level = 1; int iso9660_namelen = LEN_ISONAME; /* 31 characters, may be set to 37 */ int full_iso9660_filenames = 0; /* Full 31 character iso9660 filenames */ @@ -1388,6 +1391,7 @@ /* * No restrictions */ + do_largefiles++; break; case 4: /* @@ -1406,6 +1410,7 @@ relaxed_filenames++; /* all chars */ allow_lowercase++; /* even lowcase */ allow_multidot++; /* > 1 dots */ + do_largefiles++; break; default: @@ -2718,6 +2723,11 @@ exit(1); #endif } + if (apple_hyb) { + if (do_largefiles) printf("Warning: cannot support large files with -hfs\n"); + do_largefiles = 0; + maxnonlarge = (off_t)0x7FFFFFFF; + } if (apple_hyb && use_genboot) { #ifdef USE_LIBSCHILY comerrno(EX_BAD, "Can't have -hfs with -generic-boot\n"); --- genisoimage/genisoimage.h +++ genisoimage/genisoimage.h @@ -11,6 +11,7 @@ */ /* @(#)genisoimage.h 1.95 05/05/01 joerg */ +/* Parts from @(#) 1.132 08/08/06 joerg */ /* * Header file genisoimage.h - assorted structure definitions and typecasts. * @@ -60,8 +61,7 @@ #endif #endif -/*#if _LFS_LARGEFILE*/ -#ifdef HAVE_LARGEFILES +#ifdef USE_LARGEFILES /* * XXX Hack until fseeko()/ftello() are available everywhere or until * XXX we know a secure way to let autoconf ckeck for fseeko()/ftello() @@ -106,6 +106,9 @@ struct iso_directory_record isorec; unsigned int starting_block; off_t size; +#ifdef USE_LARGEFILES + int mxpart; /* Extent number */ +#endif unsigned short priority; unsigned char jreclen; /* Joliet record len */ char *name; @@ -113,6 +116,7 @@ char *whole_name; struct directory *filedir; struct directory_entry *parent_rec; + struct directory_entry *mxroot; /* Pointer to orig entry */ unsigned int de_flags; ino_t inode; /* Used in the hash table */ dev_t dev; /* Used in the hash table */ @@ -364,6 +368,8 @@ extern int no_rr; extern int transparent_compression; extern Uint RR_relocation_depth; +extern int do_largefiles; +extern off_t maxnonlarge; extern int iso9660_level; extern int iso9660_namelen; extern int full_iso9660_filenames; @@ -447,6 +453,8 @@ extern int insert_file_entry(struct directory *, char *, char *); #endif /* APPLE_HYB */ +extern struct directory_entry * + dup_directory_entry __PR((struct directory_entry *s_entry)); extern void generate_iso9660_directories(struct directory *, FILE *); extern void dump_tree(struct directory * node); extern struct directory_entry * @@ -749,6 +757,8 @@ #define MEMORY_FILE 0x80 /* de_flags only */ #define HIDDEN_FILE 0x100 /* de_flags only */ #define DIR_WAS_SCANNED 0x200 /* dir_flags only */ +#define MULTI_EXTENT 0x1000 /* de_flags only */ +#define INHIBIT_UDF_ENTRY 0x2000 /* * Volume sequence number to use in all of the iso directory records. --- genisoimage/iso9660.h +++ genisoimage/iso9660.h @@ -10,7 +10,7 @@ * */ -/* @(#)iso9660.h 1.19 04/03/02 joerg */ +/* @(#)iso9660.h 1.21 07/07/26 joerg */ /* * Header file iso9660.h - assorted structure definitions and typecasts. * specific to iso9660 filesystem. @@ -18,7 +18,7 @@ * Written by Eric Youngdale (1993). * * Copyright 1993 Yggdrasil Computing, Incorporated - * Copyright (c) 1999,2000-2004 J. Schilling + * Copyright (c) 1999,2000-2008 J. Schilling * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -231,7 +231,7 @@ char extent [ISODCL(3, 10)]; /* 733 */ char size [ISODCL(11, 18)]; /* 733 */ char date [ISODCL(19, 25)]; /* 7 by 711 */ - char flags [ISODCL(26, 26)]; + unsigned char flags [ISODCL(26, 26)]; char file_unit_size [ISODCL(27, 27)]; /* 711 */ char interleave [ISODCL(28, 28)]; /* 711 */ char volume_sequence_number [ISODCL(29, 32)]; /* 723 */ --- genisoimage/joliet.c +++ genisoimage/joliet.c @@ -11,6 +11,7 @@ */ /* @(#)joliet.c 1.38 05/05/01 joerg */ +/* Parts from @(#)joliet.c>1.54 07/10/20 joerg */ /* * File joliet.c - handle Win95/WinNT long file/unicode extensions for iso9660. * @@ -507,7 +508,9 @@ } } /* skip if hidden - but not for the rr_moved dir */ - if (dpnt->subdir && (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) || dpnt == reloc_dir)) { + if (dpnt->subdir && + ((dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) == 0 || + dpnt == reloc_dir)) { assign_joliet_directory_addresses(dpnt->subdir); } dpnt = dpnt->next; @@ -643,6 +646,7 @@ char *npnt; char *npnt1; int tablesize; + unsigned int jpindex; /* First allocate memory for the tables and initialize the memory */ tablesize = jpath_blocks << 11; @@ -723,10 +727,10 @@ set_732(jpath_table_m + jpath_table_index, dpnt->jextent); jpath_table_index += 4; - if (dpnt->parent->jpath_index > 0xffff) { + + if (dpnt->parent != reloc_dir) { #ifdef USE_LIBSCHILY - comerrno(EX_BAD, - "Unable to generate sane path tables - too many directories (%d)\n", + set_721(jpath_table_l + jpath_table_index, dpnt->parent->jpath_index); #else fprintf(stderr, @@ -734,18 +738,31 @@ dpnt->parent->jpath_index); exit(1); #endif - } - - if (dpnt->parent != reloc_dir) { - set_721(jpath_table_l + jpath_table_index, - dpnt->parent->jpath_index); set_722(jpath_table_m + jpath_table_index, dpnt->parent->jpath_index); + jpindex = dpnt->parent->jpath_index; } else { set_721(jpath_table_l + jpath_table_index, dpnt->self->parent_rec->filedir->jpath_index); set_722(jpath_table_m + jpath_table_index, dpnt->self->parent_rec->filedir->jpath_index); + jpindex = dpnt->self->parent_rec->filedir->jpath_index; + } + + if (jpindex > 0xffff) { + static int warned = 0; + + if (!warned) { + warned++; + errmsgno(EX_BAD, + "Unable to generate sane Joliet path tables - too many directories (%u)\n", + jpindex); + } + /* + * Let it point to the root directory instead. + */ + set_721(jpath_table_l + jpath_table_index, 1); + set_722(jpath_table_m + jpath_table_index, 1); } jpath_table_index += 2; @@ -1149,18 +1166,25 @@ /* * If the entries are the same, this is an error. * Joliet specs allow for a maximum of 64 characters. + * If we see different multi extent parts, it is OK to + * have the same name more than once. */ if (strncmp(rpnt, lpnt, jlen) == 0) { +#ifdef USE_LARGEFILES + if ((*r)->mxpart == (*l)->mxpart) +#endif + { #ifdef USE_LIBSCHILY - errmsgno(EX_BAD, - "Error: %s and %s have the same Joliet name\n", - (*r)->whole_name, (*l)->whole_name); + errmsgno(EX_BAD, + "Error: %s and %s have the same Joliet name\n", + (*r)->whole_name, (*l)->whole_name); #else - fprintf(stderr, - "Error: %s and %s have the same Joliet name\n", - (*r)->whole_name, (*l)->whole_name); + fprintf(stderr, + "Error: %s and %s have the same Joliet name\n", + (*r)->whole_name, (*l)->whole_name); #endif - jsort_goof++; + jsort_goof++; + } } /* * Put the '.' and '..' entries on the head of the sorted list. @@ -1253,6 +1277,15 @@ return (1); if (*lpnt) return (-1); +#ifdef USE_LARGEFILES + /* + * (*r)->mxpart == (*l)->mxpart cannot happen here + */ + if ((*r)->mxpart < (*l)->mxpart) + return (-1); + else if ((*r)->mxpart > (*l)->mxpart) + return (1); +#endif return (0); } @@ -1275,8 +1308,11 @@ s_entry = *sort_dir; while (s_entry) { - /* skip hidden entries */ - if (!(s_entry->de_flags & INHIBIT_JOLIET_ENTRY)) + /* + * only colletc non-hidden entries + */ + if ((s_entry->de_flags & (INHIBIT_JOLIET_ENTRY|INHIBIT_UDF_ENTRY)) != + (INHIBIT_JOLIET_ENTRY|INHIBIT_UDF_ENTRY)) dcount++; s_entry = s_entry->next; } @@ -1288,8 +1324,11 @@ dcount = 0; s_entry = *sort_dir; while (s_entry) { - /* skip hidden entries */ - if (!(s_entry->de_flags & INHIBIT_JOLIET_ENTRY)) { + /* + * only collect non-hidden entries + */ + if ((s_entry->de_flags & (INHIBIT_JOLIET_ENTRY|INHIBIT_UDF_ENTRY)) != + (INHIBIT_JOLIET_ENTRY|INHIBIT_UDF_ENTRY)) { sortlist[dcount] = s_entry; dcount++; } --- genisoimage/multi.c +++ genisoimage/multi.c @@ -11,6 +11,7 @@ */ /* @(#)multi.c 1.68 05/05/15 joerg */ +/* Parts from @(#)multi.c 1.88 08/08/28 joerg */ /* * File multi.c - scan existing iso9660 image and merge into * iso9660 filesystem. Used for multisession support. @@ -90,6 +91,9 @@ static void free_directory_entry(struct directory_entry * dirp); static void merge_remaining_entries(struct directory *, struct directory_entry **, int); +LOCAL int iso_dir_ents __PR((struct directory_entry *de)); +LOCAL void copy_mult_extent __PR((struct directory_entry *se1, + struct directory_entry *se2)); static int merge_old_directory_into_tree(struct directory_entry *, struct directory *); @@ -586,6 +590,8 @@ int len; int nbytes; int nent; + int nmult; /* # of multi extent root entries */ + int mx; struct directory_entry **pnt; int rlen; struct directory_entry **rtn; @@ -620,6 +626,8 @@ i = 0; *nentp = 0; nent = 0; + nmult = 0; + mx = 0; while (i < len) { idr = (struct iso_directory_record *) & dirbuff[i]; if (idr->length[0] == 0) { @@ -627,14 +635,20 @@ continue; } nent++; + if ((mx & ISO_MULTIEXTENT) == 0 && + (idr->flags[0] & ISO_MULTIEXTENT) != 0) { + nmult++; /* Need a multi extent root entry */ + } + mx = idr->flags[0]; i += idr->length[0]; } /* * Now allocate the buffer which will hold the array we are about to - * return. + * return. We need one entry per real directory entry and in addition + * one multi-extent root entry per multi-extent file. */ - rtn = (struct directory_entry **) e_malloc(nent * sizeof (*rtn)); + rtn = (struct directory_entry **) e_malloc((nent+nmult) * sizeof (*rtn)); /* * Finally, scan the directory one last time, and pick out the relevant @@ -646,6 +660,7 @@ tt_extent = 0; seen_rockridge = 0; tt_size = 0; + mx = 0; while (i < len) { idr = (struct iso_directory_record *) & dirbuff[i]; if (idr->length[0] == 0) { @@ -790,7 +805,52 @@ if (tt_extent == 0) tt_size = 0; } + /* + * The beginning of a new multi extent directory chain is when + * the last directory had no ISO_MULTIEXTENT flag set and the + * current entry did set ISO_MULTIEXTENT. + */ + if ((mx & ISO_MULTIEXTENT) == 0 && + (idr->flags[0] & ISO_MULTIEXTENT) != 0) { + struct directory_entry *s_entry; + struct iso_directory_record *idr2 = idr; + int i2 = i; + off_t tsize = 0; + + /* + * Sum up the total file size for the multi extent file + */ + while (i2 < len) { + idr2 = (struct iso_directory_record *) &dirbuff[i2]; + + tsize += get_733(idr2->size); + if ((idr2->flags[0] & ISO_MULTIEXTENT) == 0) + break; + i2 += idr2->length[0]; + } + + s_entry = dup_directory_entry(*pnt); /* dup first for mxroot */ + s_entry->de_flags |= MULTI_EXTENT; + s_entry->de_flags |= INHIBIT_ISO9660_ENTRY|INHIBIT_JOLIET_ENTRY; + s_entry->size = tsize; + s_entry->starting_block = (*pnt)->starting_block; + s_entry->mxroot = s_entry; + s_entry->mxpart = 0; + s_entry->next = *pnt; /* Next in list */ + pnt[1] = pnt[0]; /* Move to next slot */ + *pnt = s_entry; /* First slot is mxroot */ + pnt++; /* Point again to cur. */ + } + if ((mx & ISO_MULTIEXTENT) != 0 || + (idr->flags[0] & ISO_MULTIEXTENT) != 0) { + (*pnt)->de_flags |= MULTI_EXTENT; + (*pnt)->de_flags |= INHIBIT_UDF_ENTRY; + (pnt[-1])->next = *pnt; + (*pnt)->mxroot = (pnt[-1])->mxroot; + (*pnt)->mxpart = (pnt[-1])->mxpart + 1; + } pnt++; + mx = idr->flags[0]; i += idr->length[0]; } #ifdef APPLE_HYB @@ -814,6 +874,10 @@ * in the Joliet tree */ (*pnt)->de_flags |= INHIBIT_JOLIET_ENTRY; + /* + * XXX Is it correct to exclude UDF too? + */ + (*pnt)->de_flags |= INHIBIT_UDF_ENTRY; /* * as we have associated files, then @@ -927,7 +991,7 @@ if (dirbuff != NULL) { free(dirbuff); } - *nentp = nent; + *nentp = nent + nmult; return (rtn); }/* read_merging_directory */ @@ -989,7 +1053,7 @@ { int i; int rr; - int retcode = 0; /* Default not found */ + int retcode = -2; /* Default not found */ for (i = 0; i < len; i++) { if (ptr[i] == NULL) { /* Used or empty entry skip */ @@ -1024,7 +1088,7 @@ * in tree.c for an explaination of why this must be the case. */ if ((curr_entry->isorec.flags[0] & ISO_DIRECTORY) != 0) { - retcode = 2; /* Flag directory case */ + retcode = i; goto found_it; } /* @@ -1037,7 +1101,7 @@ * we probably have a different file, and we need to write it * out again. */ - retcode = 1; /* We found a non directory */ + retcode = i; if (ptr[i]->rr_attributes != NULL) { if ((rr = check_rr_dates(ptr[i], curr_entry, statbuf, @@ -1066,11 +1130,24 @@ memcpy(curr_entry->isorec.extent, ptr[i]->isorec.extent, 8); curr_entry->starting_block = isonum_733((unsigned char *)ptr[i]->isorec.extent); curr_entry->de_flags |= SAFE_TO_REUSE_TABLE_ENTRY; + + if ((curr_entry->isorec.flags[0] & ISO_MULTIEXTENT) || + (ptr[i]->isorec.flags[0] & ISO_MULTIEXTENT)) { + copy_mult_extent(curr_entry, ptr[i]); + } goto found_it; } return (retcode); found_it: + if (ptr[i]->mxroot == ptr[i]) { /* Remove all multi ext. entries */ + int j = i + 1; /* First one will be removed below */ + + while (j < len && ptr[j] && ptr[j]->mxroot == ptr[i]) { + free(ptr[j]); + ptr[j++] = NULL; + } + } if (odpnt != NULL) { *odpnt = ptr[i]; } else { @@ -1081,6 +1158,106 @@ } /* + * Return the number of directory entries for a file. This is usually 1 + * but may be 3 or more in case of multi extent files. + */ +LOCAL int +iso_dir_ents(de) + struct directory_entry *de; +{ + struct directory_entry *de2; + int ret = 0; + + if (de->mxroot == NULL) + return (1); + de2 = de; + while (de2 != NULL && de2->mxroot == de->mxroot) { + ret++; + de2 = de2->next; + } + return (ret); +} + +/* + * Copy old multi-extent directory information from the previous session. + * If both the old session and the current session are created by genisoimage + * then this code could be extremely simple as the information is only copied + * in case that the file did not change since the last session was made. + * As we don't know the other ISO formatter program, any combination of + * multi-extent files and even a single extent file could be possible. + * We need to handle all files the same way ad the old session was created as + * we reuse the data extents from the file in the old session. + */ +LOCAL void +copy_mult_extent(se1, se2) + struct directory_entry *se1; + struct directory_entry *se2; +{ + struct directory_entry *curr_entry = se1; + int len1; + int len2; + int mxpart = 0; + + len1 = iso_dir_ents(se1); + len2 = iso_dir_ents(se2); + + if (len1 == 1) { + /* + * Convert single-extent to multi-extent. + * If *se1 is not multi-extent, *se2 definitely is + * and we need to set up a MULTI_EXTENT directory header. + */ + se1->de_flags |= MULTI_EXTENT; + se1->isorec.flags[0] |= ISO_MULTIEXTENT; + se1->mxroot = curr_entry; + se1->mxpart = 0; + se1 = dup_directory_entry(se1); + curr_entry->de_flags |= INHIBIT_ISO9660_ENTRY|INHIBIT_JOLIET_ENTRY; + se1->de_flags |= INHIBIT_UDF_ENTRY; + se1->next = curr_entry->next; + curr_entry->next = se1; + se1 = curr_entry; + len1 = 2; + } + + while (se2->isorec.flags[0] & ISO_MULTIEXTENT) { + len1--; + len2--; + if (len1 <= 0) { + struct directory_entry *sex = dup_directory_entry(se1); + + sex->mxroot = curr_entry; + sex->next = se1->next; + se1->next = sex; + len1++; + } + memcpy(se1->isorec.extent, se2->isorec.extent, 8); + se1->starting_block = get_733(se2->isorec.extent); + se1->de_flags |= SAFE_TO_REUSE_TABLE_ENTRY; + se1->de_flags |= MULTI_EXTENT; + se1->isorec.flags[0] |= ISO_MULTIEXTENT; + se1->mxroot = curr_entry; + se1->mxpart = mxpart++; + + se1 = se1->next; + se2 = se2->next; + } + memcpy(se1->isorec.extent, se2->isorec.extent, 8); + se1->starting_block = get_733(se2->isorec.extent); + se1->de_flags |= SAFE_TO_REUSE_TABLE_ENTRY; + se1->isorec.flags[0] &= ~ISO_MULTIEXTENT; /* Last entry */ + se1->mxpart = mxpart; + while (len1 > 1) { /* Drop other entries */ + struct directory_entry *sex; + + sex = se1->next; + se1->next = sex->next; + free(sex); + len1--; + } +} + +/* * open_merge_image: Open an existing image. */ int @@ -1631,6 +1808,19 @@ &statbuf, &lstatbuf, NULL); if (retcode == -1) return (-1); + /* + * Skip other directory entries for multi-extent files + */ + if (s_entry->de_flags & MULTI_EXTENT) { + struct directory_entry *s_e; + + for (s_e = s_entry->mxroot; + s_e && s_e->mxroot == s_entry->mxroot; + s_e = s_e->next) { + s_entry = s_e; + ; + } + } } merge_remaining_entries(this_dir, orig_contents, n_orig); @@ -1682,14 +1872,14 @@ * The check_prev_session function looks for an identical * entry in the previous session. If we see it, then we copy * the extent number to s_entry, and cross it off the list. - * It returns 2 if it's a directory */ retcode = check_prev_session(orig_contents, n_orig, s_entry, &statbuf, &lstatbuf, &odpnt); if (retcode == -1) return (-1); - if (retcode == 2 && odpnt != NULL) { + if (odpnt != NULL && + (s_entry->isorec.flags[0] & ISO_DIRECTORY) != 0) { int dflag; if (strcmp(s_entry->name, ".") != 0 && @@ -1718,6 +1908,23 @@ odpnt = NULL; } } + if (odpnt) { + free(odpnt); + odpnt = NULL; + } + /* + * Skip other directory entries for multi-extent files + */ + if (s_entry->de_flags & MULTI_EXTENT) { + struct directory_entry *s_e; + + for (s_e = s_entry->mxroot; + s_e && s_e->mxroot == s_entry->mxroot; + s_e = s_e->next) { + s_entry = s_e; + ; + } + } } if (!reloc_old_root) { --- genisoimage/tree.c +++ genisoimage/tree.c @@ -11,6 +11,7 @@ */ /* @(#)tree.c 1.82 04/06/12 joerg */ +/* Parets from @(#)tree.c 1.112 08/08/14 joerg */ /* * File tree.c - scan directory tree and build memory structures for iso9660 * filesystem @@ -101,6 +102,8 @@ struct stat* stat_template); static void delete_directory(struct directory *parent, struct directory *child); +EXPORT struct directory_entry * + dup_directory_entry __PR((struct directory_entry *s_entry)); int sort_tree(struct directory *node); void dump_tree(struct directory *node); void update_nlink_field(struct directory *node); @@ -292,6 +295,17 @@ flush_file_hash(); s_entry = this_dir->contents; while (s_entry) { +#ifdef USE_LARGEFILES + /* + * Skip all but the last extent from a multi extent file, + * we like them all have the same name. + */ + if ((s_entry->de_flags & MULTI_EXTENT) && + (s_entry->isorec.flags[0] & ISO_MULTIEXTENT)) { + s_entry = s_entry->next; + continue; + } +#endif /* ignore if it's hidden */ if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY) { s_entry = s_entry->next; @@ -438,6 +452,7 @@ this_dir->whole_name, SPATH_SEPARATOR, s_entry->name, s_entry1->name); } + s_entry->isorec.name_len[0] = strlen(newname); new_reclen = offsetof(struct iso_directory_record, name[0]) + @@ -451,6 +466,22 @@ new_reclen++; /* Pad to an even byte */ s_entry->isorec.length[0] = new_reclen; strcpy(s_entry->isorec.name, newname); +#ifdef USE_LARGEFILES + if (s_entry->de_flags & MULTI_EXTENT) { + struct directory_entry *s_e; + + /* + * Copy over the new name to all other entries + */ + for (s_e = s_entry->mxroot; + s_e && s_e->mxroot == s_entry->mxroot; + s_e = s_e->next) { + s_e->isorec.length[0] = new_reclen; + s_e->isorec.name_len[0] = s_entry->isorec.name_len[0]; + strcpy(s_e->isorec.name, newname); + } + } +#endif #ifdef APPLE_HYB /* has resource fork - needs new name */ if (apple_both && s_entry->assoc) { @@ -489,6 +520,22 @@ new_reclen++; /* Pad to an even byte */ s_entry1->isorec.length[0] = new_reclen; strcpy(s_entry1->isorec.name, newname); +#ifdef USE_LARGEFILES + if (s_entry1->de_flags & MULTI_EXTENT) { + struct directory_entry *s_e; + + /* + * Copy over the new name to all other entries + */ + for (s_e = s_entry1->mxroot; + s_e && s_e->mxroot == s_entry1->mxroot; + s_e = s_e->next) { + s_e->isorec.length[0] = new_reclen; + s_e->isorec.name_len[0] = s_entry1->isorec.name_len[0]; + strcpy(s_e->isorec.name, newname); + } + } +#endif add_file_hash(s_entry1); #ifdef APPLE_HYB /* has resource fork - needs new name */ @@ -562,6 +609,10 @@ table->filedir = this_dir; if (jhide_trans_tbl) table->de_flags |= INHIBIT_JOLIET_ENTRY; + /* + * Always hide transtable from UDF tree. + */ + table->de_flags |= INHIBIT_UDF_ENTRY; /* table->name = strdup("<translation table>");*/ table->name = strdup(trans_tbl); /* @@ -808,9 +859,12 @@ s_entry->next = root->contents; reloc_dir->self = s_entry; - /* The rr_moved entry will not appear in the Joliet tree. */ + /* The rr_moved entry will not appear in the Joliet nor the UDF tree. */ reloc_dir->dir_flags |= INHIBIT_JOLIET_ENTRY; s_entry->de_flags |= INHIBIT_JOLIET_ENTRY; + + reloc_dir->dir_flags |= INHIBIT_UDF_ENTRY; + s_entry->de_flags |= INHIBIT_UDF_ENTRY; /* Hiding RR_MOVED seems not to be possible..... */ #ifdef HIDE_RR @@ -1551,14 +1605,14 @@ return (0); } /* print a warning but don't spam too much */ - if (S_ISREG(lstatbuf.st_mode) && (lstatbuf.st_size >= (off_t)0xFFFFFFFF)) { + if (S_ISREG(lstatbuf.st_mode) && (lstatbuf.st_size >= maxnonlarge) && !do_largefiles) { static int udf_warned; if( !allow_limited_size || verbose>1) fprintf(stderr, "File %s is larger than 4GiB-1.\n", whole_path); if( !allow_limited_size) { - fprintf(stderr, "-allow-limited-size was not specified. There is no way do represent this file size. Aborting.\n"); + fprintf(stderr, "There is no way do represent this file size. Aborting. See -iso-level 3 or -allow-limited-size options\n"); exit(1); } if(verbose>=1 && ! udf_warned ) { @@ -1773,6 +1827,20 @@ s_entry->de_flags |= INHIBIT_JOLIET_ENTRY; } } + if (this_dir != reloc_dir && + this_dir->dir_flags & INHIBIT_UDF_ENTRY) { + s_entry->de_flags |= INHIBIT_UDF_ENTRY; + } /* else if (strcmp(short_name, ".") != 0 && + strcmp(short_name, "..") != 0) { + if (u_matches(short_name) || u_matches(whole_path)) { + if (verbose > 1) { + fprintf(stderr, + "Hidden from UDF tree: %s\n", + whole_path); + } + s_entry->de_flags |= INHIBIT_UDF_ENTRY; + } + } */ #ifdef SORTING /* inherit any sort weight from parent directory */ @@ -1829,9 +1897,10 @@ s_entry->hfs_type = have_rsrc; /* * don't want the rsrc file to be included in any - * Joliet tree + * Joliet/UDF tree */ s_entry->de_flags |= INHIBIT_JOLIET_ENTRY; + s_entry->de_flags |= INHIBIT_UDF_ENTRY; } else if (s_entry->next) { /* * if previous entry is an associated file, @@ -2161,8 +2230,10 @@ * directory */ if (s_entry->hfs_ent && - !(s_entry->de_flags & RELOCATED_DIRECTORY)) + !(s_entry->de_flags & RELOCATED_DIRECTORY) && + (s_entry->isorec.flags[0] & ISO_MULTIEXTENT) == 0) { free(s_entry->hfs_ent); + } s_entry->hfs_ent = NULL; } /* @@ -2194,9 +2265,110 @@ &statbuf, &lstatbuf, deep_flag); } + +#ifdef USE_LARGEFILES +#define LARGE_EXTENT 0xFFFFF800UL +#define MAX_EXTENT 0xFFFFFFFEUL + /* + * Break up files greater than (4GB -2) into multiple extents. + * The original entry, with ->size untouched, remains for UDF. + * Each of the new file sections will get its own entry. + * The file sections are the only entries actually written out to the + * disk. The UDF entry will use "mxroot" to get the same start + * block as the first file section, and all the sections will end up + * in the ISO9660 directory in the correct order by "mxpart", + * which the directory sorting routine knows about. + * + * If we ever need to be able to find mxpart == 1 after sorting, + * we need to add another pointer to s_entry or to be very careful + * with the loops above where the ISO-9660 name is copied back to + * all multi-extent parts. + */ + if (s_entry->size > MAX_EXTENT && do_largefiles) { + off_t size; + + s_entry->de_flags |= MULTI_EXTENT; + s_entry->isorec.flags[0] |= ISO_MULTIEXTENT; + s_entry->mxroot = s_entry; + s_entry->mxpart = 0; + set_733((char *)s_entry->isorec.size, LARGE_EXTENT); + s_entry1 = dup_directory_entry(s_entry); + s_entry->next = s_entry1; + + /* + * full size UDF version + */ + s_entry->de_flags |= INHIBIT_ISO9660_ENTRY|INHIBIT_JOLIET_ENTRY; + if (s_entry->size > (((off_t)190)*0x3FFFF800)) { +#ifndef EOVERFLOW +#define EOVERFLOW EFBIG +#endif + errmsgno(EOVERFLOW, + "File %s is too large - hiding from UDF tree.\n", + whole_path); + s_entry->de_flags |= INHIBIT_UDF_ENTRY; + } + + /* + * Prepare the first file multi-extent section of the file. + */ + s_entry = s_entry1; + s_entry->de_flags |= INHIBIT_UDF_ENTRY; + size = s_entry->size; + s_entry->size = LARGE_EXTENT; + s_entry->mxpart++; + + /* + * Additional extents, as needed + */ + while (size > MAX_EXTENT) { + s_entry1 = dup_directory_entry(s_entry); + s_entry->next = s_entry1; + + s_entry = s_entry1; + s_entry->mxpart++; + size -= LARGE_EXTENT; + } + /* + * That was the last one. + */ + s_entry->isorec.flags[0] &= ~ISO_MULTIEXTENT; + s_entry->size = size; + set_733((char *)s_entry->isorec.size, (UInt32_t)s_entry->size); + } +#endif /* USE_LARGEFILES */ + return (1); } +EXPORT struct directory_entry * +dup_directory_entry(s_entry) + struct directory_entry *s_entry; +{ + struct directory_entry *s_entry1; + + s_entry1 = (struct directory_entry *) + e_malloc(sizeof (struct directory_entry)); + memcpy(s_entry1, s_entry, sizeof (struct directory_entry)); + + if (s_entry->rr_attributes) { + s_entry1->rr_attributes = + e_malloc(s_entry->total_rr_attr_size); + memcpy(s_entry1->rr_attributes, s_entry->rr_attributes, + s_entry->total_rr_attr_size); + } + if (s_entry->name) + s_entry1->name = strdup(s_entry->name); + if (s_entry->whole_name) + s_entry1->whole_name = strdup(s_entry->whole_name); +#ifdef APPLE_HYB + /* + * If we also duplicate s_entry->hfs_ent, we would need to change + * free_one_directory() and other calls to free(s_entry->hfs_ent) too. + */ +#endif + return (s_entry1); +} void generate_iso9660_directories(struct directory *node, FILE *outfile) --- genisoimage/udf.c +++ genisoimage/udf.c @@ -11,6 +11,7 @@ */ /* @(#)udf.c 1.14 04/04/15 Copyright 2001 J. Schilling */ +/* Parts from @(#)udf.c 1.31 08/08/13 Copyright 2001-2007 J. Schilling */ /* * udf.c - UDF support for genisoimage * @@ -136,7 +137,7 @@ /* directory contents */ for (de = dpnt->jcontents; de; de = de->jnext) { - if (!(de->de_flags & INHIBIT_JOLIET_ENTRY)) { + if (!(de->de_flags & INHIBIT_UDF_ENTRY)) { char *name = USE_MAC_NAME(de) ? de->hfs_ent->name : de->name; /* skip . and .. */ if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) @@ -150,12 +151,12 @@ static void assign_udf_directory_addresses(struct directory *dpnt) { - if (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY)) { + if (!(dpnt->dir_flags & INHIBIT_UDF_ENTRY)) { dpnt->self->udf_file_entry_sector = last_extent; last_extent += 1 + ISO_BLOCKS(directory_size(dpnt)); ++num_udf_directories; } - if (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) || dpnt == reloc_dir) { + if (!(dpnt->dir_flags & INHIBIT_UDF_ENTRY) || dpnt == reloc_dir) { for (dpnt = dpnt->subdir; dpnt; dpnt = dpnt->next) { assign_udf_directory_addresses(dpnt); } @@ -165,7 +166,7 @@ static void assign_udf_file_entry_addresses(struct directory *dpnt) { - if (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY)) { + if (!(dpnt->dir_flags & INHIBIT_UDF_ENTRY)) { struct directory_entry *de; for (de = dpnt->jcontents; de; de = de->jnext) { if (!(de->de_flags & RELOCATED_DIRECTORY) && @@ -175,7 +176,7 @@ } } } - if (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) || dpnt == reloc_dir) { + if (!(dpnt->dir_flags & INHIBIT_UDF_ENTRY) || dpnt == reloc_dir) { for (dpnt = dpnt->subdir; dpnt; dpnt = dpnt->next) { assign_udf_file_entry_addresses(dpnt); } @@ -654,6 +655,13 @@ } static void +udf_size_panic(int n) +{ + comerrno(EX_BAD, + "Panic: UDF file size error, too many extents (%d).\n", n); +} + +static void set_file_entry(unsigned char *buf, unsigned rba, unsigned file_rba, uint64_t length, const char *iso_date, int is_directory, unsigned link_count, unsigned unique_id) @@ -752,6 +760,18 @@ file_rba += chunk >> 11; allocation_desc++; } + if (((Uchar *)allocation_desc) > &buf[2048]) + udf_size_panic(allocation_desc - &fe->allocation_desc); + + if (((Uchar *)allocation_desc) > &buf[2048]) + udf_size_panic(allocation_desc - &fe->allocation_desc); + + if (((Uchar *)allocation_desc) > &buf[2048]) + udf_size_panic(allocation_desc - &fe->allocation_desc); + + if (((Uchar *)allocation_desc) > &buf[2048]) + udf_size_panic(allocation_desc - &fe->allocation_desc); + set32(&fe->length_of_allocation_descs, (unsigned char *) allocation_desc - (unsigned char *) &fe->allocation_desc); @@ -772,14 +792,14 @@ /* count relocated subdirectories */ for (de = dpnt->jcontents; de; de = de->jnext) { if ((de->de_flags & - (INHIBIT_JOLIET_ENTRY | RELOCATED_DIRECTORY)) == + (INHIBIT_UDF_ENTRY | RELOCATED_DIRECTORY)) == RELOCATED_DIRECTORY) { link_count++; } } /* count ordinary subdirectories */ for (dpnt = dpnt->subdir; dpnt; dpnt = dpnt->next) { - if (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY)) { + if (!(dpnt->dir_flags & INHIBIT_UDF_ENTRY)) { link_count++; } } @@ -833,7 +853,7 @@ char *name; struct directory_entry *de1; - if (de->de_flags & INHIBIT_JOLIET_ENTRY) + if (de->de_flags & INHIBIT_UDF_ENTRY) continue; name = USE_MAC_NAME(de) ? de->hfs_ent->name : de->name; @@ -888,10 +908,10 @@ static void write_udf_directories(struct directory *dpnt, FILE *outfile) { - if (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY)) { + if (!(dpnt->dir_flags & INHIBIT_UDF_ENTRY)) { write_one_udf_directory(dpnt, outfile); } - if (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) || dpnt == reloc_dir) { + if (!(dpnt->dir_flags & INHIBIT_UDF_ENTRY) || dpnt == reloc_dir) { for (dpnt = dpnt->subdir; dpnt; dpnt = dpnt->next) { write_udf_directories(dpnt, outfile); } @@ -905,7 +925,7 @@ memset(buf, 0, SECTOR_SIZE); - if (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY)) { + if (!(dpnt->dir_flags & INHIBIT_UDF_ENTRY)) { struct directory_entry *de; for (de = dpnt->jcontents; de; de = de->jnext) { if (!(de->de_flags & RELOCATED_DIRECTORY) && @@ -926,7 +946,7 @@ } } } - if (!(dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) || dpnt == reloc_dir) { + if (!(dpnt->dir_flags & INHIBIT_UDF_ENTRY) || dpnt == reloc_dir) { for (dpnt = dpnt->subdir; dpnt; dpnt = dpnt->next) { write_udf_file_entries(dpnt, outfile); } --- genisoimage/write.c +++ genisoimage/write.c @@ -12,6 +12,7 @@ /* @(#)write.c 1.88 06/02/01 joerg */ /* Parts from @(#)write.c 1.106 07/02/17 joerg */ +/* Parts from @(#)write.c 1.117 07/12/16 joerg */ /* * Program write.c - dump memory structures to file for iso9660 filesystem. * @@ -92,7 +93,7 @@ void xfwrite(void *buffer, int size, int count, FILE *file, int submode, BOOL islast); static int assign_directory_addresses(struct directory *node); -#ifdef APPLE_HYB +#if defined(APPLE_HYB) || defined(USE_LARGEFILES) static void write_one_file(char *filename, off_t size, FILE *outfile, off_t off); #else @@ -417,13 +418,13 @@ return (0); } -#ifdef APPLE_HYB +#if defined(APPLE_HYB) || defined(USE_LARGEFILES) static void write_one_file(char *filename, off_t size, FILE *outfile, off_t off) #else static void write_one_file(char *filename, off_t size, FILE *outfile) -#endif /* APPLE_HYB */ +#endif /* APPLE_HYB || USE_LARGEFILES */ { /* * It seems that there are still stone age C-compilers @@ -456,9 +457,9 @@ exit(1); #endif } -#ifdef APPLE_HYB +#if defined(APPLE_HYB) || defined(USE_LARGEFILES) fseek(infile, off, SEEK_SET); -#endif /* APPLE_HYB */ +#endif /* APPLE_HYB || USE_LARGEFILES */ remain = size; if (include_in_jigdo) @@ -655,8 +656,18 @@ return (-1); #endif /* APPLE_HYB */ - /* If the entries are the same, this is an error. */ + /* + * If the names are the same, multiple extent sections of the same file + * are sorted by part number. If the part numbers do not differ, this + * is an error. + */ if (strcmp(rpnt, lpnt) == 0) { +#ifdef USE_LARGEFILES + if ((*r)->mxpart < (*l)->mxpart) + return (-1); + else if ((*r)->mxpart > (*l)->mxpart) + return (1); +#endif #ifdef USE_LIBSCHILY errmsgno(EX_BAD, "Error: '%s' and '%s' have the same ISO9660 name '%s'.\n", @@ -1065,11 +1076,10 @@ } #endif /* DVD_VIDEO */ - s_entry = dpnt->contents; for (s_entry = dpnt->contents; s_entry; s_entry = s_entry->next) { /* - * If we already have an extent for this entry, then + * If we already have an extent for this entry, then * don't assign a new one. It must have come from a * previous session on the disc. Note that we don't * end up scheduling the thing for writing either. @@ -1078,7 +1088,9 @@ continue; } /* - * This saves some space if there are symlinks present + * This saves some space if there are symlinks present. + * If this is a multi-extent file, we get mxpart == 1 + * from find_hash(). */ s_hash = find_hash(s_entry->dev, s_entry->inode); if (s_hash) { @@ -1091,6 +1103,36 @@ s_hash->starting_block); set_733((char *) s_entry->isorec.size, s_hash->size); +#ifdef USE_LARGEFILES + if (s_entry->de_flags & MULTI_EXTENT) { + struct directory_entry *s_e; + unsigned int ext = s_hash->starting_block; + + /* + * Skip the multi extent root entry. + */ + if (s_entry->mxpart == 0) + continue; + /* + * The directory is sorted, so we should + * see s_entry->mxpart == 1 first. + */ + if (s_entry->mxpart != 1) { + comerrno(EX_BAD, + "Panic: Multi extent parts for %s not sorted.\n", + s_entry->whole_name); + } + s_entry->mxroot->starting_block = ext; + for (s_e = s_entry; + s_e && s_e->mxroot == s_entry->mxroot; + s_e = s_e->next) { + set_733((char *) s_e->isorec.extent, + ext); + ext += ISO_BLOCKS(s_e->size); + } + } +#endif + #ifdef SORTING /* check for non-directory files */ if (do_sort && ((s_entry->isorec.flags[0] & ISO_DIRECTORY) == 0)) { @@ -1247,8 +1289,54 @@ set_733((char *) s_entry->isorec.extent, last_extent); s_entry->starting_block = last_extent; +#ifdef USE_LARGEFILES + /* + * Update the entries for multi-section files + * as we now know the starting extent numbers. + */ + if (s_entry->de_flags & MULTI_EXTENT) { + struct directory_entry *s_e; + unsigned int ext = last_extent; + + /* + * Skip the multi extent root entry. + */ + if (s_entry->mxpart == 0) + continue; + /* + * The directory is sorted, so we should + * see s_entry->mxpart == 1 first. + */ + if (s_entry->mxpart != 1) { + comerrno(EX_BAD, + "Panic: Multi extent parts for %s not sorted.\n", + s_entry->whole_name); + } + dwpnt->size = s_entry->mxroot->size; + s_entry->mxroot->starting_block = ext; + /* + * Set the mxroot (mxpart == 0) to allow + * the UDF code to fetch the starting + * extent number. + */ + set_733((char *) s_entry->mxroot->isorec.extent, ext); + for (s_e = s_entry; + s_e && s_e->mxroot == s_entry->mxroot; + s_e = s_e->next) { + if (s_e->mxpart == 0) + continue; + set_733((char *) s_e->isorec.extent, + ext); + ext += ISO_BLOCKS(s_e->size); + } + add_hash(s_entry); + } +#endif add_hash(s_entry); - last_extent += ISO_BLOCKS(s_entry->size); + /* + * The cache holds the full size of the file + */ + last_extent += ISO_BLOCKS(dwpnt->size); #ifdef DVD_VIDEO /* Shouldn't we always add the pad info? */ if (dvd_video) { @@ -1343,8 +1431,10 @@ s_entry_d->whole_name = NULL; } #ifdef APPLE_HYB - if (apple_both && s_entry_d->hfs_ent && !s_entry_d->assoc) + if (apple_both && s_entry_d->hfs_ent && !s_entry_d->assoc && + (s_entry_d->isorec.flags[0] & ISO_MULTIEXTENT) == 0) { free(s_entry_d->hfs_ent); + } #endif /* APPLE_HYB */ free(s_entry_d);
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor