Robert Millan 2009-11-08 22:51:08 +00:00
parent 79cb3a568b
commit 4b4c4f6400
15 changed files with 6395 additions and 0 deletions

44
util/mkisofs/defaults.h Normal file
View file

@ -0,0 +1,44 @@
/*
* 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 $
*/
#define PREPARER_DEFAULT NULL
#define PUBLISHER_DEFAULT NULL
#define APPID_DEFAULT NULL
#define COPYRIGHT_DEFAULT NULL
#define BIBLIO_DEFAULT NULL
#define ABSTRACT_DEFAULT NULL
#define VOLSET_ID_DEFAULT NULL
#define VOLUME_ID_DEFAULT "CDROM"
#define BOOT_CATALOG_DEFAULT "boot.catalog"
#define BOOT_IMAGE_DEFAULT NULL
#ifdef __QNX__
#define SYSTEM_ID_DEFAULT "QNX"
#endif
#ifdef __osf__
#define SYSTEM_ID_DEFAULT "OSF"
#endif
#ifdef __sun
#define SYSTEM_ID_DEFAULT "Solaris"
#endif
#ifdef __hpux
#define SYSTEM_ID_DEFAULT "HP-UX"
#endif
#ifdef __sgi
#define SYSTEM_ID_DEFAULT "SGI"
#endif
#ifdef _AIX
#define SYSTEM_ID_DEFAULT "AIX"
#endif
#ifndef SYSTEM_ID_DEFAULT
#define SYSTEM_ID_DEFAULT "LINUX"
#endif

265
util/mkisofs/eltorito.c Normal file
View file

@ -0,0 +1,265 @@
/*
* Program eltorito.c - Handle El Torito specific extensions to iso9660.
*
Written by Michael Fulbright <msf@redhat.com> (1996).
Copyright 1996 RedHat Software, Incorporated
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: eltorito.c,v 1.7 1997/05/17 15:44:31 eric Exp $";
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include "mkisofs.h"
#include "iso9660.h"
#undef MIN
#define MIN(a, b) (((a) < (b))? (a): (b))
static struct eltorito_validation_entry valid_desc;
static struct eltorito_defaultboot_entry default_desc;
/*
* Check for presence of boot catalog. If it does not exist then make it
*/
void FDECL1(init_boot_catalog, const char *, path)
{
int bcat;
char * bootpath; /* filename of boot catalog */
char * buf;
struct stat statbuf;
bootpath = (char *) e_malloc(strlen(boot_catalog)+strlen(path)+2);
strcpy(bootpath, path);
if (bootpath[strlen(bootpath)-1] != '/')
{
strcat(bootpath,"/");
}
strcat(bootpath, boot_catalog);
/*
* check for the file existing
*/
#ifdef DEBUG_TORITO
printf("Looking for boot catalog file %s\n",bootpath);
#endif
if (!stat_filter(bootpath, &statbuf))
{
/*
* make sure its big enough to hold what we want
*/
if (statbuf.st_size == 2048)
{
/*
* printf("Boot catalog exists, so we do nothing\n");
*/
free(bootpath);
return;
}
else
{
fprintf(stderr, "A boot catalog exists and appears corrupted.\n");
fprintf(stderr, "Please check the following file: %s.\n",bootpath);
fprintf(stderr, "This file must be removed before a bootable CD can be done.\n");
free(bootpath);
exit(1);
}
}
/*
* 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 );
if (bcat == -1)
{
fprintf(stderr, "Error creating boot catalog, exiting...\n");
perror("");
exit(1);
}
buf = (char *) e_malloc( 2048 );
write(bcat, buf, 2048);
close(bcat);
free(bootpath);
} /* init_boot_catalog(... */
void FDECL1(get_torito_desc, struct eltorito_boot_descriptor *, boot_desc)
{
int bootcat;
int checksum;
unsigned char * checksum_ptr;
struct directory_entry * de;
struct directory_entry * de2;
int i;
int nsectors;
memset(boot_desc, 0, sizeof(*boot_desc));
boot_desc->id[0] = 0;
memcpy(boot_desc->id2, ISO_STANDARD_ID, sizeof(ISO_STANDARD_ID));
boot_desc->version[0] = 1;
memcpy(boot_desc->system_id, EL_TORITO_ID, sizeof(EL_TORITO_ID));
/*
* search from root of iso fs to find boot catalog
*/
de2 = search_tree_file(root, boot_catalog);
if (!de2)
{
fprintf(stderr,"Uh oh, I cant find the boot catalog!\n");
exit(1);
}
set_731(boot_desc->bootcat_ptr,
(unsigned int) get_733(de2->isorec.extent));
/*
* now adjust boot catalog
* lets find boot image first
*/
de=search_tree_file(root, boot_image);
if (!de)
{
fprintf(stderr,"Uh oh, I cant find the boot image!\n");
exit(1);
}
/*
* we have the boot image, so write boot catalog information
* Next we write out the primary descriptor for the disc
*/
memset(&valid_desc, 0, sizeof(valid_desc));
valid_desc.headerid[0] = 1;
valid_desc.arch[0] = EL_TORITO_ARCH_x86;
/*
* we'll shove start of publisher id into id field, may get truncated
* but who really reads this stuff!
*/
if (publisher)
memcpy_max(valid_desc.id, publisher, MIN(23, strlen(publisher)));
valid_desc.key1[0] = 0x55;
valid_desc.key2[0] = 0xAA;
/*
* compute the checksum
*/
checksum=0;
checksum_ptr = (unsigned char *) &valid_desc;
for (i=0; i<sizeof(valid_desc); i+=2)
{
/*
* skip adding in ckecksum word, since we dont have it yet!
*/
if (i == 28)
{
continue;
}
checksum += (unsigned int)checksum_ptr[i];
checksum += ((unsigned int)checksum_ptr[i+1])*256;
}
/*
* now find out the real checksum
*/
checksum = -checksum;
set_721(valid_desc.cksum, (unsigned int) checksum);
/*
* now make the initial/default entry for boot catalog
*/
memset(&default_desc, 0, sizeof(default_desc));
default_desc.boot_id[0] = EL_TORITO_BOOTABLE;
/*
* use default BIOS loadpnt
*/
set_721(default_desc.loadseg, 0);
default_desc.arch[0] = EL_TORITO_ARCH_x86;
/*
* figure out size of boot image in sectors, for now hard code to
* assume 512 bytes/sector on a bootable floppy
*/
nsectors = ((de->size + 511) & ~(511))/512;
printf("\nSize of boot image is %d sectors -> ", nsectors);
/*
* choose size of emulated floppy based on boot image size
*/
if (nsectors == 2880 )
{
default_desc.boot_media[0] = EL_TORITO_MEDIA_144FLOP;
printf("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");
}
else if (nsectors == 2400 )
{
default_desc.boot_media[0] = EL_TORITO_MEDIA_12FLOP;
printf("Emulating a 1.2 meg floppy\n");
}
else
{
fprintf(stderr,"\nError - boot image is not the an allowable size.\n");
exit(1);
}
/*
* FOR NOW LOAD 1 SECTOR, JUST LIKE FLOPPY BOOT!!!
*/
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));
#endif
set_731(default_desc.bootoff,
(unsigned int) get_733(de->isorec.extent));
/*
* now write it to disk
*/
bootcat = open(de2->whole_name, O_RDWR);
if (bootcat == -1)
{
fprintf(stderr,"Error opening boot catalog for update.\n");
perror("");
exit(1);
}
/*
* write out
*/
write(bootcat, &valid_desc, 32);
write(bootcat, &default_desc, 32);
close(bootcat);
} /* get_torito_desc(... */

10
util/mkisofs/exclude.h Normal file
View file

@ -0,0 +1,10 @@
/*
* 9-Dec-93 R.-D. Marzusch, marzusch@odiehh.hanse.de:
* added 'exclude' option (-x) to specify pathnames NOT to be included in
* CD image.
*
* $Id: exclude.h,v 1.1 1997/02/23 15:53:19 eric Rel $
*/
void exclude();
int is_excluded();

226
util/mkisofs/fnmatch.c Normal file
View file

@ -0,0 +1,226 @@
/* Copyright (C) 1991, 1992, 1993 Free Software Foundation, Inc.
NOTE: The canonical source of this file is maintained with the GNU C Library.
Bugs can be reported to bug-glibc@prep.ai.mit.edu.
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, 675 Mass Ave, Cambridge, MA 02139, USA. */
static char rcsid[] ="$Id: fnmatch.c,v 1.3 1997/03/22 02:53:13 eric Rel $";
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <errno.h>
#include <fnmatch.h>
#ifndef FNM_FILE_NAME
#define FNM_FILE_NAME FNM_PATHNAME /* Preferred GNU name. */
#endif
#ifndef FNM_LEADING_DIR
#define FNM_LEADING_DIR (1 << 3) /* Ignore `/...' after a match. */
#endif
#ifndef FNM_CASEFOLD
#define FNM_CASEFOLD (1 << 4) /* Compare without regard to case. */
#endif
#include <ctype.h>
#if defined (STDC_HEADERS) || !defined (isascii)
#define ISASCII(c) 1
#else
#define ISASCII(c) isascii(c)
#endif
#define ISUPPER(c) (ISASCII (c) && isupper (c))
/* 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. */
#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
#if !defined(__GNU_LIBRARY__) && !defined(STDC_HEADERS)
extern int errno;
#endif
/* Match STRING against the filename pattern PATTERN, returning zero if
it matches, nonzero if not. */
int
fnmatch (pattern, string, flags)
const char *pattern;
const char *string;
int flags;
{
register const char *p = pattern, *n = string;
register char c;
/* Note that this evalutes C many times. */
#define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c))
while ((c = *p++) != '\0')
{
c = FOLD (c);
switch (c)
{
case '?':
if (*n == '\0')
return FNM_NOMATCH;
else if ((flags & FNM_FILE_NAME) && *n == '/')
return FNM_NOMATCH;
else if ((flags & FNM_PERIOD) && *n == '.' &&
(n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
return FNM_NOMATCH;
break;
case '\\':
if (!(flags & FNM_NOESCAPE))
{
c = *p++;
c = FOLD (c);
}
if (FOLD (*n) != c)
return FNM_NOMATCH;
break;
case '*':
if ((flags & FNM_PERIOD) && *n == '.' &&
(n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
return FNM_NOMATCH;
for (c = *p++; c == '?' || c == '*'; c = *p++, ++n)
if (((flags & FNM_FILE_NAME) && *n == '/') ||
(c == '?' && *n == '\0'))
return FNM_NOMATCH;
if (c == '\0')
return 0;
{
char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
c1 = FOLD (c1);
for (--p; *n != '\0'; ++n)
if ((c == '[' || FOLD (*n) == c1) &&
fnmatch (p, n, flags & ~FNM_PERIOD) == 0)
return 0;
return FNM_NOMATCH;
}
case '[':
{
/* Nonzero if the sense of the character class is inverted. */
register int not;
if (*n == '\0')
return FNM_NOMATCH;
if ((flags & FNM_PERIOD) && *n == '.' &&
(n == string || ((flags & FNM_FILE_NAME) && n[-1] == '/')))
return FNM_NOMATCH;
not = (*p == '!' || *p == '^');
if (not)
++p;
c = *p++;
for (;;)
{
register char cstart = c, cend = c;
if (!(flags & FNM_NOESCAPE) && c == '\\')
cstart = cend = *p++;
cstart = cend = FOLD (cstart);
if (c == '\0')
/* [ (unterminated) loses. */
return FNM_NOMATCH;
c = *p++;
c = FOLD (c);
if ((flags & FNM_FILE_NAME) && c == '/')
/* [/] can never match. */
return FNM_NOMATCH;
if (c == '-' && *p != ']')
{
cend = *p++;
if (!(flags & FNM_NOESCAPE) && cend == '\\')
cend = *p++;
if (cend == '\0')
return FNM_NOMATCH;
cend = FOLD (cend);
c = *p++;
}
if (FOLD (*n) >= cstart && FOLD (*n) <= cend)
goto matched;
if (c == ']')
break;
}
if (!not)
return FNM_NOMATCH;
break;
matched:;
/* Skip the rest of the [...] that already matched. */
while (c != ']')
{
if (c == '\0')
/* [... (unterminated) loses. */
return FNM_NOMATCH;
c = *p++;
if (!(flags & FNM_NOESCAPE) && c == '\\')
/* XXX 1003.2d11 is unclear if this is right. */
++p;
}
if (not)
return FNM_NOMATCH;
}
break;
default:
if (c != FOLD (*n))
return FNM_NOMATCH;
}
++n;
}
if (*n == '\0')
return 0;
if ((flags & FNM_LEADING_DIR) && *n == '/')
/* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */
return 0;
return FNM_NOMATCH;
}
#endif /* _LIBC or not __GNU_LIBRARY__. */

226
util/mkisofs/hash.c Normal file
View file

@ -0,0 +1,226 @@
/*
* File hash.c - generate hash tables for iso9660 filesystem.
Written by Eric Youngdale (1993).
Copyright 1993 Yggdrasil Computing, Incorporated
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: hash.c,v 1.2 1997/02/23 16:11:15 eric Rel $";
#include <stdlib.h>
#include "mkisofs.h"
#define NR_HASH 1024
#define HASH_FN(DEV, INO) ((DEV + INO + (INO >> 2) + (INO << 8)) % NR_HASH)
static struct file_hash * hash_table[NR_HASH] = {0,};
void FDECL1(add_hash, struct directory_entry *, spnt){
struct file_hash * s_hash;
unsigned int hash_number;
if(spnt->size == 0 || spnt->starting_block == 0)
if(spnt->size != 0 || spnt->starting_block != 0) {
fprintf(stderr,"Non zero-length file assigned zero extent.\n");
exit(1);
};
if (spnt->dev == (dev_t) UNCACHED_DEVICE || spnt->inode == UNCACHED_INODE) return;
hash_number = HASH_FN((unsigned int) spnt->dev, (unsigned int) spnt->inode);
#if 0
if (verbose) fprintf(stderr,"%s ",spnt->name);
#endif
s_hash = (struct file_hash *) e_malloc(sizeof(struct file_hash));
s_hash->next = hash_table[hash_number];
s_hash->inode = spnt->inode;
s_hash->dev = spnt->dev;
s_hash->starting_block = spnt->starting_block;
s_hash->size = spnt->size;
hash_table[hash_number] = s_hash;
}
struct file_hash * FDECL2(find_hash, dev_t, dev, ino_t, inode){
unsigned int hash_number;
struct file_hash * spnt;
hash_number = HASH_FN((unsigned int) dev, (unsigned int) inode);
if (dev == (dev_t) UNCACHED_DEVICE || inode == UNCACHED_INODE) return NULL;
spnt = hash_table[hash_number];
while(spnt){
if(spnt->inode == inode && spnt->dev == dev) return spnt;
spnt = spnt->next;
};
return NULL;
}
static struct file_hash * directory_hash_table[NR_HASH] = {0,};
void FDECL2(add_directory_hash, dev_t, dev, ino_t, inode){
struct file_hash * s_hash;
unsigned int hash_number;
if (dev == (dev_t) UNCACHED_DEVICE || inode == UNCACHED_INODE) return;
hash_number = HASH_FN((unsigned int) dev, (unsigned int) inode);
s_hash = (struct file_hash *) e_malloc(sizeof(struct file_hash));
s_hash->next = directory_hash_table[hash_number];
s_hash->inode = inode;
s_hash->dev = dev;
directory_hash_table[hash_number] = s_hash;
}
struct file_hash * FDECL2(find_directory_hash, dev_t, dev, ino_t, inode){
unsigned int hash_number;
struct file_hash * spnt;
hash_number = HASH_FN((unsigned int) dev, (unsigned int) inode);
if (dev == (dev_t) UNCACHED_DEVICE || inode == UNCACHED_INODE) return NULL;
spnt = directory_hash_table[hash_number];
while(spnt){
if(spnt->inode == inode && spnt->dev == dev) return spnt;
spnt = spnt->next;
};
return NULL;
}
struct name_hash
{
struct name_hash * next;
struct directory_entry * de;
};
#define NR_NAME_HASH 128
static struct name_hash * name_hash_table[NR_NAME_HASH] = {0,};
/*
* Find the hash bucket for this name.
*/
static unsigned int FDECL1(name_hash, const char *, name)
{
unsigned int hash = 0;
const char * p;
p = name;
while (*p)
{
/*
* Don't hash the iso9660 version number. This way
* we can detect duplicates in cases where we have
* directories (i.e. foo) and non-directories
* (i.e. foo;1).
*/
if( *p == ';' )
{
break;
}
hash = (hash << 15) + (hash << 3) + (hash >> 3) + *p++;
}
return hash % NR_NAME_HASH;
}
void FDECL1(add_file_hash, struct directory_entry *, de){
struct name_hash * new;
int hash;
new = (struct name_hash *) e_malloc(sizeof(struct name_hash));
new->de = de;
new->next = NULL;
hash = name_hash(de->isorec.name);
/* Now insert into the hash table */
new->next = name_hash_table[hash];
name_hash_table[hash] = new;
}
struct directory_entry * FDECL1(find_file_hash, char *, name)
{
struct name_hash * nh;
char * p1;
char * p2;
for(nh = name_hash_table[name_hash(name)]; nh; nh = nh->next)
{
p1 = name;
p2 = nh->de->isorec.name;
/*
* Look for end of string, or a mismatch.
*/
while(1==1)
{
if( (*p1 == '\0' || *p1 == ';')
|| (*p2 == '\0' || *p2 == ';')
|| (*p1 != *p2) )
{
break;
}
p1++;
p2++;
}
/*
* If we are at the end of both strings, then
* we have a match.
*/
if( (*p1 == '\0' || *p1 == ';')
&& (*p2 == '\0' || *p2 == ';') )
{
return nh->de;
}
}
return NULL;
}
int FDECL1(delete_file_hash, struct directory_entry *, de){
struct name_hash * nh, *prev;
int hash;
prev = NULL;
hash = name_hash(de->isorec.name);
for(nh = name_hash_table[hash]; nh; nh = nh->next) {
if(nh->de == de) break;
prev = nh;
}
if(!nh) return 1;
if(!prev)
name_hash_table[hash] = nh->next;
else
prev->next = nh->next;
free(nh);
return 0;
}
void flush_file_hash(){
struct name_hash * nh, *nh1;
int i;
for(i=0; i<NR_NAME_HASH; i++) {
nh = name_hash_table[i];
while(nh) {
nh1 = nh->next;
free(nh);
nh = nh1;
}
name_hash_table[i] = NULL;
}
}

157
util/mkisofs/iso9660.h Normal file
View file

@ -0,0 +1,157 @@
/*
* Header file iso9660.h - assorted structure definitions and typecasts.
* specific to iso9660 filesystem.
Written by Eric Youngdale (1993).
Copyright 1993 Yggdrasil Computing, Incorporated
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. */
/*
* $Id: iso9660.h,v 1.1 1997/02/23 15:55:25 eric Rel $
*/
#ifndef _ISOFS_FS_H
#define _ISOFS_FS_H
/*
* The isofs filesystem constants/structures
*/
/* This part borrowed from the bsd386 isofs */
#define ISODCL(from, to) (to - from + 1)
struct iso_volume_descriptor {
char type[ISODCL(1,1)]; /* 711 */
char id[ISODCL(2,6)];
char version[ISODCL(7,7)];
char data[ISODCL(8,2048)];
};
/* volume descriptor types */
#define ISO_VD_PRIMARY 1
#define ISO_VD_END 255
#define ISO_STANDARD_ID "CD001"
#define EL_TORITO_ID "EL TORITO SPECIFICATION"
#define EL_TORITO_ARCH_x86 0
#define EL_TORITO_ARCH_PPC 1
#define EL_TORITO_ARCH_MAC 2
#define EL_TORITO_BOOTABLE 0x88
#define EL_TORITO_MEDIA_NOEMUL 0
#define EL_TORITO_MEDIA_12FLOP 1
#define EL_TORITO_MEDIA_144FLOP 2
#define EL_TORITO_MEDIA_288FLOP 3
#define EL_TORITO_MEDIA_HD 4
struct iso_primary_descriptor {
char type [ISODCL ( 1, 1)]; /* 711 */
char id [ISODCL ( 2, 6)];
char version [ISODCL ( 7, 7)]; /* 711 */
char unused1 [ISODCL ( 8, 8)];
char system_id [ISODCL ( 9, 40)]; /* achars */
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 volume_set_size [ISODCL (121, 124)]; /* 723 */
char volume_sequence_number [ISODCL (125, 128)]; /* 723 */
char logical_block_size [ISODCL (129, 132)]; /* 723 */
char path_table_size [ISODCL (133, 140)]; /* 733 */
char type_l_path_table [ISODCL (141, 144)]; /* 731 */
char opt_type_l_path_table [ISODCL (145, 148)]; /* 731 */
char type_m_path_table [ISODCL (149, 152)]; /* 732 */
char opt_type_m_path_table [ISODCL (153, 156)]; /* 732 */
char root_directory_record [ISODCL (157, 190)]; /* 9.1 */
char volume_set_id [ISODCL (191, 318)]; /* dchars */
char publisher_id [ISODCL (319, 446)]; /* achars */
char preparer_id [ISODCL (447, 574)]; /* achars */
char application_id [ISODCL (575, 702)]; /* achars */
char copyright_file_id [ISODCL (703, 739)]; /* 7.5 dchars */
char abstract_file_id [ISODCL (740, 776)]; /* 7.5 dchars */
char bibliographic_file_id [ISODCL (777, 813)]; /* 7.5 dchars */
char creation_date [ISODCL (814, 830)]; /* 8.4.26.1 */
char modification_date [ISODCL (831, 847)]; /* 8.4.26.1 */
char expiration_date [ISODCL (848, 864)]; /* 8.4.26.1 */
char effective_date [ISODCL (865, 881)]; /* 8.4.26.1 */
char file_structure_version [ISODCL (882, 882)]; /* 711 */
char unused4 [ISODCL (883, 883)];
char application_data [ISODCL (884, 1395)];
char unused5 [ISODCL (1396, 2048)];
};
/* El Torito Boot Record Volume Descriptor */
struct eltorito_boot_descriptor {
char id [ISODCL ( 1, 1)]; /* 711 */
char id2 [ISODCL ( 2, 6)];
char version [ISODCL ( 7, 7)]; /* 711 */
char system_id [ISODCL ( 8, 39)];
char unused2 [ISODCL ( 40, 71)];
char bootcat_ptr [ISODCL ( 72 , 75)];
char unused5 [ISODCL ( 76, 2048)];
};
/* Validation entry for El Torito */
struct eltorito_validation_entry {
char headerid [ISODCL ( 1, 1)]; /* 711 */
char arch [ISODCL ( 2, 2)];
char pad1 [ISODCL ( 3, 4)]; /* 711 */
char id [ISODCL ( 5, 28)];
char cksum [ISODCL ( 29, 30)];
char key1 [ISODCL ( 31, 31)];
char key2 [ISODCL ( 32, 32)];
};
/* El Torito initial/default entry in boot catalog */
struct eltorito_defaultboot_entry {
char boot_id [ISODCL ( 1, 1)]; /* 711 */
char boot_media [ISODCL ( 2, 2)];
char loadseg [ISODCL ( 3, 4)]; /* 711 */
char arch [ISODCL ( 5, 5)];
char pad1 [ISODCL ( 6, 6)];
char nsect [ISODCL ( 7, 8)];
char bootoff [ISODCL ( 9, 12)];
char pad2 [ISODCL ( 13, 32)];
};
/* We use this to help us look up the parent inode numbers. */
struct iso_path_table{
unsigned char name_len[2]; /* 721 */
char extent[4]; /* 731 */
char parent[2]; /* 721 */
char name[1];
};
struct iso_directory_record {
unsigned char length [ISODCL (1, 1)]; /* 711 */
char ext_attr_length [ISODCL (2, 2)]; /* 711 */
char extent [ISODCL (3, 10)]; /* 733 */
char size [ISODCL (11, 18)]; /* 733 */
char date [ISODCL (19, 25)]; /* 7 by 711 */
char flags [ISODCL (26, 26)];
char file_unit_size [ISODCL (27, 27)]; /* 711 */
char interleave [ISODCL (28, 28)]; /* 711 */
char volume_sequence_number [ISODCL (29, 32)]; /* 723 */
unsigned char name_len [ISODCL (33, 33)]; /* 711 */
char name [34]; /* Not really, but we need something here */
};
#endif

56
util/mkisofs/match.c Normal file
View file

@ -0,0 +1,56 @@
/*
* 27-Mar-96: Jan-Piet Mens <jpm@mens.de>
* added 'match' option (-m) to specify regular expressions NOT to be included
* in the CD image.
*/
static char rcsid[] ="$Id: match.c,v 1.2 1997/02/23 16:10:42 eric Rel $";
#include <stdio.h>
#ifndef VMS
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#else
#include <stdlib.h>
#endif
#endif
#include <string.h>
#include "match.h"
#define MAXMATCH 1000
static char *mat[MAXMATCH];
void add_match(fn)
char * fn;
{
register int i;
for (i=0; mat[i] && i<MAXMATCH; i++);
if (i == MAXMATCH) {
fprintf(stderr,"Can't exclude RE '%s' - too many entries in table\n",fn);
return;
}
mat[i] = (char *) malloc(strlen(fn)+1);
if (! mat[i]) {
fprintf(stderr,"Can't allocate memory for excluded filename\n");
return;
}
strcpy(mat[i],fn);
}
int matches(fn)
char * fn;
{
/* very dumb search method ... */
register int i;
for (i=0; mat[i] && i<MAXMATCH; i++) {
if (fnmatch(mat[i], fn, FNM_FILE_NAME) != FNM_NOMATCH) {
return 1; /* found -> excluded filenmae */
}
}
return 0; /* not found -> not excluded */
}

14
util/mkisofs/match.h Normal file
View file

@ -0,0 +1,14 @@
/*
* 27th March 1996. Added by Jan-Piet Mens for matching regular expressions
* in paths.
*
*/
/*
* $Id: match.h,v 1.1 1997/02/23 15:56:12 eric Rel $
*/
#include "fnmatch.h"
void add_match();
int matches();

660
util/mkisofs/mkisofs.c Normal file
View file

@ -0,0 +1,660 @@
/*
* Program mkisofs.c - generate iso9660 filesystem based upon directory
* tree on hard disk.
Written by Eric Youngdale (1993).
Copyright 1993 Yggdrasil Computing, Incorporated
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: 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 */
#include <errno.h>
#include "mkisofs.h"
#include "config.h"
#ifdef linux
#include <getopt.h>
#endif
#include "iso9660.h"
#include <ctype.h>
#ifndef VMS
#include <time.h>
#else
#include <sys/time.h>
#include "vms.h"
#endif
#include <stdlib.h>
#include <sys/stat.h>
#ifndef VMS
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#endif
#include "exclude.h"
#ifdef __NetBSD__
#include <sys/time.h>
#include <sys/resource.h>
#endif
struct directory * root = NULL;
static char version_string[] = "mkisofs v1.11.3";
FILE * discimage;
unsigned int next_extent = 0;
unsigned int last_extent = 0;
unsigned int session_start = 0;
unsigned int path_table_size = 0;
unsigned int path_table[4] = {0,};
unsigned int path_blocks = 0;
struct iso_directory_record root_record;
char * extension_record = NULL;
int extension_record_extent = 0;
static 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 all_files = 0;
int follow_links = 0;
int rationalize = 0;
int generate_tables = 0;
char * preparer = PREPARER_DEFAULT;
char * publisher = PUBLISHER_DEFAULT;
char * appid = APPID_DEFAULT;
char * copyright = COPYRIGHT_DEFAULT;
char * biblio = BIBLIO_DEFAULT;
char * abstract = ABSTRACT_DEFAULT;
char * volset_id = VOLSET_ID_DEFAULT;
char * volume_id = VOLUME_ID_DEFAULT;
char * system_id = SYSTEM_ID_DEFAULT;
char * boot_catalog = BOOT_CATALOG_DEFAULT;
char * boot_image = BOOT_IMAGE_DEFAULT;
int omit_period = 0; /* Violates iso9660, but these are a pain */
int transparent_compression = 0; /* So far only works with linux */
int omit_version_number = 0; /* May violate iso9660, but noone uses vers*/
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 */
struct rcopts{
char * tag;
char ** variable;
};
struct rcopts rcopt[] = {
{"PREP", &preparer},
{"PUBL", &publisher},
{"APPI", &appid},
{"COPY", &copyright},
{"BIBL", &biblio},
{"ABST", &abstract},
{"VOLS", &volset_id},
{"VOLI", &volume_id},
{"SYSI", &system_id},
{NULL, NULL}
};
#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;}
#endif
void FDECL1(read_rcfile, char *, appname)
{
FILE * rcfile;
struct rcopts * rco;
char * pnt, *pnt1;
char linebuffer[256];
static char rcfn[] = ".mkisofsrc";
char filename[1000];
int linum;
strcpy(filename, rcfn);
rcfile = fopen(filename, "r");
if (!rcfile && errno != ENOENT)
perror(filename);
if (!rcfile)
{
pnt = getenv("MKISOFSRC");
if (pnt && strlen(pnt) <= sizeof(filename))
{
strcpy(filename, pnt);
rcfile = fopen(filename, "r");
if (!rcfile && errno != ENOENT)
perror(filename);
}
}
if (!rcfile)
{
pnt = getenv("HOME");
if (pnt && strlen(pnt) + strlen(rcfn) + 2 <= sizeof(filename))
{
strcpy(filename, pnt);
strcat(filename, "/");
strcat(filename, rcfn);
rcfile = fopen(filename, "r");
if (!rcfile && errno != ENOENT)
perror(filename);
}
}
if (!rcfile && strlen(appname)+sizeof(rcfn)+2 <= sizeof(filename))
{
strcpy(filename, appname);
pnt = strrchr(filename, '/');
if (pnt)
{
strcpy(pnt + 1, rcfn);
rcfile = fopen(filename, "r");
if (!rcfile && errno != ENOENT)
perror(filename);
}
}
if (!rcfile)
return;
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))
{
char *name;
char *name_end;
++linum;
/* skip any leading white space */
pnt = linebuffer;
while (*pnt == ' ' || *pnt == '\t')
++pnt;
/* If we are looking at a # character, this line is a comment. */
if (*pnt == '#')
continue;
/* The name should begin in the left margin. Make sure it is in
upper case. Stop when we see white space or a comment. */
name = pnt;
while (*pnt && isalpha(*pnt))
{
if(islower(*pnt))
*pnt = toupper(*pnt);
pnt++;
}
if (name == pnt)
{
fprintf(stderr, "%s:%d: name required\n", filename, linum);
continue;
}
name_end = pnt;
/* Skip past white space after the name */
while (*pnt == ' ' || *pnt == '\t')
pnt++;
/* silently ignore errors in the rc file. */
if (*pnt != '=')
{
fprintf(stderr, "%s:%d: equals sign required\n", filename, linum);
continue;
}
/* Skip pas the = sign, and any white space following it */
pnt++; /* Skip past '=' sign */
while (*pnt == ' ' || *pnt == '\t')
pnt++;
/* now it is safe to NUL terminate the name */
*name_end = 0;
/* Now get rid of trailing newline */
pnt1 = pnt;
while (*pnt1)
{
if (*pnt1 == '\n')
{
*pnt1 = 0;
break;
}
pnt1++;
};
/* OK, now figure out which option we have */
for(rco = rcopt; rco->tag; rco++) {
if(strcmp(rco->tag, name) == 0)
{
*rco->variable = strdup(pnt);
break;
};
}
if (rco->tag == NULL)
{
fprintf(stderr, "%s:%d: field name \"%s\" unknown\n", filename, linum,
name);
}
}
if (ferror(rcfile))
perror(filename);
fclose(rcfile);
}
char * path_table_l = NULL;
char * path_table_m = NULL;
int goof = 0;
void usage(){
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);
}
/*
* Fill in date in the iso9660 format
*
* The standards state that the timezone offset is in multiples of 15
* minutes, and is what you add to GMT to get the localtime. The U.S.
* is always at a negative offset, from -5h to -8h (can vary a little
* with DST, I guess). The Linux iso9660 filesystem has had the sign
* of this wrong for ages (mkisofs had it wrong too for the longest time).
*/
int FDECL2(iso9660_date,char *, result, time_t, ctime){
struct tm *local;
local = localtime(&ctime);
result[0] = local->tm_year;
result[1] = local->tm_mon + 1;
result[2] = local->tm_mday;
result[3] = local->tm_hour;
result[4] = local->tm_min;
result[5] = local->tm_sec;
/*
* Must recalculate proper timezone offset each time,
* as some files use daylight savings time and some don't...
*/
result[6] = local->tm_yday; /* save yday 'cause gmtime zaps it */
local = gmtime(&ctime);
local->tm_year -= result[0];
local->tm_yday -= result[6];
local->tm_hour -= result[3];
local->tm_min -= result[4];
if (local->tm_year < 0)
{
local->tm_yday = -1;
}
else
{
if (local->tm_year > 0) local->tm_yday = 1;
}
result[6] = -(local->tm_min + 60*(local->tm_hour + 24*local->tm_yday)) / 15;
return 0;
}
extern char * cdwrite_data;
int FDECL2(main, int, argc, char **, argv){
char * outfile;
struct directory_entry de;
unsigned long mem_start;
struct stat statbuf;
char * scan_tree;
char * merge_image = NULL;
struct iso_directory_record * mrootp = NULL;
int c;
#ifdef ADD_FILES
char *add_file_file = NULL;
#endif
if (argc < 2)
usage();
/* Get the defaults from the .mkisofsrc file */
read_rcfile(argv[0]);
outfile = NULL;
while ((c = getopt(argc, argv, "i:o:V:RrfvaTp:P:b:c:x:dDlLNzA:M:m:C:")) != EOF)
switch (c)
{
case 'C':
/*
* This is a temporary hack until cdwrite gets the proper hooks in
* it.
*/
cdwrite_data = optarg;
break;
case 'a':
all_files++;
break;
case 'b':
use_eltorito++;
boot_image = optarg; /* pathname of the boot image on cd */
if (boot_image == NULL) {
fprintf(stderr,"Required boot image pathname missing\n");
exit(1);
}
break;
case 'c':
use_eltorito++;
boot_catalog = optarg; /* pathname of the boot image on cd */
if (boot_catalog == NULL) {
fprintf(stderr,"Required boot catalog pathname missing\n");
exit(1);
}
break;
case 'A':
appid = optarg;
if(strlen(appid) > 128) {
fprintf(stderr,"Application-id string too long\n");
exit(1);
};
break;
case 'd':
omit_period++;
break;
case 'D':
RR_relocation_depth = 32767;
break;
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;
case 'L':
allow_leading_dots++;
break;
case 'M':
merge_image = optarg;
break;
case 'N':
omit_version_number++;
break;
case 'o':
outfile = optarg;
break;
case 'p':
preparer = optarg;
if(strlen(preparer) > 128) {
fprintf(stderr,"Preparer string too long\n");
exit(1);
};
break;
case 'P':
publisher = optarg;
if(strlen(publisher) > 128) {
fprintf(stderr,"Publisher string too long\n");
exit(1);
};
break;
case 'R':
use_RockRidge++;
break;
case 'r':
rationalize++;
use_RockRidge++;
break;
case 'T':
generate_tables++;
break;
case 'V':
volume_id = optarg;
break;
case 'v':
verbose++;
break;
case 'z':
#ifdef VMS
fprintf(stderr,"Transparent compression not supported with VMS\n");
exit(1);
#else
transparent_compression++;
#endif
break;
case 'm':
add_match(optarg);
break;
case 'x':
exclude(optarg);
break;
default:
usage();
exit(1);
}
#ifdef __NetBSD__
{
int resource;
struct rlimit rlp;
if (getrlimit(RLIMIT_DATA,&rlp) == -1)
perror("Warning: getrlimit");
else {
rlp.rlim_cur=33554432;
if (setrlimit(RLIMIT_DATA,&rlp) == -1)
perror("Warning: setrlimit");
}
}
#endif
#ifdef HAVE_SBRK
mem_start = (unsigned long) sbrk(0);
#endif
if(verbose) fprintf(stderr,"%s\n", version_string);
if( (cdwrite_data != NULL && merge_image == NULL)
|| (cdwrite_data == NULL && merge_image != NULL) )
{
fprintf(stderr,"Multisession usage bug - both -C and -M must be specified.\n");
exit(0);
}
/* The first step is to scan the directory tree, and take some notes */
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();
exit(1);
};
#ifndef VMS
if(scan_tree[strlen(scan_tree)-1] != '/') {
scan_tree = (char *) e_malloc(strlen(argv[optind])+2);
strcpy(scan_tree, argv[optind]);
strcat(scan_tree, "/");
};
#endif
if(use_RockRidge){
#if 1
extension_record = generate_rr_extension_record("RRIP_1991A",
"THE ROCK RIDGE INTERCHANGE PROTOCOL PROVIDES SUPPORT FOR POSIX FILE SYSTEM SEMANTICS",
"PLEASE CONTACT DISC PUBLISHER FOR SPECIFICATION SOURCE. SEE PUBLISHER IDENTIFIER IN PRIMARY VOLUME DESCRIPTOR FOR CONTACT INFORMATION.", &extension_record_size);
#else
extension_record = generate_rr_extension_record("IEEE_P1282",
"THE IEEE P1282 PROTOCOL PROVIDES SUPPORT FOR POSIX FILE SYSTEM SEMANTICS",
"PLEASE CONTACT THE IEEE STANDARDS DEPARTMENT, PISCATAWAY, NJ, USA FOR THE P1282 SPECIFICATION.", &extension_record_size);
#endif
}
/*
* See if boot catalog file exists in root directory, if not
* we will create it.
*/
if (use_eltorito)
init_boot_catalog(argv[optind]);
/*
* Find the device and inode number of the root directory.
* Record this in the hash table so we don't scan it more than
* once.
*/
stat_filter(argv[optind], &statbuf);
add_directory_hash(statbuf.st_dev, STAT_INODE(statbuf));
memset(&de, 0, sizeof(de));
de.filedir = root; /* We need this to bootstrap */
if( merge_image != NULL )
{
mrootp = merge_isofs(merge_image);
if( mrootp == NULL )
{
/*
* Complain and die.
*/
fprintf(stderr,"Unable to open previous session image %s\n",
merge_image);
exit(1);
}
memcpy(&de.isorec.extent, mrootp->extent, 8);
}
/*
* Scan the actual directory (and any we find below it)
* for files to write out to the output image.
*/
if (!scan_directory_tree(argv[optind], &de, mrootp))
{
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 */
if(reloc_dir) sort_n_finish(reloc_dir);
if (goof) exit(1);
/*
* OK, ready to write the file. Open it up, and generate the thing.
*/
if (outfile){
discimage = fopen(outfile, "w");
if (!discimage){
fprintf(stderr,"Unable to open disc image file\n");
exit(1);
};
} else
discimage = stdout;
/* Now assign addresses on the disc for the path table. */
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;
last_extent += path_table[2] - session_start + path_blocks;
/* The next free block */
/* The next step is to go through the directory tree and assign extent
numbers for all of the directories */
assign_directory_addresses(root);
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);
};
if (use_RockRidge && reloc_dir)
finish_cl_pl_entries();
/* 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();
if (verbose)
dump_tree(root);
if( in_image != NULL )
{
fclose(in_image);
}
iso_write(discimage);
#ifdef HAVE_SBRK
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);
#ifdef VMS
return 1;
#else
return 0;
#endif
}
void *
FDECL1(e_malloc, size_t, size)
{
void* pt = 0;
if( (size > 0) && ((pt=malloc(size))==NULL) ) {
fprintf(stderr, "Not enough memory\n");
exit (1);
}
return pt;
}

339
util/mkisofs/mkisofs.h Normal file
View file

@ -0,0 +1,339 @@
/*
* Header file mkisofs.h - assorted structure definitions and typecasts.
Written by Eric Youngdale (1993).
Copyright 1993 Yggdrasil Computing, Incorporated
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. */
/*
* $Id: mkisofs.h,v 1.5 1997/05/17 15:50:28 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
symlinks, devices, and so forth available. Just files and dirs */
#ifdef VMS
#define NON_UNIXFS
#endif
#ifdef DJGPP
#define NON_UNIXFS
#endif
#ifdef VMS
#include <sys/dir.h>
#define dirent direct
#else
#include <dirent.h>
#endif
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef linux
#include <sys/dir.h>
#endif
#ifdef ultrix
extern char *strdup();
#endif
#ifdef __STDC__
#define DECL(NAME,ARGS) NAME ARGS
#define FDECL1(NAME,TYPE0, ARG0) \
NAME(TYPE0 ARG0)
#define FDECL2(NAME,TYPE0, ARG0,TYPE1, ARG1) \
NAME(TYPE0 ARG0, TYPE1 ARG1)
#define FDECL3(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2) \
NAME(TYPE0 ARG0, TYPE1 ARG1, TYPE2 ARG2)
#define FDECL4(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2, TYPE3, ARG3) \
NAME(TYPE0 ARG0, TYPE1 ARG1, TYPE2 ARG2, TYPE3 ARG3)
#define FDECL5(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2, TYPE3, ARG3, TYPE4, ARG4) \
NAME(TYPE0 ARG0, TYPE1 ARG1, TYPE2 ARG2, TYPE3 ARG3, TYPE4 ARG4)
#define FDECL6(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2, TYPE3, ARG3, TYPE4, ARG4, TYPE5, ARG5) \
NAME(TYPE0 ARG0, TYPE1 ARG1, TYPE2 ARG2, TYPE3 ARG3, TYPE4 ARG4, TYPE5 ARG5)
#else
#define DECL(NAME,ARGS) NAME()
#define FDECL1(NAME,TYPE0, ARG0) NAME(ARG0) TYPE0 ARG0;
#define FDECL2(NAME,TYPE0, ARG0,TYPE1, ARG1) NAME(ARG0, ARG1) TYPE0 ARG0; TYPE1 ARG1;
#define FDECL3(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2) \
NAME(ARG0, ARG1, ARG2) TYPE0 ARG0; TYPE1 ARG1; TYPE2 ARG2;
#define FDECL4(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2, TYPE3, ARG3) \
NAME(ARG0, ARG1, ARG2, ARG3, ARG4) TYPE0 ARG0; TYPE1 ARG1; TYPE2 ARG2; TYPE3 ARG3;
#define FDECL5(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2, TYPE3, ARG3, TYPE4, ARG4) \
NAME(ARG0, ARG1, ARG2, ARG3, ARG4) TYPE0 ARG0; TYPE1 ARG1; TYPE2 ARG2; TYPE3 ARG3; TYPE4 ARG4;
#define FDECL6(NAME,TYPE0, ARG0,TYPE1, ARG1, TYPE2, ARG2, TYPE3, ARG3, TYPE4, ARG4, TYPE5, ARG5) \
NAME(ARG0, ARG1, ARG2, ARG3, ARG4, ARG5) TYPE0 ARG0; TYPE1 ARG1; TYPE2 ARG2; TYPE3 ARG3; TYPE4 ARG4; TYPE5 ARG5;
#define const
#endif
#ifdef __svr4__
#include <stdlib.h>
#else
extern int optind;
extern char *optarg;
/* extern int getopt (int __argc, char **__argv, char *__optstring); */
#endif
#include "iso9660.h"
#include "defaults.h"
struct directory_entry{
struct directory_entry * next;
struct iso_directory_record isorec;
unsigned int starting_block;
unsigned int size;
unsigned int priority;
char * name;
char * table;
char * whole_name;
struct directory * filedir;
struct directory_entry * parent_rec;
unsigned int de_flags;
ino_t inode; /* Used in the hash table */
dev_t dev; /* Used in the hash table */
unsigned char * rr_attributes;
unsigned int rr_attr_size;
unsigned int total_rr_attr_size;
};
struct file_hash{
struct file_hash * next;
ino_t inode; /* Used in the hash table */
dev_t dev; /* Used in the hash table */
unsigned int starting_block;
unsigned int size;
};
/*
* This structure describes one complete directory. It has pointers
* to other directories in the overall tree so that it is clear where
* this directory lives in the tree, and it also must contain pointers
* to the contents of the directory. Note that subdirectories of this
* directory exist twice in this stucture. Once in the subdir chain,
* and again in the contents chain.
*/
struct directory{
struct directory * next; /* Next directory at same level as this one */
struct directory * subdir; /* First subdirectory in this directory */
struct directory * parent;
struct directory_entry * contents;
struct directory_entry * self;
char * whole_name; /* Entire path */
char * de_name; /* Entire path */
unsigned int ce_bytes; /* Number of bytes of CE entries reqd for this dir */
unsigned int depth;
unsigned int size;
unsigned int extent;
unsigned short path_index;
};
struct deferred{
struct deferred * next;
unsigned int starting_block;
char * name;
struct directory * filedir;
unsigned int flags;
};
extern int goof;
extern struct directory * root;
extern struct directory * reloc_dir;
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 struct iso_directory_record root_record;
extern int use_eltorito;
extern int use_RockRidge;
extern int rationalize;
extern int follow_links;
extern int verbose;
extern int all_files;
extern int generate_tables;
extern int omit_period;
extern int omit_version_number;
extern int transparent_compression;
extern int RR_relocation_depth;
extern int full_iso9660_filenames;
/* 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 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));
/* 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 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));
/* multi.c */
extern FILE * in_image;
extern struct iso_directory_record *
DECL(merge_isofs,(char * path));
extern int DECL(free_mdinfo, (struct directory_entry **, int len));
extern struct directory_entry **
DECL(read_merging_directory,(struct iso_directory_record *, int*));
extern void
DECL(merge_remaining_entries, (struct directory *,
struct directory_entry **, int));
/* match.c */
extern int DECL(matches, (char *));
extern void DECL(add_match, (char *));
/* files.c */
struct dirent * DECL(readdir_add_files, (char **, char *, DIR *));
/* */
extern int DECL(iso9660_file_length,(const char* name,
struct directory_entry * sresult, int flag));
extern int DECL(iso9660_date,(char *, time_t));
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 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 *));
extern int DECL(generate_rock_ridge_attributes,(char *, char *,
struct directory_entry *,
struct stat *, struct stat *,
int deep_flag));
extern char * DECL(generate_rr_extension_record,(char * id, char * descriptor,
char * source, int * size));
extern int DECL(check_prev_session, (struct directory_entry **, int len,
struct directory_entry *,
struct stat *,
struct stat *,
struct directory_entry **));
#ifdef USE_SCG
/* scsi.c */
extern int readsecs(int startsecno, void *buffer, int sectorcount);
extern int scsidev_open(char *path);
#endif
extern char * extension_record;
extern int extension_record_extent;
extern int n_data_extents;
/* These are a few goodies that can be specified on the command line, and are
filled into the root record */
extern char * preparer;
extern char * publisher;
extern char * copyright;
extern char * biblio;
extern char * abstract;
extern char * appid;
extern char * volset_id;
extern char * system_id;
extern char * volume_id;
extern char * boot_catalog;
extern char * boot_image;
extern void * DECL(e_malloc,(size_t));
#define SECTOR_SIZE (2048)
#define ROUND_UP(X) ((X + (SECTOR_SIZE - 1)) & ~(SECTOR_SIZE - 1))
#define NEED_RE 1
#define NEED_PL 2
#define NEED_CL 4
#define NEED_CE 8
#define NEED_SP 16
#define PREV_SESS_DEV (sizeof(dev_t) >= 4 ? 0x7ffffffd : 0x7ffd)
#define TABLE_INODE (sizeof(ino_t) >= 4 ? 0x7ffffffe : 0x7ffe)
#define UNCACHED_INODE (sizeof(ino_t) >= 4 ? 0x7fffffff : 0x7fff)
#define UNCACHED_DEVICE (sizeof(dev_t) >= 4 ? 0x7fffffff : 0x7fff)
#ifdef VMS
#define STAT_INODE(X) (X.st_ino[0])
#define PATH_SEPARATOR ']'
#define SPATH_SEPARATOR ""
#else
#define STAT_INODE(X) (X.st_ino)
#define PATH_SEPARATOR '/'
#define SPATH_SEPARATOR "/"
#endif
/*
* When using multi-session, indicates that we can reuse the
* TRANS.TBL information for this directory entry. If this flag
* 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
/*
* Volume sequence number to use in all of the iso directory records.
*/
#define DEF_VSN 1
/*
* Make sure we have a definition for this. If not, take a very conservative
* guess. From what I can tell SunOS is the only one with this trouble.
*/
#ifndef NAME_MAX
#ifdef FILENAME_MAX
#define NAME_MAX FILENAME_MAX
#else
#define NAME_MAX 128
#endif
#endif

1018
util/mkisofs/multi.c Normal file

File diff suppressed because it is too large Load diff

390
util/mkisofs/name.c Normal file
View file

@ -0,0 +1,390 @@
/*
* File name.c - map full Unix file names to unique 8.3 names that
* would be valid on DOS.
*
Written by Eric Youngdale (1993).
Copyright 1993 Yggdrasil Computing, Incorporated
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: name.c,v 1.7 1997/11/09 16:42:51 eric Exp $";
#include "mkisofs.h"
#include <ctype.h>
extern int allow_leading_dots;
/*
* Function: iso9660_file_length
*
* Purpose: Map file name to 8.3 format, return length
* of result.
*
* Arguments: name file name we need to map.
* sresult directory entry structure to contain mapped name.
* dirflag flag indicating whether this is a directory or not.
*
* Notes: This procedure probably needs to be rationalized somehow.
* New options to affect the behavior of this function
* would also be nice to have.
*/
int FDECL3(iso9660_file_length,
const char*, name,
struct directory_entry *, sresult,
int, dirflag)
{
char * c;
int chars_after_dot = 0;
int chars_before_dot = 0;
int current_length = 0;
int extra = 0;
int ignore = 0;
char * last_dot;
const char * pnt;
int priority = 32767;
char * result;
int seen_dot = 0;
int seen_semic = 0;
int tildes = 0;
result = sresult->isorec.name;
/*
* For the '.' entry, generate the correct record, and return
* 1 for the length.
*/
if(strcmp(name,".") == 0)
{
if(result)
{
*result = 0;
}
return 1;
}
/*
* For the '..' entry, generate the correct record, and return
* 1 for the length.
*/
if(strcmp(name,"..") == 0)
{
if(result)
{
*result++ = 1;
*result++ = 0;
}
return 1;
}
/*
* Now scan the directory one character at a time, and figure out
* what to do.
*/
pnt = name;
/*
* Find the '.' that we intend to use for the extension. Usually this
* is the last dot, but if we have . followed by nothing or a ~, we
* would consider this to be unsatisfactory, and we keep searching.
*/
last_dot = strrchr (pnt,'.');
if( (last_dot != NULL)
&& ( (last_dot[1] == '~')
|| (last_dot[1] == '\0')
|| (last_dot[1] == '\0')) )
{
c = last_dot;
*c = '\0';
last_dot = strrchr (pnt,'.');
*c = '.';
}
while(*pnt)
{
#ifdef VMS
if( strcmp(pnt,".DIR;1") == 0 )
{
break;
}
#endif
/*
* This character indicates a Unix style of backup file
* generated by some editors. Lower the priority of
* the file.
*/
if(*pnt == '#')
{
priority = 1;
pnt++;
continue;
}
/*
* This character indicates a Unix style of backup file
* generated by some editors. Lower the priority of
* the file.
*/
if(*pnt == '~')
{
priority = 1;
tildes++;
pnt++;
continue;
}
/*
* This might come up if we had some joker already try and put
* iso9660 version numbers into the file names. This would be
* 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.
*/
if(*pnt == ';')
{
seen_semic = 1;
*result++ = *pnt++;
continue;
}
/*
* If we have a name with multiple '.' characters, we ignore everything
* after we have gotten the extension.
*/
if(ignore)
{
pnt++;
continue;
}
/*
* Spin past any iso9660 version number we might have.
*/
if(seen_semic)
{
if(*pnt >= '0' && *pnt <= '9')
{
*result++ = *pnt;
}
extra++;
pnt++;
continue;
}
/*
* If we have full names, the names we generate will not
* work on a DOS machine, since they are not guaranteed
* to be 8.3. Nonetheless, in many cases this is a useful
* option. We still only allow one '.' character in the
* name, however.
*/
if(full_iso9660_filenames)
{
/* Here we allow a more relaxed syntax. */
if(*pnt == '.')
{
if (seen_dot)
{
ignore++;
continue;
}
seen_dot++;
}
if(current_length < 30)
{
if( *pnt < 0 )
{
*result++ = '_';
}
else
{
*result++ = (islower(*pnt) ? toupper(*pnt) : *pnt);
}
}
}
else
{
/*
* Dos style filenames. We really restrict the
* names here.
*/
/* It would be nice to have .tar.gz transform to .tgz,
* .ps.gz to .psz, ...
*/
if(*pnt == '.')
{
if (!chars_before_dot && !allow_leading_dots)
{
/* DOS can't read files with dot first */
chars_before_dot++;
if (result)
{
*result++ = '_'; /* Substitute underscore */
}
}
else if( pnt != last_dot )
{
/*
* If this isn't the dot that we use for the extension,
* then change the character into a '_' instead.
*/
if(chars_before_dot < 8)
{
chars_before_dot++;
if(result)
{
*result++ = '_';
}
}
}
else
{
if (seen_dot)
{
ignore++; continue;
}
if(result)
{
*result++ = '.';
}
seen_dot++;
}
}
else
{
if( (seen_dot && (chars_after_dot < 3) && ++chars_after_dot)
|| (!seen_dot && (chars_before_dot < 8) && ++chars_before_dot) )
{
if(result)
{
switch (*pnt)
{
default:
if( *pnt < 0 )
{
*result++ = '_';
}
else
{
*result++ = islower(*pnt) ? toupper(*pnt) : *pnt;
}
break;
/*
* Descriptions of DOS's 'Parse Filename'
* (function 29H) describes V1 and V2.0+
* separator and terminator characters.
* These characters in a DOS name make
* the file visible but un-manipulable
* (all useful operations error off.
*/
/* separators */
case '+':
case '=':
case '%': /* not legal DOS filename */
case ':':
case ';': /* already handled */
case '.': /* already handled */
case ',': /* already handled */
case '\t':
case ' ':
/* V1 only separators */
case '/':
case '"':
case '[':
case ']':
/* terminators */
case '>':
case '<':
case '|':
/* Hmm - what to do here? Skip?
* Win95 looks like it substitutes '_'
*/
*result++ = '_';
break;
} /* switch (*pnt) */
} /* if (result) */
} /* if (chars_{after,before}_dot) ... */
} /* else *pnt == '.' */
} /* else DOS file names */
current_length++;
pnt++;
} /* while (*pnt) */
/*
* OK, that wraps up the scan of the name. Now tidy up a few other
* things.
*/
/*
* Look for emacs style of numbered backups, like foo.c.~3~. If
* we see this, convert the version number into the priority
* number. In case of name conflicts, this is what would end
* up being used as the 'extension'.
*/
if(tildes == 2)
{
int prio1 = 0;
pnt = name;
while (*pnt && *pnt != '~')
{
pnt++;
}
if (*pnt)
{
pnt++;
}
while(*pnt && *pnt != '~')
{
prio1 = 10*prio1 + *pnt - '0';
pnt++;
}
priority = prio1;
}
/*
* If this is not a directory, force a '.' in case we haven't
* seen one, and add a version number if we haven't seen one
* of those either.
*/
if (!dirflag)
{
if (!seen_dot && !omit_period)
{
if (result) *result++ = '.';
extra++;
}
if(!omit_version_number && !seen_semic)
{
if(result)
{
*result++ = ';';
*result++ = '1';
};
extra += 2;
}
}
if(result)
{
*result++ = 0;
}
sresult->priority = priority;
return (chars_before_dot + chars_after_dot + seen_dot + extra);
}

556
util/mkisofs/rock.c Normal file
View file

@ -0,0 +1,556 @@
/*
* File rock.c - generate RRIP records for iso9660 filesystems.
Written by Eric Youngdale (1993).
Copyright 1993 Yggdrasil Computing, Incorporated
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: rock.c,v 1.3 1997/05/17 15:45:26 eric Exp $";
#include <stdlib.h>
#include "config.h"
#ifndef VMS
#if defined(MAJOR_IN_SYSMACROS)
#include <sys/sysmacros.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#endif
#if defined(MAJOR_IN_MKDEV)
#include <sys/types.h>
#include <sys/mkdev.h>
#endif
#include "mkisofs.h"
#include "iso9660.h"
#include <string.h>
#ifdef NON_UNIXFS
#define S_ISLNK(m) (0)
#else
#ifndef S_ISLNK
#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
#endif
#endif
#define SU_VERSION 1
#define SL_ROOT 8
#define SL_PARENT 4
#define SL_CURRENT 2
#define SL_CONTINUE 1
#define CE_SIZE 28
#define CL_SIZE 12
#define ER_SIZE 8
#define NM_SIZE 5
#define PL_SIZE 12
#define PN_SIZE 20
#define PX_SIZE 36
#define RE_SIZE 4
#define SL_SIZE 20
#define ZZ_SIZE 15
#ifdef __QNX__
#define TF_SIZE (5 + 4 * 7)
#else
#define TF_SIZE (5 + 3 * 7)
#endif
/* If we need to store this number of bytes, make sure we
do not box ourselves in so that we do not have room for
a CE entry for the continuation record */
#define MAYBE_ADD_CE_ENTRY(BYTES) \
(BYTES + CE_SIZE + currlen + (ipnt - recstart) > reclimit ? 1 : 0)
/*
* Buffer to build RR attributes
*/
static unsigned char Rock[16384];
static unsigned char symlink_buff[256];
static int ipnt = 0;
static int recstart = 0;
static int currlen = 0;
static int mainrec = 0;
static int reclimit;
static void add_CE_entry(){
if(recstart)
set_733((char*)Rock + recstart - 8, ipnt + 28 - recstart);
Rock[ipnt++] ='C';
Rock[ipnt++] ='E';
Rock[ipnt++] = CE_SIZE;
Rock[ipnt++] = SU_VERSION;
set_733((char*)Rock + ipnt, 0);
ipnt += 8;
set_733((char*)Rock + ipnt, 0);
ipnt += 8;
set_733((char*)Rock + ipnt, 0);
ipnt += 8;
recstart = ipnt;
currlen = 0;
if(!mainrec) mainrec = ipnt;
reclimit = SECTOR_SIZE - 8; /* Limit to one sector */
}
#ifdef __STDC__
int generate_rock_ridge_attributes (char * whole_name, char * name,
struct directory_entry * s_entry,
struct stat * statbuf,
struct stat * lstatbuf,
int deep_opt)
#else
int generate_rock_ridge_attributes (whole_name, name,
s_entry,
statbuf,
lstatbuf,
deep_opt)
char * whole_name; char * name; struct directory_entry * s_entry;
struct stat * statbuf, *lstatbuf;
int deep_opt;
#endif
{
int flagpos, flagval;
int need_ce;
statbuf = statbuf; /* this shuts up unreferenced compiler warnings */
mainrec = recstart = ipnt = 0;
reclimit = 0xf8;
/* Obtain the amount of space that is currently used for the directory
record. Assume max for name, since name conflicts may cause us
to rename the file later on */
currlen = sizeof(s_entry->isorec);
/* Identify that we are using the SUSP protocol */
if(deep_opt & NEED_SP){
Rock[ipnt++] ='S';
Rock[ipnt++] ='P';
Rock[ipnt++] = 7;
Rock[ipnt++] = SU_VERSION;
Rock[ipnt++] = 0xbe;
Rock[ipnt++] = 0xef;
Rock[ipnt++] = 0;
};
/* First build the posix name field */
Rock[ipnt++] ='R';
Rock[ipnt++] ='R';
Rock[ipnt++] = 5;
Rock[ipnt++] = SU_VERSION;
flagpos = ipnt;
flagval = 0;
Rock[ipnt++] = 0; /* We go back and fix this later */
if(strcmp(name,".") && strcmp(name,"..")){
char * npnt;
int remain, use;
remain = strlen(name);
npnt = name;
while(remain){
use = remain;
need_ce = 0;
/* Can we fit this SUSP and a CE entry? */
if(use + currlen + CE_SIZE + (ipnt - recstart) > reclimit) {
use = reclimit - currlen - CE_SIZE - (ipnt - recstart);
need_ce++;
}
/* Only room for 256 per SUSP field */
if(use > 0xf8) use = 0xf8;
/* First build the posix name field */
Rock[ipnt++] ='N';
Rock[ipnt++] ='M';
Rock[ipnt++] = NM_SIZE + use;
Rock[ipnt++] = SU_VERSION;
Rock[ipnt++] = (remain != use ? 1 : 0);
flagval |= (1<<3);
strncpy((char *)&Rock[ipnt], npnt, use);
npnt += use;
ipnt += use;
remain -= use;
if(remain && need_ce) add_CE_entry();
};
};
/*
* Add the posix modes
*/
if(MAYBE_ADD_CE_ENTRY(PX_SIZE)) add_CE_entry();
Rock[ipnt++] ='P';
Rock[ipnt++] ='X';
Rock[ipnt++] = PX_SIZE;
Rock[ipnt++] = SU_VERSION;
flagval |= (1<<0);
set_733((char*)Rock + ipnt, lstatbuf->st_mode);
ipnt += 8;
set_733((char*)Rock + ipnt, lstatbuf->st_nlink);
ipnt += 8;
set_733((char*)Rock + ipnt, lstatbuf->st_uid);
ipnt += 8;
set_733((char*)Rock + ipnt, lstatbuf->st_gid);
ipnt += 8;
/*
* Check for special devices
*/
#ifndef NON_UNIXFS
if (S_ISCHR(lstatbuf->st_mode) || S_ISBLK(lstatbuf->st_mode)) {
if(MAYBE_ADD_CE_ENTRY(PN_SIZE)) add_CE_entry();
Rock[ipnt++] ='P';
Rock[ipnt++] ='N';
Rock[ipnt++] = PN_SIZE;
Rock[ipnt++] = SU_VERSION;
flagval |= (1<<1);
#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));
ipnt += 8;
#else
/*
* If we don't have sysmacros.h, then we have to guess as to how
* best to pick apart the device number for major/minor.
* Note: this may very well be wrong for many systems, so
* it is always best to use the major/minor macros if the
* system supports it.
*/
if(sizeof(dev_t) <= 2) {
set_733((char*)Rock + ipnt, (lstatbuf->st_rdev >> 8));
ipnt += 8;
set_733((char*)Rock + ipnt, lstatbuf->st_rdev & 0xff);
ipnt += 8;
}
else if(sizeof(dev_t) <= 4) {
set_733((char*)Rock + ipnt, (lstatbuf->st_rdev >> 8) >> 8);
ipnt += 8;
set_733((char*)Rock + ipnt, lstatbuf->st_rdev & 0xffff);
ipnt += 8;
}
else {
set_733((char*)Rock + ipnt, (lstatbuf->st_rdev >> 16) >> 16);
ipnt += 8;
set_733((char*)Rock + ipnt, lstatbuf->st_rdev);
ipnt += 8;
}
#endif
};
#endif
/*
* Check for and symbolic links. VMS does not have these.
*/
if (S_ISLNK(lstatbuf->st_mode)){
int lenpos, lenval, j0, j1;
int nchar;
unsigned char * cpnt, *cpnt1;
nchar = readlink(whole_name, symlink_buff, sizeof(symlink_buff));
symlink_buff[nchar < 0 ? 0 : nchar] = 0;
set_733(s_entry->isorec.size, 0);
cpnt = &symlink_buff[0];
flagval |= (1<<2);
while(nchar){
if(MAYBE_ADD_CE_ENTRY(SL_SIZE)) add_CE_entry();
Rock[ipnt++] ='S';
Rock[ipnt++] ='L';
lenpos = ipnt;
Rock[ipnt++] = SL_SIZE;
Rock[ipnt++] = SU_VERSION;
Rock[ipnt++] = 0; /* Flags */
lenval = 5;
while(*cpnt){
cpnt1 = (unsigned char *) strchr((char *) cpnt, '/');
if(cpnt1) {
nchar--;
*cpnt1 = 0;
};
/* We treat certain components in a special way. */
if(cpnt[0] == '.' && cpnt[1] == '.' && cpnt[2] == 0){
if(MAYBE_ADD_CE_ENTRY(2)) add_CE_entry();
Rock[ipnt++] = SL_PARENT;
Rock[ipnt++] = 0; /* length is zero */
lenval += 2;
nchar -= 2;
} else if(cpnt[0] == '.' && cpnt[1] == 0){
if(MAYBE_ADD_CE_ENTRY(2)) add_CE_entry();
Rock[ipnt++] = SL_CURRENT;
Rock[ipnt++] = 0; /* length is zero */
lenval += 2;
nchar -= 1;
} else if(cpnt[0] == 0){
if(MAYBE_ADD_CE_ENTRY(2)) add_CE_entry();
Rock[ipnt++] = SL_ROOT;
Rock[ipnt++] = 0; /* length is zero */
lenval += 2;
} 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;
}
j0 = strlen((char *) cpnt);
while(j0) {
j1 = j0;
if(j1 > 0xf8) j1 = 0xf8;
need_ce = 0;
if(j1 + currlen + CE_SIZE + (ipnt - recstart) > reclimit) {
j1 = reclimit - currlen - CE_SIZE - (ipnt - recstart);
need_ce++;
}
Rock[ipnt++] = (j1 != j0 ? SL_CONTINUE : 0);
Rock[ipnt++] = j1;
strncpy((char *) Rock + ipnt, (char *) cpnt, j1);
ipnt += j1;
lenval += j1 + 2;
cpnt += j1;
nchar -= j1; /* Number we processed this time */
j0 -= j1;
if(need_ce) {
add_CE_entry();
if(cpnt1) {
*cpnt1 = '/';
nchar++;
cpnt1 = NULL; /* A kluge so that we can restart properly */
}
break;
}
}
};
if(cpnt1) {
cpnt = cpnt1 + 1;
} else
break;
}
Rock[lenpos] = lenval;
if(nchar) Rock[lenpos + 2] = SL_CONTINUE; /* We need another SL entry */
} /* while nchar */
} /* Is a symbolic link */
/*
* Add in the Rock Ridge TF time field
*/
if(MAYBE_ADD_CE_ENTRY(TF_SIZE)) add_CE_entry();
Rock[ipnt++] ='T';
Rock[ipnt++] ='F';
Rock[ipnt++] = TF_SIZE;
Rock[ipnt++] = SU_VERSION;
#ifdef __QNX__
Rock[ipnt++] = 0x0f;
#else
Rock[ipnt++] = 0x0e;
#endif
flagval |= (1<<7);
#ifdef __QNX__
iso9660_date((char *) &Rock[ipnt], lstatbuf->st_ftime);
ipnt += 7;
#endif
iso9660_date((char *) &Rock[ipnt], lstatbuf->st_mtime);
ipnt += 7;
iso9660_date((char *) &Rock[ipnt], lstatbuf->st_atime);
ipnt += 7;
iso9660_date((char *) &Rock[ipnt], lstatbuf->st_ctime);
ipnt += 7;
/*
* Add in the Rock Ridge RE time field
*/
if(deep_opt & NEED_RE){
if(MAYBE_ADD_CE_ENTRY(RE_SIZE)) add_CE_entry();
Rock[ipnt++] ='R';
Rock[ipnt++] ='E';
Rock[ipnt++] = RE_SIZE;
Rock[ipnt++] = SU_VERSION;
flagval |= (1<<6);
};
/*
* Add in the Rock Ridge PL record, if required.
*/
if(deep_opt & NEED_PL){
if(MAYBE_ADD_CE_ENTRY(PL_SIZE)) add_CE_entry();
Rock[ipnt++] ='P';
Rock[ipnt++] ='L';
Rock[ipnt++] = PL_SIZE;
Rock[ipnt++] = SU_VERSION;
set_733((char*)Rock + ipnt, 0);
ipnt += 8;
flagval |= (1<<5);
};
/*
* Add in the Rock Ridge CL field, if required.
*/
if(deep_opt & NEED_CL){
if(MAYBE_ADD_CE_ENTRY(CL_SIZE)) add_CE_entry();
Rock[ipnt++] ='C';
Rock[ipnt++] ='L';
Rock[ipnt++] = CL_SIZE;
Rock[ipnt++] = SU_VERSION;
set_733((char*)Rock + ipnt, 0);
ipnt += 8;
flagval |= (1<<4);
};
#ifndef VMS
/* If transparent compression was requested, fill in the correct
field for this file */
if(transparent_compression &&
S_ISREG(lstatbuf->st_mode) &&
strlen(name) > 3 &&
strcmp(name + strlen(name) - 3,".gZ") == 0){
FILE * zipfile;
char * checkname;
unsigned int file_size;
unsigned char header[8];
int OK_flag;
/* First open file and verify that the correct algorithm was used */
file_size = 0;
OK_flag = 1;
zipfile = fopen(whole_name, "r");
fread(header, 1, sizeof(header), zipfile);
/* Check some magic numbers from gzip. */
if(header[0] != 0x1f || header[1] != 0x8b || header[2] != 8) OK_flag = 0;
/* Make sure file was blocksized. */
if(((header[3] & 0x40) == 0)) OK_flag = 0;
/* OK, now go to the end of the file and get some more info */
if(OK_flag){
int status;
status = (long)lseek(fileno(zipfile), (off_t)(-8), SEEK_END);
if(status == -1) OK_flag = 0;
}
if(OK_flag){
if(read(fileno(zipfile), (char*)header, sizeof(header)) != sizeof(header))
OK_flag = 0;
else {
int blocksize;
blocksize = (header[3] << 8) | header[2];
file_size = ((unsigned int)header[7] << 24) |
((unsigned int)header[6] << 16) |
((unsigned int)header[5] << 8) | header[4];
#if 0
fprintf(stderr,"Blocksize = %d %d\n", blocksize, file_size);
#endif
if(blocksize != SECTOR_SIZE) OK_flag = 0;
}
}
fclose(zipfile);
checkname = strdup(whole_name);
checkname[strlen(whole_name)-3] = 0;
zipfile = fopen(checkname, "r");
if(zipfile) {
OK_flag = 0;
fprintf(stderr,"Unable to insert transparent compressed file - name conflict\n");
fclose(zipfile);
}
free(checkname);
if(OK_flag){
if(MAYBE_ADD_CE_ENTRY(ZZ_SIZE)) add_CE_entry();
Rock[ipnt++] ='Z';
Rock[ipnt++] ='Z';
Rock[ipnt++] = ZZ_SIZE;
Rock[ipnt++] = SU_VERSION;
Rock[ipnt++] = 'g'; /* Identify compression technique used */
Rock[ipnt++] = 'z';
Rock[ipnt++] = 3;
set_733((char*)Rock + ipnt, file_size); /* Real file size */
ipnt += 8;
};
}
#endif
/*
* Add in the Rock Ridge CE field, if required. We use this for the
* extension record that is stored in the root directory.
*/
if(deep_opt & NEED_CE) add_CE_entry();
/*
* Done filling in all of the fields. Now copy it back to a buffer for the
* file in question.
*/
/* Now copy this back to the buffer for the file */
Rock[flagpos] = flagval;
/* If there was a CE, fill in the size field */
if(recstart)
set_733((char*)Rock + recstart - 8, ipnt - recstart);
s_entry->rr_attributes = (unsigned char *) e_malloc(ipnt);
s_entry->total_rr_attr_size = ipnt;
s_entry->rr_attr_size = (mainrec ? mainrec : ipnt);
memcpy(s_entry->rr_attributes, Rock, ipnt);
return ipnt;
}
/* Guaranteed to return a single sector with the relevant info */
char * FDECL4(generate_rr_extension_record, char *, id, char *, descriptor,
char *, source, int *, size){
int ipnt = 0;
char * pnt;
int len_id, len_des, len_src;
len_id = strlen(id);
len_des = strlen(descriptor);
len_src = strlen(source);
Rock[ipnt++] ='E';
Rock[ipnt++] ='R';
Rock[ipnt++] = ER_SIZE + len_id + len_des + len_src;
Rock[ipnt++] = 1;
Rock[ipnt++] = len_id;
Rock[ipnt++] = len_des;
Rock[ipnt++] = len_src;
Rock[ipnt++] = 1;
memcpy(Rock + ipnt, id, len_id);
ipnt += len_id;
memcpy(Rock + ipnt, descriptor, len_des);
ipnt += len_des;
memcpy(Rock + ipnt, source, len_src);
ipnt += len_src;
if(ipnt > SECTOR_SIZE) {
fprintf(stderr,"Extension record too long\n");
exit(1);
};
pnt = (char *) e_malloc(SECTOR_SIZE);
memset(pnt, 0, SECTOR_SIZE);
memcpy(pnt, Rock, ipnt);
*size = ipnt;
return pnt;
}

1292
util/mkisofs/tree.c Normal file

File diff suppressed because it is too large Load diff

1142
util/mkisofs/write.c Normal file

File diff suppressed because it is too large Load diff