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

📄 write.c

📁 创建一个符合iso-9660标准的iso文件系统
💻 C
📖 第 1 页 / 共 4 页
字号:
	 *  (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. */intsort_directory(sort_dir, rr)	struct directory_entry **sort_dir;	int		rr;{	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) {#ifdef	USE_LIBSCHILY		errmsgno(EX_BAD,			"Directory size too small (. or .. missing ???)\n");#else		fprintf(stderr,			"Directory size too small (. or .. missing ???)\n");#endif		sort_goof = 1;	} else {		/* only sort the non-hidden entries */		sort_goof = 0;		is_rr_dir = rr;#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];		}		sortlist[dcount + xcount - 1]->next = NULL;		*sort_dir = sortlist[0];	}	free(sortlist);	sortlist = NULL;	return sort_goof;}static introot_gen(){	init_fstatbuf();	root_record.length[0] = 1 +			offsetof(struct iso_directory_record, name[0]);	root_record.ext_attr_length[0] = 0;	set_733((char *) root_record.extent, root->extent);	set_733((char *) root_record.size, ISO_ROUND_UP(root->size));	iso9660_date(root_record.date, root_statbuf.st_mtime);	root_record.flags[0] = ISO_DIRECTORY;	root_record.file_unit_size[0] = 0;	root_record.interleave[0] = 0;	set_723(root_record.volume_sequence_number, volume_sequence_number);	root_record.name_len[0] = 1;	return 0;}#ifdef SORTING/*  *	sorts deferred_write entries based on the sort weight */static intcompare_sort(rr, ll)	const void	*rr;	const void	*ll;{	struct deferred_write	**r;	struct deferred_write	**l;	int			r_sort;	int			l_sort;	r = (struct deferred_write **) rr;	l = (struct deferred_write **) ll;	r_sort = (*r)->s_entry->sort;	l_sort = (*l)->s_entry->sort;	return (r_sort < l_sort ? 1 : -1);}/* *	reassign start extents to files that are "hard links" to *	files that may have been sorted */static voidreassign_link_addresses(dpnt)	struct directory	*dpnt;{	struct directory_entry	*s_entry;	struct file_hash	*s_hash;	while (dpnt) {		s_entry = dpnt->contents;		for(s_entry = dpnt->contents; s_entry; s_entry = s_entry->next) {			/* link files have already been given the weight NOT_SORTED */			if (s_entry->sort != NOT_SORTED)				continue;			/* update the start extent */			s_hash = find_hash(s_entry->dev, s_entry->inode);			if(s_hash) {				set_733((char *) s_entry->isorec.extent, s_hash->starting_block);				s_entry->starting_block = s_hash->starting_block;			}		}		if(dpnt->subdir) {			reassign_link_addresses(dpnt->subdir);		}		dpnt = dpnt->next;	}}/* *	sort files in order of the given sort weight */static intsort_file_addresses(){	struct deferred_write	*dwpnt;	struct deferred_write	**sortlist;	struct directory_entry	*s_entry;	int			start_extent;	int			num = 0;	int			i;	/* need to store start extents for linked files */	flush_hash();	/* find out how many files we have */	dwpnt = dw_head;	while (dwpnt) {		num++;		dwpnt = dwpnt->next;	}	/* return if we have none */	if (num == 0) {		return (1);	}	/* save the start extent of the first file */	start_extent = dw_head->extent;	/* set up vector to store entries */	sortlist = (struct deferred_write **)		e_malloc(sizeof(struct deferred_write *) * num);	for (i=0,dwpnt=dw_head;i<num;i++,dwpnt=dwpnt->next)		sortlist[i] = dwpnt;	/* sort the list */#ifdef __STDC__	qsort(sortlist, num, sizeof(struct deferred_write *),		(int (*)(const void *, const void *))compare_sort);#else	qsort(sortlist, num, sizeof(struct deferred_write *), compare_sort);#endif	/* reconstruct the linked list */	for(i=0; i<num-1; i++) {		sortlist[i]->next = sortlist[i+1];	}	sortlist[num-1]->next = NULL;	dw_head = sortlist[0];	free(sortlist);	/* set the new start extents for the sorted list */	for (i=0,dwpnt=dw_head;i<num;i++,dwpnt=dwpnt->next) {		s_entry = dwpnt->s_entry;		dwpnt->extent = s_entry->starting_block = start_extent;		set_733((char *) s_entry->isorec.extent, start_extent);		start_extent += ISO_ROUND_UP(s_entry->size) >> 11;		/* cache start extents for any linked files */		add_hash(s_entry);	}	return (0);}#endif /* SORTING */static voidassign_file_addresses(dpnt)	struct directory	*dpnt;{	struct directory *finddir;	struct directory_entry *s_entry;	struct file_hash *s_hash;	struct deferred_write *dwpnt;	char		whole_path[1024];	while (dpnt) {		s_entry = dpnt->contents;		for (s_entry = dpnt->contents; s_entry;						s_entry = s_entry->next) {			/*			 * If we already have an  extent for this entry, then			 * don't assign a new one.  It must have come from a			 * previous session on the disc.  Note that we don't			 * end up scheduling the thing for writing either.			 */			if (isonum_733((unsigned char *)						s_entry->isorec.extent) != 0) {				continue;			}			/*			 * This saves some space if there are symlinks present			 */			s_hash = find_hash(s_entry->dev, s_entry->inode);			if (s_hash) {				if (verbose > 2) {					fprintf(stderr, "Cache hit for %s%s%s\n", s_entry->filedir->de_name,						SPATH_SEPARATOR,						s_entry->name);				}				set_733((char *) s_entry->isorec.extent,						s_hash->starting_block);				set_733((char *) s_entry->isorec.size,						s_hash->size);#ifdef SORTING				/* check for non-directory files */				if (do_sort && ((s_entry->isorec.flags[0] & ISO_DIRECTORY) == 0)) {					/* make sure the real file has the highest weighting */					s_hash->de->sort = MAX(s_entry->sort, s_hash->de->sort);					/* flag this as a potential non-sorted file */					s_entry->sort = NOT_SORTED;				}#endif /* SORTING */				continue;			}			/*			 * If this is for a directory that is not a . or			 * a .. entry, then look up the information for the			 * entry.  We have already assigned extents for			 * directories, so we just need to fill in the blanks			 * here.			 */			if (strcmp(s_entry->name, ".") != 0 &&					strcmp(s_entry->name, "..") != 0 &&					s_entry->isorec.flags[0] & ISO_DIRECTORY) {				finddir = dpnt->subdir;				while (1 == 1) {					if (finddir->self == s_entry)						break;					finddir = finddir->next;					if (!finddir) {#ifdef	USE_LIBSCHILY						comerrno(EX_BAD,							"Fatal goof - could not find dir entry for '%s'\n",							s_entry->name);#else						fprintf(stderr,							"Fatal goof - could not find dir entry for '%s'\n",							s_entry->name);						exit(1);#endif					}				}				set_733((char *) s_entry->isorec.extent,						finddir->extent);				s_entry->starting_block = finddir->extent;				s_entry->size = ISO_ROUND_UP(finddir->size);				total_dir_size += s_entry->size;				add_hash(s_entry);				set_733((char *) s_entry->isorec.size,						ISO_ROUND_UP(finddir->size));				continue;			}			/*			 * If this is . or .., then look up the relevant info			 * from the tables.			 */			if (strcmp(s_entry->name, ".") == 0) {				set_733((char *) s_entry->isorec.extent,								dpnt->extent);				/*				 * Set these so that the hash table has the				 * correct information				 */				s_entry->starting_block = dpnt->extent;				s_entry->size = ISO_ROUND_UP(dpnt->size);				add_hash(s_entry);				s_entry->starting_block = dpnt->extent;				set_733((char *) s_entry->isorec.size,						ISO_ROUND_UP(dpnt->size));				continue;			}			if (strcmp(s_entry->name, "..") == 0) {				if (dpnt == root) {					total_dir_size += root->size;				}				set_733((char *) s_entry->isorec.extent,							dpnt->parent->extent);				/*				 * Set these so that the hash table has the				 * correct information				 */				s_entry->starting_block = dpnt->parent->extent;				s_entry->size =					ISO_ROUND_UP(dpnt->parent->size);				add_hash(s_entry);				s_entry->starting_block = dpnt->parent->extent;				set_733((char *) s_entry->isorec.size,					ISO_ROUND_UP(dpnt->parent->size));				continue;			}			/*			 * Some ordinary non-directory file.  Just schedule			 * the file to be written.  This is all quite			 * straightforward, just make a list and assign			 * extents as we go.  Once we get through writing all			 * of the directories, we should be ready write out			 * these files			 */			if (s_entry->size) {				dwpnt = (struct deferred_write *)					e_malloc(sizeof(struct deferred_write));				/* save this directory entry for later use */				dwpnt->s_entry = s_entry;				/* set the initial padding to zero */				dwpnt->pad = 0;#ifdef APPLE_HYB				/*				 * maybe an offset to start of the real				 * file/fork				 */				dwpnt->off = s_entry->hfs_off;#else				dwpnt->off = 0;#endif	/* APPLE_HYB */				if (dw_tail) {					dw_tail->next = dwpnt;					dw_tail = dwpnt;				} else {					dw_head = dwpnt;					dw_tail = dwpnt;				}				if (s_entry->inode == TABLE_INODE) {					dwpnt->table = s_entry->table;					dwpnt->name = NULL;					sprintf(whole_path, "%s%s%s",						s_entry->filedir->whole_name,						SPATH_SEPARATOR, trans_tbl);				} else {					dwpnt->table = NULL;					strcpy(whole_path,							s_entry->whole_name);					dwpnt->name = strdup(whole_path);				}				dwpnt->next = NULL;				dwpnt->size = s_entry->size;				dwpnt->extent = last_extent;				set_733((char *) s_entry->isorec.extent,								last_extent);				s_entry->starting_block = last_extent;				add_hash(s_entry);				last_extent +=					ISO_ROUND_UP(s_entry->size) >> 11;				if (verbose > 2) {					fprintf(stderr, "%d %d %s\n",						s_entry->starting_block,						last_extent - 1, whole_path);				}#ifdef DBG_ISO				if ((ISO_ROUND_UP(s_entry->size) >> 11) >									500) {					fprintf(stderr,						"Warning: large file %s\n",						whole_path);					fprintf(stderr,						"Starting block is %d\n",						s_entry->starting_block);					fprintf(stderr,					"Reported file size is %d extents\n",						s_entry->size);				}#endif#ifdef	NOT_NEEDED	/* Never use this code if you like to create a DVD */				if (last_extent > (800000000 >> 11)) {					/* More than 800Mb? Punt */					fprintf(stderr,					"Extent overflow processing file %s\n",						 whole_path);					fprintf(stderr,						"Starting block is %d\n",						s_entry->starting_block);					fprintf(stderr,					"Reported file size is %d extents\n",								s_entry->size);					exit(1);				}#endif				continue;			}			/*			 * This is for zero-length files.  If we leave the			 * extent 0, then we get screwed, because many readers			 * simply drop files that have an extent of zero.			 * Thus we leave the size 0, and just assign the			 * extent number.			 */			set_733((char *) s_entry->isorec.extent, last_extent);		}		if (dpnt->subdir) {			assign_file_addresses(dpnt->subdir);		}		dpnt = dpnt->next;	}}/* assign_file_addresses(... */static voidfree_one_directory(dpnt)	struct directory	*dpnt;{	struct directory_entry *s_entry;	struct directory_entry *s_entry_d;	s_entry = dpnt->contents;	while (s_entry) {		s_entry_d = s_entry;		s_entry = s_entry->next;		if (s_entry_d->rr_attributes) {			free(s_entry_d->rr_attributes);			s_entry_d->rr_attributes = NULL;		}		if (s_entry_d->name != NULL) {			free(s_entry_d->name);			s_entry_d->name = NULL;		}		if (s_entry_d->whole_name != NULL) {			free(s_entry_d->whole_name);			s_entry_d->whole_name = NULL;		}#ifdef APPLE_HYB		if (apple_both && s_entry_d->hfs_ent && !s_entry_d->assoc)			free(s_entry_d->hfs_ent);#endif	/* APPLE_HYB */		free(s_entry_d);		s_entry_d = NULL;	}	dpnt->contents = NULL;}/* free_one_directory(... */static voidfree_directories(dpnt)	struct directory	*dpnt;{	while (dpnt) {		free_one_directory(dpnt);		if (dpnt->subdir)			free_directories(dpnt->subdir);		dpnt = dpnt->next;	}}voidgenerate_one_directory(dpnt, outfile)	struct directory	*dpnt;	FILE			*outfile;{	unsigned int	ce_address = 0;	char		*ce_buffer;	unsigned int	ce_index = 0;	unsigned int	ce_size;	unsigned int	dir_index;	char		*directory_buffer;	int		new_reclen;	struct directory_entry *s_entry;	struct directory_entry *s_entry_d;	unsigned int	total_size;	total_size = (dpnt->size + (SECTOR_SIZE - 1)) & ~(SECTOR_SIZE - 1);	directory_buffer = (char *) e_malloc(total_size);	memset(directory_buffer, 0, total_size);	dir_index = 0;	ce_size = (dpnt->ce_bytes + (SECTOR_SIZE - 1)) & ~(SECTOR_SIZE - 1);	ce_buffer = NULL;	if (ce_size > 0) {		ce_buffer = (char *) e_malloc(ce_size);		memset(ce_buffer, 0, ce_size);		ce_index = 0;		/* Absolute byte address of CE entries for this directory */		ce_address = last_extent_written + (total_size >> 11);		ce_address = ce_address << 11;	}	s_entry = dpnt->contents;	while (s_entry) {		/* skip if it's hidden */		if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY) {			s_entry = s_entry->next;			continue;		}		/*		 * We do not allow directory entries to cross sector		 * boundaries. Simply pad, and then start the next entry at		 * the next sector		 */		new_reclen = s_entry->isorec.length[0];		if ((dir_index & (SECTOR_SIZE - 1)) + new_reclen >=								SECTOR_SIZE) {			dir_index = (dir_index + (SECTOR_SIZE - 1)) &

⌨️ 快捷键说明

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