📄 tree.c
字号:
/* @(#)tree.c 1.53 00/05/07 joerg */#ifndef lintstatic char sccsid[] = "@(#)tree.c 1.53 00/05/07 joerg";#endif/* * File tree.c - scan directory tree and build memory structures for iso9660 * filesystem Written by Eric Youngdale (1993). Copyright 1993 Yggdrasil Computing, Incorporated 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. *//* ADD_FILES changes made by Ross Biro biro@yggdrasil.com 2/23/95 *//* APPLE_HYB James Pearson j.pearson@ge.ucl.ac.uk 23/2/2000 */#include "config.h"#include <stdxlib.h>#include <strdefs.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 __PR((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"#include <statdefs.h>#ifdef USE_LIBSCHILY#include <standard.h>#include <schily.h>#endif#ifdef __SVR4extern char *strdup __PR((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)); int stat_filter __PR((char *path, struct stat *st)); int lstat_filter __PR((char *path, struct stat *st));static int sort_n_finish __PR((struct directory *this_dir));static void generate_reloc_directory __PR((void));static void attach_dot_entries __PR((struct directory * dirnode, struct stat * parent_stat));static void update_nlink __PR((struct directory_entry *s_entry, int value));static void increment_nlink __PR((struct directory_entry *s_entry)); char *find_rr_attribute __PR((unsigned char *pnt, int len, char *attr_type)); void finish_cl_pl_entries __PR((void)); int scan_directory_tree __PR((struct directory *this_dir, char *path, struct directory_entry *de));#ifdef APPLE_HYB int insert_file_entry __PR((struct directory *this_dir, char *whole_path, char *short_name, int have_rsrc));#else int insert_file_entry __PR((struct directory *this_dir, char *whole_path, char *short_name));#endif void generate_iso9660_directories __PR((struct directory *node, FILE *outfile));struct directory *find_or_create_directory __PR((struct directory *parent, const char *path, struct directory_entry *de, int flag));static void delete_directory __PR((struct directory * parent, struct directory * child)); int sort_tree __PR((struct directory *node)); void dump_tree __PR((struct directory *node)); void update_nlink_field __PR((struct directory *node));struct directory_entry *search_tree_file __PR((struct directory *node, char *filename)); void init_fstatbuf __PR((void));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 voidstat_fix(st) 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;}intstat_filter(path, st) char *path; struct stat *st;{ int result = stat(path, st); if (result >= 0 && rationalize) stat_fix(st); return result;}intlstat_filter(path, st) char *path; struct stat *st;{ int result = lstat(path, st); if (result >= 0 && rationalize) stat_fix(st); return result;}static intsort_n_finish(this_dir) 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[MAX_ISONAME+1]; char rootname[MAX_ISONAME+1]; char extname[MAX_ISONAME+1]; /* * 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; }#ifdef APPLE_HYB /* * if the pair are associated, then skip (as they have the * same name!) */ if (apple_both && s_entry1->assoc && s_entry1->assoc == s_entry) { s_entry = s_entry->next; continue; }#endif /* APPLE_HYB */ 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); /* * 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, '.'); } extname[0] = '\0'; /* In case we have no ext. */ if (c) { strcpy(extname, c); *c = 0; /* Cut off complete ext. */ } else { /* * Could not find any '.'. */ c = strchr(rootname, ';'); if (c) { *c = 0; /* Cut off version number */ } } c = strchr(extname, ';'); if (c) { *c = 0; /* Cut off version number */ } d1 = strlen(rootname); if (full_iso9660_filenames || iso9660_level > 1) { d2 = strlen(extname); /* * 31/37 chars minus the 3 characters we are * appending below to create unique filenames. */ if ((d1 + d2) > (iso9660_namelen - 3)) rootname[iso9660_namelen - 3 - d2] = 0; } else { if (d1 > 5) rootname[5] = 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%s", rootname, (d1 <= 9 ? '0' + d1 : 'A' + d1 - 10), (d2 <= 9 ? '0' + d2 : 'A' + d2 - 10), (d3 <= 9 ? '0' + d3 : 'A' + d3 - 10), extname, ((s_entry->isorec.flags[0] & ISO_DIRECTORY) || 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);#ifdef APPLE_HYB /* has resource fork - needs new name */ if (apple_both && s_entry->assoc) { struct directory_entry *s_entry2 = s_entry->assoc; /* * resource fork name *should* be the same as * the data fork */ s_entry2->isorec.name_len[0] = s_entry->isorec.name_len[0]; strcpy(s_entry2->isorec.name, s_entry->isorec.name); s_entry2->isorec.length[0] = new_reclen; }#endif /* APPLE_HYB */ } 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);#ifdef APPLE_HYB /* has resource fork - needs new name */ if (apple_both && s_entry1->assoc) { struct directory_entry *s_entry2 = s_entry1->assoc; /* * resource fork name *should* be the same as * the data fork */ s_entry2->isorec.name_len[0] = s_entry1->isorec.name_len[0]; strcpy(s_entry2->isorec.name, s_entry1->isorec.name); s_entry2->isorec.length[0] = new_reclen; }#endif /* APPLE_HYB */ } 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;#ifdef APPLE_HYB /* skip table entry for the resource fork */ if (apple_both &&
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -