📄 eltorito.c
字号:
/* @(#)eltorito.c 1.17 00/05/28 joerg */#ifndef lintstatic char sccsid[] = "@(#)eltorito.c 1.17 00/05/28 joerg";#endif/* * 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. */#include "config.h"#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <unixstd.h>#include <stdxlib.h>#include <fctldefs.h>#include "mkisofs.h"#include "match.h"#include "iso9660.h"#include "diskmbr.h"#include "bootinfo.h"#ifdef USE_LIBSCHILY#include <standard.h>#include <schily.h>#endif#include <utypes.h>#include <intcvt.h>#undef MIN#define MIN(a, b) (((a) < (b))? (a): (b))static struct eltorito_validation_entry valid_desc;static struct eltorito_boot_descriptor gboot_desc;static struct disk_master_boot_record disk_mbr;static unsigned int bcat_de_flags; void init_boot_catalog __PR((const char *path)); void insert_boot_cat __PR((void));static void get_torito_desc __PR((struct eltorito_boot_descriptor *boot_desc));static void fill_boot_desc __PR((struct eltorito_defaultboot_entry *boot_desc_entry, struct eltorito_boot_entry_info *boot_entry)); void get_boot_entry __PR((void)); void new_boot_entry __PR((void));static int tvd_write __PR((FILE * outfile));/* * Make sure any existing boot catalog is excluded */voidinit_boot_catalog(path) const char *path;{ char *bootpath; /* filename of boot catalog */ bootpath = (char *) e_malloc(strlen(boot_catalog) + strlen(path) + 2); strcpy(bootpath, path); if (bootpath[strlen(bootpath) - 1] != '/') { strcat(bootpath, "/"); } strcat(bootpath, boot_catalog); /* * we are going to create a virtual catalog file * - so make sure any existing is excluded */ add_match(bootpath); /* flag the file as a memory file */ bcat_de_flags = MEMORY_FILE; /* find out if we want to "hide" this file */ if (i_matches(boot_catalog) || i_matches(bootpath)) bcat_de_flags |= INHIBIT_ISO9660_ENTRY; if (j_matches(boot_catalog) || j_matches(bootpath)) bcat_de_flags |= INHIBIT_JOLIET_ENTRY; free(bootpath);}/* init_boot_catalog(... *//* * Create a boot catalog file in memory - mkisofs already uses this type of * file for the TRANS.TBL files. Therefore the boot catalog is set up in * similar way */voidinsert_boot_cat(){ struct directory_entry *de, *s_entry; char *p1, *p2, *p3; struct directory *this_dir, *dir; char *buffer; init_fstatbuf(); buffer = (char *) e_malloc(SECTOR_SIZE); memset(buffer, 0, SECTOR_SIZE); /* * try to find the directory that will contain the boot.cat file * - not very neat, but I can't think of a better way */ p1 = strdup(boot_catalog); /* get dirname (p1) and basename (p2) of boot.cat */ if ((p2 = strrchr(p1, '/')) != NULL) { *p2 = '\0'; p2++; /* find the dirname directory entry */ de = search_tree_file(root, p1); if (!de) {#ifdef USE_LIBSCHILY comerrno(EX_BAD, "Uh oh, I cant find the boot catalog directory '%s'!\n", p1);#else fprintf(stderr, "Uh oh, I cant find the boot catalog directory '%s'!\n", p1); exit(1);#endif } this_dir = 0; /* get the basename (p3) of the directory */ if ((p3 = strrchr(p1, '/')) != NULL) p3++; else p3 = p1; /* find the correct sub-directory entry */ for (dir = de->filedir->subdir; dir; dir = dir->next) if (!(strcmp(dir->de_name, p3))) this_dir = dir; if (this_dir == 0) {#ifdef USE_LIBSCHILY comerrno(EX_BAD, "Uh oh, I cant find the boot catalog directory '%s'!\n", p3);#else fprintf(stderr, "Uh oh, I cant find the boot catalog directory '%s'!\n", p3); exit(1);#endif } } else { /* boot.cat is in the root directory */ this_dir = root; p2 = p1; } /* * make a directory entry in memory (using the same set up as for table * entries */ s_entry = (struct directory_entry *) e_malloc(sizeof(struct directory_entry)); memset(s_entry, 0, sizeof(struct directory_entry)); s_entry->next = this_dir->contents; this_dir->contents = s_entry; s_entry->isorec.flags[0] = ISO_FILE; s_entry->priority = 32768; iso9660_date(s_entry->isorec.date, fstatbuf.st_mtime); s_entry->inode = TABLE_INODE; s_entry->dev = (dev_t) UNCACHED_DEVICE; set_723(s_entry->isorec.volume_sequence_number, volume_sequence_number); set_733((char *) s_entry->isorec.size, SECTOR_SIZE); s_entry->size = SECTOR_SIZE; s_entry->filedir = this_dir; s_entry->name = strdup(p2); iso9660_file_length(p2, s_entry, 0); /* flag file as necessary */ s_entry->de_flags = bcat_de_flags; if (use_RockRidge && !(bcat_de_flags & INHIBIT_ISO9660_ENTRY)) { fstatbuf.st_mode = 0444 | S_IFREG; fstatbuf.st_nlink = 1; generate_rock_ridge_attributes("", p2, s_entry, &fstatbuf, &fstatbuf, 0); } /* * memory files are stored at s_entry->table * - but this is also used for each s_entry to generate * TRANS.TBL entries. So if we are generating tables, * store the TRANS.TBL data here for the moment */ if (generate_tables && !(bcat_de_flags & INHIBIT_ISO9660_ENTRY)) { sprintf(buffer, "F\t%s\n", s_entry->name); /* copy the TRANS.TBL entry info and clear the buffer */ s_entry->table = strdup(buffer); memset(buffer, 0, SECTOR_SIZE); /* * store the (empty) file data in the * unused s_entry->whole_name element for the time being * - this will be transferred to s_entry->table after any * TRANS.TBL processing later */ s_entry->whole_name = buffer; } else { /* store the (empty) file data in the s_entry->table element */ s_entry->table = buffer; s_entry->whole_name = NULL; }}static voidget_torito_desc(boot_desc) struct eltorito_boot_descriptor *boot_desc;{ int checksum; unsigned char *checksum_ptr; struct directory_entry *de2; /* Boot catalog */ int i; int offset; struct eltorito_defaultboot_entry boot_desc_record; memset(boot_desc, 0, sizeof(*boot_desc)); boot_desc->type[0] = 0; memcpy(boot_desc->id, 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 * - we already know where the boot catalog is * - we created it above - but lets search for it anyway * - good sanity check! */ de2 = search_tree_file(root, boot_catalog); if (!de2 || !(de2->de_flags & MEMORY_FILE)) {#ifdef USE_LIBSCHILY comerrno(EX_BAD, "Uh oh, I cant find the boot catalog '%s'!\n", boot_catalog);#else fprintf(stderr, "Uh oh, I cant find the boot catalog '%s'!\n", boot_catalog); exit(1);#endif } set_731(boot_desc->bootcat_ptr, (unsigned int) get_733(de2->isorec.extent)); /* * 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] = (char) 0x55; valid_desc.key2[0] = (char) 0xAA; /* compute the checksum */ checksum = 0; checksum_ptr = (unsigned char *) &valid_desc; /* Set checksum to 0 before computing checksum */ set_721(valid_desc.cksum, 0); for (i = 0; i < sizeof(valid_desc); i += 2) { 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 write it to the virtual boot catalog */ memcpy(de2->table, &valid_desc, 32); for (current_boot_entry = first_boot_entry,offset = sizeof(valid_desc); current_boot_entry != NULL; current_boot_entry = current_boot_entry->next, offset += sizeof(boot_desc_record)) { if (offset >= SECTOR_SIZE) {#ifdef USE_LIBSCHILY comerrno(EX_BAD, "Too many El Torito boot entries\n");#else fprintf(stderr, "Too many El Torito boot entries\n"); exit(1);#endif } fill_boot_desc (&boot_desc_record, current_boot_entry); memcpy(de2->table + offset, &boot_desc_record, sizeof(boot_desc_record)); }}/* get_torito_desc(... */static void
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -