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

📄 multi.c

📁 创建一个符合iso-9660标准的iso文件系统
💻 C
📖 第 1 页 / 共 3 页
字号:
/* @(#)multi.c	1.40 00/05/28 joerg */#ifndef lintstatic	char sccsid[] =	"@(#)multi.c	1.40 00/05/28 joerg";#endif/* * File multi.c - scan existing iso9660 image and merge into * iso9660 filesystem.  Used for multisession support. * * Written by Eric Youngdale (1996). * 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. */#include "config.h"#include <stdxlib.h>#include <unixstd.h>#include <strdefs.h>#include <time.h>#include <errno.h>#include <sys/types.h>#include <sys/stat.h>#ifdef VMS#include <sys/file.h>#include <vms/fabdef.h>#include "vms.h"extern char    *strdup(const char *);#endif#include "mkisofs.h"#include "iso9660.h"#ifdef	USE_LIBSCHILY#include <standard.h>#include <schily.h>#endif#include <standard.h>			/* Needed for scsitransp.h	*/#include <utypes.h>			/* Needed for scsitransp.h	*/#include <scg/scsitransp.h>		/* Needed for scsiprbytes()	*/#include <ctype.h>			/* Needed for printasc()	*/#ifndef howmany#define howmany(x, y)   (((x)+((y)-1))/(y))#endif#ifndef roundup#define roundup(x, y)   ((((x)+((y)-1))/(y))*(y))#endif/* * Cannot debug memset() with gdb on Linux, so use fillbytes() *//*#define	memset(s, c, n)	fillbytes(s, n, c)*/#define TF_CREATE 1#define TF_MODIFY 2#define TF_ACCESS 4#define TF_ATTRIBUTES 8static int	isonum_711	__PR((unsigned char *p));static int	isonum_721	__PR((unsigned char *p));static int	isonum_723	__PR((unsigned char *p));static int	isonum_731	__PR((unsigned char *p));static	void	printasc	__PR((char *txt, unsigned char *p, int len));unsigned char	*parse_xa	__PR((unsigned char *pnt, int *lenp,					struct directory_entry *dpnt));static int	parse_rr	__PR((unsigned char *pnt, int len,					struct directory_entry *dpnt));static int	check_rr_dates	__PR((struct directory_entry *dpnt,					struct directory_entry *current,					struct stat *statbuf,					struct stat *lstatbuf));static void	free_directory_entry __PR((struct directory_entry * dirp));static int	merge_old_directory_into_tree __PR((struct directory_entry *,							struct directory *));static void	check_rr_relocation __PR((struct directory_entry * de));#ifdef	__STDC__static intisonum_711(unsigned char *p)#elsestatic intisonum_711(p)	unsigned char	*p;#endif{	return (*p & 0xff);}#ifdef	__STDC__static intisonum_721(unsigned char *p)#elsestatic intisonum_721(p)	unsigned char	*p;#endif{	return ((p[0] & 0xff) | ((p[1] & 0xff) << 8));}#ifdef	__STDC__static intisonum_723(unsigned char *p)#elsestatic intisonum_723(p)	unsigned char	*p;#endif{#if 0	if (p[0] != p[3] || p[1] != p[2]) {#ifdef	USE_LIBSCHILY		comerrno(EX_BAD, "invalid format 7.2.3 number\n");#else		fprintf(stderr, "invalid format 7.2.3 number\n");		exit(1);#endif	}#endif	return (isonum_721(p));}#ifdef	__STDC__static intisonum_731(unsigned char *p)#elsestatic intisonum_731(p)	unsigned char	*p;#endif{	return ((p[0] & 0xff)		| ((p[1] & 0xff) << 8)		| ((p[2] & 0xff) << 16)		| ((p[3] & 0xff) << 24));}#ifdef	__STDC__intisonum_733(unsigned char *p)#elseintisonum_733(p)	unsigned char	*p;#endif{	return (isonum_731(p));}FILE           *in_image = NULL;#ifndef	USE_SCG/* * Don't define readsecs if mkisofs is linked with * the SCSI library. * readsecs() will be implemented as SCSI command in this case. * * Use global var in_image directly in readsecs() * the SCSI equivalent will not use a FILE* for I/O. * * The main point of this pointless abstraction is that Solaris won't let * you read 2K sectors from the cdrom driver.  The fact that 99.9% of the * discs out there have a 2K sectorsize doesn't seem to matter that much. * Anyways, this allows the use of a scsi-generics type of interface on * Solaris. */#ifdef	__STDC__static intreadsecs(int startsecno, void *buffer, int sectorcount)#elsestatic intreadsecs(startsecno, buffer, sectorcount)	int		startsecno;	void		*buffer;	int		sectorcount;#endif{	int		f = fileno(in_image);	if (lseek(f, (off_t) startsecno * SECTOR_SIZE, 0) == (off_t) - 1) {#ifdef	USE_LIBSCHILY		comerr(" Seek error on old image\n");#else		fprintf(stderr, " Seek error on old image\n");		exit(10);#endif	}	if (read(f, buffer, (sectorcount * SECTOR_SIZE))		!= (sectorcount * SECTOR_SIZE)) {#ifdef	USE_LIBSCHILY		comerr(" Read error on old image\n");#else		fprintf(stderr, " Read error on old image\n");		exit(10);#endif	}	return sectorcount * SECTOR_SIZE;}#endifstatic voidprintasc(txt, p, len)	char		*txt;	unsigned char	*p;	int		len;{	int		i;	error("%s ", txt);	for (i=0; i < len; i++) {		if (isprint(p[i]))			error("%c", p[i]);		else			error(".");	}	error("\n");}unsigned char *parse_xa(pnt, lenp, dpnt)	unsigned char	*pnt;	int		*lenp;	struct directory_entry *dpnt;{	struct iso_xa_dir_record *xadp;	int		len = *lenp;static	int		did_xa = 0;/*error("len: %d\n", len);*/	if (len >= 14) {		xadp = (struct iso_xa_dir_record *)pnt;/*		if (dpnt) scsiprbytes("XA ", pnt, len);*/		if (xadp->signature[0] == 'X' && xadp->signature[1] == 'A'				&& xadp->reserved[0] == '\0') {			len -= 14;			pnt += 14;			*lenp = len;			if (!did_xa) {				did_xa = 1;				errmsgno(EX_BAD, "Found XA directory extension record.\n");			}		} else if (pnt[2] == 0) {			char *cp = NULL;			if (dpnt)				cp = (char *)&dpnt->isorec;			if (cp) {				scsiprbytes("ISOREC:", (Uchar *)cp, 33+cp[32]);				printasc("ISOREC:", (Uchar *)cp, 33+cp[32]);				scsiprbytes("XA REC:", pnt, len);				printasc("XA REC:", pnt, len);			}			no_rr =1;			*lenp = 0;			if (cp) {				errmsgno(EX_BAD, "Problems with old ISO directory entry for file: '%s'.\n", &cp[33]);			}			errmsgno(EX_BAD, "Illegal extended directory attributes found (bad XA disk?).\n");/*			errmsgno(EX_BAD, "Disabling Rock Ridge for old session.\n");*/			comerrno(EX_BAD, "Try again using the -no-rr option.\n");		}	}	if (len >= 4 && pnt[3] != 1 && pnt[3] != 2) {		scsiprbytes("BAD RR ATTRIBUTES:", pnt, len);		printasc("BAD RR ATTRIBUTES:", pnt, len);	}	return (pnt);}/* * Parse the RR attributes so we can find the file name. */static intparse_rr(pnt, len, dpnt)	unsigned char	*pnt;	int		len;	struct directory_entry *dpnt;{	int		cont_extent;	int		cont_offset;	int		cont_size;	char		name_buf[256];	cont_extent = cont_offset = cont_size = 0;	pnt = parse_xa(pnt, &len, dpnt /*0*/);	while (len >= 4) {		if (pnt[3] != 1 && pnt[3] != 2) {#ifdef	USE_LIBSCHILY			errmsgno(EX_BAD,				"**BAD RRVERSION (%d) for %c%c\n",				pnt[3], pnt[0], pnt[1]);#else			fprintf(stderr,				"**BAD RRVERSION (%d) for %c%c\n",				pnt[3], pnt[0], pnt[1]);#endif			return -1;		};		if (strncmp((char *) pnt, "NM", 2) == 0) {			strncpy(name_buf, (char *) pnt + 5, pnt[2] - 5);			name_buf[pnt[2] - 5] = 0;			dpnt->name = strdup(name_buf);			dpnt->got_rr_name = 1;			return 0;		}		if (strncmp((char *) pnt, "CE", 2) == 0) {			cont_extent = isonum_733(pnt + 4);			cont_offset = isonum_733(pnt + 12);			cont_size = isonum_733(pnt + 20);		};		len -= pnt[2];		pnt += pnt[2];		if (len <= 3 && cont_extent) {			unsigned char   sector[SECTOR_SIZE];			readsecs(cont_extent, sector, 1);			if (parse_rr(&sector[cont_offset],							cont_size, dpnt) == -1)				return (-1);		};	};	/* Fall back to the iso name if no RR name found */	if (dpnt->name == NULL) {		char           *cp;		strcpy(name_buf, dpnt->isorec.name);		cp = strchr(name_buf, ';');		if (cp != NULL) {			*cp = '\0';		}		dpnt->name = strdup(name_buf);	}	return 0;}/* parse_rr *//* * Returns 1 if the two files are identical * Returns 0 if the two files differ */static intcheck_rr_dates(dpnt, current, statbuf, lstatbuf)	struct directory_entry *dpnt;	struct directory_entry *current;	struct stat	*statbuf;	struct stat	*lstatbuf;{	int		cont_extent;	int		cont_offset;	int		cont_size;	int		offset;	unsigned char	*pnt;	int		len;	int		same_file;	int		same_file_type;	mode_t		mode;	char		time_buf[7];	cont_extent = cont_offset = cont_size = 0;	same_file = 1;	same_file_type = 1;	pnt = dpnt->rr_attributes;	len = dpnt->rr_attr_size;	/*	 * We basically need to parse the rr attributes again, and dig out the	 * dates and file types.	 */	pnt = parse_xa(pnt, &len, /*dpnt*/ 0);	while (len >= 4) {		if (pnt[3] != 1 && pnt[3] != 2) {#ifdef	USE_LIBSCHILY			errmsgno(EX_BAD,				"**BAD RRVERSION (%d) for %c%c\n",				pnt[3], pnt[0], pnt[1]);#else			fprintf(stderr,				"**BAD RRVERSION (%d) for %c%c\n",				pnt[3], pnt[0], pnt[1]);#endif			return -1;		};		/*		 * If we have POSIX file modes, make sure that the file type is		 * the same.  If it isn't, then we must always write the new		 * file.		 */		if (strncmp((char *) pnt, "PX", 2) == 0) {			mode = isonum_733(pnt + 4);			if ((lstatbuf->st_mode & S_IFMT) != (mode & S_IFMT)) {				same_file_type = 0;				same_file = 0;			}		}		if (strncmp((char *) pnt, "TF", 2) == 0) {			offset = 5;			if (pnt[4] & TF_CREATE) {				iso9660_date((char *) time_buf,							lstatbuf->st_ctime);				if (memcmp(time_buf, pnt + offset, 7) != 0)					same_file = 0;				offset += 7;			}			if (pnt[4] & TF_MODIFY) {				iso9660_date((char *) time_buf,							lstatbuf->st_mtime);				if (memcmp(time_buf, pnt + offset, 7) != 0)					same_file = 0;				offset += 7;			}		}		if (strncmp((char *) pnt, "CE", 2) == 0) {			cont_extent = isonum_733(pnt + 4);			cont_offset = isonum_733(pnt + 12);			cont_size = isonum_733(pnt + 20);		};		len -= pnt[2];		pnt += pnt[2];		if (len <= 3 && cont_extent) {			unsigned char   sector[SECTOR_SIZE];			readsecs(cont_extent, sector, 1);			if (parse_rr(&sector[cont_offset],							cont_size, dpnt) == -1)				return (-1);		};	};	/*	 * If we have the same fundamental file type, then it is clearly safe	 * to reuse the TRANS.TBL entry.	 */	if (same_file_type) {		current->de_flags |= SAFE_TO_REUSE_TABLE_ENTRY;	}	return same_file;}struct directory_entry **read_merging_directory(mrootp, nent)	struct iso_directory_record *mrootp;	int		*nent;{	unsigned char	*cpnt;	unsigned char	*cpnt1;	char		*p;	char		*dirbuff;	int		i;	struct iso_directory_record *idr;	int		len;	int		nbytes;	struct directory_entry **pnt;	int		rlen;	struct directory_entry **rtn;	int		seen_rockridge;	unsigned char	*tt_buf;	int		tt_extent;	int		tt_size;	static int	warning_given = 0;	/*	 * This is the number of sectors we will need to read.  We need to	 * round up to get the last fractional sector - we are asking for the	 * data in terms of a number of sectors.	 */	nbytes = roundup(isonum_733((unsigned char *) mrootp->size),								SECTOR_SIZE);	/*	 * First, allocate a buffer large enough to read in the entire	 * directory.	 */	dirbuff = (char *) e_malloc(nbytes);	readsecs(isonum_733((unsigned char *) mrootp->extent), dirbuff,		nbytes / SECTOR_SIZE);	/*	 * Next look over the directory, and count up how many entries we have.	 */	len = isonum_733((unsigned char *) mrootp->size);	i = 0;	*nent = 0;	while (i < len) {		idr = (struct iso_directory_record *) & dirbuff[i];		if (idr->length[0] == 0) {			i = (i + SECTOR_SIZE - 1) & ~(SECTOR_SIZE - 1);			continue;		}		(*nent)++;		i += idr->length[0];	}	/*	 * Now allocate the buffer which will hold the array we are about to	 * return.	 */	rtn = (struct directory_entry **) e_malloc(*nent * sizeof(*rtn));	/*	 * Finally, scan the directory one last time, and pick out the relevant	 * bits of information, and store it in the relevant bits of the	 * structure.	 */	i = 0;	pnt = rtn;	tt_extent = 0;	seen_rockridge = 0;	tt_size = 0;	while (i < len) {		idr = (struct iso_directory_record *) & dirbuff[i];		if (idr->length[0] == 0) {

⌨️ 快捷键说明

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