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

📄 write.c

📁 一款功能很强的光盘镜象制作工具
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Program write.c - dump memory  structures to  file for iso9660 filesystem.   Written by Eric Youngdale (1993).   Copyright 1993 Yggdrasil Computing, 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.  */static char rcsid[] ="$Id: write.c,v 1.21 1999/03/07 17:41:19 eric Exp $";#include <string.h>#include <stdlib.h>#include "config.h"#include "mkisofs.h"#include "iso9660.h"#include <time.h>#include <errno.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include "foolhash.h"#include "md5.h"#ifdef HAVE_UNISTD_H#include <unistd.h>#endif #ifdef __SVR4extern char * strdup(const char *);#endif#ifdef VMSextern char * strdup(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;struct output_fragment * out_tail;struct output_fragment * out_list;struct iso_primary_descriptor vol_desc;static int root_gen	__PR((void));static int generate_path_tables	__PR((void));static int file_gen	__PR((void));static int dirtree_dump	__PR((void));/* 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))void FDECL2(set_721, char *, pnt, unsigned int, i){     pnt[0] = i & 0xff;     pnt[1] = (i >> 8) &  0xff;}void FDECL2(set_722, char *, pnt, unsigned int, i){     pnt[0] = (i >> 8) &  0xff;     pnt[1] = i & 0xff;}void FDECL2(set_723, char *, pnt, unsigned int, i){     pnt[3] = pnt[0] = i & 0xff;     pnt[2] = pnt[1] = (i >> 8) &  0xff;}void FDECL2(set_731, char *, pnt, unsigned int, i){     pnt[0] = i & 0xff;     pnt[1] = (i >> 8) &  0xff;     pnt[2] = (i >> 16) &  0xff;     pnt[3] = (i >> 24) &  0xff;}void FDECL2(set_732, char *, pnt, unsigned int, i){     pnt[3] = i & 0xff;     pnt[2] = (i >> 8) &  0xff;     pnt[1] = (i >> 16) &  0xff;     pnt[0] = (i >> 24) &  0xff;}int FDECL1(get_733, char *, p){     return ((p[0] & 0xff)	     | ((p[1] & 0xff) << 8)	     | ((p[2] & 0xff) << 16)	     | ((p[3] & 0xff) << 24));}void FDECL2(set_733, 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;}void FDECL4(xfwrite, 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) {			fprintf(stderr, "Cannot open '%s'.\n", nbuf);			exit(1);		}	}     while(count)      {	  int got = fwrite(buffer,size,count,file);	  if(got<=0) 	  {	       fprintf(stderr,"cannot fwrite %d*%d\n",size,count);	       exit(1);	  }	  count-=got,*(char**)&buffer+=size*got;     }}struct deferred_write{  struct deferred_write * next;  char			* table;  unsigned int		  extent;  unsigned int		  size;  char			* name;};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 int FDECL1(assign_directory_addresses, 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 += ROUND_UP(dpnt->ce_bytes) >> 11;	       }	  }	  if(dpnt->subdir) 	  {	       assign_directory_addresses(dpnt->subdir);	  }	  dpnt = dpnt->next;     }     return 0;}static void FDECL3(write_one_file, char *, filename, 		   unsigned int, size, FILE *, outfile){     char		  buffer[SECTOR_SIZE * NSECT];     FILE		* infile;     int		  remain;     int		  use;     if ((infile = fopen(filename, "rb")) == NULL)      {#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);     }     remain = size;     while(remain > 0)     {	  use =  (remain >  SECTOR_SIZE * NSECT - 1 ? NSECT*SECTOR_SIZE : remain);	  use = ROUND_UP(use); /* Round up to nearest sector boundary */	  memset(buffer, 0, use);	  if (fread(buffer, 1, use, infile) == 0) 	  {		fprintf(stderr,"cannot read from %s\n",filename); 		exit(1);	  }	  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 % 5000) < use/SECTOR_SIZE)	  {	       time_t now;	       time_t the_end;	       double frac;	       	       time(&now);	       frac = last_extent_written / (double)last_extent;	       the_end = begun + (now - begun) / frac;	       fprintf(stderr, "%6.2f%% done, estimate finish %s",		       frac * 100., ctime(&the_end));	  }#endif	  remain -= use;     }     fclose(infile);} /* write_one_file(... */static void FDECL1(write_files, FILE *, outfile){     struct deferred_write * dwpnt, *dwnext;     dwpnt = dw_head;     while(dwpnt)     {	  if(dwpnt->table) 	  {	       xfwrite(dwpnt->table,  1, ROUND_UP(dwpnt->size), outfile);	       last_extent_written += ROUND_UP(dwpnt->size) / SECTOR_SIZE;	       table_size += dwpnt->size;/*		  fprintf(stderr,"Size %d ", dwpnt->size); */	       free(dwpnt->table);	  } 	  else 	  {#ifdef VMS	       vms_write_one_file(dwpnt->name, dwpnt->size, outfile);#else	       write_one_file(dwpnt->name, dwpnt->size, outfile);#endif	       free(dwpnt->name);	  }	  dwnext = dwpnt;	  dwpnt = dwpnt->next;	  free(dwnext);     }} /* write_files(... */#if 0static void dump_filelist(){     struct deferred_write * dwpnt;     dwpnt = dw_head;     while(dwpnt)     {	  fprintf(stderr, "File %s\n",dwpnt->name);	  dwpnt = dwpnt->next;     }     fprintf(stderr,"\n");}#endifstatic int FDECL2(compare_dirs, 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;     /*      * If the entries are the same, this is an error.      */     if( strcmp(rpnt, lpnt) == 0 )       {	 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 taht 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.      *      * (TF, Tue Dec 29 13:49:24 CET 1998)      */     if((*r)->isorec.name_len[0] == 1 && *rpnt == 0) return -1; /* '.' */     if((*l)->isorec.name_len[0] == 1 && *lpnt == 0) return 1;     if((*r)->isorec.name_len[0] == 1 && *rpnt == 1) return -1; /* '..' */     if((*l)->isorec.name_len[0] == 1 && *lpnt == 1) return 1;#endif     while(*rpnt && *lpnt)      {	  if(*rpnt == ';' && *lpnt != ';') return -1;	  if(*rpnt != ';' && *lpnt == ';') return 1;	  	  if(*rpnt == ';' && *lpnt == ';') return 0;	  	  if(*rpnt == '.' && *lpnt != '.') return -1;	  if(*rpnt != '.' && *lpnt == '.') return 1;	  	  if((unsigned char)*rpnt < (unsigned char)*lpnt) return -1;	  if((unsigned char)*rpnt > (unsigned char)*lpnt) return 1;	  rpnt++;  lpnt++;     }     if(*rpnt) return 1;     if(*lpnt) return -1;     return 0;}/*  * Function:		sort_directory * * Purpose:		Sort the directory in the appropriate ISO9660 *			order. * * Notes:		Returns 0 if OK, returns > 0 if an error occurred. */int FDECL1(sort_directory, struct directory_entry **, sort_dir){     int dcount = 0;     int xcount = 0;     int j;     int i, len;     struct directory_entry * s_entry;     struct directory_entry ** sortlist;          /* need to keep a count of how many entries are hidden */     s_entry = *sort_dir;     while(s_entry)     {	  if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY)	    xcount++;	  dcount++;	  s_entry = s_entry->next;     }     if( dcount == 0 )     {          return 0;     }     /*      * OK, now we know how many there are.  Build a vector for sorting.       */     sortlist =   (struct directory_entry **) 	  e_malloc(sizeof(struct directory_entry *) * dcount);     j = dcount - 1;     dcount = 0;     s_entry = *sort_dir;     while(s_entry)     {	if(s_entry->de_flags & INHIBIT_ISO9660_ENTRY)	 {	  /* put any hidden entries at the end of the vector */	  sortlist[j--] = s_entry;	 }	else	 {	  sortlist[dcount] = s_entry;	  dcount++;	 }	 len = s_entry->isorec.name_len[0];	 s_entry->isorec.name[len] = 0;	 s_entry = s_entry->next;     }       /*      * Each directory is required to contain at least . and ..      */     if( dcount < 2 )       {	 sort_goof = 1;	        }     else       {	 /* only sort the non-hidden entries */	 sort_goof = 0;#ifdef __STDC__	 qsort(sortlist, dcount, sizeof(struct directory_entry *), 	       (int (*)(const void *, const void *))compare_dirs);#else	 qsort(sortlist, dcount, sizeof(struct directory_entry *), 	       compare_dirs);#endif	 	 /* 	  * Now reassemble the linked list in the proper sorted order 	  * We still need the hidden entries, as they may be used in the	  * Joliet tree.	  */	 for(i=0; i<dcount+xcount-1; i++)	   {	     sortlist[i]->next = sortlist[i+1];	   }	 

⌨️ 快捷键说明

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