📄 write.c
字号:
/* @(#)write.c 1.63 02/10/04 joerg */#ifndef lintstatic char sccsid[] = "@(#)write.c 1.63 02/10/04 joerg";#endif/* * Program write.c - dump memory structures to file for iso9660 filesystem. Written by Eric Youngdale (1993). Copyright 1993 Yggdrasil Computing, Incorporated Copyright (c) 1999,2000,2001 J. Schilling This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by 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. *//* APPLE_HYB James Pearson j.pearson@ge.ucl.ac.uk 23/2/2000 */#include <mconfig.h>#include "mkisofs.h"#include "foolhash.h"#include "md5.h"#include <timedefs.h>#include <fctldefs.h>#ifdef SORTING#include "match.h"#endif /* SORTING */#include <errno.h>#include <schily.h>#ifdef DVD_VIDEO#include "dvd_reader.h"#include "dvd_file.h"#include "ifo_read.h"#endif#ifdef APPLE_HYB#include <ctype.h>#endif#ifdef __SVR4extern char *strdup __PR((const char *));#endif#ifdef VMSextern char *strdup __PR((const char *));#endifextern struct hash_table *md5_hash;/* Max number of sectors we will write at one time */#define NSECT 16/* Counters for statistics */static int table_size = 0;static int total_dir_size = 0;static int rockridge_size = 0;static struct directory **pathlist;static int next_path_index = 1;static int sort_goof;static int is_rr_dir = 0;static int showcount = 0;struct output_fragment *out_tail;struct output_fragment *out_list;struct iso_primary_descriptor vol_desc; void set_721 __PR((char *pnt, unsigned int i)); void set_722 __PR((char *pnt, unsigned int i)); void set_723 __PR((char *pnt, unsigned int i)); void set_731 __PR((char *pnt, unsigned int i)); void set_732 __PR((char *pnt, unsigned int i)); void set_733 __PR((char *pnt, unsigned int i)); int get_731 __PR((char *p)); int get_732 __PR((char *p)); int get_733 __PR((char *p)); void xfwrite __PR((void *buffer, int count, int size, FILE *file));static int assign_directory_addresses __PR((struct directory *node));#ifdef APPLE_HYBstatic void write_one_file __PR((char *filename, unsigned int size, FILE *outfile, off_t off));#elsestatic void write_one_file __PR((char *filename, unsigned int size, FILE *outfile));#endifstatic void write_files __PR((FILE *outfile));#if 0static void dump_filelist __PR((void));#endifstatic int compare_dirs __PR((const void *rr, const void *ll)); int sort_directory __PR((struct directory_entry **sort_dir, int rr));static int root_gen __PR((void));static void assign_file_addresses __PR((struct directory *dpnt));static void free_one_directory __PR((struct directory *dpnt));static void free_directories __PR((struct directory *dpnt)); void generate_one_directory __PR((struct directory *dpnt, FILE *outfile));static void build_pathlist __PR((struct directory *node));static int compare_paths __PR((void const *r, void const *l));static int generate_path_tables __PR((void)); void memcpy_max __PR((char *to, char *from, int max)); void outputlist_insert __PR((struct output_fragment *frag));static int file_write __PR((FILE *outfile));static int pvd_write __PR((FILE *outfile));static int evd_write __PR((FILE *outfile));static int vers_write __PR((FILE *outfile));static int graftcp __PR((char *to, char *from, char *ep));static int pathcp __PR((char *to, char *from, char *ep));static int pathtab_write __PR((FILE *outfile));static int exten_write __PR((FILE *outfile)); int oneblock_size __PR((int starting_extent));static int pathtab_size __PR((int starting_extent));static int padblock_size __PR((int starting_extent));static int padend_size __PR((int starting_extent));static int file_gen __PR((void));static int dirtree_dump __PR((void));static int dirtree_fixup __PR((int starting_extent));static int dirtree_size __PR((int starting_extent));static int ext_size __PR((int starting_extent));static int dirtree_write __PR((FILE *outfile));static int dirtree_cleanup __PR((FILE *outfile));static int padblock_write __PR((FILE *outfile));static int padend_write __PR((FILE *outfile));#ifdef APPLE_HYBstatic int hfs_pad;static int hfs_get_parms __PR((char * key));static void hfs_file_gen __PR((int start_extent));static void gen_prepboot __PR((void)); Ulong get_adj_size __PR((int Csize)); int adj_size __PR((int Csize, int start_extent, int extra)); void adj_size_other __PR((struct directory *dpnt));static int hfs_hce_write __PR((FILE * outfile)); int insert_padding_file __PR((int size));#endif /* APPLE_HYB */#ifdef SORTINGstatic int compare_sort __PR((const void * rr, const void * ll));static void reassign_link_addresses __PR((struct directory * dpnt));static int sort_file_addresses __PR((void));#endif /* SORTING *//* * Routines to actually write the disc. We write sequentially so that * we could write a tape, or write the disc directly */#define FILL_SPACE(X) memset(vol_desc.X, ' ', sizeof(vol_desc.X))voidset_721(pnt, i) char *pnt; unsigned int i;{ pnt[0] = i & 0xff; pnt[1] = (i >> 8) & 0xff;}voidset_722(pnt, i) char *pnt; unsigned int i;{ pnt[0] = (i >> 8) & 0xff; pnt[1] = i & 0xff;}voidset_723(pnt, i) char *pnt; unsigned int i;{ pnt[3] = pnt[0] = i & 0xff; pnt[2] = pnt[1] = (i >> 8) & 0xff;}voidset_731(pnt, i) char *pnt; unsigned int i;{ pnt[0] = i & 0xff; pnt[1] = (i >> 8) & 0xff; pnt[2] = (i >> 16) & 0xff; pnt[3] = (i >> 24) & 0xff;}voidset_732(pnt, i) char *pnt; unsigned int i;{ pnt[3] = i & 0xff; pnt[2] = (i >> 8) & 0xff; pnt[1] = (i >> 16) & 0xff; pnt[0] = (i >> 24) & 0xff;}voidset_733(pnt, i) char *pnt; unsigned int i;{ pnt[7] = pnt[0] = i & 0xff; pnt[6] = pnt[1] = (i >> 8) & 0xff; pnt[5] = pnt[2] = (i >> 16) & 0xff; pnt[4] = pnt[3] = (i >> 24) & 0xff;}intget_731(p) char *p;{ return ((p[0] & 0xff) | ((p[1] & 0xff) << 8) | ((p[2] & 0xff) << 16) | ((p[3] & 0xff) << 24));}intget_732(p) char *p;{ return ((p[3] & 0xff) | ((p[2] & 0xff) << 8) | ((p[1] & 0xff) << 16) | ((p[0] & 0xff) << 24));}intget_733(p) char *p;{ return ((p[0] & 0xff) | ((p[1] & 0xff) << 8) | ((p[2] & 0xff) << 16) | ((p[3] & 0xff) << 24));}voidxfwrite(buffer, count, size, file) void *buffer; int count; int size; FILE *file;{ /* * 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. */ static int idx = 0; if (split_output != 0 && (idx == 0 || ftell(file) >= ((off_t)1024 * 1024 * 1024))) { char nbuf[512]; extern char *outfile; if (idx == 0) unlink(outfile); sprintf(nbuf, "%s_%02d", outfile, idx++); file = freopen(nbuf, "wb", file); if (file == NULL) {#ifdef USE_LIBSCHILY comerr("Cannot open '%s'.\n", nbuf);#else fprintf(stderr, "Cannot open '%s'.\n", nbuf); exit(1);#endif } } while (count) { int got = fwrite(buffer, size, count, file); if (got <= 0) {#ifdef USE_LIBSCHILY comerr("cannot fwrite %d*%d\n", size, count);#else fprintf(stderr, "cannot fwrite %d*%d\n", size, count); exit(1);#endif } count -= got, *(char **) &buffer += size * got; }}#ifdef APPLE_HYB/* * use the deferred_write struct to store info about the hfs_boot_file */static struct deferred_write mac_boot;#endif /* APPLE_HYB */static struct deferred_write *dw_head = NULL, *dw_tail = NULL;unsigned int last_extent_written = 0;static Uint path_table_index;static time_t begun;/* * We recursively walk through all of the directories and assign extent * numbers to them. We have already assigned extent numbers to everything that * goes in front of them */static intassign_directory_addresses(node) struct directory *node;{ int dir_size; struct directory *dpnt; dpnt = node; while (dpnt) { /* skip if it's hidden */ if (dpnt->dir_flags & INHIBIT_ISO9660_ENTRY) { dpnt = dpnt->next; continue; } /* * If we already have an extent for this (i.e. it came from a * multisession disc), then don't reassign a new extent. */ dpnt->path_index = next_path_index++; if (dpnt->extent == 0) { dpnt->extent = last_extent; dir_size = ISO_BLOCKS(dpnt->size); last_extent += dir_size; /* * Leave room for the CE entries for this directory. * Keep them close to the reference directory so that * access will be quick. */ if (dpnt->ce_bytes) { last_extent += ISO_BLOCKS(dpnt->ce_bytes); } } if (dpnt->subdir) { assign_directory_addresses(dpnt->subdir); } dpnt = dpnt->next; } return 0;}#ifdef APPLE_HYBstatic voidwrite_one_file(filename, size, outfile, off) char *filename; unsigned int size; FILE *outfile; off_t off;#elsestatic voidwrite_one_file(filename, size, outfile) char *filename; unsigned int size; FILE *outfile;#endif /* APPLE_HYB */{ /* * It seems that there are still stone age C-compilers * around. * The Metrowerks C found on BeOS/PPC does not allow * more than 32kB of local vars. * As we do not need to call write_one_file() recursively * we make buffer static. */static char buffer[SECTOR_SIZE * NSECT]; FILE *infile; int remain; int use; if ((infile = fopen(filename, "rb")) == NULL) {#ifdef USE_LIBSCHILY comerr("cannot open '%s'\n", filename);#else#ifndef HAVE_STRERROR fprintf(stderr, "cannot open '%s': (%d)\n", filename, errno);#else fprintf(stderr, "cannot open '%s': %s\n", filename, strerror(errno));#endif exit(1);#endif }#ifdef APPLE_HYB fseek(infile, off, SEEK_SET);#endif /* APPLE_HYB */ remain = size; while (remain > 0) { use = (remain > SECTOR_SIZE * NSECT - 1 ? NSECT * SECTOR_SIZE : remain); use = ISO_ROUND_UP(use); /* Round up to nearest sector boundary */ memset(buffer, 0, use); if (fread(buffer, 1, use, infile) == 0) {#ifdef USE_LIBSCHILY comerr("cannot read from '%s'\n", filename);#else fprintf(stderr, "cannot read from '%s'\n", filename); exit(1);#endif } xfwrite(buffer, 1, use, outfile); last_extent_written += use / SECTOR_SIZE;#if 0 if ((last_extent_written % 1000) < use / SECTOR_SIZE) { fprintf(stderr, "%d..", last_extent_written); }#else if (verbose > 0 && (int)(last_extent_written % (gui ? 500 : 5000)) < use / SECTOR_SIZE) { time_t now; time_t the_end; double frac; time(&now); frac = last_extent_written / (1.0 * last_extent); the_end = begun + (now - begun) / frac;#ifndef NO_FLOATINGPOINT fprintf(stderr, "%6.2f%% done, estimate finish %s", frac * 100., ctime(&the_end));#else fprintf(stderr, "%3d.%-02d%% done, estimate finish %s", (int)(frac * 100.), (int)((frac+.00005) * 10000.)%100, ctime(&the_end));#endif fflush(stderr); }#endif remain -= use; } fclose(infile);}/* write_one_file(... */static voidwrite_files(outfile) FILE *outfile;{ struct deferred_write *dwpnt, *dwnext; dwpnt = dw_head; while (dwpnt) {#ifdef DEBUG fprintf(stderr, "The file name is %s and pad is %d, size is %d and extent is %d\n", dwpnt->name, dwpnt->pad, dwpnt->size, dwpnt->extent);#endif if (dwpnt->table) { xfwrite(dwpnt->table, 1, ISO_ROUND_UP(dwpnt->size), outfile); last_extent_written += ISO_BLOCKS(dwpnt->size); table_size += dwpnt->size;/* fprintf(stderr, "Size %d ", dwpnt->size); */ free(dwpnt->table); dwpnt->table = NULL; } else {#ifdef VMS vms_write_one_file(dwpnt->name, dwpnt->size, outfile);#else#ifdef APPLE_HYB write_one_file(dwpnt->name, dwpnt->size, outfile, dwpnt->off);#else write_one_file(dwpnt->name, dwpnt->size, outfile);#endif /* APPLE_HYB */#endif free(dwpnt->name); dwpnt->name = NULL; } #ifndef DVD_VIDEO#define dvd_video 0#endif#ifndef APPLE_HYB#define apple_hyb 0#endif #if defined(APPLE_HYB) || defined(DVD_VIDEO) if (apple_hyb || dvd_video) { /* * we may have to pad out ISO files to work with HFS * clump sizes */ char blk[SECTOR_SIZE]; Uint i; for (i = 0; i < dwpnt->pad; i++) xfwrite(blk, 1, SECTOR_SIZE, outfile); last_extent_written += dwpnt->pad; }#endif /* APPLE_HYB || DVD_VIDEO */ dwnext = dwpnt; dwpnt = dwpnt->next; free(dwnext); dwnext = NULL; }}/* write_files(... */#if 0static voiddump_filelist(){ struct deferred_write *dwpnt; dwpnt = dw_head; while (dwpnt) { fprintf(stderr, "File %s\n", dwpnt->name); dwpnt = dwpnt->next; } fprintf(stderr, "\n");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -