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

📄 tree.c

📁 刻录光盘的程序
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * File tree.c - scan directory  tree and build memory structures 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: tree.c,v 1.29 1999/03/07 17:41:19 eric Exp $";/* ADD_FILES changes made by Ross Biro biro@yggdrasil.com 2/23/95 */#include "config.h"#include <stdlib.h>#include <string.h>#include <time.h>#include <errno.h>#include <unixstd.h>#include <fctldefs.h>#include <device.h>#ifdef VMS#include <sys/file.h>#include <vms/fabdef.h>#include "vms.h"extern char * strdup(const char *);#endif/* * Autoconf should be able to figure this one out for us and let us know * whether the system has memmove or not. */# ifndef HAVE_MEMMOVE#  define memmove(d, s, n) bcopy ((s), (d), (n))# endif#include "mkisofs.h"#include "iso9660.h"#include "match.h"#include <sys/stat.h>#include "exclude.h"#ifdef	DOESNT_WORK/* * This is the dead code */#ifdef NON_UNIXFS#define S_ISLNK(m)	(0)#define S_ISSOCK(m)	(0)#define S_ISFIFO(m)	(0)#else#ifndef S_ISLNK#define S_ISLNK(m)	(((m) & S_IFMT) == S_IFLNK)#endif#ifndef S_ISSOCK# ifdef S_IFSOCK#   define S_ISSOCK(m)	(((m) & S_IFMT) == S_IFSOCK)# else#   define S_ISSOCK(m)	(0)# endif#endif#endif#else/* * This is the new code */#include <statdefs.h>#endif#ifdef	USE_LIBSCHILY#include <standard.h>#endif#ifdef __SVR4extern char * strdup(const char *);#endifstatic unsigned char symlink_buff[256];static char * filetype	__PR((int t));static char * rstr	__PR((char *s1, char *s2));static void stat_fix	__PR((struct stat * st));static void generate_reloc_directory __PR((void));static void DECL(attach_dot_entries, (struct directory * dirnode,		   struct stat * parent_stat));static void DECL(delete_directory, (struct directory * parent, struct directory * child));extern int verbose;struct stat fstatbuf = {0,};  /* We use this for the artificial entries we create */struct stat root_statbuf = {0, };  /* Stat buffer for root directory */struct directory * reloc_dir = NULL;static char *filetype(t)	int	t;{	if ((t & S_IFMT) == 0)		/* 0 (unallocated) */		return ("unallocated");	if (S_ISFIFO(t))		/* 1 */		return ("fifo");	if (S_ISCHR(t))			/* 2 */		return ("chr");	if ((t & S_IFMT) == 3)		/* 3 (multiplexed chr) */		return ("multiplexed chr");	if (S_ISDIR(t))			/* 4 */		return ("dir");	if ((t & S_IFMT) == 5)		/* 5 (named file) */		return ("named file");	if (S_ISBLK(t))			/* 6 */		return ("blk");	if ((t & S_IFMT) == 7)		/* 7 (multiplexed blk) */		return ("multiplexed blk");	if (S_ISREG(t))			/* 8 */		return ("regular file");	if (S_ISCNT(t))			/* 9 */		return ("contiguous file");	if (S_ISLNK(t))			/* 10 */		return ("symlink");	if ((t & S_IFMT) == 11)		/* 11 (Solaris shadow inode) */		return ("Solaris shadow inode");	if (S_ISSOCK(t))		/* 12 */		return ("socket");	if (S_ISDOOR(t))		/* 13 */		return ("door");	if ((t & S_IFMT) == 14)		/* 14 (CPIO acl) */		return ("CPIO acl");	if ((t & S_IFMT) == 15)		/* 15 (unused) */		return ("unused 15");	return ("BLETCH");}/* * Check if s1 ends in strings s2 */static char *rstr(s1, s2)	char	*s1;	char	*s2;{	int	l1;	int	l2;	l1 = strlen(s1);	l2 = strlen(s2);	if (l2 > l1)		return ((char *)NULL);	if (strcmp(&s1[l1 - l2], s2) == 0)		return (&s1[l1 - l2]);	return ((char *)NULL);}static voidFDECL1(stat_fix, struct stat *, st){  /* Remove the uid and gid, they will only be useful on the author's     system.  */  st->st_uid = 0;  st->st_gid = 0; /*  * Make sure the file modes make sense.  Turn on all read bits.  Turn  * on all exec/search bits if any exec/search bit is set.  Turn off  * all write bits, and all special mode bits (on a r/o fs lock bits  * are useless, and with uid+gid 0 don't want set-id bits, either).  */  st->st_mode |= 0444;#ifndef _WIN32		/* make all file "executable" */  if (st->st_mode & 0111)#endif /* _WIN32 */    st->st_mode |= 0111;  st->st_mode &= ~07222;}intFDECL2(stat_filter, char *, path, struct stat *, st){  int result = stat(path, st);  if (result >= 0 && rationalize)    stat_fix(st);  return result;}intFDECL2(lstat_filter, char *, path, struct stat *, st){  int result = lstat(path, st);  if (result >= 0 && rationalize)    stat_fix(st);  return result;}static int FDECL1(sort_n_finish, struct directory *, this_dir){  struct directory_entry  * s_entry;  struct directory_entry  * s_entry1;  struct directory_entry  * table;  int			    count;  int			    d1;  int			    d2;  int			    d3;  int			    new_reclen;  char			 *  c;  int			    status = 0;  int			    tablesize = 0;  char			    newname[34];  char			    rootname[34];  /* Here we can take the opportunity to toss duplicate entries from the     directory.  */  /* ignore if it's hidden */  if(this_dir->dir_flags & INHIBIT_ISO9660_ENTRY)    {      return 0;    }  table = NULL;  init_fstatbuf();  /*   * If we had artificially created this directory, then we might be   * missing the required '.' entries.  Create these now if we need   * them.   */  if( (this_dir->dir_flags & (DIR_HAS_DOT | DIR_HAS_DOTDOT)) !=       (DIR_HAS_DOT | DIR_HAS_DOTDOT) )    {      attach_dot_entries(this_dir, &fstatbuf);    }  flush_file_hash();  s_entry = this_dir->contents;  while(s_entry)    {    /* ignore if it's hidden */    if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY)      {	s_entry = s_entry->next;	continue;      }	        /*       * First assume no conflict, and handle this case        */      if(!(s_entry1 = find_file_hash(s_entry->isorec.name)))	{	  add_file_hash(s_entry);	  s_entry = s_entry->next;	  continue;	}	        if(s_entry1 == s_entry)	{#ifdef	USE_LIBSCHILY	  comerrno(EX_BAD, "Fatal goof, file '%s' already in hash table.\n", s_entry->isorec.name);#else	  fprintf(stderr, "Fatal goof, file '%s' already in hash table.\n", s_entry->isorec.name);	  exit(1);#endif	}            /*        * OK, handle the conflicts.  Try substitute names until we come       * up with a winner        */      strcpy(rootname, s_entry->isorec.name);      if(full_iso9660_filenames) 	{		/*		 * 27 is 30 chars minus the 3 characters we are		 * appending below to create unique filenames.		 */	  if(strlen(rootname) > 27) rootname[27] = 0;	}      /*       * Strip off the non-significant part of the name so that we are left       * with a sensible root filename.  If we don't find a '.', then try       * a ';'.       */      c  = strchr(rootname, '.');	/*	 * In case we ever allow more than on dot, only modify the section	 * past the last dot if the file name starts with a dot.	 */      if (c != NULL && c == rootname && c != strrchr(rootname, '.'))	c = strrchr(rootname, '.');      if (c) 	*c = 0;      else	{	  c  = strchr(rootname, ';');	  if (c) *c = 0;	}      for(d1 = 0; d1 < 36; d1++)	{	  for(d2 = 0; d2 < 36; d2++)	    {	      for(d3 = 0; d3 < 36; d3++)		{		  sprintf(newname,"%s.%c%c%c%s", rootname,  			  (d1 <= 9 ? '0' + d1 : 'A' + d1 - 10),			  (d2 <= 9 ? '0' + d2 : 'A' + d2 - 10),			  (d3 <= 9 ? '0' + d3 : 'A' + d3 - 10),			  (s_entry->isorec.flags[0] == 2 || 			   omit_version_number ? "" : ";1"));		  #ifdef VMS		  /* Sigh.  VAXCRTL seems to be broken here */		  {		    int ijk = 0;		    while(newname[ijk]) 		      {			if(newname[ijk] == ' ') newname[ijk] = '0';			ijk++;		      }		  }#endif		  		  if(!find_file_hash(newname)) goto got_valid_name;		}	    }	}      /*       * If we fell off the bottom here, we were in real trouble.       */#ifdef	USE_LIBSCHILY      comerrno(EX_BAD, "Unable to generate unique name for file %s\n", s_entry->name);#else      fprintf(stderr,"Unable to generate unique name for file %s\n", s_entry->name);      exit(1);#endifgot_valid_name:            /*        * OK, now we have a good replacement name.  Now decide which one       * of these two beasts should get the name changed        */      if(s_entry->priority < s_entry1->priority) 	{	  if( verbose > 0 )	    {	      fprintf(stderr,"Using %s for  %s%s%s (%s)\n", newname,  		      this_dir->whole_name, SPATH_SEPARATOR, 		      s_entry->name, s_entry1->name);	    }	  s_entry->isorec.name_len[0] =  strlen(newname);	  new_reclen =  offsetof(struct iso_directory_record, name[0]) +	    strlen(newname);	  if(use_RockRidge) 	    {	      if (new_reclen & 1) new_reclen++;  /* Pad to an even byte */	      new_reclen += s_entry->rr_attr_size;	    }	  if (new_reclen & 1) new_reclen++;  /* Pad to an even byte */	  s_entry->isorec.length[0] = new_reclen;	  strcpy(s_entry->isorec.name, newname);	}      else 	{	  delete_file_hash(s_entry1);	  if( verbose > 0 )	    {	      fprintf(stderr,"Using %s for  %s%s%s (%s)\n", newname,  		      this_dir->whole_name, SPATH_SEPARATOR, 		      s_entry1->name, s_entry->name);	    }	  s_entry1->isorec.name_len[0] =  strlen(newname);	  new_reclen =  offsetof(struct iso_directory_record, name[0]) +	    strlen(newname);	  if(use_RockRidge) 	    {	      if (new_reclen & 1) new_reclen++;  /* Pad to an even byte */	      new_reclen += s_entry1->rr_attr_size;	    }	  if (new_reclen & 1) new_reclen++;  /* Pad to an even byte */	  s_entry1->isorec.length[0] = new_reclen;	  strcpy(s_entry1->isorec.name, newname);	  add_file_hash(s_entry1);	}      add_file_hash(s_entry);      s_entry = s_entry->next;    }  if(generate_tables      && !find_file_hash(trans_tbl)      && (reloc_dir != this_dir)     && (this_dir->extent == 0) )    {      /*        * First we need to figure out how big this table is        */      for (s_entry = this_dir->contents; s_entry; s_entry = s_entry->next)	{	  if(strcmp(s_entry->name, ".") == 0  ||	     strcmp(s_entry->name, "..") == 0) continue; 	  if(s_entry->de_flags & INHIBIT_ISO9660_ENTRY) continue;	  if(s_entry->table) tablesize += 35 + strlen(s_entry->table);	}    }  if( tablesize > 0 )    {      table = (struct directory_entry *) 	e_malloc(sizeof (struct directory_entry));      memset(table, 0, sizeof(struct directory_entry));      table->table = NULL;      table->next = this_dir->contents;      this_dir->contents = table;            table->filedir = root;      table->isorec.flags[0] = 0;      table->priority  = 32768;      iso9660_date(table->isorec.date, fstatbuf.st_mtime);      table->inode = TABLE_INODE;      table->dev = (dev_t) UNCACHED_DEVICE;      set_723(table->isorec.volume_sequence_number, volume_sequence_number);      set_733((char *) table->isorec.size, tablesize);      table->size = tablesize;      table->filedir = this_dir;      if (jhide_trans_tbl)      	table->de_flags    |= INHIBIT_JOLIET_ENTRY;/*      table->name = strdup("<translation table>");*/      table->name = strdup(trans_tbl);      table->table = (char *) e_malloc(ROUND_UP(tablesize));      memset(table->table, 0, ROUND_UP(tablesize));      iso9660_file_length  (trans_tbl, table, 0);            if(use_RockRidge)	{	  fstatbuf.st_mode = 0444 | S_IFREG;	  fstatbuf.st_nlink = 1;	  generate_rock_ridge_attributes("",					 trans_tbl, table,					 &fstatbuf, &fstatbuf, 0);	}    }    /*   * We have now chosen the 8.3 names and we should now know the length   * of every entry in the directory.   */  for(s_entry = this_dir->contents; s_entry; s_entry = s_entry->next)    {      /* skip if it's hidden */      if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY)	{	  continue;	}      new_reclen = strlen(s_entry->isorec.name);	        /*       * First update the path table sizes for directories.       */      if(s_entry->isorec.flags[0] ==  2)	{	  if (strcmp(s_entry->name,".") != 0 && strcmp(s_entry->name,"..") != 0)	    {	      path_table_size += new_reclen + offsetof(struct iso_path_table, name[0]);	      if (new_reclen & 1) path_table_size++;	    }	  else 	    {	      new_reclen = 1;	      if (this_dir == root && strlen(s_entry->name) == 1)		{		  path_table_size += new_reclen + offsetof(struct iso_path_table, name[0]);		}	    }	}      if(path_table_size & 1) path_table_size++;  /* For odd lengths we pad */      s_entry->isorec.name_len[0] = new_reclen;            new_reclen += offsetof(struct iso_directory_record, name[0]);            if (new_reclen & 1)		new_reclen++;            new_reclen += s_entry->rr_attr_size;            if (new_reclen & 1) new_reclen++;            if(new_reclen > 0xff) 	{#ifdef	USE_LIBSCHILY	  comerrno(EX_BAD, "Fatal error - RR overflow for file %s\n",		  s_entry->name);#else	  fprintf(stderr,"Fatal error - RR overflow for file %s\n",		  s_entry->name);	  exit(1);#endif	}      s_entry->isorec.length[0] = new_reclen;    }  status = sort_directory(&this_dir->contents, (reloc_dir == this_dir));  if( status > 0 )    {#ifdef	USE_LIBSCHILY      comerrno(EX_BAD, "Unable to sort directory %s\n", 	      this_dir->whole_name);

⌨️ 快捷键说明

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