⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 write.c

📁 创建一个符合iso-9660标准的iso文件系统
💻 C
📖 第 1 页 / 共 4 页
字号:
/* @(#)write.c	1.44 00/06/05 joerg */#ifndef lintstatic	char sccsid[] =	"@(#)write.c	1.44 00/06/05 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 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 "config.h"#include <strdefs.h>#include <stdxlib.h>#include "mkisofs.h"#include "iso9660.h"#ifdef SORTING#include "match.h"#endif /* SORTING */#include <time.h>#include <errno.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <unixstd.h>#ifdef	USE_LIBSCHILY#include <standard.h>#include <schily.h>#endif#ifdef __SVR4extern char    *strdup	__PR((const char *));#endif#ifdef VMSextern char    *strdup	__PR((const char *));#endif/* 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;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, unsigned int 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	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	void	hfs_file_gen	__PR((int start_extent));static	void	gen_prepboot	__PR((void));	int	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) >= (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 int	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 = (dpnt->size + (SECTOR_SIZE - 1)) >> 11;			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_ROUND_UP(dpnt->ce_bytes) >> 11;			}		}		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;	unsigned int	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#if defined(sun) || defined(_AUX_SOURCE)		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 ((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) {		if (dwpnt->table) {			xfwrite(dwpnt->table, 1, ISO_ROUND_UP(dwpnt->size),								outfile);			last_extent_written +=				ISO_ROUND_UP(dwpnt->size) / SECTOR_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;		}#ifdef APPLE_HYB		if (apple_hyb) {			/*			 * we may have to pad out ISO files to work with HFS			 * clump sizes			 */			char	blk[SECTOR_SIZE];			int	i;			for (i = 0; i < dwpnt->pad; i++)				xfwrite(blk, 1, SECTOR_SIZE, outfile);			last_extent_written += dwpnt->pad;		}#endif	/* APPLE_HYB */		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");}#endifstatic intcompare_dirs(rr, ll)	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)->isorec.name;	lpnt = (*l)->isorec.name;#ifdef APPLE_HYB	/*	 * resource fork MUST (not sure if this is true for HFS volumes) be	 * before the data fork - so force it here	 */	if ((*r)->assoc && (*r)->assoc == (*l))		return 1;	if ((*l)->assoc && (*l)->assoc == (*r))		return -1;#endif	/* APPLE_HYB */	/* If the entries are the same, this is an error. */	if (strcmp(rpnt, lpnt) == 0) {#ifdef	USE_LIBSCHILY		errmsgno(EX_BAD,			"Error: %s and %s have the same ISO9660 name\n",			(*r)->whole_name, (*l)->whole_name);#else		fprintf(stderr,			"Error: %s and %s have the same ISO9660 name\n",			(*r)->whole_name, (*l)->whole_name);#endif		sort_goof++;	}	/* Check we don't have the same RR name */	if (use_RockRidge && !is_rr_dir) {		/*		 * entries *can* have the same RR name in the "rr_moved"		 * directory so skip checks if we're in reloc_dir		 */		if (!(strcmp((*r)->name, (*l)->name))) {#ifdef	USE_LIBSCHILY			errmsgno(EX_BAD,			"Error: %s and %s have the same Rock Ridge name\n",				(*r)->whole_name, (*l)->whole_name);#else			fprintf(stderr,			"Error: %s and %s have the same Rock Ridge name\n",				(*r)->whole_name, (*l)->whole_name);#endif			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 that 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 0	if (strcmp(rpnt, ".") == 0)		return -1;	if (strcmp(lpnt, ".") == 0)		return 1;	if (strcmp(rpnt, "..") == 0)		return -1;	if (strcmp(lpnt, "..") == 0)		return 1;#else	/*	 * The code above is wrong (as explained in Eric's comment), leading to	 * incorrect sort order iff the -L option ("allow leading dots") is in	 * effect and a directory contains entries that start with a dot.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -