📄 multi.c
字号:
/* * File multi.c - scan existing iso9660 image and merge into * iso9660 filesystem. Used for multisession support. * * Written by Eric Youngdale (1996). * * 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: multi.c,v 1.15 1999/11/22 02:36:28 eric Exp $";#include "config.h"#include <stdlib.h>#include <string.h>#include <time.h>#include <errno.h>#include <sys/types.h>#include <sys/stat.h>#ifndef VMS#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#else#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>#endif#ifndef howmany#define howmany(x, y) (((x)+((y)-1))/(y))#endif#ifndef roundup#define roundup(x, y) ((((x)+((y)-1))/(y))*(y))#endif#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 DECL(free_directory_entry, (struct directory_entry * dirp));static int DECL(merge_old_directory_into_tree, (struct directory_entry *, struct directory *));#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;}#endif/* * Parse the RR attributes so we can find the file name. */static int FDECL3(parse_rr, unsigned char *, pnt, int, len, struct directory_entry *,dpnt){ int cont_extent, cont_offset, cont_size; char name_buf[256]; cont_extent = cont_offset = cont_size = 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(§or[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 int FDECL4(check_rr_dates, struct directory_entry *, dpnt, struct directory_entry *, current, struct stat *, statbuf, struct stat *,lstatbuf){ int cont_extent, cont_offset, 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. */ 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(§or[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 **FDECL2(read_merging_directory, struct iso_directory_record *, mrootp, int *, nent){ unsigned char * cpnt; unsigned char * cpnt1; 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) { i = (i + SECTOR_SIZE - 1) & ~(SECTOR_SIZE - 1); continue; } *pnt = (struct directory_entry *) e_malloc(sizeof(**rtn)); (*pnt)->next = NULL; (*pnt)->isorec = *idr; (*pnt)->starting_block = isonum_733((unsigned char *)idr->extent); (*pnt)->size = isonum_733((unsigned char *)idr->size); (*pnt)->priority = 0; (*pnt)->name = NULL; (*pnt)->got_rr_name = 0; (*pnt)->table = NULL; (*pnt)->whole_name = NULL; (*pnt)->filedir = NULL; (*pnt)->parent_rec = NULL; /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -