This commit is contained in:
parent
4b4c4f6400
commit
63eb2d63b1
14 changed files with 4270 additions and 812 deletions
|
@ -2,7 +2,7 @@
|
|||
* Header file defaults.h - assorted default values for character strings in
|
||||
* the volume descriptor.
|
||||
*
|
||||
* $Id: defaults.h,v 1.4 1997/04/10 03:31:53 eric Rel $
|
||||
* $Id: defaults.h,v 1.6 1998/06/02 02:40:37 eric Exp $
|
||||
*/
|
||||
|
||||
#define PREPARER_DEFAULT NULL
|
||||
|
@ -24,7 +24,11 @@
|
|||
#endif
|
||||
|
||||
#ifdef __sun
|
||||
#define SYSTEM_ID_DEFAULT "Solaris"
|
||||
#ifdef __svr4__
|
||||
#define SYSTEM_ID_DEFAULT "Solaris"
|
||||
#else
|
||||
#define SYSTEM_ID_DEFAULT "SunOS"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __hpux
|
||||
|
@ -39,6 +43,10 @@
|
|||
#define SYSTEM_ID_DEFAULT "AIX"
|
||||
#endif
|
||||
|
||||
#ifdef _WIN
|
||||
#define SYSTEM_ID_DEFAULT "Win32"
|
||||
#endif /* _WIN */
|
||||
|
||||
#ifndef SYSTEM_ID_DEFAULT
|
||||
#define SYSTEM_ID_DEFAULT "LINUX"
|
||||
#endif
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
|
||||
static char rcsid[] ="$Id: eltorito.c,v 1.7 1997/05/17 15:44:31 eric Exp $";
|
||||
static char rcsid[] ="$Id: eltorito.c,v 1.12 1998/06/02 02:40:37 eric Exp $";
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
|
@ -30,14 +30,22 @@ static char rcsid[] ="$Id: eltorito.c,v 1.7 1997/05/17 15:44:31 eric Exp $";
|
|||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "mkisofs.h"
|
||||
#include "iso9660.h"
|
||||
|
||||
/* used by Win32 for opening binary file - not used by Unix */
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif /* O_BINARY */
|
||||
|
||||
#undef MIN
|
||||
#define MIN(a, b) (((a) < (b))? (a): (b))
|
||||
|
||||
static struct eltorito_validation_entry valid_desc;
|
||||
static struct eltorito_defaultboot_entry default_desc;
|
||||
static struct eltorito_boot_descriptor boot_desc;
|
||||
|
||||
|
||||
/*
|
||||
* Check for presence of boot catalog. If it does not exist then make it
|
||||
|
@ -63,7 +71,7 @@ void FDECL1(init_boot_catalog, const char *, path)
|
|||
* check for the file existing
|
||||
*/
|
||||
#ifdef DEBUG_TORITO
|
||||
printf("Looking for boot catalog file %s\n",bootpath);
|
||||
fprintf(stderr,"Looking for boot catalog file %s\n",bootpath);
|
||||
#endif
|
||||
|
||||
if (!stat_filter(bootpath, &statbuf))
|
||||
|
@ -93,7 +101,7 @@ void FDECL1(init_boot_catalog, const char *, path)
|
|||
* file does not exist, so we create it
|
||||
* make it one CD sector long
|
||||
*/
|
||||
bcat = open(bootpath, O_WRONLY | O_CREAT, S_IROTH | S_IRGRP | S_IRWXU );
|
||||
bcat = open(bootpath, O_WRONLY | O_CREAT | O_BINARY, S_IROTH | S_IRGRP | S_IRWXU );
|
||||
if (bcat == -1)
|
||||
{
|
||||
fprintf(stderr, "Error creating boot catalog, exiting...\n");
|
||||
|
@ -207,7 +215,7 @@ void FDECL1(get_torito_desc, struct eltorito_boot_descriptor *, boot_desc)
|
|||
* assume 512 bytes/sector on a bootable floppy
|
||||
*/
|
||||
nsectors = ((de->size + 511) & ~(511))/512;
|
||||
printf("\nSize of boot image is %d sectors -> ", nsectors);
|
||||
fprintf(stderr, "\nSize of boot image is %d sectors -> ", nsectors);
|
||||
|
||||
/*
|
||||
* choose size of emulated floppy based on boot image size
|
||||
|
@ -215,17 +223,17 @@ void FDECL1(get_torito_desc, struct eltorito_boot_descriptor *, boot_desc)
|
|||
if (nsectors == 2880 )
|
||||
{
|
||||
default_desc.boot_media[0] = EL_TORITO_MEDIA_144FLOP;
|
||||
printf("Emulating a 1.44 meg floppy\n");
|
||||
fprintf(stderr, "Emulating a 1.44 meg floppy\n");
|
||||
}
|
||||
else if (nsectors == 5760 )
|
||||
{
|
||||
default_desc.boot_media[0] = EL_TORITO_MEDIA_288FLOP;
|
||||
printf("Emulating a 2.88 meg floppy\n");
|
||||
fprintf(stderr,"Emulating a 2.88 meg floppy\n");
|
||||
}
|
||||
else if (nsectors == 2400 )
|
||||
{
|
||||
default_desc.boot_media[0] = EL_TORITO_MEDIA_12FLOP;
|
||||
printf("Emulating a 1.2 meg floppy\n");
|
||||
fprintf(stderr,"Emulating a 1.2 meg floppy\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -240,7 +248,7 @@ void FDECL1(get_torito_desc, struct eltorito_boot_descriptor *, boot_desc)
|
|||
nsectors = 1;
|
||||
set_721(default_desc.nsect, (unsigned int) nsectors );
|
||||
#ifdef DEBUG_TORITO
|
||||
printf("Extent of boot images is %d\n",get_733(de->isorec.extent));
|
||||
fprintf(stderr,"Extent of boot images is %d\n",get_733(de->isorec.extent));
|
||||
#endif
|
||||
set_731(default_desc.bootoff,
|
||||
(unsigned int) get_733(de->isorec.extent));
|
||||
|
@ -248,7 +256,7 @@ void FDECL1(get_torito_desc, struct eltorito_boot_descriptor *, boot_desc)
|
|||
/*
|
||||
* now write it to disk
|
||||
*/
|
||||
bootcat = open(de2->whole_name, O_RDWR);
|
||||
bootcat = open(de2->whole_name, O_RDWR | O_BINARY);
|
||||
if (bootcat == -1)
|
||||
{
|
||||
fprintf(stderr,"Error opening boot catalog for update.\n");
|
||||
|
@ -263,3 +271,19 @@ void FDECL1(get_torito_desc, struct eltorito_boot_descriptor *, boot_desc)
|
|||
write(bootcat, &default_desc, 32);
|
||||
close(bootcat);
|
||||
} /* get_torito_desc(... */
|
||||
|
||||
/*
|
||||
* Function to write the EVD for the disc.
|
||||
*/
|
||||
int FDECL1(tvd_write, FILE *, outfile)
|
||||
{
|
||||
/*
|
||||
* Next we write out the boot volume descriptor for the disc
|
||||
*/
|
||||
get_torito_desc(&boot_desc);
|
||||
xfwrite(&boot_desc, 1, 2048, outfile);
|
||||
last_extent_written ++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct output_fragment torito_desc = {NULL, oneblock_size, NULL, tvd_write};
|
||||
|
|
760
util/mkisofs/getopt.c
Normal file
760
util/mkisofs/getopt.c
Normal file
|
@ -0,0 +1,760 @@
|
|||
/* Getopt for GNU.
|
||||
NOTE: getopt is now part of the C library, so if you don't know what
|
||||
"Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
|
||||
before changing it!
|
||||
|
||||
Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of the libiberty library. This library is free
|
||||
software; you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the
|
||||
Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU CC; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
As a special exception, if you link this library with files
|
||||
compiled with a GNU compiler to produce an executable, this does not cause
|
||||
the resulting executable to be covered by the GNU General Public License.
|
||||
This exception does not however invalidate any other reasons why
|
||||
the executable file might be covered by the GNU General Public License. */
|
||||
|
||||
/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
|
||||
Ditto for AIX 3.2 and <stdlib.h>. */
|
||||
#ifndef _NO_PROTO
|
||||
#define _NO_PROTO
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#if defined (emacs) || defined (CONFIG_BROKETS)
|
||||
/* We use <config.h> instead of "config.h" so that a compilation
|
||||
using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
|
||||
(which it would do because it found this file in $srcdir). */
|
||||
#include <config.h>
|
||||
#else
|
||||
#include "config.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef __STDC__
|
||||
/* This is a separate conditional since some stdc systems
|
||||
reject `defined (const)'. */
|
||||
#ifndef const
|
||||
#define const
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* Comment out all this code if we are using the GNU C Library, and are not
|
||||
actually compiling the library itself. This code is part of the GNU C
|
||||
Library, but also included in many other GNU distributions. Compiling
|
||||
and linking in this code is a waste when using the GNU C library
|
||||
(especially if it is a shared library). Rather than having every GNU
|
||||
program understand `configure --with-gnu-libc' and omit the object files,
|
||||
it is simpler to just do this in the source for each such file. */
|
||||
/* Many versions of the Linux C library include older, broken versions
|
||||
of these routines, which will break the linker's command-line
|
||||
parsing. */
|
||||
|
||||
#if defined (_LIBC) || !defined (__GNU_LIBRARY__) || defined (__linux__)
|
||||
|
||||
|
||||
/* This needs to come after some library #include
|
||||
to get __GNU_LIBRARY__ defined. */
|
||||
#ifdef __GNU_LIBRARY__
|
||||
/* Don't include stdlib.h for non-GNU C libraries because some of them
|
||||
contain conflicting prototypes for getopt. */
|
||||
#include <stdlib.h>
|
||||
#endif /* GNU C library. */
|
||||
|
||||
/* This version of `getopt' appears to the caller like standard Unix `getopt'
|
||||
but it behaves differently for the user, since it allows the user
|
||||
to intersperse the options with the other arguments.
|
||||
|
||||
As `getopt' works, it permutes the elements of ARGV so that,
|
||||
when it is done, all the options precede everything else. Thus
|
||||
all application programs are extended to handle flexible argument order.
|
||||
|
||||
Setting the environment variable POSIXLY_CORRECT disables permutation.
|
||||
Then the behavior is completely standard.
|
||||
|
||||
GNU application programs can use a third alternative mode in which
|
||||
they can distinguish the relative order of options and other arguments. */
|
||||
|
||||
#include "getopt.h"
|
||||
|
||||
/* For communication from `getopt' to the caller.
|
||||
When `getopt' finds an option that takes an argument,
|
||||
the argument value is returned here.
|
||||
Also, when `ordering' is RETURN_IN_ORDER,
|
||||
each non-option ARGV-element is returned here. */
|
||||
|
||||
char *optarg = NULL;
|
||||
|
||||
/* Index in ARGV of the next element to be scanned.
|
||||
This is used for communication to and from the caller
|
||||
and for communication between successive calls to `getopt'.
|
||||
|
||||
On entry to `getopt', zero means this is the first call; initialize.
|
||||
|
||||
When `getopt' returns EOF, this is the index of the first of the
|
||||
non-option elements that the caller should itself scan.
|
||||
|
||||
Otherwise, `optind' communicates from one call to the next
|
||||
how much of ARGV has been scanned so far. */
|
||||
|
||||
/* XXX 1003.2 says this must be 1 before any call. */
|
||||
int optind = 0;
|
||||
|
||||
/* The next char to be scanned in the option-element
|
||||
in which the last option character we returned was found.
|
||||
This allows us to pick up the scan where we left off.
|
||||
|
||||
If this is zero, or a null string, it means resume the scan
|
||||
by advancing to the next ARGV-element. */
|
||||
|
||||
static char *nextchar;
|
||||
|
||||
/* Callers store zero here to inhibit the error message
|
||||
for unrecognized options. */
|
||||
|
||||
int opterr = 1;
|
||||
|
||||
/* Set to an option character which was unrecognized.
|
||||
This must be initialized on some systems to avoid linking in the
|
||||
system's own getopt implementation. */
|
||||
|
||||
int optopt = '?';
|
||||
|
||||
/* Describe how to deal with options that follow non-option ARGV-elements.
|
||||
|
||||
If the caller did not specify anything,
|
||||
the default is REQUIRE_ORDER if the environment variable
|
||||
POSIXLY_CORRECT is defined, PERMUTE otherwise.
|
||||
|
||||
REQUIRE_ORDER means don't recognize them as options;
|
||||
stop option processing when the first non-option is seen.
|
||||
This is what Unix does.
|
||||
This mode of operation is selected by either setting the environment
|
||||
variable POSIXLY_CORRECT, or using `+' as the first character
|
||||
of the list of option characters.
|
||||
|
||||
PERMUTE is the default. We permute the contents of ARGV as we scan,
|
||||
so that eventually all the non-options are at the end. This allows options
|
||||
to be given in any order, even with programs that were not written to
|
||||
expect this.
|
||||
|
||||
RETURN_IN_ORDER is an option available to programs that were written
|
||||
to expect options and other ARGV-elements in any order and that care about
|
||||
the ordering of the two. We describe each non-option ARGV-element
|
||||
as if it were the argument of an option with character code 1.
|
||||
Using `-' as the first character of the list of option characters
|
||||
selects this mode of operation.
|
||||
|
||||
The special argument `--' forces an end of option-scanning regardless
|
||||
of the value of `ordering'. In the case of RETURN_IN_ORDER, only
|
||||
`--' can cause `getopt' to return EOF with `optind' != ARGC. */
|
||||
|
||||
static enum
|
||||
{
|
||||
REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
|
||||
} ordering;
|
||||
|
||||
#ifdef __GNU_LIBRARY__
|
||||
/* We want to avoid inclusion of string.h with non-GNU libraries
|
||||
because there are many ways it can cause trouble.
|
||||
On some systems, it contains special magic macros that don't work
|
||||
in GCC. */
|
||||
#include <string.h>
|
||||
#define my_index strchr
|
||||
#else
|
||||
|
||||
/* Avoid depending on library functions or files
|
||||
whose names are inconsistent. */
|
||||
|
||||
char *getenv ();
|
||||
|
||||
static char *
|
||||
my_index (str, chr)
|
||||
const char *str;
|
||||
int chr;
|
||||
{
|
||||
while (*str)
|
||||
{
|
||||
if (*str == chr)
|
||||
return (char *) str;
|
||||
str++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If using GCC, we can safely declare strlen this way.
|
||||
If not using GCC, it is ok not to declare it. */
|
||||
#ifdef __GNUC__
|
||||
/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
|
||||
That was relevant to code that was here before. */
|
||||
#ifndef __STDC__
|
||||
/* gcc with -traditional declares the built-in strlen to return int,
|
||||
and has done so at least since version 2.4.5. -- rms. */
|
||||
extern int strlen (const char *);
|
||||
#endif /* not __STDC__ */
|
||||
#endif /* __GNUC__ */
|
||||
|
||||
#endif /* not __GNU_LIBRARY__ */
|
||||
|
||||
/* Handle permutation of arguments. */
|
||||
|
||||
/* Describe the part of ARGV that contains non-options that have
|
||||
been skipped. `first_nonopt' is the index in ARGV of the first of them;
|
||||
`last_nonopt' is the index after the last of them. */
|
||||
|
||||
static int first_nonopt;
|
||||
static int last_nonopt;
|
||||
|
||||
/* Exchange two adjacent subsequences of ARGV.
|
||||
One subsequence is elements [first_nonopt,last_nonopt)
|
||||
which contains all the non-options that have been skipped so far.
|
||||
The other is elements [last_nonopt,optind), which contains all
|
||||
the options processed since those non-options were skipped.
|
||||
|
||||
`first_nonopt' and `last_nonopt' are relocated so that they describe
|
||||
the new indices of the non-options in ARGV after they are moved. */
|
||||
|
||||
static void
|
||||
exchange (argv)
|
||||
char **argv;
|
||||
{
|
||||
int bottom = first_nonopt;
|
||||
int middle = last_nonopt;
|
||||
int top = optind;
|
||||
char *tem;
|
||||
|
||||
/* Exchange the shorter segment with the far end of the longer segment.
|
||||
That puts the shorter segment into the right place.
|
||||
It leaves the longer segment in the right place overall,
|
||||
but it consists of two parts that need to be swapped next. */
|
||||
|
||||
while (top > middle && middle > bottom)
|
||||
{
|
||||
if (top - middle > middle - bottom)
|
||||
{
|
||||
/* Bottom segment is the short one. */
|
||||
int len = middle - bottom;
|
||||
register int i;
|
||||
|
||||
/* Swap it with the top part of the top segment. */
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
tem = argv[bottom + i];
|
||||
argv[bottom + i] = argv[top - (middle - bottom) + i];
|
||||
argv[top - (middle - bottom) + i] = tem;
|
||||
}
|
||||
/* Exclude the moved bottom segment from further swapping. */
|
||||
top -= len;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Top segment is the short one. */
|
||||
int len = top - middle;
|
||||
register int i;
|
||||
|
||||
/* Swap it with the bottom part of the bottom segment. */
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
tem = argv[bottom + i];
|
||||
argv[bottom + i] = argv[middle + i];
|
||||
argv[middle + i] = tem;
|
||||
}
|
||||
/* Exclude the moved top segment from further swapping. */
|
||||
bottom += len;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update records for the slots the non-options now occupy. */
|
||||
|
||||
first_nonopt += (optind - last_nonopt);
|
||||
last_nonopt = optind;
|
||||
}
|
||||
|
||||
/* Initialize the internal data when the first call is made. */
|
||||
|
||||
static const char *
|
||||
_getopt_initialize (optstring)
|
||||
const char *optstring;
|
||||
{
|
||||
/* Start processing options with ARGV-element 1 (since ARGV-element 0
|
||||
is the program name); the sequence of previously skipped
|
||||
non-option ARGV-elements is empty. */
|
||||
|
||||
first_nonopt = last_nonopt = optind = 1;
|
||||
|
||||
nextchar = NULL;
|
||||
|
||||
/* Determine how to handle the ordering of options and nonoptions. */
|
||||
|
||||
if (optstring[0] == '-')
|
||||
{
|
||||
ordering = RETURN_IN_ORDER;
|
||||
++optstring;
|
||||
}
|
||||
else if (optstring[0] == '+')
|
||||
{
|
||||
ordering = REQUIRE_ORDER;
|
||||
++optstring;
|
||||
}
|
||||
else if (getenv ("POSIXLY_CORRECT") != NULL)
|
||||
ordering = REQUIRE_ORDER;
|
||||
else
|
||||
ordering = PERMUTE;
|
||||
|
||||
return optstring;
|
||||
}
|
||||
|
||||
/* Scan elements of ARGV (whose length is ARGC) for option characters
|
||||
given in OPTSTRING.
|
||||
|
||||
If an element of ARGV starts with '-', and is not exactly "-" or "--",
|
||||
then it is an option element. The characters of this element
|
||||
(aside from the initial '-') are option characters. If `getopt'
|
||||
is called repeatedly, it returns successively each of the option characters
|
||||
from each of the option elements.
|
||||
|
||||
If `getopt' finds another option character, it returns that character,
|
||||
updating `optind' and `nextchar' so that the next call to `getopt' can
|
||||
resume the scan with the following option character or ARGV-element.
|
||||
|
||||
If there are no more option characters, `getopt' returns `EOF'.
|
||||
Then `optind' is the index in ARGV of the first ARGV-element
|
||||
that is not an option. (The ARGV-elements have been permuted
|
||||
so that those that are not options now come last.)
|
||||
|
||||
OPTSTRING is a string containing the legitimate option characters.
|
||||
If an option character is seen that is not listed in OPTSTRING,
|
||||
return '?' after printing an error message. If you set `opterr' to
|
||||
zero, the error message is suppressed but we still return '?'.
|
||||
|
||||
If a char in OPTSTRING is followed by a colon, that means it wants an arg,
|
||||
so the following text in the same ARGV-element, or the text of the following
|
||||
ARGV-element, is returned in `optarg'. Two colons mean an option that
|
||||
wants an optional arg; if there is text in the current ARGV-element,
|
||||
it is returned in `optarg', otherwise `optarg' is set to zero.
|
||||
|
||||
If OPTSTRING starts with `-' or `+', it requests different methods of
|
||||
handling the non-option ARGV-elements.
|
||||
See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
|
||||
|
||||
Long-named options begin with `--' instead of `-'.
|
||||
Their names may be abbreviated as long as the abbreviation is unique
|
||||
or is an exact match for some defined option. If they have an
|
||||
argument, it follows the option name in the same ARGV-element, separated
|
||||
from the option name by a `=', or else the in next ARGV-element.
|
||||
When `getopt' finds a long-named option, it returns 0 if that option's
|
||||
`flag' field is nonzero, the value of the option's `val' field
|
||||
if the `flag' field is zero.
|
||||
|
||||
The elements of ARGV aren't really const, because we permute them.
|
||||
But we pretend they're const in the prototype to be compatible
|
||||
with other systems.
|
||||
|
||||
LONGOPTS is a vector of `struct option' terminated by an
|
||||
element containing a name which is zero.
|
||||
|
||||
LONGIND returns the index in LONGOPT of the long-named option found.
|
||||
It is only valid when a long-named option has been found by the most
|
||||
recent call.
|
||||
|
||||
If LONG_ONLY is nonzero, '-' as well as '--' can introduce
|
||||
long-named options. */
|
||||
|
||||
int
|
||||
_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
|
||||
int argc;
|
||||
char *const *argv;
|
||||
const char *optstring;
|
||||
const struct option *longopts;
|
||||
int *longind;
|
||||
int long_only;
|
||||
{
|
||||
optarg = NULL;
|
||||
|
||||
if (optind == 0)
|
||||
optstring = _getopt_initialize (optstring);
|
||||
|
||||
if (argc == 0)
|
||||
return EOF;
|
||||
|
||||
if (nextchar == NULL || *nextchar == '\0')
|
||||
{
|
||||
/* Advance to the next ARGV-element. */
|
||||
|
||||
if (ordering == PERMUTE)
|
||||
{
|
||||
/* If we have just processed some options following some non-options,
|
||||
exchange them so that the options come first. */
|
||||
|
||||
if (first_nonopt != last_nonopt && last_nonopt != optind)
|
||||
exchange ((char **) argv);
|
||||
else if (last_nonopt != optind)
|
||||
first_nonopt = optind;
|
||||
|
||||
/* Skip any additional non-options
|
||||
and extend the range of non-options previously skipped. */
|
||||
|
||||
while (optind < argc
|
||||
&& (argv[optind][0] != '-' || argv[optind][1] == '\0'))
|
||||
optind++;
|
||||
last_nonopt = optind;
|
||||
}
|
||||
|
||||
/* The special ARGV-element `--' means premature end of options.
|
||||
Skip it like a null option,
|
||||
then exchange with previous non-options as if it were an option,
|
||||
then skip everything else like a non-option. */
|
||||
|
||||
if (optind != argc && !strcmp (argv[optind], "--"))
|
||||
{
|
||||
optind++;
|
||||
|
||||
if (first_nonopt != last_nonopt && last_nonopt != optind)
|
||||
exchange ((char **) argv);
|
||||
else if (first_nonopt == last_nonopt)
|
||||
first_nonopt = optind;
|
||||
last_nonopt = argc;
|
||||
|
||||
optind = argc;
|
||||
}
|
||||
|
||||
/* If we have done all the ARGV-elements, stop the scan
|
||||
and back over any non-options that we skipped and permuted. */
|
||||
|
||||
if (optind == argc)
|
||||
{
|
||||
/* Set the next-arg-index to point at the non-options
|
||||
that we previously skipped, so the caller will digest them. */
|
||||
if (first_nonopt != last_nonopt)
|
||||
optind = first_nonopt;
|
||||
return EOF;
|
||||
}
|
||||
|
||||
/* If we have come to a non-option and did not permute it,
|
||||
either stop the scan or describe it to the caller and pass it by. */
|
||||
|
||||
if ((argv[optind][0] != '-' || argv[optind][1] == '\0'))
|
||||
{
|
||||
if (ordering == REQUIRE_ORDER)
|
||||
return EOF;
|
||||
optarg = argv[optind++];
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* We have found another option-ARGV-element.
|
||||
Skip the initial punctuation. */
|
||||
|
||||
nextchar = (argv[optind] + 1
|
||||
+ (longopts != NULL && argv[optind][1] == '-'));
|
||||
}
|
||||
|
||||
/* Decode the current option-ARGV-element. */
|
||||
|
||||
/* Check whether the ARGV-element is a long option.
|
||||
|
||||
If long_only and the ARGV-element has the form "-f", where f is
|
||||
a valid short option, don't consider it an abbreviated form of
|
||||
a long option that starts with f. Otherwise there would be no
|
||||
way to give the -f short option.
|
||||
|
||||
On the other hand, if there's a long option "fubar" and
|
||||
the ARGV-element is "-fu", do consider that an abbreviation of
|
||||
the long option, just like "--fu", and not "-f" with arg "u".
|
||||
|
||||
This distinction seems to be the most useful approach. */
|
||||
|
||||
if (longopts != NULL
|
||||
&& (argv[optind][1] == '-'
|
||||
|| (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))
|
||||
{
|
||||
char *nameend;
|
||||
const struct option *p;
|
||||
const struct option *pfound = NULL;
|
||||
int exact = 0;
|
||||
int ambig = 0;
|
||||
int indfound;
|
||||
int option_index;
|
||||
|
||||
for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
|
||||
/* Do nothing. */ ;
|
||||
|
||||
/* Test all long options for either exact match
|
||||
or abbreviated matches. */
|
||||
for (p = longopts, option_index = 0; p->name; p++, option_index++)
|
||||
if (!strncmp (p->name, nextchar, nameend - nextchar))
|
||||
{
|
||||
if (nameend - nextchar == strlen (p->name))
|
||||
{
|
||||
/* Exact match found. */
|
||||
pfound = p;
|
||||
indfound = option_index;
|
||||
exact = 1;
|
||||
break;
|
||||
}
|
||||
else if (pfound == NULL)
|
||||
{
|
||||
/* First nonexact match found. */
|
||||
pfound = p;
|
||||
indfound = option_index;
|
||||
}
|
||||
else
|
||||
/* Second or later nonexact match found. */
|
||||
ambig = 1;
|
||||
}
|
||||
|
||||
if (ambig && !exact)
|
||||
{
|
||||
if (opterr)
|
||||
fprintf (stderr, "%s: option `%s' is ambiguous\n",
|
||||
argv[0], argv[optind]);
|
||||
nextchar += strlen (nextchar);
|
||||
optind++;
|
||||
return '?';
|
||||
}
|
||||
|
||||
if (pfound != NULL)
|
||||
{
|
||||
option_index = indfound;
|
||||
optind++;
|
||||
if (*nameend)
|
||||
{
|
||||
/* Don't test has_arg with >, because some C compilers don't
|
||||
allow it to be used on enums. */
|
||||
if (pfound->has_arg)
|
||||
optarg = nameend + 1;
|
||||
else
|
||||
{
|
||||
if (opterr)
|
||||
{
|
||||
if (argv[optind - 1][1] == '-')
|
||||
/* --option */
|
||||
fprintf (stderr,
|
||||
"%s: option `--%s' doesn't allow an argument\n",
|
||||
argv[0], pfound->name);
|
||||
else
|
||||
/* +option or -option */
|
||||
fprintf (stderr,
|
||||
"%s: option `%c%s' doesn't allow an argument\n",
|
||||
argv[0], argv[optind - 1][0], pfound->name);
|
||||
}
|
||||
nextchar += strlen (nextchar);
|
||||
return '?';
|
||||
}
|
||||
}
|
||||
else if (pfound->has_arg == 1)
|
||||
{
|
||||
if (optind < argc)
|
||||
optarg = argv[optind++];
|
||||
else
|
||||
{
|
||||
if (opterr)
|
||||
fprintf (stderr, "%s: option `%s' requires an argument\n",
|
||||
argv[0], argv[optind - 1]);
|
||||
nextchar += strlen (nextchar);
|
||||
return optstring[0] == ':' ? ':' : '?';
|
||||
}
|
||||
}
|
||||
nextchar += strlen (nextchar);
|
||||
if (longind != NULL)
|
||||
*longind = option_index;
|
||||
if (pfound->flag)
|
||||
{
|
||||
*(pfound->flag) = pfound->val;
|
||||
return 0;
|
||||
}
|
||||
return pfound->val;
|
||||
}
|
||||
|
||||
/* Can't find it as a long option. If this is not getopt_long_only,
|
||||
or the option starts with '--' or is not a valid short
|
||||
option, then it's an error.
|
||||
Otherwise interpret it as a short option. */
|
||||
if (!long_only || argv[optind][1] == '-'
|
||||
|| my_index (optstring, *nextchar) == NULL)
|
||||
{
|
||||
if (opterr)
|
||||
{
|
||||
if (argv[optind][1] == '-')
|
||||
/* --option */
|
||||
fprintf (stderr, "%s: unrecognized option `--%s'\n",
|
||||
argv[0], nextchar);
|
||||
else
|
||||
/* +option or -option */
|
||||
fprintf (stderr, "%s: unrecognized option `%c%s'\n",
|
||||
argv[0], argv[optind][0], nextchar);
|
||||
}
|
||||
nextchar = (char *) "";
|
||||
optind++;
|
||||
return '?';
|
||||
}
|
||||
}
|
||||
|
||||
/* Look at and handle the next short option-character. */
|
||||
|
||||
{
|
||||
char c = *nextchar++;
|
||||
char *temp = my_index (optstring, c);
|
||||
|
||||
/* Increment `optind' when we start to process its last character. */
|
||||
if (*nextchar == '\0')
|
||||
++optind;
|
||||
|
||||
if (temp == NULL || c == ':')
|
||||
{
|
||||
if (opterr)
|
||||
{
|
||||
/* 1003.2 specifies the format of this message. */
|
||||
fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c);
|
||||
}
|
||||
optopt = c;
|
||||
return '?';
|
||||
}
|
||||
if (temp[1] == ':')
|
||||
{
|
||||
if (temp[2] == ':')
|
||||
{
|
||||
/* This is an option that accepts an argument optionally. */
|
||||
if (*nextchar != '\0')
|
||||
{
|
||||
optarg = nextchar;
|
||||
optind++;
|
||||
}
|
||||
else
|
||||
optarg = NULL;
|
||||
nextchar = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This is an option that requires an argument. */
|
||||
if (*nextchar != '\0')
|
||||
{
|
||||
optarg = nextchar;
|
||||
/* If we end this ARGV-element by taking the rest as an arg,
|
||||
we must advance to the next element now. */
|
||||
optind++;
|
||||
}
|
||||
else if (optind == argc)
|
||||
{
|
||||
if (opterr)
|
||||
{
|
||||
/* 1003.2 specifies the format of this message. */
|
||||
fprintf (stderr, "%s: option requires an argument -- %c\n",
|
||||
argv[0], c);
|
||||
}
|
||||
optopt = c;
|
||||
if (optstring[0] == ':')
|
||||
c = ':';
|
||||
else
|
||||
c = '?';
|
||||
}
|
||||
else
|
||||
/* We already incremented `optind' once;
|
||||
increment it again when taking next ARGV-elt as argument. */
|
||||
optarg = argv[optind++];
|
||||
nextchar = NULL;
|
||||
}
|
||||
}
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
getopt (argc, argv, optstring)
|
||||
int argc;
|
||||
char *const *argv;
|
||||
const char *optstring;
|
||||
{
|
||||
return _getopt_internal (argc, argv, optstring,
|
||||
(const struct option *) 0,
|
||||
(int *) 0,
|
||||
0);
|
||||
}
|
||||
|
||||
#endif /* _LIBC or not __GNU_LIBRARY__. */
|
||||
|
||||
#ifdef TEST
|
||||
|
||||
/* Compile with -DTEST to make an executable for use in testing
|
||||
the above definition of `getopt'. */
|
||||
|
||||
int
|
||||
main (argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
int c;
|
||||
int digit_optind = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
int this_option_optind = optind ? optind : 1;
|
||||
|
||||
c = getopt (argc, argv, "abc:d:0123456789");
|
||||
if (c == EOF)
|
||||
break;
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
if (digit_optind != 0 && digit_optind != this_option_optind)
|
||||
printf ("digits occur in two different argv-elements.\n");
|
||||
digit_optind = this_option_optind;
|
||||
printf ("option %c\n", c);
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
printf ("option a\n");
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
printf ("option b\n");
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
printf ("option c with value `%s'\n", optarg);
|
||||
break;
|
||||
|
||||
case '?':
|
||||
break;
|
||||
|
||||
default:
|
||||
printf ("?? getopt returned character code 0%o ??\n", c);
|
||||
}
|
||||
}
|
||||
|
||||
if (optind < argc)
|
||||
{
|
||||
printf ("non-option ARGV-elements: ");
|
||||
while (optind < argc)
|
||||
printf ("%s ", argv[optind++]);
|
||||
printf ("\n");
|
||||
}
|
||||
|
||||
exit (0);
|
||||
}
|
||||
|
||||
#endif /* TEST */
|
190
util/mkisofs/getopt1.c
Normal file
190
util/mkisofs/getopt1.c
Normal file
|
@ -0,0 +1,190 @@
|
|||
/* getopt_long and getopt_long_only entry points for GNU getopt.
|
||||
Copyright (C) 1987, 88, 89, 90, 91, 92, 1993
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License
|
||||
as published by the Free Software Foundation; either version 2, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#if defined (emacs) || defined (CONFIG_BROKETS)
|
||||
/* We use <config.h> instead of "config.h" so that a compilation
|
||||
using -I. -I$srcdir will use ./config.h rather than $srcdir/config.h
|
||||
(which it would do because it found this file in $srcdir). */
|
||||
#include <config.h>
|
||||
#else
|
||||
#include "config.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "getopt.h"
|
||||
|
||||
#ifndef __STDC__
|
||||
/* This is a separate conditional since some stdc systems
|
||||
reject `defined (const)'. */
|
||||
#ifndef const
|
||||
#define const
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* Comment out all this code if we are using the GNU C Library, and are not
|
||||
actually compiling the library itself. This code is part of the GNU C
|
||||
Library, but also included in many other GNU distributions. Compiling
|
||||
and linking in this code is a waste when using the GNU C library
|
||||
(especially if it is a shared library). Rather than having every GNU
|
||||
program understand `configure --with-gnu-libc' and omit the object files,
|
||||
it is simpler to just do this in the source for each such file. */
|
||||
/* Many versions of the Linux C library include older, broken versions
|
||||
of these routines, which will break the linker's command-line
|
||||
parsing. */
|
||||
|
||||
#if defined (_LIBC) || !defined (__GNU_LIBRARY__) || defined (__linux__)
|
||||
|
||||
|
||||
/* This needs to come after some library #include
|
||||
to get __GNU_LIBRARY__ defined. */
|
||||
#ifdef __GNU_LIBRARY__
|
||||
#include <stdlib.h>
|
||||
#else
|
||||
char *getenv ();
|
||||
#endif
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL 0
|
||||
#endif
|
||||
|
||||
int
|
||||
getopt_long (argc, argv, options, long_options, opt_index)
|
||||
int argc;
|
||||
char *const *argv;
|
||||
const char *options;
|
||||
const struct option *long_options;
|
||||
int *opt_index;
|
||||
{
|
||||
return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
|
||||
}
|
||||
|
||||
/* Like getopt_long, but '-' as well as '--' can indicate a long option.
|
||||
If an option that starts with '-' (not '--') doesn't match a long option,
|
||||
but does match a short option, it is parsed as a short option
|
||||
instead. */
|
||||
|
||||
int
|
||||
getopt_long_only (argc, argv, options, long_options, opt_index)
|
||||
int argc;
|
||||
char *const *argv;
|
||||
const char *options;
|
||||
const struct option *long_options;
|
||||
int *opt_index;
|
||||
{
|
||||
return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
|
||||
}
|
||||
|
||||
|
||||
#endif /* _LIBC or not __GNU_LIBRARY__. */
|
||||
|
||||
#ifdef TEST
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int
|
||||
main (argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
int c;
|
||||
int digit_optind = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
int this_option_optind = optind ? optind : 1;
|
||||
int option_index = 0;
|
||||
static struct option long_options[] =
|
||||
{
|
||||
{"add", 1, 0, 0},
|
||||
{"append", 0, 0, 0},
|
||||
{"delete", 1, 0, 0},
|
||||
{"verbose", 0, 0, 0},
|
||||
{"create", 0, 0, 0},
|
||||
{"file", 1, 0, 0},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
c = getopt_long (argc, argv, "abc:d:0123456789",
|
||||
long_options, &option_index);
|
||||
if (c == EOF)
|
||||
break;
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case 0:
|
||||
printf ("option %s", long_options[option_index].name);
|
||||
if (optarg)
|
||||
printf (" with arg %s", optarg);
|
||||
printf ("\n");
|
||||
break;
|
||||
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
case '8':
|
||||
case '9':
|
||||
if (digit_optind != 0 && digit_optind != this_option_optind)
|
||||
printf ("digits occur in two different argv-elements.\n");
|
||||
digit_optind = this_option_optind;
|
||||
printf ("option %c\n", c);
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
printf ("option a\n");
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
printf ("option b\n");
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
printf ("option c with value `%s'\n", optarg);
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
printf ("option d with value `%s'\n", optarg);
|
||||
break;
|
||||
|
||||
case '?':
|
||||
break;
|
||||
|
||||
default:
|
||||
printf ("?? getopt returned character code 0%o ??\n", c);
|
||||
}
|
||||
}
|
||||
|
||||
if (optind < argc)
|
||||
{
|
||||
printf ("non-option ARGV-elements: ");
|
||||
while (optind < argc)
|
||||
printf ("%s ", argv[optind++]);
|
||||
printf ("\n");
|
||||
}
|
||||
|
||||
exit (0);
|
||||
}
|
||||
|
||||
#endif /* TEST */
|
|
@ -19,9 +19,10 @@
|
|||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
static char rcsid[] ="$Id: hash.c,v 1.2 1997/02/23 16:11:15 eric Rel $";
|
||||
static char rcsid[] ="$Id: hash.c,v 1.4 1997/12/06 21:05:04 eric Exp $";
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "config.h"
|
||||
#include "mkisofs.h"
|
||||
|
||||
#define NR_HASH 1024
|
||||
|
@ -44,7 +45,7 @@ void FDECL1(add_hash, struct directory_entry *, spnt){
|
|||
hash_number = HASH_FN((unsigned int) spnt->dev, (unsigned int) spnt->inode);
|
||||
|
||||
#if 0
|
||||
if (verbose) fprintf(stderr,"%s ",spnt->name);
|
||||
if (verbose > 1) fprintf(stderr,"%s ",spnt->name);
|
||||
#endif
|
||||
s_hash = (struct file_hash *) e_malloc(sizeof(struct file_hash));
|
||||
s_hash->next = hash_table[hash_number];
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
/*
|
||||
* $Id: iso9660.h,v 1.1 1997/02/23 15:55:25 eric Rel $
|
||||
* $Id: iso9660.h,v 1.2 1997/05/17 15:46:44 eric Exp $
|
||||
*/
|
||||
|
||||
#ifndef _ISOFS_FS_H
|
||||
|
@ -42,8 +42,9 @@ struct iso_volume_descriptor {
|
|||
};
|
||||
|
||||
/* volume descriptor types */
|
||||
#define ISO_VD_PRIMARY 1
|
||||
#define ISO_VD_END 255
|
||||
#define ISO_VD_PRIMARY 1
|
||||
#define ISO_VD_SUPPLEMENTARY 2 /* Used by Joliet */
|
||||
#define ISO_VD_END 255
|
||||
|
||||
#define ISO_STANDARD_ID "CD001"
|
||||
|
||||
|
@ -67,7 +68,7 @@ struct iso_primary_descriptor {
|
|||
char volume_id [ISODCL ( 41, 72)]; /* dchars */
|
||||
char unused2 [ISODCL ( 73, 80)];
|
||||
char volume_space_size [ISODCL ( 81, 88)]; /* 733 */
|
||||
char unused3 [ISODCL ( 89, 120)];
|
||||
char escape_sequences [ISODCL ( 89, 120)];
|
||||
char volume_set_size [ISODCL (121, 124)]; /* 723 */
|
||||
char volume_sequence_number [ISODCL (125, 128)]; /* 723 */
|
||||
char logical_block_size [ISODCL (129, 132)]; /* 723 */
|
||||
|
|
972
util/mkisofs/joliet.c
Normal file
972
util/mkisofs/joliet.c
Normal file
|
@ -0,0 +1,972 @@
|
|||
/*
|
||||
* File joliet.c - handle Win95/WinNT long file/unicode extensions for iso9660.
|
||||
|
||||
Copyright 1997 Eric Youngdale.
|
||||
|
||||
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
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
static char rcsid[] ="$Id: joliet.c,v 1.12 1998/06/02 02:40:37 eric Exp $";
|
||||
|
||||
|
||||
/*
|
||||
* Joliet extensions for ISO9660. These are spottily documented by
|
||||
* Microsoft. In their infinite stupidity, they completely ignored
|
||||
* the possibility of using an SUSP record with the long filename
|
||||
* in it, and instead wrote out a duplicate directory tree with the
|
||||
* long filenames in it.
|
||||
*
|
||||
* I am not sure why they did this. One reason is that they get the path
|
||||
* tables with the long filenames in them.
|
||||
*
|
||||
* There are two basic principles to Joliet, and the non-Unicode variant
|
||||
* known as Romeo. Long filenames seem to be the main one, and the second
|
||||
* is that the character set and a few other things is substantially relaxed.
|
||||
*
|
||||
* The SVD is identical to the PVD, except:
|
||||
*
|
||||
* Id is 2, not 1 (indicates SVD).
|
||||
* escape_sequences contains UCS-2 indicator (levels 1, 2 or 3).
|
||||
* The root directory record points to a different extent (with different
|
||||
* size).
|
||||
* There are different path tables for the two sets of directory trees.
|
||||
*
|
||||
* The following fields are recorded in Unicode:
|
||||
* system_id
|
||||
* volume_id
|
||||
* volume_set_id
|
||||
* publisher_id
|
||||
* preparer_id
|
||||
* application_id
|
||||
* copyright_file_id
|
||||
* abstract_file_id
|
||||
* bibliographic_file_id
|
||||
*
|
||||
* Unicode strings are always encoded in big-endian format.
|
||||
*
|
||||
* In a directory record, everything is the same as with iso9660, except
|
||||
* that the name is recorded in unicode. The name length is specified in
|
||||
* total bytes, not in number of unicode characters.
|
||||
*
|
||||
* The character set used for the names is different with UCS - the
|
||||
* restrictions are that the following are not allowed:
|
||||
*
|
||||
* Characters (00)(00) through (00)(1f) (control chars)
|
||||
* (00)(2a) '*'
|
||||
* (00)(2f) '/'
|
||||
* (00)(3a) ':'
|
||||
* (00)(3b) ';'
|
||||
* (00)(3f) '?'
|
||||
* (00)(5c) '\'
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "mkisofs.h"
|
||||
#include "iso9660.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
static jpath_table_index;
|
||||
static struct directory ** jpathlist;
|
||||
static next_jpath_index = 1;
|
||||
static int sort_goof;
|
||||
|
||||
static int DECL(joliet_sort_directory, (struct directory_entry ** sort_dir));
|
||||
static void DECL(assign_joliet_directory_addresses, (struct directory * node));
|
||||
|
||||
/*
|
||||
* Function: convert_to_unicode
|
||||
*
|
||||
* Purpose: Perform a 1/2 assed unicode conversion on a text
|
||||
* string.
|
||||
*
|
||||
* Notes:
|
||||
*/
|
||||
static void FDECL3(convert_to_unicode, unsigned char *, buffer, int, size, char *, source )
|
||||
{
|
||||
unsigned char * tmpbuf;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
/*
|
||||
* If we get a NULL pointer for the source, it means we have an inplace
|
||||
* copy, and we need to make a temporary working copy first.
|
||||
*/
|
||||
if( source == NULL )
|
||||
{
|
||||
tmpbuf = (u_char *) e_malloc(size);
|
||||
memcpy( tmpbuf, buffer, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
tmpbuf = (u_char *)source;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now start copying characters. If the size was specified to be 0, then
|
||||
* assume the input was 0 terminated.
|
||||
*/
|
||||
j = 0;
|
||||
for(i=0; i < size ; i += 2, j++)
|
||||
{
|
||||
buffer[i] = 0;
|
||||
if( tmpbuf[j] < 0x1f && tmpbuf[j] != 0 )
|
||||
{
|
||||
buffer[i+1] = '_';
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(tmpbuf[j])
|
||||
{
|
||||
case '*':
|
||||
case '/':
|
||||
case ':':
|
||||
case ';':
|
||||
case '?':
|
||||
case '\\':
|
||||
/*
|
||||
* Even Joliet has some standards as to what is allowed in a pathname.
|
||||
* Pretty tame in comparison to what DOS restricts you to.
|
||||
*/
|
||||
buffer[i+1] = '_';
|
||||
break;
|
||||
default:
|
||||
buffer[i+1] = tmpbuf[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( source == NULL )
|
||||
{
|
||||
free(tmpbuf);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Function: joliet_strlen
|
||||
*
|
||||
* Purpose: Return length in bytes of string after conversion to unicode.
|
||||
*
|
||||
* Notes: This is provided mainly as a convenience so that when more intelligent
|
||||
* Unicode conversion for either Multibyte or 8-bit codes is available that
|
||||
* we can easily adapt.
|
||||
*/
|
||||
static int FDECL1(joliet_strlen, const char *, string)
|
||||
{
|
||||
int rtn;
|
||||
struct iso_directory_record foobar;
|
||||
|
||||
rtn = strlen(string) << 1;
|
||||
|
||||
/*
|
||||
* We do clamp the maximum length of a Joliet string to be the
|
||||
* maximum path size. This helps to ensure that we don't completely
|
||||
* bolix things up with very long paths. The Joliet specs say
|
||||
* that the maximum length is 128 bytes, or 64 unicode characters.
|
||||
*/
|
||||
if( rtn > 0x80)
|
||||
{
|
||||
rtn = 0x80;
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function: get_joliet_vol_desc
|
||||
*
|
||||
* Purpose: generate a Joliet compatible volume desc.
|
||||
*
|
||||
* Notes: Assume that we have the non-joliet vol desc
|
||||
* already present in the buffer. Just modifiy the
|
||||
* appropriate fields.
|
||||
*/
|
||||
static void FDECL1(get_joliet_vol_desc, struct iso_primary_descriptor *, vol_desc)
|
||||
{
|
||||
vol_desc->type[0] = ISO_VD_SUPPLEMENTARY;
|
||||
|
||||
/*
|
||||
* For now, always do Unicode level 3. I don't really know what 1 and 2
|
||||
* are - perhaps a more limited Unicode set.
|
||||
*
|
||||
* FIXME(eric) - how does Romeo fit in here?
|
||||
*/
|
||||
strcpy(vol_desc->escape_sequences, "%/E");
|
||||
|
||||
/*
|
||||
* Until we have Unicode path tables, leave these unset.
|
||||
*/
|
||||
set_733((char *) vol_desc->path_table_size, jpath_table_size);
|
||||
set_731(vol_desc->type_l_path_table, jpath_table[0]);
|
||||
set_731(vol_desc->opt_type_l_path_table, jpath_table[1]);
|
||||
set_732(vol_desc->type_m_path_table, jpath_table[2]);
|
||||
set_732(vol_desc->opt_type_m_path_table, jpath_table[3]);
|
||||
|
||||
/*
|
||||
* Set this one up.
|
||||
*/
|
||||
memcpy(vol_desc->root_directory_record, &jroot_record,
|
||||
sizeof(struct iso_directory_record) + 1);
|
||||
|
||||
/*
|
||||
* Finally, we have a bunch of strings to convert to Unicode.
|
||||
* FIXME(eric) - I don't know how to do this in general, so we will
|
||||
* just be really lazy and do a char -> short conversion. We probably
|
||||
* will want to filter any characters >= 0x80.
|
||||
*/
|
||||
convert_to_unicode((u_char *)vol_desc->system_id, sizeof(vol_desc->system_id), NULL);
|
||||
convert_to_unicode((u_char *)vol_desc->volume_id, sizeof(vol_desc->volume_id), NULL);
|
||||
convert_to_unicode((u_char *)vol_desc->volume_set_id, sizeof(vol_desc->volume_set_id), NULL);
|
||||
convert_to_unicode((u_char *)vol_desc->publisher_id, sizeof(vol_desc->publisher_id), NULL);
|
||||
convert_to_unicode((u_char *)vol_desc->preparer_id, sizeof(vol_desc->preparer_id), NULL);
|
||||
convert_to_unicode((u_char *)vol_desc->application_id, sizeof(vol_desc->application_id), NULL);
|
||||
convert_to_unicode((u_char *)vol_desc->copyright_file_id, sizeof(vol_desc->copyright_file_id), NULL);
|
||||
convert_to_unicode((u_char *)vol_desc->abstract_file_id, sizeof(vol_desc->abstract_file_id), NULL);
|
||||
convert_to_unicode((u_char *)vol_desc->bibliographic_file_id, sizeof(vol_desc->bibliographic_file_id), NULL);
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void FDECL1(assign_joliet_directory_addresses, struct directory *, node)
|
||||
{
|
||||
int dir_size;
|
||||
struct directory * dpnt;
|
||||
|
||||
dpnt = node;
|
||||
|
||||
while (dpnt)
|
||||
{
|
||||
if( (dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) == 0 )
|
||||
{
|
||||
/*
|
||||
* If we already have an extent for this (i.e. it came from
|
||||
* a multisession disc), then don't reassign a new extent.
|
||||
*/
|
||||
dpnt->jpath_index = next_jpath_index++;
|
||||
if( dpnt->jextent == 0 )
|
||||
{
|
||||
dpnt->jextent = last_extent;
|
||||
dir_size = (dpnt->jsize + (SECTOR_SIZE - 1)) >> 11;
|
||||
last_extent += dir_size;
|
||||
}
|
||||
}
|
||||
|
||||
if(dpnt->subdir)
|
||||
{
|
||||
assign_joliet_directory_addresses(dpnt->subdir);
|
||||
}
|
||||
dpnt = dpnt->next;
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void FDECL1(build_jpathlist, struct directory *, node)
|
||||
{
|
||||
struct directory * dpnt;
|
||||
|
||||
dpnt = node;
|
||||
|
||||
while (dpnt)
|
||||
|
||||
{
|
||||
if( (dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) == 0 )
|
||||
{
|
||||
jpathlist[dpnt->jpath_index] = dpnt;
|
||||
}
|
||||
if(dpnt->subdir) build_jpathlist(dpnt->subdir);
|
||||
dpnt = dpnt->next;
|
||||
}
|
||||
} /* build_jpathlist(... */
|
||||
|
||||
static int FDECL2(joliet_compare_paths, void const *, r, void const *, l)
|
||||
{
|
||||
struct directory const *ll = *(struct directory * const *)l;
|
||||
struct directory const *rr = *(struct directory * const *)r;
|
||||
int rparent, lparent;
|
||||
|
||||
rparent = rr->parent->jpath_index;
|
||||
lparent = ll->parent->jpath_index;
|
||||
if( rr->parent == reloc_dir )
|
||||
{
|
||||
rparent = rr->self->parent_rec->filedir->jpath_index;
|
||||
}
|
||||
|
||||
if( ll->parent == reloc_dir )
|
||||
{
|
||||
lparent = ll->self->parent_rec->filedir->jpath_index;
|
||||
}
|
||||
|
||||
if (rparent < lparent)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (rparent > lparent)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return strcmp(rr->self->name, ll->self->name);
|
||||
|
||||
} /* compare_paths(... */
|
||||
|
||||
static int generate_joliet_path_tables()
|
||||
{
|
||||
struct directory_entry * de;
|
||||
struct directory * dpnt;
|
||||
int fix;
|
||||
int j;
|
||||
int namelen;
|
||||
char * npnt;
|
||||
char * npnt1;
|
||||
int tablesize;
|
||||
|
||||
/*
|
||||
* First allocate memory for the tables and initialize the memory
|
||||
*/
|
||||
tablesize = jpath_blocks << 11;
|
||||
jpath_table_m = (char *) e_malloc(tablesize);
|
||||
jpath_table_l = (char *) e_malloc(tablesize);
|
||||
memset(jpath_table_l, 0, tablesize);
|
||||
memset(jpath_table_m, 0, tablesize);
|
||||
|
||||
/*
|
||||
* Now start filling in the path tables. Start with root directory
|
||||
*/
|
||||
jpath_table_index = 0;
|
||||
jpathlist = (struct directory **) e_malloc(sizeof(struct directory *)
|
||||
* next_jpath_index);
|
||||
memset(jpathlist, 0, sizeof(struct directory *) * next_jpath_index);
|
||||
build_jpathlist(root);
|
||||
|
||||
do
|
||||
{
|
||||
fix = 0;
|
||||
qsort(&jpathlist[1], next_jpath_index-1, sizeof(struct directory *),
|
||||
(int (*)(const void *, const void *))joliet_compare_paths);
|
||||
|
||||
for(j=1; j<next_jpath_index; j++)
|
||||
{
|
||||
if(jpathlist[j]->jpath_index != j)
|
||||
{
|
||||
jpathlist[j]->jpath_index = j;
|
||||
fix++;
|
||||
}
|
||||
}
|
||||
} while(fix);
|
||||
|
||||
for(j=1; j<next_jpath_index; j++)
|
||||
{
|
||||
dpnt = jpathlist[j];
|
||||
if(!dpnt)
|
||||
{
|
||||
fprintf(stderr,"Entry %d not in path tables\n", j);
|
||||
exit(1);
|
||||
}
|
||||
npnt = dpnt->de_name;
|
||||
|
||||
npnt1 = strrchr(npnt, PATH_SEPARATOR);
|
||||
if(npnt1)
|
||||
{
|
||||
npnt = npnt1 + 1;
|
||||
}
|
||||
|
||||
de = dpnt->self;
|
||||
if(!de)
|
||||
{
|
||||
fprintf(stderr,"Fatal goof - directory has amnesia\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
namelen = joliet_strlen(de->name);
|
||||
|
||||
if( dpnt == root )
|
||||
{
|
||||
jpath_table_l[jpath_table_index] = 1;
|
||||
jpath_table_m[jpath_table_index] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
jpath_table_l[jpath_table_index] = namelen;
|
||||
jpath_table_m[jpath_table_index] = namelen;
|
||||
}
|
||||
jpath_table_index += 2;
|
||||
|
||||
set_731(jpath_table_l + jpath_table_index, dpnt->jextent);
|
||||
set_732(jpath_table_m + jpath_table_index, dpnt->jextent);
|
||||
jpath_table_index += 4;
|
||||
|
||||
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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
jpath_table_index += 2;
|
||||
|
||||
/*
|
||||
* The root directory is still represented in non-unicode fashion.
|
||||
*/
|
||||
if( dpnt == root )
|
||||
{
|
||||
jpath_table_l[jpath_table_index] = 0;
|
||||
jpath_table_m[jpath_table_index] = 0;
|
||||
jpath_table_index ++;
|
||||
}
|
||||
else
|
||||
{
|
||||
convert_to_unicode((u_char *)jpath_table_l + jpath_table_index,
|
||||
namelen, de->name);
|
||||
convert_to_unicode((u_char *)jpath_table_m + jpath_table_index,
|
||||
namelen, de->name);
|
||||
jpath_table_index += namelen;
|
||||
}
|
||||
|
||||
if(jpath_table_index & 1)
|
||||
{
|
||||
jpath_table_index++; /* For odd lengths we pad */
|
||||
}
|
||||
}
|
||||
|
||||
free(jpathlist);
|
||||
if(jpath_table_index != jpath_table_size)
|
||||
{
|
||||
fprintf(stderr,"Joliet path table lengths do not match %d %d\n",
|
||||
jpath_table_index,
|
||||
jpath_table_size);
|
||||
}
|
||||
return 0;
|
||||
} /* generate_path_tables(... */
|
||||
|
||||
static void FDECL2(generate_one_joliet_directory, struct directory *, dpnt, FILE *, outfile)
|
||||
{
|
||||
unsigned int dir_index;
|
||||
char * directory_buffer;
|
||||
int new_reclen;
|
||||
struct directory_entry * s_entry;
|
||||
struct directory_entry * s_entry1;
|
||||
struct iso_directory_record jrec;
|
||||
unsigned int total_size;
|
||||
int cvt_len;
|
||||
struct directory * finddir;
|
||||
|
||||
total_size = (dpnt->jsize + (SECTOR_SIZE - 1)) & ~(SECTOR_SIZE - 1);
|
||||
directory_buffer = (char *) e_malloc(total_size);
|
||||
memset(directory_buffer, 0, total_size);
|
||||
dir_index = 0;
|
||||
|
||||
s_entry = dpnt->jcontents;
|
||||
while(s_entry)
|
||||
{
|
||||
if( (s_entry->de_flags & INHIBIT_JOLIET_ENTRY) == 0 )
|
||||
{
|
||||
/*
|
||||
* If this entry was a directory that was relocated, we have a bit
|
||||
* of trouble here. We need to dig out the real thing and put it
|
||||
* back here. In the Joliet tree, there is no relocated rock
|
||||
* ridge, as there are no depth limits to a directory tree.
|
||||
*/
|
||||
if( (s_entry->de_flags & RELOCATED_DIRECTORY) != 0 )
|
||||
{
|
||||
for(s_entry1 = reloc_dir->contents; s_entry1; s_entry1 = s_entry1->next)
|
||||
{
|
||||
if( s_entry1->parent_rec == s_entry )
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( s_entry1 == NULL )
|
||||
{
|
||||
/*
|
||||
* We got trouble.
|
||||
*/
|
||||
fprintf(stderr, "Unable to locate relocated directory\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
s_entry1 = s_entry;
|
||||
}
|
||||
|
||||
/*
|
||||
* We do not allow directory entries to cross sector boundaries.
|
||||
* Simply pad, and then start the next entry at the next sector
|
||||
*/
|
||||
new_reclen = s_entry1->jreclen;
|
||||
if( (dir_index & (SECTOR_SIZE - 1)) + new_reclen >= SECTOR_SIZE )
|
||||
{
|
||||
dir_index = (dir_index + (SECTOR_SIZE - 1)) &
|
||||
~(SECTOR_SIZE - 1);
|
||||
}
|
||||
|
||||
memcpy(&jrec, &s_entry1->isorec, sizeof(struct iso_directory_record) -
|
||||
sizeof(s_entry1->isorec.name));
|
||||
|
||||
cvt_len = joliet_strlen(s_entry1->name);
|
||||
|
||||
/*
|
||||
* Fix the record length - this was the non-Joliet version we
|
||||
* were seeing.
|
||||
*/
|
||||
jrec.name_len[0] = cvt_len;
|
||||
jrec.length[0] = s_entry1->jreclen;
|
||||
|
||||
/*
|
||||
* If this is a directory, fix the correct size and extent
|
||||
* number.
|
||||
*/
|
||||
if( (jrec.flags[0] & 2) != 0 )
|
||||
{
|
||||
if(strcmp(s_entry1->name,".") == 0)
|
||||
{
|
||||
jrec.name_len[0] = 1;
|
||||
set_733((char *) jrec.extent, dpnt->jextent);
|
||||
set_733((char *) jrec.size, ROUND_UP(dpnt->jsize));
|
||||
}
|
||||
else if(strcmp(s_entry1->name,"..") == 0)
|
||||
{
|
||||
jrec.name_len[0] = 1;
|
||||
if( dpnt->parent == reloc_dir )
|
||||
{
|
||||
set_733((char *) jrec.extent, dpnt->self->parent_rec->filedir->jextent);
|
||||
set_733((char *) jrec.size, ROUND_UP(dpnt->self->parent_rec->filedir->jsize));
|
||||
}
|
||||
else
|
||||
|
||||
{
|
||||
set_733((char *) jrec.extent, dpnt->parent->jextent);
|
||||
set_733((char *) jrec.size, ROUND_UP(dpnt->parent->jsize));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( (s_entry->de_flags & RELOCATED_DIRECTORY) != 0 )
|
||||
{
|
||||
finddir = reloc_dir->subdir;
|
||||
}
|
||||
else
|
||||
{
|
||||
finddir = dpnt->subdir;
|
||||
}
|
||||
while(1==1)
|
||||
{
|
||||
if(finddir->self == s_entry1) break;
|
||||
finddir = finddir->next;
|
||||
if(!finddir)
|
||||
{
|
||||
fprintf(stderr,"Fatal goof - unable to find directory location\n"); exit(1);
|
||||
}
|
||||
}
|
||||
set_733((char *) jrec.extent, finddir->jextent);
|
||||
set_733((char *) jrec.size, ROUND_UP(finddir->jsize));
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(directory_buffer + dir_index, &jrec,
|
||||
sizeof(struct iso_directory_record) -
|
||||
sizeof(s_entry1->isorec.name));
|
||||
|
||||
|
||||
dir_index += sizeof(struct iso_directory_record) -
|
||||
sizeof (s_entry1->isorec.name);
|
||||
|
||||
/*
|
||||
* Finally dump the Unicode version of the filename.
|
||||
* Note - . and .. are the same as with non-Joliet discs.
|
||||
*/
|
||||
if( (jrec.flags[0] & 2) != 0
|
||||
&& strcmp(s_entry1->name, ".") == 0 )
|
||||
{
|
||||
directory_buffer[dir_index++] = 0;
|
||||
}
|
||||
else if( (jrec.flags[0] & 2) != 0
|
||||
&& strcmp(s_entry1->name, "..") == 0 )
|
||||
{
|
||||
directory_buffer[dir_index++] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
convert_to_unicode((u_char *)directory_buffer + dir_index,
|
||||
cvt_len,
|
||||
s_entry1->name);
|
||||
dir_index += cvt_len;
|
||||
}
|
||||
|
||||
if(dir_index & 1)
|
||||
{
|
||||
directory_buffer[dir_index++] = 0;
|
||||
}
|
||||
}
|
||||
s_entry = s_entry->jnext;
|
||||
}
|
||||
|
||||
if(dpnt->jsize != dir_index)
|
||||
{
|
||||
fprintf(stderr,"Unexpected joliet directory length %d %d %s\n",dpnt->jsize,
|
||||
dir_index, dpnt->de_name);
|
||||
}
|
||||
|
||||
xfwrite(directory_buffer, 1, total_size, outfile);
|
||||
last_extent_written += total_size >> 11;
|
||||
free(directory_buffer);
|
||||
} /* generate_one_joliet_directory(... */
|
||||
|
||||
static int FDECL1(joliet_sort_n_finish, struct directory *, this_dir)
|
||||
{
|
||||
struct directory_entry * s_entry;
|
||||
int status = 0;
|
||||
|
||||
for(s_entry = this_dir->contents; s_entry; s_entry = s_entry->next)
|
||||
{
|
||||
if( (s_entry->de_flags & INHIBIT_JOLIET_ENTRY) != 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* First update the path table sizes for directories.
|
||||
*
|
||||
* Finally, set the length of the directory entry if Joliet is used.
|
||||
* The name is longer, but no Rock Ridge is ever used here, so
|
||||
* depending upon the options the entry size might turn out to be about
|
||||
* the same. The Unicode name is always a multiple of 2 bytes, so
|
||||
* we always add 1 to make it an even number.
|
||||
*/
|
||||
if(s_entry->isorec.flags[0] == 2)
|
||||
{
|
||||
if (strcmp(s_entry->name,".") && strcmp(s_entry->name,".."))
|
||||
{
|
||||
jpath_table_size += joliet_strlen(s_entry->name) + sizeof(struct iso_path_table) - 1;
|
||||
if (jpath_table_size & 1)
|
||||
{
|
||||
jpath_table_size++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this_dir == root && strlen(s_entry->name) == 1)
|
||||
{
|
||||
jpath_table_size += sizeof(struct iso_path_table);
|
||||
if (jpath_table_size & 1) jpath_table_size++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (strcmp(s_entry->name,".") && strcmp(s_entry->name,".."))
|
||||
{
|
||||
s_entry->jreclen = sizeof(struct iso_directory_record)
|
||||
- sizeof(s_entry->isorec.name)
|
||||
+ joliet_strlen(s_entry->name)
|
||||
+ 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Special - for '.' and '..' we generate the same records we
|
||||
* did for non-Joliet discs.
|
||||
*/
|
||||
s_entry->jreclen = sizeof(struct iso_directory_record)
|
||||
- sizeof(s_entry->isorec.name)
|
||||
+ 1;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
if( (this_dir->dir_flags & INHIBIT_JOLIET_ENTRY) != 0 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
this_dir->jcontents = this_dir->contents;
|
||||
status = joliet_sort_directory(&this_dir->jcontents);
|
||||
|
||||
/*
|
||||
* Now go through the directory and figure out how large this one will be.
|
||||
* Do not split a directory entry across a sector boundary
|
||||
*/
|
||||
s_entry = this_dir->jcontents;
|
||||
for(s_entry = this_dir->jcontents; s_entry; s_entry = s_entry->jnext)
|
||||
{
|
||||
int jreclen;
|
||||
|
||||
if( (s_entry->de_flags & INHIBIT_JOLIET_ENTRY) != 0 )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
jreclen = s_entry->jreclen;
|
||||
|
||||
if ((this_dir->jsize & (SECTOR_SIZE - 1)) + jreclen >= SECTOR_SIZE)
|
||||
{
|
||||
this_dir->jsize = (this_dir->jsize + (SECTOR_SIZE - 1)) &
|
||||
~(SECTOR_SIZE - 1);
|
||||
}
|
||||
this_dir->jsize += jreclen;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
* Similar to the iso9660 case, except here we perform a full sort based upon the
|
||||
* regular name of the file, not the 8.3 version.
|
||||
*/
|
||||
static int FDECL2(joliet_compare_dirs, const void *, rr, const void *, ll)
|
||||
{
|
||||
char * rpnt, *lpnt;
|
||||
struct directory_entry ** r, **l;
|
||||
|
||||
r = (struct directory_entry **) rr;
|
||||
l = (struct directory_entry **) ll;
|
||||
rpnt = (*r)->name;
|
||||
lpnt = (*l)->name;
|
||||
|
||||
/*
|
||||
* If the entries are the same, this is an error.
|
||||
*/
|
||||
if( strcmp(rpnt, lpnt) == 0 )
|
||||
{
|
||||
sort_goof++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Put the '.' and '..' entries on the head of the sorted list.
|
||||
* For normal ASCII, this always happens to be the case, but out of
|
||||
* band characters cause this not to be the case sometimes.
|
||||
*/
|
||||
if( strcmp(rpnt, ".") == 0 ) return -1;
|
||||
if( strcmp(lpnt, ".") == 0 ) return 1;
|
||||
|
||||
if( strcmp(rpnt, "..") == 0 ) return -1;
|
||||
if( strcmp(lpnt, "..") == 0 ) return 1;
|
||||
|
||||
while(*rpnt && *lpnt)
|
||||
{
|
||||
if(*rpnt == ';' && *lpnt != ';') return -1;
|
||||
if(*rpnt != ';' && *lpnt == ';') return 1;
|
||||
|
||||
if(*rpnt == ';' && *lpnt == ';') return 0;
|
||||
|
||||
/*
|
||||
* Extensions are not special here. Don't treat the dot as something that
|
||||
* must be bumped to the start of the list.
|
||||
*/
|
||||
#if 0
|
||||
if(*rpnt == '.' && *lpnt != '.') return -1;
|
||||
if(*rpnt != '.' && *lpnt == '.') return 1;
|
||||
#endif
|
||||
|
||||
if(*rpnt < *lpnt) return -1;
|
||||
if(*rpnt > *lpnt) return 1;
|
||||
rpnt++; lpnt++;
|
||||
}
|
||||
if(*rpnt) return 1;
|
||||
if(*lpnt) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function: sort_directory
|
||||
*
|
||||
* Purpose: Sort the directory in the appropriate ISO9660
|
||||
* order.
|
||||
*
|
||||
* Notes: Returns 0 if OK, returns > 0 if an error occurred.
|
||||
*/
|
||||
static int FDECL1(joliet_sort_directory, struct directory_entry **, sort_dir)
|
||||
{
|
||||
int dcount = 0;
|
||||
int i, len;
|
||||
struct directory_entry * s_entry;
|
||||
struct directory_entry ** sortlist;
|
||||
|
||||
s_entry = *sort_dir;
|
||||
while(s_entry)
|
||||
{
|
||||
dcount++;
|
||||
s_entry = s_entry->next;
|
||||
}
|
||||
|
||||
/*
|
||||
* OK, now we know how many there are. Build a vector for sorting.
|
||||
*/
|
||||
sortlist = (struct directory_entry **)
|
||||
e_malloc(sizeof(struct directory_entry *) * dcount);
|
||||
|
||||
dcount = 0;
|
||||
s_entry = *sort_dir;
|
||||
while(s_entry)
|
||||
{
|
||||
sortlist[dcount] = s_entry;
|
||||
dcount++;
|
||||
s_entry = s_entry->next;
|
||||
}
|
||||
|
||||
sort_goof = 0;
|
||||
qsort(sortlist, dcount, sizeof(struct directory_entry *),
|
||||
(int (*)(const void *, const void *))joliet_compare_dirs);
|
||||
|
||||
/*
|
||||
* Now reassemble the linked list in the proper sorted order
|
||||
*/
|
||||
for(i=0; i<dcount-1; i++)
|
||||
{
|
||||
sortlist[i]->jnext = sortlist[i+1];
|
||||
}
|
||||
|
||||
sortlist[dcount-1]->jnext = NULL;
|
||||
*sort_dir = sortlist[0];
|
||||
|
||||
free(sortlist);
|
||||
return sort_goof;
|
||||
}
|
||||
|
||||
int FDECL1(joliet_sort_tree, struct directory *, node)
|
||||
{
|
||||
struct directory * dpnt;
|
||||
int goof = 0;
|
||||
|
||||
dpnt = node;
|
||||
|
||||
while (dpnt){
|
||||
goof = joliet_sort_n_finish(dpnt);
|
||||
if( goof )
|
||||
{
|
||||
break;
|
||||
}
|
||||
if(dpnt->subdir) goof = joliet_sort_tree(dpnt->subdir);
|
||||
if( goof )
|
||||
{
|
||||
break;
|
||||
}
|
||||
dpnt = dpnt->next;
|
||||
}
|
||||
return goof;
|
||||
}
|
||||
|
||||
static void FDECL2(generate_joliet_directories, struct directory *, node, FILE*, outfile){
|
||||
struct directory * dpnt;
|
||||
|
||||
dpnt = node;
|
||||
|
||||
while (dpnt)
|
||||
{
|
||||
if( (dpnt->dir_flags & INHIBIT_JOLIET_ENTRY) == 0 )
|
||||
{
|
||||
/*
|
||||
* In theory we should never reuse a directory, so this doesn't
|
||||
* make much sense.
|
||||
*/
|
||||
if( dpnt->extent > session_start )
|
||||
{
|
||||
generate_one_joliet_directory(dpnt, outfile);
|
||||
}
|
||||
}
|
||||
if(dpnt->subdir) generate_joliet_directories(dpnt->subdir, outfile);
|
||||
dpnt = dpnt->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function to write the EVD for the disc.
|
||||
*/
|
||||
static int FDECL1(jpathtab_write, FILE *, outfile)
|
||||
{
|
||||
/*
|
||||
* Next we write the path tables
|
||||
*/
|
||||
xfwrite(jpath_table_l, 1, jpath_blocks << 11, outfile);
|
||||
xfwrite(jpath_table_m, 1, jpath_blocks << 11, outfile);
|
||||
last_extent_written += 2*jpath_blocks;
|
||||
free(jpath_table_l);
|
||||
free(jpath_table_m);
|
||||
jpath_table_l = NULL;
|
||||
jpath_table_m = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int FDECL1(jdirtree_size, int, starting_extent)
|
||||
{
|
||||
assign_joliet_directory_addresses(root);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int jroot_gen()
|
||||
{
|
||||
jroot_record.length[0] = 1 + sizeof(struct iso_directory_record)
|
||||
- sizeof(jroot_record.name);
|
||||
jroot_record.ext_attr_length[0] = 0;
|
||||
set_733((char *) jroot_record.extent, root->jextent);
|
||||
set_733((char *) jroot_record.size, ROUND_UP(root->jsize));
|
||||
iso9660_date(jroot_record.date, root_statbuf.st_mtime);
|
||||
jroot_record.flags[0] = 2;
|
||||
jroot_record.file_unit_size[0] = 0;
|
||||
jroot_record.interleave[0] = 0;
|
||||
set_723(jroot_record.volume_sequence_number, DEF_VSN);
|
||||
jroot_record.name_len[0] = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int FDECL1(jdirtree_write, FILE *, outfile)
|
||||
{
|
||||
generate_joliet_directories(root, outfile);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function to write the EVD for the disc.
|
||||
*/
|
||||
static int FDECL1(jvd_write, FILE *, outfile)
|
||||
{
|
||||
struct iso_primary_descriptor jvol_desc;
|
||||
|
||||
/*
|
||||
* Next we write out the boot volume descriptor for the disc
|
||||
*/
|
||||
jvol_desc = vol_desc;
|
||||
get_joliet_vol_desc(&jvol_desc);
|
||||
xfwrite(&jvol_desc, 1, 2048, outfile);
|
||||
last_extent_written ++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Functions to describe padding block at the start of the disc.
|
||||
*/
|
||||
static int FDECL1(jpathtab_size, int, starting_extent)
|
||||
{
|
||||
jpath_table[0] = starting_extent;
|
||||
jpath_table[1] = 0;
|
||||
jpath_table[2] = jpath_table[0] + jpath_blocks;
|
||||
jpath_table[3] = 0;
|
||||
|
||||
last_extent += 2*jpath_blocks;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct output_fragment joliet_desc = {NULL, oneblock_size, jroot_gen,jvd_write};
|
||||
struct output_fragment jpathtable_desc= {NULL, jpathtab_size, generate_joliet_path_tables, jpathtab_write};
|
||||
struct output_fragment jdirtree_desc = {NULL, jdirtree_size, NULL, jdirtree_write};
|
|
@ -20,16 +20,16 @@
|
|||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
static char rcsid[] ="$Id: mkisofs.c,v 1.10.1.3 1998/06/02 03:36:16 eric Exp $";
|
||||
|
||||
/* ADD_FILES changes made by Ross Biro biro@yggdrasil.com 2/23/95 */
|
||||
static char rcsid[] ="$Id: mkisofs.c,v 1.29 1998/06/02 03:43:45 eric Exp $";
|
||||
|
||||
#include <errno.h>
|
||||
#include "mkisofs.h"
|
||||
#include "config.h"
|
||||
#include "mkisofs.h"
|
||||
|
||||
#ifdef linux
|
||||
#include <getopt.h>
|
||||
#else
|
||||
#include "getopt.h"
|
||||
#endif
|
||||
|
||||
#include "iso9660.h"
|
||||
|
@ -60,7 +60,7 @@ static char rcsid[] ="$Id: mkisofs.c,v 1.10.1.3 1998/06/02 03:36:16 eric Exp $";
|
|||
|
||||
struct directory * root = NULL;
|
||||
|
||||
static char version_string[] = "mkisofs v1.11.3";
|
||||
static char version_string[] = "mkisofs 1.12b4";
|
||||
|
||||
FILE * discimage;
|
||||
unsigned int next_extent = 0;
|
||||
|
@ -69,19 +69,30 @@ unsigned int session_start = 0;
|
|||
unsigned int path_table_size = 0;
|
||||
unsigned int path_table[4] = {0,};
|
||||
unsigned int path_blocks = 0;
|
||||
|
||||
|
||||
unsigned int jpath_table_size = 0;
|
||||
unsigned int jpath_table[4] = {0,};
|
||||
unsigned int jpath_blocks = 0;
|
||||
|
||||
struct iso_directory_record root_record;
|
||||
struct iso_directory_record jroot_record;
|
||||
|
||||
char * extension_record = NULL;
|
||||
int extension_record_extent = 0;
|
||||
static int extension_record_size = 0;
|
||||
int extension_record_size = 0;
|
||||
|
||||
/* These variables are associated with command line options */
|
||||
int use_eltorito = 0;
|
||||
int use_RockRidge = 0;
|
||||
int verbose = 0;
|
||||
int use_Joliet = 0;
|
||||
int verbose = 1;
|
||||
int all_files = 0;
|
||||
int follow_links = 0;
|
||||
int rationalize = 0;
|
||||
int generate_tables = 0;
|
||||
int print_size = 0;
|
||||
int split_output = 0;
|
||||
char * preparer = PREPARER_DEFAULT;
|
||||
char * publisher = PUBLISHER_DEFAULT;
|
||||
char * appid = APPID_DEFAULT;
|
||||
|
@ -101,6 +112,8 @@ int RR_relocation_depth = 6; /* Violates iso9660, but most systems work */
|
|||
int full_iso9660_filenames = 0; /* Used with Amiga. Disc will not work with
|
||||
DOS */
|
||||
int allow_leading_dots = 0; /* DOS cannot read names with leading dots */
|
||||
int split_SL_component = 1; /* circumvent a bug in the SunOS driver */
|
||||
int split_SL_field = 1; /* circumvent a bug in the SunOS */
|
||||
|
||||
struct rcopts{
|
||||
char * tag;
|
||||
|
@ -120,6 +133,110 @@ struct rcopts rcopt[] = {
|
|||
{NULL, NULL}
|
||||
};
|
||||
|
||||
/*
|
||||
* In case it isn't obvious, the option handling code was ripped off from GNU-ld.
|
||||
*/
|
||||
struct ld_option
|
||||
{
|
||||
/* The long option information. */
|
||||
struct option opt;
|
||||
/* The short option with the same meaning ('\0' if none). */
|
||||
char shortopt;
|
||||
/* The name of the argument (NULL if none). */
|
||||
const char *arg;
|
||||
/* The documentation string. If this is NULL, this is a synonym for
|
||||
the previous option. */
|
||||
const char *doc;
|
||||
enum
|
||||
{
|
||||
/* Use one dash before long option name. */
|
||||
ONE_DASH,
|
||||
/* Use two dashes before long option name. */
|
||||
TWO_DASHES,
|
||||
/* Don't mention this option in --help output. */
|
||||
NO_HELP
|
||||
} control;
|
||||
};
|
||||
|
||||
/* Codes used for the long options with no short synonyms. 150 isn't
|
||||
special; it's just an arbitrary non-ASCII char value. */
|
||||
#define OPTION_HELP 150
|
||||
#define OPTION_QUIET 151
|
||||
#define OPTION_NOSPLIT_SL_COMPONENT 152
|
||||
#define OPTION_NOSPLIT_SL_FIELD 153
|
||||
#define OPTION_PRINT_SIZE 154
|
||||
#define OPTION_SPLIT_OUTPUT 155
|
||||
|
||||
static const struct ld_option ld_options[] =
|
||||
{
|
||||
{ {"all-files", no_argument, NULL, 'a'},
|
||||
'a', NULL, "Process all files (don't skip backup files)", ONE_DASH },
|
||||
{ {"appid", required_argument, NULL, 'A'},
|
||||
'A', "ID", "Set Application ID" , ONE_DASH },
|
||||
{ {"eltorito-boot", required_argument, NULL, 'b'},
|
||||
'b', "FILE", "Set El Torito boot image name" , ONE_DASH },
|
||||
{ {"eltorito-catalog", required_argument, NULL, 'c'},
|
||||
'c', "FILE", "Set El Torito boot catalog name" , ONE_DASH },
|
||||
{ {"cdwrite-params", required_argument, NULL, 'C'},
|
||||
'C', "PARAMS", "Magic paramters from cdwrite" , ONE_DASH },
|
||||
{ {"omit-period", no_argument, NULL, 'd'},
|
||||
'd', NULL, "Omit trailing periods from filenames", ONE_DASH },
|
||||
{ {"disable-deep-relocation", no_argument, NULL, 'D'},
|
||||
'D', NULL, "Disable deep directory relocation", ONE_DASH },
|
||||
{ {"follow-links", no_argument, NULL, 'f'},
|
||||
'f', NULL, "Follow symbolic links", ONE_DASH },
|
||||
{ {"help", no_argument, NULL, OPTION_HELP},
|
||||
'\0', NULL, "Print option help", ONE_DASH },
|
||||
{ {NULL, required_argument, NULL, 'i'},
|
||||
'i', "ADD_FILES", "No longer supported" , TWO_DASHES },
|
||||
{ {"joliet", no_argument, NULL, 'J'},
|
||||
'J', NULL, "Generate Joliet directory information", ONE_DASH },
|
||||
{ {"full-iso9660-filenames", no_argument, NULL, 'l'},
|
||||
'l', NULL, "Allow full 32 character filenames for iso9660 names", ONE_DASH },
|
||||
{ {"allow-leading-dots", no_argument, NULL, 'L'},
|
||||
'L', NULL, "Allow iso9660 filenames to start with '.'", ONE_DASH },
|
||||
{ {"exclude", required_argument, NULL, 'm'},
|
||||
'm', "GLOBFILE", "Exclude file name" , ONE_DASH },
|
||||
{ {"prev-session", required_argument, NULL, 'M'},
|
||||
'M', "FILE", "Set path to previous session to merge" , ONE_DASH },
|
||||
{ {"omit-version-number", no_argument, NULL, 'N'},
|
||||
'N', NULL, "Omit version number from iso9660 filename", ONE_DASH },
|
||||
{ {"no-split-symlink-components", no_argument, NULL, 0},
|
||||
0, NULL, "Inhibit splitting symlink components" , ONE_DASH },
|
||||
{ {"no-split-symlink-fields", no_argument, NULL, 0},
|
||||
0, NULL, "Inhibit splitting symlink fields" , ONE_DASH },
|
||||
{ {"output", required_argument, NULL, 'o'},
|
||||
'o', "FILE", "Set output file name" , ONE_DASH },
|
||||
{ {"preparer", required_argument, NULL, 'p'},
|
||||
'p', "PREP", "Set Volume preparer" , ONE_DASH },
|
||||
{ {"print-size", no_argument, NULL, OPTION_PRINT_SIZE},
|
||||
'\0', NULL, "Print estimated filesystem size and exit", ONE_DASH },
|
||||
{ {"publisher", required_argument, NULL, 'P'},
|
||||
'P', "PUB", "Set Volume publisher" , ONE_DASH },
|
||||
{ {"quiet", no_argument, NULL, OPTION_QUIET},
|
||||
'\0', NULL, "Run quietly", ONE_DASH },
|
||||
{ {"rational-rock", no_argument, NULL, 'r'},
|
||||
'r', NULL, "Generate rationalized Rock Ridge directory information", ONE_DASH },
|
||||
{ {"rock", no_argument, NULL, 'R'},
|
||||
'R', NULL, "Generate Rock Ridge directory information", ONE_DASH },
|
||||
{ {"split-output", no_argument, NULL, OPTION_SPLIT_OUTPUT},
|
||||
'\0', NULL, "Split output into files of approx. 1GB size", ONE_DASH },
|
||||
{ {"translation-table", no_argument, NULL, 'T'},
|
||||
'T', NULL, "Generate translation tables for systems that don't understand long filenames", ONE_DASH },
|
||||
{ {"verbose", no_argument, NULL, 'v'},
|
||||
'v', NULL, "Verbose", ONE_DASH },
|
||||
{ {"volid", required_argument, NULL, 'V'},
|
||||
'V', "ID", "Set Volume ID" , ONE_DASH },
|
||||
{ {"old-exclude", required_argument, NULL, 'x'},
|
||||
'x', "FILE", "Exclude file name(depreciated)" , ONE_DASH }
|
||||
#ifdef ERIC_neverdef
|
||||
{ {"transparent-compression", no_argument, NULL, 'z'},
|
||||
'z', NULL, "Enable transparent compression of files", ONE_DASH },
|
||||
#endif
|
||||
};
|
||||
|
||||
#define OPTION_COUNT (sizeof ld_options / sizeof ld_options[0])
|
||||
|
||||
#if defined(ultrix) || defined(_AUX_SOURCE)
|
||||
char *strdup(s)
|
||||
char *s;{char *c;if(c=(char *)malloc(strlen(s)+1))strcpy(c,s);return c;}
|
||||
|
@ -179,7 +296,11 @@ void FDECL1(read_rcfile, char *, appname)
|
|||
}
|
||||
if (!rcfile)
|
||||
return;
|
||||
fprintf(stderr, "Using \"%s\"\n", filename);
|
||||
if ( verbose > 0 )
|
||||
{
|
||||
fprintf(stderr, "Using \"%s\"\n", filename);
|
||||
}
|
||||
|
||||
/* OK, we got it. Now read in the lines and parse them */
|
||||
linum = 0;
|
||||
while (fgets(linebuffer, sizeof(linebuffer), rcfile))
|
||||
|
@ -260,20 +381,113 @@ void FDECL1(read_rcfile, char *, appname)
|
|||
|
||||
char * path_table_l = NULL;
|
||||
char * path_table_m = NULL;
|
||||
|
||||
char * jpath_table_l = NULL;
|
||||
char * jpath_table_m = NULL;
|
||||
|
||||
int goof = 0;
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
void usage(){
|
||||
const char * program_name = "mkisofs";
|
||||
#if 0
|
||||
fprintf(stderr,"Usage:\n");
|
||||
fprintf(stderr,
|
||||
"mkisofs [-o outfile] [-R] [-V volid] [-v] [-a] \
|
||||
[-T]\n [-l] [-d] [-V] [-D] [-L] [-p preparer]"
|
||||
#ifdef ADD_FILES
|
||||
"[-i file] \n"
|
||||
#endif
|
||||
"[-P publisher] [ -A app_id ] [-z] \n \
|
||||
[-b boot_image_name] [-c boot_catalog-name] \
|
||||
[-x path -x path ...] path\n");
|
||||
exit(1);
|
||||
#endif
|
||||
|
||||
int i;
|
||||
const char **targets, **pp;
|
||||
|
||||
fprintf (stderr, "Usage: %s [options] file...\n", program_name);
|
||||
|
||||
fprintf (stderr, "Options:\n");
|
||||
for (i = 0; i < OPTION_COUNT; i++)
|
||||
{
|
||||
if (ld_options[i].doc != NULL)
|
||||
{
|
||||
int comma;
|
||||
int len;
|
||||
int j;
|
||||
|
||||
fprintf (stderr, " ");
|
||||
|
||||
comma = FALSE;
|
||||
len = 2;
|
||||
|
||||
j = i;
|
||||
do
|
||||
{
|
||||
if (ld_options[j].shortopt != '\0'
|
||||
&& ld_options[j].control != NO_HELP)
|
||||
{
|
||||
fprintf (stderr, "%s-%c", comma ? ", " : "", ld_options[j].shortopt);
|
||||
len += (comma ? 2 : 0) + 2;
|
||||
if (ld_options[j].arg != NULL)
|
||||
{
|
||||
if (ld_options[j].opt.has_arg != optional_argument)
|
||||
{
|
||||
fprintf (stderr, " ");
|
||||
++len;
|
||||
}
|
||||
fprintf (stderr, "%s", ld_options[j].arg);
|
||||
len += strlen (ld_options[j].arg);
|
||||
}
|
||||
comma = TRUE;
|
||||
}
|
||||
++j;
|
||||
}
|
||||
while (j < OPTION_COUNT && ld_options[j].doc == NULL);
|
||||
|
||||
j = i;
|
||||
do
|
||||
{
|
||||
if (ld_options[j].opt.name != NULL
|
||||
&& ld_options[j].control != NO_HELP)
|
||||
{
|
||||
fprintf (stderr, "%s-%s%s",
|
||||
comma ? ", " : "",
|
||||
ld_options[j].control == TWO_DASHES ? "-" : "",
|
||||
ld_options[j].opt.name);
|
||||
len += ((comma ? 2 : 0)
|
||||
+ 1
|
||||
+ (ld_options[j].control == TWO_DASHES ? 1 : 0)
|
||||
+ strlen (ld_options[j].opt.name));
|
||||
if (ld_options[j].arg != NULL)
|
||||
{
|
||||
fprintf (stderr, " %s", ld_options[j].arg);
|
||||
len += 1 + strlen (ld_options[j].arg);
|
||||
}
|
||||
comma = TRUE;
|
||||
}
|
||||
++j;
|
||||
}
|
||||
while (j < OPTION_COUNT && ld_options[j].doc == NULL);
|
||||
|
||||
if (len >= 30)
|
||||
{
|
||||
fprintf (stderr, "\n");
|
||||
len = 0;
|
||||
}
|
||||
|
||||
for (; len < 30; len++)
|
||||
fputc (' ', stderr);
|
||||
|
||||
fprintf (stderr, "%s\n", ld_options[i].doc);
|
||||
}
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
|
@ -326,15 +540,18 @@ extern char * cdwrite_data;
|
|||
int FDECL2(main, int, argc, char **, argv){
|
||||
char * outfile;
|
||||
struct directory_entry de;
|
||||
#ifdef HAVE_SBRK
|
||||
unsigned long mem_start;
|
||||
#endif
|
||||
struct stat statbuf;
|
||||
char * scan_tree;
|
||||
char * merge_image = NULL;
|
||||
struct iso_directory_record * mrootp = NULL;
|
||||
struct output_fragment * opnt;
|
||||
int longind;
|
||||
char shortopts[OPTION_COUNT * 3 + 2];
|
||||
struct option longopts[OPTION_COUNT + 1];
|
||||
int c;
|
||||
#ifdef ADD_FILES
|
||||
char *add_file_file = NULL;
|
||||
#endif
|
||||
|
||||
if (argc < 2)
|
||||
usage();
|
||||
|
@ -343,9 +560,56 @@ int FDECL2(main, int, argc, char **, argv){
|
|||
read_rcfile(argv[0]);
|
||||
|
||||
outfile = NULL;
|
||||
while ((c = getopt(argc, argv, "i:o:V:RrfvaTp:P:b:c:x:dDlLNzA:M:m:C:")) != EOF)
|
||||
|
||||
/*
|
||||
* Copy long option initialization from GNU-ld.
|
||||
*/
|
||||
/* Starting the short option string with '-' is for programs that
|
||||
expect options and other ARGV-elements in any order and that care about
|
||||
the ordering of the two. We describe each non-option ARGV-element
|
||||
as if it were the argument of an option with character code 1. */
|
||||
{
|
||||
int i, is, il;
|
||||
shortopts[0] = '-';
|
||||
is = 1;
|
||||
il = 0;
|
||||
for (i = 0; i < OPTION_COUNT; i++)
|
||||
{
|
||||
if (ld_options[i].shortopt != '\0')
|
||||
{
|
||||
shortopts[is] = ld_options[i].shortopt;
|
||||
++is;
|
||||
if (ld_options[i].opt.has_arg == required_argument
|
||||
|| ld_options[i].opt.has_arg == optional_argument)
|
||||
{
|
||||
shortopts[is] = ':';
|
||||
++is;
|
||||
if (ld_options[i].opt.has_arg == optional_argument)
|
||||
{
|
||||
shortopts[is] = ':';
|
||||
++is;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ld_options[i].opt.name != NULL)
|
||||
{
|
||||
longopts[il] = ld_options[i].opt;
|
||||
++il;
|
||||
}
|
||||
}
|
||||
shortopts[is] = '\0';
|
||||
longopts[il].name = NULL;
|
||||
}
|
||||
|
||||
while ((c = getopt_long_only (argc, argv, shortopts, longopts, &longind)) != EOF)
|
||||
switch (c)
|
||||
{
|
||||
case 1:
|
||||
/*
|
||||
* A filename that we take as input.
|
||||
*/
|
||||
optind--;
|
||||
goto parse_input_files;
|
||||
case 'C':
|
||||
/*
|
||||
* This is a temporary hack until cdwrite gets the proper hooks in
|
||||
|
@ -353,6 +617,13 @@ int FDECL2(main, int, argc, char **, argv){
|
|||
*/
|
||||
cdwrite_data = optarg;
|
||||
break;
|
||||
case 'i':
|
||||
fprintf(stderr, "-i option no longer supported.\n");
|
||||
exit(1);
|
||||
break;
|
||||
case 'J':
|
||||
use_Joliet++;
|
||||
break;
|
||||
case 'a':
|
||||
all_files++;
|
||||
break;
|
||||
|
@ -388,14 +659,6 @@ int FDECL2(main, int, argc, char **, argv){
|
|||
case 'f':
|
||||
follow_links++;
|
||||
break;
|
||||
case 'i':
|
||||
#ifdef ADD_FILES
|
||||
add_file_file = optarg;
|
||||
break;
|
||||
#else
|
||||
usage();
|
||||
exit(1);
|
||||
#endif
|
||||
case 'l':
|
||||
full_iso9660_filenames++;
|
||||
break;
|
||||
|
@ -418,6 +681,9 @@ int FDECL2(main, int, argc, char **, argv){
|
|||
exit(1);
|
||||
};
|
||||
break;
|
||||
case OPTION_PRINT_SIZE:
|
||||
print_size++;
|
||||
break;
|
||||
case 'P':
|
||||
publisher = optarg;
|
||||
if(strlen(publisher) > 128) {
|
||||
|
@ -425,6 +691,9 @@ int FDECL2(main, int, argc, char **, argv){
|
|||
exit(1);
|
||||
};
|
||||
break;
|
||||
case OPTION_QUIET:
|
||||
verbose = 0;
|
||||
break;
|
||||
case 'R':
|
||||
use_RockRidge++;
|
||||
break;
|
||||
|
@ -432,6 +701,9 @@ int FDECL2(main, int, argc, char **, argv){
|
|||
rationalize++;
|
||||
use_RockRidge++;
|
||||
break;
|
||||
case OPTION_SPLIT_OUTPUT:
|
||||
split_output++;
|
||||
break;
|
||||
case 'T':
|
||||
generate_tables++;
|
||||
break;
|
||||
|
@ -449,16 +721,32 @@ int FDECL2(main, int, argc, char **, argv){
|
|||
transparent_compression++;
|
||||
#endif
|
||||
break;
|
||||
case 'x':
|
||||
case 'm':
|
||||
/*
|
||||
* Somehow two options to do basically the same thing got added somewhere along
|
||||
* the way. The 'match' code supports limited globbing, so this is the one
|
||||
* that got selected. Unfortunately the 'x' switch is probably more intuitive.
|
||||
*/
|
||||
add_match(optarg);
|
||||
break;
|
||||
case 'x':
|
||||
exclude(optarg);
|
||||
case OPTION_HELP:
|
||||
usage ();
|
||||
exit (0);
|
||||
break;
|
||||
case OPTION_NOSPLIT_SL_COMPONENT:
|
||||
split_SL_component = 0;
|
||||
break;
|
||||
case OPTION_NOSPLIT_SL_FIELD:
|
||||
split_SL_field = 0;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
parse_input_files:
|
||||
|
||||
#ifdef __NetBSD__
|
||||
{
|
||||
int resource;
|
||||
|
@ -476,7 +764,7 @@ int FDECL2(main, int, argc, char **, argv){
|
|||
mem_start = (unsigned long) sbrk(0);
|
||||
#endif
|
||||
|
||||
if(verbose) fprintf(stderr,"%s\n", version_string);
|
||||
if(verbose > 1) fprintf(stderr,"%s\n", version_string);
|
||||
|
||||
if( (cdwrite_data != NULL && merge_image == NULL)
|
||||
|| (cdwrite_data == NULL && merge_image != NULL) )
|
||||
|
@ -489,12 +777,6 @@ int FDECL2(main, int, argc, char **, argv){
|
|||
|
||||
scan_tree = argv[optind];
|
||||
|
||||
#ifdef ADD_FILES
|
||||
if (add_file_file) {
|
||||
add_file(add_file_file);
|
||||
}
|
||||
add_file_list (argc, argv, optind+1);
|
||||
#endif
|
||||
|
||||
if(!scan_tree){
|
||||
usage();
|
||||
|
@ -557,28 +839,186 @@ int FDECL2(main, int, argc, char **, argv){
|
|||
}
|
||||
|
||||
/*
|
||||
* Scan the actual directory (and any we find below it)
|
||||
* for files to write out to the output image.
|
||||
* Create an empty root directory. If we ever scan it for real, we will fill in the
|
||||
* contents.
|
||||
*/
|
||||
if (!scan_directory_tree(argv[optind], &de, mrootp))
|
||||
find_or_create_directory(NULL, "", &de, TRUE);
|
||||
|
||||
/*
|
||||
* Scan the actual directory (and any we find below it)
|
||||
* for files to write out to the output image. Note - we
|
||||
* take multiple source directories and keep merging them
|
||||
* onto the image.
|
||||
*/
|
||||
while(optind < argc)
|
||||
{
|
||||
exit(1);
|
||||
char * node;
|
||||
struct directory * graft_dir;
|
||||
struct stat st;
|
||||
char * short_name;
|
||||
int status;
|
||||
char graft_point[1024];
|
||||
|
||||
/*
|
||||
* We would like a syntax like:
|
||||
*
|
||||
* /tmp=/usr/tmp/xxx
|
||||
*
|
||||
* where the user can specify a place to graft each
|
||||
* component of the tree. To do this, we may have to create
|
||||
* directories along the way, of course.
|
||||
* Secondly, I would like to allow the user to do something
|
||||
* like:
|
||||
*
|
||||
* /home/baz/RMAIL=/u3/users/baz/RMAIL
|
||||
*
|
||||
* so that normal files could also be injected into the tree
|
||||
* at an arbitrary point.
|
||||
*
|
||||
* The idea is that the last component of whatever is being
|
||||
* entered would take the name from the last component of
|
||||
* whatever the user specifies.
|
||||
*
|
||||
* The default will be that the file is injected at the
|
||||
* root of the image tree.
|
||||
*/
|
||||
node = strchr(argv[optind], '=');
|
||||
short_name = NULL;
|
||||
|
||||
if( node != NULL )
|
||||
{
|
||||
char * pnt;
|
||||
char * xpnt;
|
||||
|
||||
*node = '\0';
|
||||
strcpy(graft_point, argv[optind]);
|
||||
*node = '=';
|
||||
node++;
|
||||
|
||||
graft_dir = root;
|
||||
xpnt = graft_point;
|
||||
if( *xpnt == PATH_SEPARATOR )
|
||||
{
|
||||
xpnt++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Loop down deeper and deeper until we
|
||||
* find the correct insertion spot.
|
||||
*/
|
||||
while(1==1)
|
||||
{
|
||||
pnt = strchr(xpnt, PATH_SEPARATOR);
|
||||
if( pnt == NULL )
|
||||
{
|
||||
if( *xpnt != '\0' )
|
||||
{
|
||||
short_name = xpnt;
|
||||
}
|
||||
break;
|
||||
}
|
||||
*pnt = '\0';
|
||||
graft_dir = find_or_create_directory(graft_dir,
|
||||
graft_point,
|
||||
NULL, TRUE);
|
||||
*pnt = PATH_SEPARATOR;
|
||||
xpnt = pnt + 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
graft_dir = root;
|
||||
node = argv[optind];
|
||||
}
|
||||
|
||||
/*
|
||||
* Now see whether the user wants to add a regular file,
|
||||
* or a directory at this point.
|
||||
*/
|
||||
status = stat_filter(node, &st);
|
||||
if( status != 0 )
|
||||
{
|
||||
/*
|
||||
* This is a fatal error - the user won't be getting what
|
||||
* they want if we were to proceed.
|
||||
*/
|
||||
fprintf(stderr, "Invalid node - %s\n", node);
|
||||
exit(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if( S_ISDIR(st.st_mode) )
|
||||
{
|
||||
if (!scan_directory_tree(graft_dir, node, &de))
|
||||
{
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( short_name == NULL )
|
||||
{
|
||||
short_name = strrchr(node, PATH_SEPARATOR);
|
||||
if( short_name == NULL || short_name < node )
|
||||
{
|
||||
short_name = node;
|
||||
}
|
||||
else
|
||||
{
|
||||
short_name++;
|
||||
}
|
||||
}
|
||||
if( !insert_file_entry(graft_dir, node, short_name) )
|
||||
{
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
optind++;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Now merge in any previous sessions. This is driven on the source
|
||||
* side, since we may need to create some additional directories.
|
||||
*/
|
||||
if( merge_image != NULL )
|
||||
{
|
||||
merge_previous_session(root, mrootp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fix a couple of things in the root directory so that everything
|
||||
* is self consistent.
|
||||
* Sort the directories in the required order (by ISO9660). Also,
|
||||
* choose the names for the 8.3 filesystem if required, and do
|
||||
* any other post-scan work.
|
||||
*/
|
||||
root->self = root->contents; /* Fix this up so that the path tables get done right */
|
||||
goof += sort_tree(root);
|
||||
|
||||
if(reloc_dir) sort_n_finish(reloc_dir);
|
||||
if( use_Joliet )
|
||||
{
|
||||
goof += joliet_sort_tree(root);
|
||||
}
|
||||
|
||||
if (goof) exit(1);
|
||||
|
||||
/*
|
||||
* Fix a couple of things in the root directory so that everything
|
||||
* is self consistent.
|
||||
*/
|
||||
root->self = root->contents; /* Fix this up so that the path
|
||||
tables get done right */
|
||||
|
||||
/*
|
||||
* OK, ready to write the file. Open it up, and generate the thing.
|
||||
*/
|
||||
if (outfile){
|
||||
if (print_size){
|
||||
discimage = fopen("/dev/null", "w");
|
||||
if (!discimage){
|
||||
fprintf(stderr,"Unable to open /dev/null\n");
|
||||
exit(1);
|
||||
}
|
||||
} else if (outfile){
|
||||
discimage = fopen(outfile, "w");
|
||||
if (!discimage){
|
||||
fprintf(stderr,"Unable to open disc image file\n");
|
||||
|
@ -593,54 +1033,120 @@ int FDECL2(main, int, argc, char **, argv){
|
|||
path_blocks = (path_table_size + (SECTOR_SIZE - 1)) >> 11;
|
||||
if (path_blocks & 1) path_blocks++;
|
||||
|
||||
path_table[0] = session_start + 0x10 + 2 + (use_eltorito ? 1 : 0);
|
||||
path_table[1] = 0;
|
||||
path_table[2] = path_table[0] + path_blocks;
|
||||
path_table[3] = 0;
|
||||
jpath_blocks = (jpath_table_size + (SECTOR_SIZE - 1)) >> 11;
|
||||
if (jpath_blocks & 1) jpath_blocks++;
|
||||
|
||||
last_extent += path_table[2] - session_start + path_blocks;
|
||||
/* The next free block */
|
||||
/*
|
||||
* Start to set up the linked list that we use to track the
|
||||
* contents of the disc.
|
||||
*/
|
||||
outputlist_insert(&padblock_desc);
|
||||
|
||||
/* The next step is to go through the directory tree and assign extent
|
||||
numbers for all of the directories */
|
||||
/*
|
||||
* PVD for disc.
|
||||
*/
|
||||
outputlist_insert(&voldesc_desc);
|
||||
|
||||
assign_directory_addresses(root);
|
||||
/*
|
||||
* SVD for El Torito. MUST be immediately after the PVD!
|
||||
*/
|
||||
if( use_eltorito)
|
||||
{
|
||||
outputlist_insert(&torito_desc);
|
||||
}
|
||||
|
||||
if(extension_record) {
|
||||
struct directory_entry * s_entry;
|
||||
extension_record_extent = last_extent++;
|
||||
s_entry = root->contents;
|
||||
set_733((char *) s_entry->rr_attributes + s_entry->rr_attr_size - 24,
|
||||
extension_record_extent);
|
||||
set_733((char *) s_entry->rr_attributes + s_entry->rr_attr_size - 8,
|
||||
extension_record_size);
|
||||
};
|
||||
/*
|
||||
* SVD for Joliet.
|
||||
*/
|
||||
if( use_Joliet)
|
||||
{
|
||||
outputlist_insert(&joliet_desc);
|
||||
}
|
||||
|
||||
if (use_RockRidge && reloc_dir)
|
||||
finish_cl_pl_entries();
|
||||
/*
|
||||
* Finally the last volume desctiptor.
|
||||
*/
|
||||
outputlist_insert(&end_vol);
|
||||
|
||||
/* Now we generate the path tables that are used by DOS to improve directory
|
||||
access times. */
|
||||
generate_path_tables();
|
||||
|
||||
/* Generate root record for volume descriptor. */
|
||||
generate_root_record();
|
||||
outputlist_insert(&pathtable_desc);
|
||||
if( use_Joliet)
|
||||
{
|
||||
outputlist_insert(&jpathtable_desc);
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
dump_tree(root);
|
||||
outputlist_insert(&dirtree_desc);
|
||||
if( use_Joliet)
|
||||
{
|
||||
outputlist_insert(&jdirtree_desc);
|
||||
}
|
||||
|
||||
outputlist_insert(&dirtree_clean);
|
||||
|
||||
if(extension_record)
|
||||
{
|
||||
outputlist_insert(&extension_desc);
|
||||
}
|
||||
|
||||
outputlist_insert(&files_desc);
|
||||
|
||||
/*
|
||||
* Allow room for the various headers we will be writing. There
|
||||
* will always be a primary and an end volume descriptor.
|
||||
*/
|
||||
last_extent = session_start;
|
||||
|
||||
/*
|
||||
* Calculate the size of all of the components of the disc, and assign
|
||||
* extent numbers.
|
||||
*/
|
||||
for(opnt = out_list; opnt; opnt = opnt->of_next )
|
||||
{
|
||||
if( opnt->of_size != NULL )
|
||||
{
|
||||
(*opnt->of_size)(last_extent);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate the contents of any of the sections that we want to generate.
|
||||
* Not all of the fragments will do anything here - most will generate the
|
||||
* data on the fly when we get to the write pass.
|
||||
*/
|
||||
for(opnt = out_list; opnt; opnt = opnt->of_next )
|
||||
{
|
||||
if( opnt->of_generate != NULL )
|
||||
{
|
||||
(*opnt->of_generate)();
|
||||
}
|
||||
}
|
||||
|
||||
if( in_image != NULL )
|
||||
{
|
||||
fclose(in_image);
|
||||
}
|
||||
|
||||
iso_write(discimage);
|
||||
/*
|
||||
* Now go through the list of fragments and write the data that corresponds to
|
||||
* each one.
|
||||
*/
|
||||
for(opnt = out_list; opnt; opnt = opnt->of_next )
|
||||
{
|
||||
if( opnt->of_write != NULL )
|
||||
{
|
||||
(*opnt->of_write)(discimage);
|
||||
}
|
||||
}
|
||||
|
||||
if( verbose > 0 )
|
||||
{
|
||||
#ifdef HAVE_SBRK
|
||||
fprintf(stderr,"Max brk space used %x\n",
|
||||
(unsigned int)(((unsigned long)sbrk(0)) - mem_start));
|
||||
fprintf(stderr,"Max brk space used %x\n",
|
||||
(unsigned int)(((unsigned long)sbrk(0)) - mem_start));
|
||||
#endif
|
||||
fprintf(stderr,"%d extents written (%d Mb)\n", last_extent, last_extent >> 9);
|
||||
fprintf(stderr,"%d extents written (%d Mb)\n", last_extent, last_extent >> 9);
|
||||
}
|
||||
|
||||
#ifdef VMS
|
||||
return 1;
|
||||
#else
|
||||
|
|
|
@ -20,11 +20,9 @@
|
|||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
/*
|
||||
* $Id: mkisofs.h,v 1.5 1997/05/17 15:50:28 eric Exp $
|
||||
* $Id: mkisofs.h,v 1.17 1998/06/02 02:40:38 eric Exp $
|
||||
*/
|
||||
|
||||
/* ADD_FILES changes made by Ross Biro biro@yggdrasil.com 2/23/95 */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* This symbol is used to indicate that we do not have things like
|
||||
|
@ -41,16 +39,39 @@
|
|||
#ifdef VMS
|
||||
#include <sys/dir.h>
|
||||
#define dirent direct
|
||||
#else
|
||||
#include <dirent.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define NON_UNIXFS
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef linux
|
||||
#include <sys/dir.h>
|
||||
#if defined(HAVE_DIRENT_H)
|
||||
# include <dirent.h>
|
||||
# define NAMLEN(dirent) strlen((dirent)->d_name)
|
||||
#else
|
||||
# define dirent direct
|
||||
# define NAMLEN(dirent) (dirent)->d_namlen
|
||||
# if defined(HAVE_SYS_NDIR_H)
|
||||
# include <sys/ndir.h>
|
||||
# endif
|
||||
# if defined(HAVE_SYS_DIR_H)
|
||||
# include <sys/dir.h>
|
||||
# endif
|
||||
# if defined(HAVE_NDIR_H)
|
||||
# include <ndir.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_STRING_H)
|
||||
#include <string.h>
|
||||
#else
|
||||
#if defined(HAVE_STRINGS_H)
|
||||
#include <strings.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef ultrix
|
||||
|
@ -100,10 +121,12 @@ extern char *optarg;
|
|||
|
||||
struct directory_entry{
|
||||
struct directory_entry * next;
|
||||
struct directory_entry * jnext;
|
||||
struct iso_directory_record isorec;
|
||||
unsigned int starting_block;
|
||||
unsigned int size;
|
||||
unsigned int priority;
|
||||
unsigned short priority;
|
||||
unsigned char jreclen; /* Joliet record len */
|
||||
char * name;
|
||||
char * table;
|
||||
char * whole_name;
|
||||
|
@ -125,6 +148,52 @@ struct file_hash{
|
|||
unsigned int size;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* This structure is used to control the output of fragments to the cdrom
|
||||
* image. Everything that will be written to the output image will eventually
|
||||
* go through this structure. There are two pieces - first is the sizing where
|
||||
* we establish extent numbers for everything, and the second is when we actually
|
||||
* generate the contents and write it to the output image.
|
||||
*
|
||||
* This makes it trivial to extend mkisofs to write special things in the image.
|
||||
* All you need to do is hook an additional structure in the list, and the rest
|
||||
* works like magic.
|
||||
*
|
||||
* The three passes each do the following:
|
||||
*
|
||||
* The 'size' pass determines the size of each component and assigns the extent number
|
||||
* for that component.
|
||||
*
|
||||
* The 'generate' pass will adjust the contents and pointers as required now that extent
|
||||
* numbers are assigned. In some cases, the contents of the record are also generated.
|
||||
*
|
||||
* The 'write' pass actually writes the data to the disc.
|
||||
*/
|
||||
struct output_fragment
|
||||
{
|
||||
struct output_fragment * of_next;
|
||||
int (*of_size)(int);
|
||||
int (*of_generate)(void);
|
||||
int (*of_write)(FILE *);
|
||||
};
|
||||
|
||||
extern struct output_fragment * out_list;
|
||||
extern struct output_fragment * out_tail;
|
||||
|
||||
extern struct output_fragment padblock_desc;
|
||||
extern struct output_fragment voldesc_desc;
|
||||
extern struct output_fragment joliet_desc;
|
||||
extern struct output_fragment torito_desc;
|
||||
extern struct output_fragment end_vol;
|
||||
extern struct output_fragment pathtable_desc;
|
||||
extern struct output_fragment jpathtable_desc;
|
||||
extern struct output_fragment dirtree_desc;
|
||||
extern struct output_fragment dirtree_clean;
|
||||
extern struct output_fragment jdirtree_desc;
|
||||
extern struct output_fragment extension_desc;
|
||||
extern struct output_fragment files_desc;
|
||||
|
||||
/*
|
||||
* This structure describes one complete directory. It has pointers
|
||||
* to other directories in the overall tree so that it is clear where
|
||||
|
@ -138,6 +207,7 @@ struct directory{
|
|||
struct directory * subdir; /* First subdirectory in this directory */
|
||||
struct directory * parent;
|
||||
struct directory_entry * contents;
|
||||
struct directory_entry * jcontents;
|
||||
struct directory_entry * self;
|
||||
char * whole_name; /* Entire path */
|
||||
char * de_name; /* Entire path */
|
||||
|
@ -145,7 +215,12 @@ struct directory{
|
|||
unsigned int depth;
|
||||
unsigned int size;
|
||||
unsigned int extent;
|
||||
unsigned int jsize;
|
||||
unsigned int jextent;
|
||||
unsigned short path_index;
|
||||
unsigned short jpath_index;
|
||||
unsigned short dir_flags;
|
||||
unsigned short dir_nlink;
|
||||
};
|
||||
|
||||
struct deferred{
|
||||
|
@ -163,57 +238,82 @@ extern unsigned int next_extent;
|
|||
extern unsigned int last_extent;
|
||||
extern unsigned int last_extent_written;
|
||||
extern unsigned int session_start;
|
||||
|
||||
extern unsigned int path_table_size;
|
||||
extern unsigned int path_table[4];
|
||||
extern unsigned int path_blocks;
|
||||
extern char * path_table_l;
|
||||
extern char * path_table_m;
|
||||
|
||||
extern unsigned int jpath_table_size;
|
||||
extern unsigned int jpath_table[4];
|
||||
extern unsigned int jpath_blocks;
|
||||
extern char * jpath_table_l;
|
||||
extern char * jpath_table_m;
|
||||
|
||||
extern struct iso_directory_record root_record;
|
||||
extern struct iso_directory_record jroot_record;
|
||||
|
||||
extern int use_eltorito;
|
||||
extern int use_RockRidge;
|
||||
extern int use_Joliet;
|
||||
extern int rationalize;
|
||||
extern int follow_links;
|
||||
extern int verbose;
|
||||
extern int all_files;
|
||||
extern int generate_tables;
|
||||
extern int print_size;
|
||||
extern int split_output;
|
||||
extern int omit_period;
|
||||
extern int omit_version_number;
|
||||
extern int transparent_compression;
|
||||
extern int RR_relocation_depth;
|
||||
extern int full_iso9660_filenames;
|
||||
extern int split_SL_component;
|
||||
extern int split_SL_field;
|
||||
|
||||
/* tree.c */
|
||||
extern int DECL(stat_filter, (char *, struct stat *));
|
||||
extern void DECL(sort_n_finish,(struct directory *));
|
||||
extern void finish_cl_pl_entries();
|
||||
extern int DECL(scan_directory_tree,(char * path,
|
||||
struct directory_entry * self,
|
||||
struct iso_directory_record *));
|
||||
extern int DECL(lstat_filter, (char *, struct stat *));
|
||||
extern int DECL(sort_tree,(struct directory *));
|
||||
extern struct directory *
|
||||
DECL(find_or_create_directory,(struct directory *, const char *,
|
||||
struct directory_entry * self, int));
|
||||
extern void DECL (finish_cl_pl_entries, (void));
|
||||
extern int DECL(scan_directory_tree,(struct directory * this_dir,
|
||||
char * path,
|
||||
struct directory_entry * self));
|
||||
extern int DECL(insert_file_entry,(struct directory *, char *,
|
||||
char *));
|
||||
|
||||
extern void DECL(generate_iso9660_directories,(struct directory *, FILE*));
|
||||
extern void DECL(dump_tree,(struct directory * node));
|
||||
extern struct directory_entry * DECL(search_tree_file, (struct
|
||||
directory * node,char * filename));
|
||||
extern void DECL(update_nlink_field,(struct directory * node));
|
||||
extern void DECL (init_fstatbuf, (void));
|
||||
extern struct stat root_statbuf;
|
||||
|
||||
/* eltorito.c */
|
||||
extern void DECL(init_boot_catalog, (const char * path ));
|
||||
extern void DECL(get_torito_desc, (struct eltorito_boot_descriptor * path ));
|
||||
|
||||
/* write.c */
|
||||
extern void DECL(assign_directory_addresses,(struct directory * root));
|
||||
extern int DECL(get_733,(char *));
|
||||
extern int DECL(isonum_733,(unsigned char *));
|
||||
extern void DECL(set_723,(char *, unsigned int));
|
||||
extern void DECL(set_731,(char *, unsigned int));
|
||||
extern void DECL(set_721,(char *, unsigned int));
|
||||
extern void DECL(set_733,(char *, unsigned int));
|
||||
extern void DECL(sort_directory,(struct directory_entry **));
|
||||
extern void generate_root_record();
|
||||
extern int DECL(sort_directory,(struct directory_entry **));
|
||||
extern void DECL(generate_one_directory,(struct directory *, FILE*));
|
||||
extern void generate_path_tables();
|
||||
extern int DECL(iso_write,(FILE * outfile));
|
||||
extern void DECL(memcpy_max, (char *, char *, int));
|
||||
|
||||
extern int DECL(oneblock_size, (int starting_extent));
|
||||
extern struct iso_primary_descriptor vol_desc;
|
||||
extern void DECL(xfwrite, (void * buffer, int count, int size, FILE * file));
|
||||
extern void DECL(set_732, (char * pnt, unsigned int i));
|
||||
extern void DECL(set_722, (char * pnt, unsigned int i));
|
||||
extern void DECL(outputlist_insert, (struct output_fragment * frag));
|
||||
|
||||
/* multi.c */
|
||||
|
||||
|
@ -228,6 +328,12 @@ extern struct directory_entry **
|
|||
extern void
|
||||
DECL(merge_remaining_entries, (struct directory *,
|
||||
struct directory_entry **, int));
|
||||
extern int
|
||||
DECL(merge_previous_session, (struct directory *,
|
||||
struct iso_directory_record *));
|
||||
|
||||
/* joliet.c */
|
||||
int DECL(joliet_sort_tree, (struct directory * node));
|
||||
|
||||
/* match.c */
|
||||
extern int DECL(matches, (char *));
|
||||
|
@ -245,7 +351,7 @@ extern void DECL(add_hash,(struct directory_entry *));
|
|||
extern struct file_hash * DECL(find_hash,(dev_t, ino_t));
|
||||
extern void DECL(add_directory_hash,(dev_t, ino_t));
|
||||
extern struct file_hash * DECL(find_directory_hash,(dev_t, ino_t));
|
||||
extern void flush_file_hash();
|
||||
extern void DECL (flush_file_hash, (void));
|
||||
extern int DECL(delete_file_hash,(struct directory_entry *));
|
||||
extern struct directory_entry * DECL(find_file_hash,(char *));
|
||||
extern void DECL(add_file_hash,(struct directory_entry *));
|
||||
|
@ -320,7 +426,13 @@ extern void * DECL(e_malloc,(size_t));
|
|||
* is set for all entries in a directory, it means we can just
|
||||
* reuse the TRANS.TBL and not generate a new one.
|
||||
*/
|
||||
#define SAFE_TO_REUSE_TABLE_ENTRY 1
|
||||
#define SAFE_TO_REUSE_TABLE_ENTRY 0x01
|
||||
#define DIR_HAS_DOT 0x02
|
||||
#define DIR_HAS_DOTDOT 0x04
|
||||
#define INHIBIT_JOLIET_ENTRY 0x08
|
||||
#define INHIBIT_RR_ENTRY 0x10
|
||||
#define RELOCATED_DIRECTORY 0x20
|
||||
|
||||
/*
|
||||
* Volume sequence number to use in all of the iso directory records.
|
||||
*/
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
static char rcsid[] ="$Id: multi.c,v 1.6.1.3 1998/06/02 03:00:25 eric Exp $";
|
||||
static char rcsid[] ="$Id: multi.c,v 1.12 1998/06/02 02:40:38 eric Exp $";
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -137,7 +137,7 @@ FDECL3(parse_rr, unsigned char *, pnt, int, len, struct directory_entry *,dpnt)
|
|||
|
||||
while(len >= 4){
|
||||
if(pnt[3] != 1) {
|
||||
printf("**BAD RRVERSION");
|
||||
fprintf(stderr,"**BAD RRVERSION");
|
||||
return -1;
|
||||
};
|
||||
if(strncmp((char *) pnt, "NM", 2) == 0) {
|
||||
|
@ -193,7 +193,7 @@ FDECL4(check_rr_dates, struct directory_entry *, dpnt,
|
|||
*/
|
||||
while(len >= 4){
|
||||
if(pnt[3] != 1) {
|
||||
printf("**BAD RRVERSION");
|
||||
fprintf(stderr,"**BAD RRVERSION");
|
||||
return -1;
|
||||
};
|
||||
|
||||
|
@ -750,6 +750,7 @@ void FDECL3(merge_remaining_entries, struct directory *, this_dir,
|
|||
struct directory_entry * s_entry;
|
||||
unsigned int ttbl_extent = 0;
|
||||
unsigned int ttbl_index = 0;
|
||||
char whole_path[1024];
|
||||
|
||||
/*
|
||||
* Whatever is leftover in the list needs to get merged back
|
||||
|
@ -762,6 +763,18 @@ void FDECL3(merge_remaining_entries, struct directory *, this_dir,
|
|||
continue;
|
||||
}
|
||||
|
||||
if( pnt[i]->name != NULL && pnt[i]->whole_name == NULL)
|
||||
{
|
||||
/*
|
||||
* Set the name for this directory.
|
||||
*/
|
||||
strcpy(whole_path, this_dir->de_name);
|
||||
strcat(whole_path, SPATH_SEPARATOR);
|
||||
strcat(whole_path, pnt[i]->name);
|
||||
|
||||
pnt[i]->whole_name = strdup(whole_path);
|
||||
}
|
||||
|
||||
if( pnt[i]->name != NULL
|
||||
&& strcmp(pnt[i]->name, "<translation table>") == 0 )
|
||||
{
|
||||
|
@ -884,6 +897,7 @@ FDECL2(merge_old_directory_into_tree, struct directory_entry *, dpnt,
|
|||
char whole_path[1024];
|
||||
|
||||
this_dir = (struct directory *) e_malloc(sizeof(struct directory));
|
||||
memset(this_dir, 0, sizeof(struct directory));
|
||||
this_dir->next = NULL;
|
||||
this_dir->subdir = NULL;
|
||||
this_dir->self = dpnt;
|
||||
|
@ -939,8 +953,23 @@ FDECL2(merge_old_directory_into_tree, struct directory_entry *, dpnt,
|
|||
if( (contents[i]->isorec.flags[0] & 2) != 0 )
|
||||
{
|
||||
memset(contents[i]->isorec.extent, 0, 8);
|
||||
|
||||
if( strcmp(contents[i]->name, ".") == 0 )
|
||||
this_dir->dir_flags |= DIR_HAS_DOT;
|
||||
|
||||
if( strcmp(contents[i]->name, "..") == 0 )
|
||||
this_dir->dir_flags |= DIR_HAS_DOTDOT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the whole name for this file.
|
||||
*/
|
||||
strcpy(whole_path, this_dir->whole_name);
|
||||
strcat(whole_path, SPATH_SEPARATOR);
|
||||
strcat(whole_path, contents[i]->name);
|
||||
|
||||
contents[i]->whole_name = strdup(whole_path);
|
||||
|
||||
contents[i]->next = this_dir->contents;
|
||||
contents[i]->filedir = this_dir;
|
||||
this_dir->contents = contents[i];
|
||||
|
@ -957,7 +986,13 @@ FDECL2(merge_old_directory_into_tree, struct directory_entry *, dpnt,
|
|||
*/
|
||||
merge_remaining_entries(this_dir, contents, n_orig);
|
||||
free_mdinfo(contents, n_orig);
|
||||
#if 0
|
||||
/*
|
||||
* This is no longer required. The post-scan sort will handle
|
||||
* all of this for us.
|
||||
*/
|
||||
sort_n_finish(this_dir);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1016,3 +1051,99 @@ FDECL1(get_session_start, int *, file_addr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function scans the directory tree, looking for files, and it makes
|
||||
* note of everything that is found. We also begin to construct the ISO9660
|
||||
* directory entries, so that we can determine how large each directory is.
|
||||
*/
|
||||
|
||||
int
|
||||
FDECL2(merge_previous_session,struct directory *, this_dir,
|
||||
struct iso_directory_record *, mrootp)
|
||||
{
|
||||
struct directory_entry **orig_contents = NULL;
|
||||
struct directory_entry * odpnt = NULL;
|
||||
int n_orig;
|
||||
struct directory_entry * s_entry;
|
||||
int dflag;
|
||||
int status, lstatus;
|
||||
struct stat statbuf, lstatbuf;
|
||||
|
||||
/*
|
||||
* Parse the same directory in the image that we are merging
|
||||
* for multisession stuff.
|
||||
*/
|
||||
orig_contents = read_merging_directory(mrootp, &n_orig);
|
||||
if( orig_contents == NULL )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Now we scan the directory itself, and look at what is inside of it. */
|
||||
|
||||
dflag = 0;
|
||||
for(s_entry = this_dir->contents; s_entry; s_entry = s_entry->next)
|
||||
{
|
||||
status = stat_filter(s_entry->whole_name, &statbuf);
|
||||
lstatus = lstat_filter(s_entry->whole_name, &lstatbuf);
|
||||
|
||||
/*
|
||||
* We always should create an entirely new directory tree whenever
|
||||
* we generate a new session, unless there were *no* changes whatsoever
|
||||
* to any of the directories, in which case it would be kind of pointless
|
||||
* to generate a new session.
|
||||
*
|
||||
* I believe it is possible to rigorously prove that any change anywhere
|
||||
* in the filesystem will force the entire tree to be regenerated
|
||||
* because the modified directory will get a new extent number. Since
|
||||
* each subdirectory of the changed directory has a '..' entry, all of
|
||||
* them will need to be rewritten too, and since the parent directory
|
||||
* of the modified directory will have an extent pointer to the directory
|
||||
* it too will need to be rewritten. Thus we will never be able to reuse
|
||||
* any directory information when writing new sessions.
|
||||
*
|
||||
* We still check the previous session so we can mark off the equivalent
|
||||
* entry in the list we got from the original disc, however.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
check_prev_session(orig_contents, n_orig, s_entry,
|
||||
&statbuf, &lstatbuf, &odpnt);
|
||||
|
||||
if(S_ISDIR(statbuf.st_mode) && odpnt != NULL)
|
||||
{
|
||||
int dflag;
|
||||
|
||||
if (strcmp(s_entry->name,".") && strcmp(s_entry->name,".."))
|
||||
{
|
||||
struct directory * child;
|
||||
|
||||
child = find_or_create_directory(this_dir,
|
||||
s_entry->whole_name,
|
||||
s_entry, 1);
|
||||
dflag = merge_previous_session(child,
|
||||
&odpnt->isorec);
|
||||
/* If unable to scan directory, mark this as a non-directory */
|
||||
if(!dflag)
|
||||
lstatbuf.st_mode = (lstatbuf.st_mode & ~S_IFMT) | S_IFREG;
|
||||
free(odpnt);
|
||||
odpnt = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Whatever is left over, are things which are no longer in the tree
|
||||
* on disk. We need to also merge these into the tree.
|
||||
*/
|
||||
merge_remaining_entries(this_dir, orig_contents, n_orig);
|
||||
free_mdinfo(orig_contents, n_orig);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,8 +21,9 @@
|
|||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
static char rcsid[] ="$Id: name.c,v 1.7 1997/11/09 16:42:51 eric Exp $";
|
||||
static char rcsid[] ="$Id: name.c,v 1.10 1998/06/02 02:40:38 eric Exp $";
|
||||
|
||||
#include "config.h"
|
||||
#include "mkisofs.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
@ -105,8 +106,7 @@ int FDECL3(iso9660_file_length,
|
|||
last_dot = strrchr (pnt,'.');
|
||||
if( (last_dot != NULL)
|
||||
&& ( (last_dot[1] == '~')
|
||||
|| (last_dot[1] == '\0')
|
||||
|| (last_dot[1] == '\0')) )
|
||||
|| (last_dot[1] == '\0')) )
|
||||
{
|
||||
c = last_dot;
|
||||
*c = '\0';
|
||||
|
@ -154,13 +154,19 @@ int FDECL3(iso9660_file_length,
|
|||
* a silly thing to do on a Unix box, but we check for it
|
||||
* anyways. If we see this, then we don't have to add our
|
||||
* own version number at the end.
|
||||
* UNLESS the ';' is part of the filename and no version
|
||||
* number is following. [VK]
|
||||
*/
|
||||
if(*pnt == ';')
|
||||
{
|
||||
seen_semic = 1;
|
||||
*result++ = *pnt++;
|
||||
continue;
|
||||
}
|
||||
if(*pnt == ';')
|
||||
{
|
||||
/* [VK] */
|
||||
if (pnt[1] != '\0' && (pnt[1] < '0' || pnt[1] > '9'))
|
||||
{
|
||||
pnt++;
|
||||
ignore++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If we have a name with multiple '.' characters, we ignore everything
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
static char rcsid[] ="$Id: rock.c,v 1.3 1997/05/17 15:45:26 eric Exp $";
|
||||
static char rcsid[] ="$Id: rock.c,v 1.7 1998/02/18 04:48:23 eric Exp $";
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
|
@ -225,7 +225,7 @@ int deep_opt;
|
|||
Rock[ipnt++] = PN_SIZE;
|
||||
Rock[ipnt++] = SU_VERSION;
|
||||
flagval |= (1<<1);
|
||||
#if !defined(MAJOR_IN_SYSMACROS) && !defined(MAJOR_IN_MKDEV)
|
||||
#if defined(MAJOR_IN_SYSMACROS) || defined(MAJOR_IN_MKDEV)
|
||||
set_733((char*)Rock + ipnt, major(lstatbuf->st_rdev ));
|
||||
ipnt += 8;
|
||||
set_733((char*)Rock + ipnt, minor(lstatbuf->st_rdev));
|
||||
|
@ -268,10 +268,36 @@ int deep_opt;
|
|||
unsigned char * cpnt, *cpnt1;
|
||||
nchar = readlink(whole_name, symlink_buff, sizeof(symlink_buff));
|
||||
symlink_buff[nchar < 0 ? 0 : nchar] = 0;
|
||||
nchar = strlen((char *) symlink_buff);
|
||||
set_733(s_entry->isorec.size, 0);
|
||||
cpnt = &symlink_buff[0];
|
||||
flagval |= (1<<2);
|
||||
|
||||
if (! split_SL_field)
|
||||
{
|
||||
int sl_bytes = 0;
|
||||
for (cpnt1 = cpnt; *cpnt1 != '\0'; cpnt1++)
|
||||
{
|
||||
if (*cpnt1 == '/')
|
||||
{
|
||||
sl_bytes += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
sl_bytes += 1;
|
||||
}
|
||||
}
|
||||
if (sl_bytes > 250)
|
||||
{
|
||||
/*
|
||||
* the symbolic link won't fit into one SL System Use Field
|
||||
* print an error message and continue with splited one
|
||||
*/
|
||||
fprintf(stderr,"symbolic link ``%s'' to long for one SL System Use Field, splitting", cpnt);
|
||||
}
|
||||
if(MAYBE_ADD_CE_ENTRY(SL_SIZE + sl_bytes)) add_CE_entry();
|
||||
}
|
||||
|
||||
while(nchar){
|
||||
if(MAYBE_ADD_CE_ENTRY(SL_SIZE)) add_CE_entry();
|
||||
Rock[ipnt++] ='S';
|
||||
|
@ -309,15 +335,18 @@ int deep_opt;
|
|||
} else {
|
||||
/* If we do not have enough room for a component, start
|
||||
a new continuations segment now */
|
||||
if(MAYBE_ADD_CE_ENTRY(6)) {
|
||||
add_CE_entry();
|
||||
if(cpnt1){
|
||||
*cpnt1 = '/';
|
||||
nchar++;
|
||||
cpnt1 = NULL; /* A kluge so that we can restart properly */
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(split_SL_component ? MAYBE_ADD_CE_ENTRY(6) :
|
||||
MAYBE_ADD_CE_ENTRY(6 + strlen ((char *) cpnt)))
|
||||
{
|
||||
add_CE_entry();
|
||||
if(cpnt1)
|
||||
{
|
||||
*cpnt1 = '/';
|
||||
nchar++;
|
||||
cpnt1 = NULL; /* A kluge so that we can restart properly */
|
||||
}
|
||||
break;
|
||||
}
|
||||
j0 = strlen((char *) cpnt);
|
||||
while(j0) {
|
||||
j1 = j0;
|
||||
|
|
1571
util/mkisofs/tree.c
1571
util/mkisofs/tree.c
File diff suppressed because it is too large
Load diff
|
@ -19,10 +19,11 @@
|
|||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
static char rcsid[] ="$Id: write.c,v 1.6.1.3 1997/11/13 05:07:13 eric Exp $";
|
||||
static char rcsid[] ="$Id: write.c,v 1.18 1998/06/02 02:40:39 eric Exp $";
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "config.h"
|
||||
#include "mkisofs.h"
|
||||
#include "iso9660.h"
|
||||
#include <time.h>
|
||||
|
@ -50,15 +51,17 @@ extern char * strdup(const char *);
|
|||
|
||||
/* Counters for statistics */
|
||||
|
||||
static int table_size = 0;
|
||||
static int total_dir_size = 0;
|
||||
static int rockridge_size = 0;
|
||||
static int table_size = 0;
|
||||
static int total_dir_size = 0;
|
||||
static int rockridge_size = 0;
|
||||
static struct directory ** pathlist;
|
||||
static next_path_index = 1;
|
||||
static next_path_index = 1;
|
||||
static int sort_goof;
|
||||
|
||||
/* Used to fill in some of the information in the volume descriptor. */
|
||||
static struct tm local;
|
||||
static struct tm gmt;
|
||||
struct output_fragment * out_tail;
|
||||
struct output_fragment * out_list;
|
||||
|
||||
struct iso_primary_descriptor vol_desc;
|
||||
|
||||
/* Routines to actually write the disc. We write sequentially so that
|
||||
we could write a tape, or write the disc directly */
|
||||
|
@ -118,8 +121,30 @@ void FDECL2(set_733, char *, pnt, unsigned int, i)
|
|||
|
||||
void FDECL4(xfwrite, void *, buffer, int, count, int, size, FILE *, file)
|
||||
{
|
||||
while(count)
|
||||
{
|
||||
/*
|
||||
* This is a hack that could be made better. XXXIs this the only place?
|
||||
* It is definitely needed on Operating Systems that do not
|
||||
* allow to write files that are > 2GB.
|
||||
* If the system is fast enough to be able to feed 1400 KB/s
|
||||
* writing speed of a DVD-R drive, use stdout.
|
||||
* If the system cannot do this reliable, you need to use this
|
||||
* hacky option.
|
||||
*/
|
||||
if (split_output != 0 && ftell(file) > (1024 * 1024 * 1024) ) {
|
||||
static int idx = 0;
|
||||
char nbuf[128];
|
||||
|
||||
sprintf(nbuf, "part_%02d", idx++);
|
||||
file = freopen(nbuf, "w", file);
|
||||
if (file == NULL) {
|
||||
fprintf(stderr, "Cannot open '%s'.\n", nbuf);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
while(count)
|
||||
{
|
||||
int got = fwrite(buffer,size,count,file);
|
||||
|
||||
if(got<=0)
|
||||
|
@ -142,11 +167,7 @@ struct deferred_write
|
|||
|
||||
static struct deferred_write * dw_head = NULL, * dw_tail = NULL;
|
||||
|
||||
static struct directory_entry * sort_dir;
|
||||
static struct eltorito_boot_descriptor boot_desc;
|
||||
|
||||
unsigned int last_extent_written =0;
|
||||
static struct iso_primary_descriptor vol_desc;
|
||||
static path_table_index;
|
||||
static time_t begun;
|
||||
|
||||
|
@ -154,7 +175,7 @@ static time_t begun;
|
|||
numbers to them. We have already assigned extent numbers to everything that
|
||||
goes in front of them */
|
||||
|
||||
void FDECL1(assign_directory_addresses, struct directory *, node)
|
||||
static int FDECL1(assign_directory_addresses, struct directory *, node)
|
||||
{
|
||||
int dir_size;
|
||||
struct directory * dpnt;
|
||||
|
@ -193,6 +214,7 @@ void FDECL1(assign_directory_addresses, struct directory *, node)
|
|||
|
||||
dpnt = dpnt->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void FDECL3(write_one_file, char *, filename,
|
||||
|
@ -222,8 +244,8 @@ static void FDECL3(write_one_file, char *, filename,
|
|||
memset(buffer, 0, use);
|
||||
if (fread(buffer, 1, use, infile) == 0)
|
||||
{
|
||||
fprintf(stderr,"cannot read from %s\n",filename);
|
||||
exit(1);
|
||||
fprintf(stderr,"cannot read from %s\n",filename);
|
||||
exit(1);
|
||||
}
|
||||
xfwrite(buffer, 1, use, outfile);
|
||||
last_extent_written += use/SECTOR_SIZE;
|
||||
|
@ -296,7 +318,7 @@ static void dump_filelist()
|
|||
}
|
||||
#endif
|
||||
|
||||
int FDECL2(compare_dirs, const void *, rr, const void *, ll)
|
||||
static int FDECL2(compare_dirs, const void *, rr, const void *, ll)
|
||||
{
|
||||
char * rpnt, *lpnt;
|
||||
struct directory_entry ** r, **l;
|
||||
|
@ -305,11 +327,24 @@ int FDECL2(compare_dirs, const void *, rr, const void *, ll)
|
|||
l = (struct directory_entry **) ll;
|
||||
rpnt = (*r)->isorec.name;
|
||||
lpnt = (*l)->isorec.name;
|
||||
|
||||
/*
|
||||
* If the entries are the same, this is an error.
|
||||
*/
|
||||
if( strcmp(rpnt, lpnt) == 0 )
|
||||
{
|
||||
sort_goof++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Put the '.' and '..' entries on the head of the sorted list.
|
||||
* For normal ASCII, this always happens to be the case, but out of
|
||||
* band characters cause this not to be the case sometimes.
|
||||
*
|
||||
* FIXME(eric) - these tests seem redundant, in taht the name is
|
||||
* never assigned these values. It will instead be \000 or \001,
|
||||
* and thus should always be sorted correctly. I need to figure
|
||||
* out why I thought I needed this in the first place.
|
||||
*/
|
||||
if( strcmp(rpnt, ".") == 0 ) return -1;
|
||||
if( strcmp(lpnt, ".") == 0 ) return 1;
|
||||
|
@ -336,7 +371,15 @@ int FDECL2(compare_dirs, const void *, rr, const void *, ll)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void FDECL1(sort_directory, struct directory_entry **, sort_dir)
|
||||
/*
|
||||
* Function: sort_directory
|
||||
*
|
||||
* Purpose: Sort the directory in the appropriate ISO9660
|
||||
* order.
|
||||
*
|
||||
* Notes: Returns 0 if OK, returns > 0 if an error occurred.
|
||||
*/
|
||||
int FDECL1(sort_directory, struct directory_entry **, sort_dir)
|
||||
{
|
||||
int dcount = 0;
|
||||
int i, len;
|
||||
|
@ -350,6 +393,11 @@ void FDECL1(sort_directory, struct directory_entry **, sort_dir)
|
|||
s_entry = s_entry->next;
|
||||
}
|
||||
|
||||
if( dcount == 0 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* OK, now we know how many there are. Build a vector for sorting.
|
||||
*/
|
||||
|
@ -367,44 +415,52 @@ void FDECL1(sort_directory, struct directory_entry **, sort_dir)
|
|||
s_entry = s_entry->next;
|
||||
}
|
||||
|
||||
qsort(sortlist, dcount, sizeof(struct directory_entry *),
|
||||
(int (*)(const void *, const void *))compare_dirs);
|
||||
|
||||
/*
|
||||
* Now reassemble the linked list in the proper sorted order
|
||||
/*
|
||||
* Each directory is required to contain at least . and ..
|
||||
*/
|
||||
for(i=0; i<dcount-1; i++)
|
||||
{
|
||||
sortlist[i]->next = sortlist[i+1];
|
||||
}
|
||||
if( dcount < 2 )
|
||||
{
|
||||
sort_goof = 1;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
sort_goof = 0;
|
||||
qsort(sortlist, dcount, sizeof(struct directory_entry *),
|
||||
(int (*)(const void *, const void *))compare_dirs);
|
||||
|
||||
/*
|
||||
* Now reassemble the linked list in the proper sorted order
|
||||
*/
|
||||
for(i=0; i<dcount-1; i++)
|
||||
{
|
||||
sortlist[i]->next = sortlist[i+1];
|
||||
}
|
||||
|
||||
sortlist[dcount-1]->next = NULL;
|
||||
*sort_dir = sortlist[0];
|
||||
}
|
||||
|
||||
sortlist[dcount-1]->next = NULL;
|
||||
*sort_dir = sortlist[0];
|
||||
|
||||
free(sortlist);
|
||||
|
||||
return sort_goof;
|
||||
}
|
||||
|
||||
void generate_root_record()
|
||||
static int root_gen()
|
||||
{
|
||||
time_t ctime;
|
||||
|
||||
time (&ctime);
|
||||
|
||||
local = *localtime(&ctime);
|
||||
gmt = *gmtime(&ctime);
|
||||
init_fstatbuf();
|
||||
|
||||
root_record.length[0] = 1 + sizeof(struct iso_directory_record)
|
||||
- sizeof(root_record.name);
|
||||
root_record.ext_attr_length[0] = 0;
|
||||
set_733((char *) root_record.extent, root->extent);
|
||||
set_733((char *) root_record.size, ROUND_UP(root->size));
|
||||
iso9660_date(root_record.date, ctime);
|
||||
iso9660_date(root_record.date, root_statbuf.st_mtime);
|
||||
root_record.flags[0] = 2;
|
||||
root_record.file_unit_size[0] = 0;
|
||||
root_record.interleave[0] = 0;
|
||||
set_723(root_record.volume_sequence_number, DEF_VSN);
|
||||
root_record.name_len[0] = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void FDECL1(assign_file_addresses, struct directory *, dpnt)
|
||||
|
@ -439,7 +495,7 @@ static void FDECL1(assign_file_addresses, struct directory *, dpnt)
|
|||
s_hash = find_hash(s_entry->dev, s_entry->inode);
|
||||
if(s_hash)
|
||||
{
|
||||
if(verbose)
|
||||
if(verbose > 1)
|
||||
{
|
||||
fprintf(stderr, "Cache hit for %s%s%s\n",s_entry->filedir->de_name,
|
||||
SPATH_SEPARATOR, s_entry->name);
|
||||
|
@ -562,7 +618,7 @@ static void FDECL1(assign_file_addresses, struct directory *, dpnt)
|
|||
s_entry->starting_block = last_extent;
|
||||
add_hash(s_entry);
|
||||
last_extent += ROUND_UP(s_entry->size) >> 11;
|
||||
if(verbose)
|
||||
if(verbose > 1)
|
||||
{
|
||||
fprintf(stderr,"%d %d %s\n", s_entry->starting_block,
|
||||
last_extent-1, whole_path);
|
||||
|
@ -576,6 +632,7 @@ static void FDECL1(assign_file_addresses, struct directory *, dpnt)
|
|||
|
||||
}
|
||||
#endif
|
||||
#ifdef NOT_NEEDED /* Never use this code if you like to create a DVD */
|
||||
if(last_extent > (800000000 >> 11))
|
||||
{
|
||||
/*
|
||||
|
@ -583,9 +640,10 @@ static void FDECL1(assign_file_addresses, struct directory *, dpnt)
|
|||
*/
|
||||
fprintf(stderr,"Extent overflow processing file %s\n", whole_path);
|
||||
fprintf(stderr,"Starting block is %d\n", s_entry->starting_block);
|
||||
fprintf(stderr,"Reported file size is %d extents\n", s_entry->size);
|
||||
fprintf(stderr,"Reported file size is %d bytes\n", s_entry->size);
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -605,6 +663,40 @@ static void FDECL1(assign_file_addresses, struct directory *, dpnt)
|
|||
}
|
||||
} /* assign_file_addresses(... */
|
||||
|
||||
static void FDECL1(free_one_directory, struct directory *, dpnt)
|
||||
{
|
||||
struct directory_entry * s_entry;
|
||||
struct directory_entry * s_entry_d;
|
||||
|
||||
s_entry = dpnt->contents;
|
||||
while(s_entry)
|
||||
{
|
||||
s_entry_d = s_entry;
|
||||
s_entry = s_entry->next;
|
||||
|
||||
if( s_entry_d->name != NULL )
|
||||
{
|
||||
free (s_entry_d->name);
|
||||
}
|
||||
if( s_entry_d->whole_name != NULL )
|
||||
{
|
||||
free (s_entry_d->whole_name);
|
||||
}
|
||||
free (s_entry_d);
|
||||
}
|
||||
dpnt->contents = NULL;
|
||||
} /* free_one_directory(... */
|
||||
|
||||
static void FDECL1(free_directories, struct directory *, dpnt)
|
||||
{
|
||||
while (dpnt)
|
||||
{
|
||||
free_one_directory(dpnt);
|
||||
if(dpnt->subdir) free_directories(dpnt->subdir);
|
||||
dpnt = dpnt->next;
|
||||
}
|
||||
}
|
||||
|
||||
void FDECL2(generate_one_directory, struct directory *, dpnt, FILE *, outfile)
|
||||
{
|
||||
unsigned int ce_address = 0;
|
||||
|
@ -743,18 +835,15 @@ void FDECL2(generate_one_directory, struct directory *, dpnt, FILE *, outfile)
|
|||
s_entry_d = s_entry;
|
||||
s_entry = s_entry->next;
|
||||
|
||||
if (s_entry_d->rr_attributes) free(s_entry_d->rr_attributes);
|
||||
if( s_entry_d->name != NULL )
|
||||
/*
|
||||
* Joliet doesn't use the Rock Ridge attributes, so we free it here.
|
||||
*/
|
||||
if (s_entry_d->rr_attributes)
|
||||
{
|
||||
free (s_entry_d->name);
|
||||
free(s_entry_d->rr_attributes);
|
||||
s_entry_d->rr_attributes = NULL;
|
||||
}
|
||||
if( s_entry_d->whole_name != NULL )
|
||||
{
|
||||
free (s_entry_d->whole_name);
|
||||
}
|
||||
free (s_entry_d);
|
||||
}
|
||||
sort_dir = NULL;
|
||||
|
||||
if(dpnt->size != dir_index)
|
||||
{
|
||||
|
@ -795,7 +884,7 @@ void FDECL1(build_pathlist, struct directory *, node)
|
|||
}
|
||||
} /* build_pathlist(... */
|
||||
|
||||
int FDECL2(compare_paths, void const *, r, void const *, l)
|
||||
static int FDECL2(compare_paths, void const *, r, void const *, l)
|
||||
{
|
||||
struct directory const *ll = *(struct directory * const *)l;
|
||||
struct directory const *rr = *(struct directory * const *)r;
|
||||
|
@ -814,7 +903,7 @@ int FDECL2(compare_paths, void const *, r, void const *, l)
|
|||
|
||||
} /* compare_paths(... */
|
||||
|
||||
void generate_path_tables()
|
||||
static int generate_path_tables()
|
||||
{
|
||||
struct directory_entry * de;
|
||||
struct directory * dpnt;
|
||||
|
@ -926,6 +1015,7 @@ void generate_path_tables()
|
|||
path_table_index,
|
||||
path_table_size);
|
||||
}
|
||||
return 0;
|
||||
} /* generate_path_tables(... */
|
||||
|
||||
void
|
||||
|
@ -940,17 +1030,102 @@ FDECL3(memcpy_max, char *, to, char *, from, int, max)
|
|||
|
||||
} /* memcpy_max(... */
|
||||
|
||||
int FDECL1(iso_write, FILE *, outfile)
|
||||
void FDECL1(outputlist_insert, struct output_fragment *, frag)
|
||||
{
|
||||
if( out_tail == NULL )
|
||||
{
|
||||
out_list = out_tail = frag;
|
||||
}
|
||||
else
|
||||
{
|
||||
out_tail->of_next = frag;
|
||||
out_tail = frag;
|
||||
}
|
||||
}
|
||||
|
||||
static int FDECL1(file_write, FILE *, outfile)
|
||||
{
|
||||
char buffer[2048];
|
||||
int i;
|
||||
char iso_time[17];
|
||||
int should_write;
|
||||
|
||||
time(&begun);
|
||||
assign_file_addresses(root);
|
||||
/*
|
||||
* OK, all done with that crap. Now write out the directories.
|
||||
* This is where the fur starts to fly, because we need to keep track of
|
||||
* each file as we find it and keep track of where we put it.
|
||||
*/
|
||||
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
should_write = last_extent - session_start;
|
||||
|
||||
if( print_size > 0 )
|
||||
{
|
||||
fprintf(stderr,"Total extents scheduled to be written = %d\n",
|
||||
last_extent - session_start);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if( verbose > 0 )
|
||||
{
|
||||
#ifdef DBG_ISO
|
||||
fprintf(stderr,"Total directory extents being written = %d\n", last_extent);
|
||||
#endif
|
||||
|
||||
fprintf(stderr,"Total extents scheduled to be written = %d\n",
|
||||
last_extent - session_start);
|
||||
}
|
||||
|
||||
/*
|
||||
* Now write all of the files that we need.
|
||||
*/
|
||||
write_files(outfile);
|
||||
|
||||
/*
|
||||
* The rest is just fluff.
|
||||
*/
|
||||
if( verbose == 0 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
fprintf(stderr,"Total extents actually written = %d\n",
|
||||
last_extent_written - session_start);
|
||||
|
||||
/*
|
||||
* Hard links throw us off here
|
||||
*/
|
||||
if(should_write != last_extent - session_start)
|
||||
{
|
||||
fprintf(stderr,"Number of extents written not what was predicted. Please fix.\n");
|
||||
fprintf(stderr,"Predicted = %d, written = %d\n", should_write, last_extent);
|
||||
}
|
||||
|
||||
fprintf(stderr,"Total translation table size: %d\n", table_size);
|
||||
fprintf(stderr,"Total rockridge attributes bytes: %d\n", rockridge_size);
|
||||
fprintf(stderr,"Total directory bytes: %d\n", total_dir_size);
|
||||
fprintf(stderr,"Path table size(bytes): %d\n", path_table_size);
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "next extent, last_extent, last_extent_written %d %d %d\n",
|
||||
next_extent, last_extent, last_extent_written);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
} /* iso_write(... */
|
||||
|
||||
/*
|
||||
* Function to write the PVD for the disc.
|
||||
*/
|
||||
static int FDECL1(pvd_write, FILE *, outfile)
|
||||
{
|
||||
char iso_time[17];
|
||||
int should_write;
|
||||
struct tm local;
|
||||
struct tm gmt;
|
||||
|
||||
|
||||
time(&begun);
|
||||
|
||||
local = *localtime(&begun);
|
||||
gmt = *gmtime(&begun);
|
||||
|
||||
/*
|
||||
* This will break in the year 2000, I supose, but there is no good way
|
||||
|
@ -965,17 +1140,6 @@ int FDECL1(iso_write, FILE *, outfile)
|
|||
local.tm_yday -= gmt.tm_yday;
|
||||
iso_time[16] = (local.tm_min + 60*(local.tm_hour + 24*local.tm_yday)) / 15;
|
||||
|
||||
/*
|
||||
* First, we output 16 sectors of all zero
|
||||
*/
|
||||
|
||||
for(i=0; i<16; i++)
|
||||
{
|
||||
xfwrite(buffer, 1, sizeof(buffer), outfile);
|
||||
}
|
||||
|
||||
last_extent_written += 16;
|
||||
|
||||
/*
|
||||
* Next we write out the primary descriptor for the disc
|
||||
*/
|
||||
|
@ -1011,7 +1175,7 @@ int FDECL1(iso_write, FILE *, outfile)
|
|||
* Now we copy the actual root directory record
|
||||
*/
|
||||
memcpy(vol_desc.root_directory_record, &root_record,
|
||||
sizeof(struct iso_directory_record) + 1);
|
||||
sizeof(struct iso_directory_record));
|
||||
|
||||
/*
|
||||
* The rest is just fluff. It looks nice to fill in many of these fields,
|
||||
|
@ -1058,16 +1222,16 @@ int FDECL1(iso_write, FILE *, outfile)
|
|||
*/
|
||||
xfwrite(&vol_desc, 1, 2048, outfile);
|
||||
last_extent_written++;
|
||||
if (use_eltorito)
|
||||
{
|
||||
/*
|
||||
* Next we write out the boot volume descriptor for the disc
|
||||
*/
|
||||
get_torito_desc(&boot_desc);
|
||||
xfwrite(&boot_desc, 1, 2048, outfile);
|
||||
last_extent_written ++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function to write the EVD for the disc.
|
||||
*/
|
||||
static int FDECL1(evd_write, FILE *, outfile)
|
||||
{
|
||||
struct iso_primary_descriptor vol_desc;
|
||||
|
||||
/*
|
||||
* Now write the end volume descriptor. Much simpler than the other one
|
||||
*/
|
||||
|
@ -1077,7 +1241,14 @@ int FDECL1(iso_write, FILE *, outfile)
|
|||
vol_desc.version[0] = 1;
|
||||
xfwrite(&vol_desc, 1, 2048, outfile);
|
||||
last_extent_written += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function to write the EVD for the disc.
|
||||
*/
|
||||
static int FDECL1(pathtab_write, FILE *, outfile)
|
||||
{
|
||||
/*
|
||||
* Next we write the path tables
|
||||
*/
|
||||
|
@ -1088,55 +1259,121 @@ int FDECL1(iso_write, FILE *, outfile)
|
|||
free(path_table_m);
|
||||
path_table_l = NULL;
|
||||
path_table_m = NULL;
|
||||
|
||||
/*
|
||||
* OK, all done with that crap. Now write out the directories.
|
||||
* This is where the fur starts to fly, because we need to keep track of
|
||||
* each file as we find it and keep track of where we put it.
|
||||
*/
|
||||
|
||||
#ifdef DBG_ISO
|
||||
fprintf(stderr,"Total directory extents being written = %d\n", last_extent);
|
||||
#endif
|
||||
#if 0
|
||||
generate_one_directory(root, outfile);
|
||||
#endif
|
||||
generate_iso9660_directories(root, outfile);
|
||||
|
||||
if(extension_record)
|
||||
{
|
||||
xfwrite(extension_record, 1, SECTOR_SIZE, outfile);
|
||||
last_extent_written++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Now write all of the files that we need.
|
||||
*/
|
||||
fprintf(stderr,"Total extents scheduled to be written = %d\n",
|
||||
last_extent - session_start);
|
||||
write_files(outfile);
|
||||
|
||||
fprintf(stderr,"Total extents actually written = %d\n",
|
||||
last_extent_written - session_start);
|
||||
/*
|
||||
* Hard links throw us off here
|
||||
*/
|
||||
if(should_write != last_extent - session_start)
|
||||
{
|
||||
fprintf(stderr,"Number of extents written not what was predicted. Please fix.\n");
|
||||
fprintf(stderr,"Predicted = %d, written = %d\n", should_write, last_extent);
|
||||
}
|
||||
|
||||
fprintf(stderr,"Total translation table size: %d\n", table_size);
|
||||
fprintf(stderr,"Total rockridge attributes bytes: %d\n", rockridge_size);
|
||||
fprintf(stderr,"Total directory bytes: %d\n", total_dir_size);
|
||||
fprintf(stderr,"Path table size(bytes): %d\n", path_table_size);
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "next extent, last_extent, last_extent_written %d %d %d\n",
|
||||
next_extent, last_extent, last_extent_written);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} /* iso_write(... */
|
||||
static int FDECL1(exten_write, FILE *, outfile)
|
||||
{
|
||||
xfwrite(extension_record, 1, SECTOR_SIZE, outfile);
|
||||
last_extent_written++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Functions to describe padding block at the start of the disc.
|
||||
*/
|
||||
int FDECL1(oneblock_size, int, starting_extent)
|
||||
{
|
||||
last_extent++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Functions to describe padding block at the start of the disc.
|
||||
*/
|
||||
static int FDECL1(pathtab_size, int, starting_extent)
|
||||
{
|
||||
path_table[0] = starting_extent;
|
||||
|
||||
path_table[1] = 0;
|
||||
path_table[2] = path_table[0] + path_blocks;
|
||||
path_table[3] = 0;
|
||||
last_extent += 2*path_blocks;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int FDECL1(padblock_size, int, starting_extent)
|
||||
{
|
||||
last_extent += 16;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int file_gen()
|
||||
{
|
||||
assign_file_addresses(root);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dirtree_dump()
|
||||
{
|
||||
if (verbose > 1)
|
||||
dump_tree(root);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int FDECL1(dirtree_fixup, int, starting_extent)
|
||||
{
|
||||
if (use_RockRidge && reloc_dir)
|
||||
finish_cl_pl_entries();
|
||||
|
||||
if (use_RockRidge )
|
||||
update_nlink_field(root);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int FDECL1(dirtree_size, int, starting_extent)
|
||||
{
|
||||
assign_directory_addresses(root);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int FDECL1(ext_size, int, starting_extent)
|
||||
{
|
||||
extern int extension_record_size;
|
||||
struct directory_entry * s_entry;
|
||||
extension_record_extent = starting_extent;
|
||||
s_entry = root->contents;
|
||||
set_733((char *) s_entry->rr_attributes + s_entry->rr_attr_size - 24,
|
||||
extension_record_extent);
|
||||
set_733((char *) s_entry->rr_attributes + s_entry->rr_attr_size - 8,
|
||||
extension_record_size);
|
||||
last_extent++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int FDECL1(dirtree_write, FILE *, outfile)
|
||||
{
|
||||
generate_iso9660_directories(root, outfile);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int FDECL1(dirtree_cleanup, FILE *, outfile)
|
||||
{
|
||||
free_directories(root);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int FDECL1(padblock_write, FILE *, outfile)
|
||||
{
|
||||
char buffer[2048];
|
||||
int i;
|
||||
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
|
||||
for(i=0; i<16; i++)
|
||||
{
|
||||
xfwrite(buffer, 1, sizeof(buffer), outfile);
|
||||
}
|
||||
|
||||
last_extent_written += 16;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct output_fragment padblock_desc = {NULL, padblock_size, NULL, padblock_write};
|
||||
struct output_fragment voldesc_desc = {NULL, oneblock_size, root_gen, pvd_write};
|
||||
struct output_fragment end_vol = {NULL, oneblock_size, NULL, evd_write};
|
||||
struct output_fragment pathtable_desc = {NULL, pathtab_size, generate_path_tables, pathtab_write};
|
||||
struct output_fragment dirtree_desc = {NULL, dirtree_size, NULL, dirtree_write};
|
||||
struct output_fragment dirtree_clean = {NULL, dirtree_fixup, dirtree_dump, dirtree_cleanup};
|
||||
struct output_fragment extension_desc = {NULL, ext_size, NULL, exten_write};
|
||||
struct output_fragment files_desc = {NULL, NULL, file_gen, file_write};
|
||||
|
|
Loading…
Reference in a new issue