📄 tree.c
字号:
/* @(#)tree.c 1.68 02/11/22 joerg */#ifndef lintstatic char sccsid[] = "@(#)tree.c 1.68 02/11/22 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,2001 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 <mconfig.h>#include "mkisofs.h"#include "match.h"#include "exclude.h"#include <timedefs.h>#include <errno.h>#include <fctldefs.h>#include <device.h>#include <schily.h>#ifdef UDF#include "udf.h"#endif#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#ifdef __SVR4extern char *strdup __PR((const char *));#endifstatic unsigned char symlink_buff[PATH_MAX+1];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; /* We use this for the artificial entries we create */struct stat root_statbuf; /* Stat buffer for root directory */struct directory *reloc_dir;static char *filetype(t) int t;{ static char unkn[32]; if (S_ISFIFO(t)) /* 1 */ return ("fifo"); if (S_ISCHR(t)) /* 2 */ return ("chr"); if (S_ISMPC(t)) /* 3 */ return ("multiplexed chr"); if (S_ISDIR(t)) /* 4 */ return ("dir"); if (S_ISNAM(t)) /* 5 */ return ("named file"); if (S_ISBLK(t)) /* 6 */ return ("blk"); if (S_ISMPB(t)) /* 7 */ 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 (S_ISSHAD(t)) /* 11 */ return ("Solaris shadow inode"); if (S_ISSOCK(t)) /* 12 */ return ("socket"); if (S_ISDOOR(t)) /* 13 */ return ("door"); if (S_ISWHT(t)) /* 14 */ return ("whiteout"); if (S_ISEVC(t)) /* 15 */ return ("event count"); /* * Needs to be last in case somebody makes this * a supported file type. */ if ((t & S_IFMT) == 0) /* 0 (unallocated) */ return ("unallocated"); sprintf(unkn, "octal '%o'", t & S_IFMT); return (unkn);}/* * 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;{ int adjust_modes = 0; if (S_ISREG(st->st_mode)) adjust_modes = rationalize_filemode; else if (S_ISDIR(st->st_mode)) adjust_modes = rationalize_dirmode; else adjust_modes = (rationalize_filemode || rationalize_dirmode); /* * If rationalizing, override the uid and gid, since the * originals will only be useful on the author's system. */ if (rationalize_uid) st->st_uid = uid_to_use; if (rationalize_gid) st->st_gid = gid_to_use; if (adjust_modes) { if (S_ISREG(st->st_mode) && (filemode_to_use != 0)) { st->st_mode = filemode_to_use | S_IFREG; } else if (S_ISDIR(st->st_mode) && (dirmode_to_use != 0)) { st->st_mode = dirmode_to_use | S_IFDIR; } else { /* * 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) { is_rrmoved++; fprintf(stderr, "\nUsing %s for %s%s%s (%s)", 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) { is_rrmoved++; fprintf(stderr, "\nUsing %s for %s%s%s (%s)", 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 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -