17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 54899432aSab196087 * Common Development and Distribution License (the "License"). 64899432aSab196087 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*57ef7aa9SRod Evans * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate /* 277c478bd9Sstevel@tonic-gate * Routines to add file and directory entries into the internal configuration 287c478bd9Sstevel@tonic-gate * information. This information is maintained in a number of hash tables which 297c478bd9Sstevel@tonic-gate * after completion of input file processing will be processed and written to 307c478bd9Sstevel@tonic-gate * the output configuration file. 317c478bd9Sstevel@tonic-gate * 327c478bd9Sstevel@tonic-gate * Each hash table is defined via a Hash_tbl structure. These are organized: 337c478bd9Sstevel@tonic-gate * 347c478bd9Sstevel@tonic-gate * c_strtbl contains a hash entry for every file, directory, pathname and 357c478bd9Sstevel@tonic-gate * alternative path (dldump(3dl) image) processed. 367c478bd9Sstevel@tonic-gate * c_strsize and c_objnum maintain the size and count of the 377c478bd9Sstevel@tonic-gate * strings added to this table and are used to size the output 387c478bd9Sstevel@tonic-gate * configuration file. 397c478bd9Sstevel@tonic-gate * 407c478bd9Sstevel@tonic-gate * c_inotbls contains a list of inode hash tables. Each element of the list 417c478bd9Sstevel@tonic-gate * identifies a unique device. Thus, for each file processed its 427c478bd9Sstevel@tonic-gate * st_dev and st_ino are used to assign its entry to the correct 437c478bd9Sstevel@tonic-gate * hash table. 447c478bd9Sstevel@tonic-gate * 457c478bd9Sstevel@tonic-gate * Each directory processed is assigned a unique id (c_dirnum) 467c478bd9Sstevel@tonic-gate * which insures each file also becomes uniquely identified. 477c478bd9Sstevel@tonic-gate * 487c478bd9Sstevel@tonic-gate * All file and directory additions come through the inspect() entry point. 497c478bd9Sstevel@tonic-gate */ 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate #include <sys/types.h> 527c478bd9Sstevel@tonic-gate #include <sys/stat.h> 537c478bd9Sstevel@tonic-gate #include <fcntl.h> 547c478bd9Sstevel@tonic-gate #include <dirent.h> 554899432aSab196087 #include <_libelf.h> 567c478bd9Sstevel@tonic-gate #include <errno.h> 577c478bd9Sstevel@tonic-gate #include <stdio.h> 587c478bd9Sstevel@tonic-gate #include <string.h> 597c478bd9Sstevel@tonic-gate #include <unistd.h> 607c478bd9Sstevel@tonic-gate #include <limits.h> 617c478bd9Sstevel@tonic-gate #include "machdep.h" 627c478bd9Sstevel@tonic-gate #include "sgs.h" 637c478bd9Sstevel@tonic-gate #include "rtc.h" 647c478bd9Sstevel@tonic-gate #include "_crle.h" 657c478bd9Sstevel@tonic-gate #include "msg.h" 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate /* 687c478bd9Sstevel@tonic-gate * Add an alternative pathname for an object. Although a configuration file 697c478bd9Sstevel@tonic-gate * may contain several pathnames that resolve to the same real file, there can 707c478bd9Sstevel@tonic-gate * only be one real file. Consequently, there can only be one alternative. 717c478bd9Sstevel@tonic-gate * For multiple pathnames that resolve to the same real file, multiple alter- 727c478bd9Sstevel@tonic-gate * natives may be specified. Always take the alternative for the real file 737c478bd9Sstevel@tonic-gate * over any others. 747c478bd9Sstevel@tonic-gate */ 757c478bd9Sstevel@tonic-gate static int 767c478bd9Sstevel@tonic-gate enteralt(Crle_desc *crle, const char *path, const char *file, Half flags, 777c478bd9Sstevel@tonic-gate Hash_obj *obj) 787c478bd9Sstevel@tonic-gate { 797c478bd9Sstevel@tonic-gate const char *fmt; 807c478bd9Sstevel@tonic-gate char alter[PATH_MAX]; 817c478bd9Sstevel@tonic-gate size_t altsz; 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate if (obj->o_alter) { 847c478bd9Sstevel@tonic-gate /* 857c478bd9Sstevel@tonic-gate * If an alternative has already been captured, only override 867c478bd9Sstevel@tonic-gate * it if the specified file is the real file. 877c478bd9Sstevel@tonic-gate */ 887c478bd9Sstevel@tonic-gate if (strcmp(path, obj->o_path)) 897c478bd9Sstevel@tonic-gate return (1); 907c478bd9Sstevel@tonic-gate } 917c478bd9Sstevel@tonic-gate 927c478bd9Sstevel@tonic-gate /* 937c478bd9Sstevel@tonic-gate * Create an alternative pathname from the file and object destination 947c478bd9Sstevel@tonic-gate * directory. If we're dumping an alternative don't allow it to 957c478bd9Sstevel@tonic-gate * override the original. 967c478bd9Sstevel@tonic-gate */ 977c478bd9Sstevel@tonic-gate if (flags & RTC_OBJ_DUMP) { 987c478bd9Sstevel@tonic-gate char _alter[PATH_MAX]; 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate (void) strcpy(_alter, crle->c_objdir); 1017c478bd9Sstevel@tonic-gate (void) realpath(_alter, _alter); 1027c478bd9Sstevel@tonic-gate (void) snprintf(alter, PATH_MAX, MSG_ORIG(MSG_FMT_PATH), 1037c478bd9Sstevel@tonic-gate _alter, file); 1047c478bd9Sstevel@tonic-gate if (strcmp(alter, obj->o_path) == 0) { 1057c478bd9Sstevel@tonic-gate (void) printf(MSG_INTL(MSG_ARG_ALT), crle->c_name, 1067c478bd9Sstevel@tonic-gate obj->o_path); 1077c478bd9Sstevel@tonic-gate return (0); 1087c478bd9Sstevel@tonic-gate } 1097c478bd9Sstevel@tonic-gate obj->o_flags |= RTC_OBJ_DUMP; 1107c478bd9Sstevel@tonic-gate } else 1117c478bd9Sstevel@tonic-gate (void) snprintf(alter, PATH_MAX, MSG_ORIG(MSG_FMT_PATH), 1127c478bd9Sstevel@tonic-gate crle->c_objdir, file); 1137c478bd9Sstevel@tonic-gate obj->o_flags |= RTC_OBJ_ALTER; 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate /* 1167c478bd9Sstevel@tonic-gate * If we're overriding an existing alternative with the real path, free 1177c478bd9Sstevel@tonic-gate * up any previous alternative. 1187c478bd9Sstevel@tonic-gate */ 1197c478bd9Sstevel@tonic-gate if (obj->o_alter) { 1207c478bd9Sstevel@tonic-gate crle->c_strsize -= strlen(alter) + 1; 1217c478bd9Sstevel@tonic-gate fmt = MSG_INTL(MSG_DIA_ALTUPDATE); 1227c478bd9Sstevel@tonic-gate } else 1237c478bd9Sstevel@tonic-gate fmt = MSG_INTL(MSG_DIA_ALTCREATE); 1247c478bd9Sstevel@tonic-gate 1257c478bd9Sstevel@tonic-gate /* 1267c478bd9Sstevel@tonic-gate * Allocate the new alternative and update the string table size. 1277c478bd9Sstevel@tonic-gate */ 1287c478bd9Sstevel@tonic-gate altsz = strlen(alter) + 1; 129*57ef7aa9SRod Evans if ((obj->o_alter = malloc(altsz)) == NULL) 1307c478bd9Sstevel@tonic-gate return (0); 1317c478bd9Sstevel@tonic-gate (void) strcpy(obj->o_alter, alter); 1327c478bd9Sstevel@tonic-gate 1337c478bd9Sstevel@tonic-gate crle->c_strsize += altsz; 1347c478bd9Sstevel@tonic-gate 1357c478bd9Sstevel@tonic-gate if (crle->c_flags & CRLE_VERBOSE) 1367c478bd9Sstevel@tonic-gate (void) printf(fmt, alter, obj->o_path); 1377c478bd9Sstevel@tonic-gate 1387c478bd9Sstevel@tonic-gate return (1); 1397c478bd9Sstevel@tonic-gate } 1407c478bd9Sstevel@tonic-gate 1417c478bd9Sstevel@tonic-gate 1427c478bd9Sstevel@tonic-gate /* 1437c478bd9Sstevel@tonic-gate * Establish an inode hash entry, this is unique for each dev hash table, and 1447c478bd9Sstevel@tonic-gate * establishes the unique object descriptor. 1457c478bd9Sstevel@tonic-gate */ 1467c478bd9Sstevel@tonic-gate static Hash_ent * 1477c478bd9Sstevel@tonic-gate enterino(Crle_desc *crle, const char *name, struct stat *status, Half flags) 1487c478bd9Sstevel@tonic-gate { 1497c478bd9Sstevel@tonic-gate Hash_ent *ent; 1507c478bd9Sstevel@tonic-gate Hash_obj *obj; 1517c478bd9Sstevel@tonic-gate Hash_tbl *tbl; 152*57ef7aa9SRod Evans Aliste idx; 1537c478bd9Sstevel@tonic-gate Addr ino = (Addr)status->st_ino; 1547c478bd9Sstevel@tonic-gate ulong_t dev = status->st_dev; 1557c478bd9Sstevel@tonic-gate Lword info; 156*57ef7aa9SRod Evans int found = 0; 1577c478bd9Sstevel@tonic-gate 1587c478bd9Sstevel@tonic-gate /* 1597c478bd9Sstevel@tonic-gate * For configuration file verification we retain information about the 1607c478bd9Sstevel@tonic-gate * file or directory. 1617c478bd9Sstevel@tonic-gate */ 1627c478bd9Sstevel@tonic-gate if (flags & RTC_OBJ_DIRENT) 1637c478bd9Sstevel@tonic-gate info = (Lword)status->st_mtime; 1647c478bd9Sstevel@tonic-gate else 1657c478bd9Sstevel@tonic-gate info = (Lword)status->st_size; 1667c478bd9Sstevel@tonic-gate 1677c478bd9Sstevel@tonic-gate /* 1687c478bd9Sstevel@tonic-gate * Determine the objects device number and establish a hash table for 1697c478bd9Sstevel@tonic-gate * for this devices inodes. 1707c478bd9Sstevel@tonic-gate */ 171*57ef7aa9SRod Evans for (APLIST_TRAVERSE(crle->c_inotbls, idx, tbl)) { 172*57ef7aa9SRod Evans if (tbl->t_ident == dev) { 173*57ef7aa9SRod Evans found = 1; 1747c478bd9Sstevel@tonic-gate break; 1757c478bd9Sstevel@tonic-gate } 176*57ef7aa9SRod Evans } 177*57ef7aa9SRod Evans if (found == 0) { 178*57ef7aa9SRod Evans if ((tbl = make_hash(crle->c_inobkts, HASH_INT, dev)) == NULL) 179*57ef7aa9SRod Evans return (NULL); 180*57ef7aa9SRod Evans if (aplist_append(&crle->c_inotbls, tbl, AL_CNT_CRLE) == NULL) 181*57ef7aa9SRod Evans return (NULL); 1827c478bd9Sstevel@tonic-gate } 1837c478bd9Sstevel@tonic-gate 1847c478bd9Sstevel@tonic-gate /* 1857c478bd9Sstevel@tonic-gate * Reuse or add this new object to the inode hash table. 1867c478bd9Sstevel@tonic-gate */ 187*57ef7aa9SRod Evans if ((ent = get_hash(tbl, ino, 0, 188*57ef7aa9SRod Evans (HASH_FND_ENT | HASH_ADD_ENT))) == NULL) 189*57ef7aa9SRod Evans return (NULL); 1907c478bd9Sstevel@tonic-gate 1917c478bd9Sstevel@tonic-gate /* 1927c478bd9Sstevel@tonic-gate * If an object descriptor doesn't yet exist create one. 1937c478bd9Sstevel@tonic-gate */ 194*57ef7aa9SRod Evans if ((obj = ent->e_obj) == NULL) { 195*57ef7aa9SRod Evans if ((obj = calloc(sizeof (Hash_obj), 1)) == NULL) 196*57ef7aa9SRod Evans return (NULL); 1977c478bd9Sstevel@tonic-gate obj->o_tbl = tbl; 1987c478bd9Sstevel@tonic-gate obj->o_flags = flags; 1997c478bd9Sstevel@tonic-gate obj->o_info = info; 2007c478bd9Sstevel@tonic-gate 2017c478bd9Sstevel@tonic-gate /* 2027c478bd9Sstevel@tonic-gate * Reallocate the objects name, as it might have been composed 2037c478bd9Sstevel@tonic-gate * and passed to us on the stack. 2047c478bd9Sstevel@tonic-gate */ 205*57ef7aa9SRod Evans if ((obj->o_path = strdup(name)) == NULL) 206*57ef7aa9SRod Evans return (NULL); 2077c478bd9Sstevel@tonic-gate 2087c478bd9Sstevel@tonic-gate /* 2097c478bd9Sstevel@tonic-gate * Assign this object to the original ino hash entry. 2107c478bd9Sstevel@tonic-gate */ 2117c478bd9Sstevel@tonic-gate ent->e_obj = obj; 2127c478bd9Sstevel@tonic-gate } 2137c478bd9Sstevel@tonic-gate return (ent); 2147c478bd9Sstevel@tonic-gate } 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate /* 2177c478bd9Sstevel@tonic-gate * Basic directory entry, establishes entry information, updated global counts 2187c478bd9Sstevel@tonic-gate * and provides any diagnostics. 2197c478bd9Sstevel@tonic-gate */ 2207c478bd9Sstevel@tonic-gate static int 2217c478bd9Sstevel@tonic-gate _enterdir(Crle_desc *crle, const char *dir, Hash_ent *ent, Hash_obj *obj) 2227c478bd9Sstevel@tonic-gate { 2237c478bd9Sstevel@tonic-gate size_t size = strlen(dir) + 1; 2247c478bd9Sstevel@tonic-gate char *ndir; 2257c478bd9Sstevel@tonic-gate 2267c478bd9Sstevel@tonic-gate /* 2277c478bd9Sstevel@tonic-gate * Establish this hash entries key (which is the directory name itself), 2287c478bd9Sstevel@tonic-gate * assign the next available directory number, and its object. 2297c478bd9Sstevel@tonic-gate */ 230*57ef7aa9SRod Evans if ((ndir = malloc(size)) == NULL) 2317c478bd9Sstevel@tonic-gate return (0); 2327c478bd9Sstevel@tonic-gate (void) strcpy(ndir, dir); 2337c478bd9Sstevel@tonic-gate 2347c478bd9Sstevel@tonic-gate ent->e_key = (Addr)ndir; 2357c478bd9Sstevel@tonic-gate ent->e_id = crle->c_dirnum++; 2367c478bd9Sstevel@tonic-gate ent->e_obj = obj; 2377c478bd9Sstevel@tonic-gate 2387c478bd9Sstevel@tonic-gate /* 2397c478bd9Sstevel@tonic-gate * Update string table information. We add a dummy filename for each 2407c478bd9Sstevel@tonic-gate * real directory so as to have a null terminated file table array for 2417c478bd9Sstevel@tonic-gate * this directory. 2427c478bd9Sstevel@tonic-gate */ 2437c478bd9Sstevel@tonic-gate crle->c_strsize += size; 2447c478bd9Sstevel@tonic-gate crle->c_hashstrnum++; 2457c478bd9Sstevel@tonic-gate crle->c_filenum++; 2467c478bd9Sstevel@tonic-gate 2477c478bd9Sstevel@tonic-gate /* 2487c478bd9Sstevel@tonic-gate * Provide any diagnostics. 2497c478bd9Sstevel@tonic-gate */ 2507c478bd9Sstevel@tonic-gate if (crle->c_flags & CRLE_VERBOSE) { 2517c478bd9Sstevel@tonic-gate const char *fmt; 2527c478bd9Sstevel@tonic-gate 2537c478bd9Sstevel@tonic-gate if (obj->o_flags & RTC_OBJ_NOEXIST) 2547c478bd9Sstevel@tonic-gate fmt = MSG_INTL(MSG_DIA_NOEXIST); 2557c478bd9Sstevel@tonic-gate else 2567c478bd9Sstevel@tonic-gate fmt = MSG_INTL(MSG_DIA_DIR); 2577c478bd9Sstevel@tonic-gate 2587c478bd9Sstevel@tonic-gate (void) printf(fmt, ent->e_id, dir); 2597c478bd9Sstevel@tonic-gate } 2607c478bd9Sstevel@tonic-gate return (1); 2617c478bd9Sstevel@tonic-gate } 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate /* 2647c478bd9Sstevel@tonic-gate * Establish a string hash entry for a directory. 2657c478bd9Sstevel@tonic-gate */ 2667c478bd9Sstevel@tonic-gate static Hash_ent * 2677c478bd9Sstevel@tonic-gate enterdir(Crle_desc *crle, const char *odir, Half flags, struct stat *status) 2687c478bd9Sstevel@tonic-gate { 2697c478bd9Sstevel@tonic-gate Hash_tbl *stbl = crle->c_strtbl; 2707c478bd9Sstevel@tonic-gate Hash_ent *ent; 2717c478bd9Sstevel@tonic-gate Hash_obj *obj; 2727c478bd9Sstevel@tonic-gate char rdir[PATH_MAX], *ndir; 2737c478bd9Sstevel@tonic-gate 2747c478bd9Sstevel@tonic-gate /* 2757c478bd9Sstevel@tonic-gate * Establish the directories real name, this is the name that will be 2767c478bd9Sstevel@tonic-gate * recorded in the object identifier. 2777c478bd9Sstevel@tonic-gate */ 278*57ef7aa9SRod Evans if (realpath(odir, rdir) == NULL) 279*57ef7aa9SRod Evans return (NULL); 2807c478bd9Sstevel@tonic-gate 2817c478bd9Sstevel@tonic-gate if (strcmp(odir, rdir)) 2827c478bd9Sstevel@tonic-gate ndir = rdir; 2837c478bd9Sstevel@tonic-gate else 2847c478bd9Sstevel@tonic-gate ndir = (char *)odir; 2857c478bd9Sstevel@tonic-gate 2867c478bd9Sstevel@tonic-gate /* 2877c478bd9Sstevel@tonic-gate * If we're not dealing with an all-entries directory (i.e., we're 2887c478bd9Sstevel@tonic-gate * recording this directory because of its explicitly specified 2897c478bd9Sstevel@tonic-gate * filename) leave off any filename specific attributes. 2907c478bd9Sstevel@tonic-gate */ 2917c478bd9Sstevel@tonic-gate if ((flags & RTC_OBJ_ALLENTS) == 0) 2927c478bd9Sstevel@tonic-gate flags &= ~(RTC_OBJ_ALTER | RTC_OBJ_DUMP | RTC_OBJ_GROUP); 2937c478bd9Sstevel@tonic-gate flags |= RTC_OBJ_DIRENT; 2947c478bd9Sstevel@tonic-gate 2957c478bd9Sstevel@tonic-gate /* 2967c478bd9Sstevel@tonic-gate * Establish a inode table entry, and the objects unique descriptor. 2977c478bd9Sstevel@tonic-gate */ 298*57ef7aa9SRod Evans if ((ent = enterino(crle, ndir, status, flags)) == NULL) 299*57ef7aa9SRod Evans return (NULL); 3007c478bd9Sstevel@tonic-gate obj = ent->e_obj; 3017c478bd9Sstevel@tonic-gate 3027c478bd9Sstevel@tonic-gate /* 3037c478bd9Sstevel@tonic-gate * Create a string table entry for the real directory. 3047c478bd9Sstevel@tonic-gate */ 3057c478bd9Sstevel@tonic-gate if ((ent = get_hash(stbl, (Addr)ndir, 0, 306*57ef7aa9SRod Evans (HASH_FND_ENT | HASH_ADD_ENT))) == NULL) 307*57ef7aa9SRod Evans return (NULL); 3087c478bd9Sstevel@tonic-gate 3097c478bd9Sstevel@tonic-gate /* 3107c478bd9Sstevel@tonic-gate * If this is a new entry reassign the directory name and assign a 3117c478bd9Sstevel@tonic-gate * unique directory id. 3127c478bd9Sstevel@tonic-gate */ 3137c478bd9Sstevel@tonic-gate if (ent->e_id == 0) { 3147c478bd9Sstevel@tonic-gate if (_enterdir(crle, ndir, ent, obj) == 0) 315*57ef7aa9SRod Evans return (NULL); 3167c478bd9Sstevel@tonic-gate } 3177c478bd9Sstevel@tonic-gate 3187c478bd9Sstevel@tonic-gate /* 3197c478bd9Sstevel@tonic-gate * If the directory name supplied is different than the real name we've 3207c478bd9Sstevel@tonic-gate * just entered, continue to create an entry for it. 3217c478bd9Sstevel@tonic-gate */ 3227c478bd9Sstevel@tonic-gate if (ndir == odir) 3237c478bd9Sstevel@tonic-gate return (ent); 3247c478bd9Sstevel@tonic-gate 3257c478bd9Sstevel@tonic-gate /* 3267c478bd9Sstevel@tonic-gate * Create a string table entry for this real directory. 3277c478bd9Sstevel@tonic-gate */ 3287c478bd9Sstevel@tonic-gate if ((ent = get_hash(stbl, (Addr)odir, 0, 329*57ef7aa9SRod Evans (HASH_FND_ENT | HASH_ADD_ENT))) == NULL) 330*57ef7aa9SRod Evans return (NULL); 3317c478bd9Sstevel@tonic-gate 3327c478bd9Sstevel@tonic-gate /* 3337c478bd9Sstevel@tonic-gate * If this is a new entry reassign the directory name and assign a 3347c478bd9Sstevel@tonic-gate * unique directory id. 3357c478bd9Sstevel@tonic-gate */ 3367c478bd9Sstevel@tonic-gate if (ent->e_id == 0) { 3377c478bd9Sstevel@tonic-gate if (_enterdir(crle, odir, ent, obj) == 0) 338*57ef7aa9SRod Evans return (NULL); 3397c478bd9Sstevel@tonic-gate } 3407c478bd9Sstevel@tonic-gate 3417c478bd9Sstevel@tonic-gate return (ent); 3427c478bd9Sstevel@tonic-gate } 3437c478bd9Sstevel@tonic-gate 3447c478bd9Sstevel@tonic-gate /* 3457c478bd9Sstevel@tonic-gate * Establish a non-existent directory entry. There is no inode entry created 3467c478bd9Sstevel@tonic-gate * for this, just a directory and its associated object. 3477c478bd9Sstevel@tonic-gate */ 3487c478bd9Sstevel@tonic-gate static Hash_ent * 3497c478bd9Sstevel@tonic-gate enternoexistdir(Crle_desc *crle, const char *dir) 3507c478bd9Sstevel@tonic-gate { 3517c478bd9Sstevel@tonic-gate Hash_ent *ent; 3527c478bd9Sstevel@tonic-gate 3537c478bd9Sstevel@tonic-gate /* 3547c478bd9Sstevel@tonic-gate * Reuse or add this new non-existent directory to the string table. 3557c478bd9Sstevel@tonic-gate */ 3567c478bd9Sstevel@tonic-gate if ((ent = get_hash(crle->c_strtbl, (Addr)dir, 0, 357*57ef7aa9SRod Evans (HASH_FND_ENT | HASH_ADD_ENT))) == NULL) 358*57ef7aa9SRod Evans return (NULL); 3597c478bd9Sstevel@tonic-gate 3607c478bd9Sstevel@tonic-gate /* 3617c478bd9Sstevel@tonic-gate * If this is a new entry, assign both the object and the directory 3627c478bd9Sstevel@tonic-gate * entry information. 3637c478bd9Sstevel@tonic-gate */ 3647c478bd9Sstevel@tonic-gate if (ent->e_id == 0) { 3657c478bd9Sstevel@tonic-gate Hash_obj * obj; 3667c478bd9Sstevel@tonic-gate 367*57ef7aa9SRod Evans if ((obj = calloc(sizeof (Hash_obj), 1)) == NULL) 368*57ef7aa9SRod Evans return (NULL); 3697c478bd9Sstevel@tonic-gate obj->o_flags = (RTC_OBJ_NOEXIST | RTC_OBJ_DIRENT); 3707c478bd9Sstevel@tonic-gate 3717c478bd9Sstevel@tonic-gate if (_enterdir(crle, dir, ent, obj) == 0) 372*57ef7aa9SRod Evans return (NULL); 3737c478bd9Sstevel@tonic-gate } 3747c478bd9Sstevel@tonic-gate return (ent); 3757c478bd9Sstevel@tonic-gate } 3767c478bd9Sstevel@tonic-gate 3777c478bd9Sstevel@tonic-gate 3787c478bd9Sstevel@tonic-gate /* 3797c478bd9Sstevel@tonic-gate * Basic file entry, establishes entry information, updated global counts 3807c478bd9Sstevel@tonic-gate * and provides any diagnostics. 3817c478bd9Sstevel@tonic-gate */ 3827c478bd9Sstevel@tonic-gate static int 3837c478bd9Sstevel@tonic-gate _enterfile(Crle_desc *crle, const char *file, int off, Hash_ent *fent, 3847c478bd9Sstevel@tonic-gate Hash_ent *rent, Hash_ent *dent, Hash_obj *obj) 3857c478bd9Sstevel@tonic-gate { 3867c478bd9Sstevel@tonic-gate size_t size = strlen(file) + 1; 3877c478bd9Sstevel@tonic-gate char *nfile; 3887c478bd9Sstevel@tonic-gate 3897c478bd9Sstevel@tonic-gate /* 3907c478bd9Sstevel@tonic-gate * If this is a full file name reallocate it, as it might have been 3917c478bd9Sstevel@tonic-gate * composed and passed to us on the stack. Otherwise reuse the original 3927c478bd9Sstevel@tonic-gate * directory name to satisfy the filename, here we record the offset of 3937c478bd9Sstevel@tonic-gate * the file in the directory name so that we can reduce the string table 3947c478bd9Sstevel@tonic-gate * in the final configuration file. 3957c478bd9Sstevel@tonic-gate */ 3967c478bd9Sstevel@tonic-gate if (off == 0) { 397*57ef7aa9SRod Evans if ((nfile = malloc(size)) == NULL) 3987c478bd9Sstevel@tonic-gate return (0); 3997c478bd9Sstevel@tonic-gate (void) strcpy(nfile, file); 4007c478bd9Sstevel@tonic-gate } else 4017c478bd9Sstevel@tonic-gate nfile = (char *)file; 4027c478bd9Sstevel@tonic-gate 4037c478bd9Sstevel@tonic-gate fent->e_key = (Addr)nfile; 4047c478bd9Sstevel@tonic-gate fent->e_off = off; 4057c478bd9Sstevel@tonic-gate 4067c478bd9Sstevel@tonic-gate /* 4077c478bd9Sstevel@tonic-gate * Assign directory and directory id, and any real (full) path 4087c478bd9Sstevel@tonic-gate * association. 4097c478bd9Sstevel@tonic-gate */ 4107c478bd9Sstevel@tonic-gate fent->e_dir = dent; 4117c478bd9Sstevel@tonic-gate fent->e_id = dent->e_id; 4127c478bd9Sstevel@tonic-gate fent->e_path = rent; 4137c478bd9Sstevel@tonic-gate 4147c478bd9Sstevel@tonic-gate /* 4157c478bd9Sstevel@tonic-gate * Increment the file count for this directory. 4167c478bd9Sstevel@tonic-gate */ 4177c478bd9Sstevel@tonic-gate dent->e_cnt++; 4187c478bd9Sstevel@tonic-gate 4197c478bd9Sstevel@tonic-gate /* 4207c478bd9Sstevel@tonic-gate * Assign this object to the new string hash entry. 4217c478bd9Sstevel@tonic-gate */ 4227c478bd9Sstevel@tonic-gate fent->e_obj = obj; 4237c478bd9Sstevel@tonic-gate 4247c478bd9Sstevel@tonic-gate /* 4257c478bd9Sstevel@tonic-gate * Update string table information. 4267c478bd9Sstevel@tonic-gate */ 4277c478bd9Sstevel@tonic-gate crle->c_strsize += size; 4287c478bd9Sstevel@tonic-gate crle->c_hashstrnum++; 4297c478bd9Sstevel@tonic-gate crle->c_filenum++; 4307c478bd9Sstevel@tonic-gate 4317c478bd9Sstevel@tonic-gate /* 4327c478bd9Sstevel@tonic-gate * Provide any diagnostics. 4337c478bd9Sstevel@tonic-gate */ 4347c478bd9Sstevel@tonic-gate if (crle->c_flags & CRLE_VERBOSE) 4357c478bd9Sstevel@tonic-gate (void) printf(MSG_INTL(MSG_DIA_FILE), fent->e_id, nfile); 4367c478bd9Sstevel@tonic-gate 4377c478bd9Sstevel@tonic-gate return (1); 4387c478bd9Sstevel@tonic-gate } 4397c478bd9Sstevel@tonic-gate 4407c478bd9Sstevel@tonic-gate 4417c478bd9Sstevel@tonic-gate /* 4427c478bd9Sstevel@tonic-gate * Establish a non-existent file entry. There is no inode entry created for 4437c478bd9Sstevel@tonic-gate * this, just the files full and simple name, and its associated object. 4447c478bd9Sstevel@tonic-gate */ 4457c478bd9Sstevel@tonic-gate static Hash_ent * 4467c478bd9Sstevel@tonic-gate enternoexistfile(Crle_desc *crle, const char *path, const char *file, 4477c478bd9Sstevel@tonic-gate Hash_ent *dent) 4487c478bd9Sstevel@tonic-gate { 4497c478bd9Sstevel@tonic-gate Hash_ent *rent, *ent; 4507c478bd9Sstevel@tonic-gate Hash_obj *obj; 4517c478bd9Sstevel@tonic-gate int off; 4527c478bd9Sstevel@tonic-gate 4537c478bd9Sstevel@tonic-gate /* 4547c478bd9Sstevel@tonic-gate * Create a string table entry for the full filename. 4557c478bd9Sstevel@tonic-gate */ 4567c478bd9Sstevel@tonic-gate if ((rent = get_hash(crle->c_strtbl, (Addr)path, 0, 457*57ef7aa9SRod Evans (HASH_FND_ENT | HASH_ADD_ENT))) == NULL) 458*57ef7aa9SRod Evans return (NULL); 4597c478bd9Sstevel@tonic-gate 4607c478bd9Sstevel@tonic-gate /* 4617c478bd9Sstevel@tonic-gate * If this is a new entry, assign both the object and the full filename 4627c478bd9Sstevel@tonic-gate * entry information. 4637c478bd9Sstevel@tonic-gate */ 4647c478bd9Sstevel@tonic-gate if (rent->e_id == 0) { 465*57ef7aa9SRod Evans if ((obj = calloc(sizeof (Hash_obj), 1)) == NULL) 466*57ef7aa9SRod Evans return (NULL); 4677c478bd9Sstevel@tonic-gate obj->o_flags = RTC_OBJ_NOEXIST; 4687c478bd9Sstevel@tonic-gate 4697c478bd9Sstevel@tonic-gate if (_enterfile(crle, path, 0, rent, 0, dent, obj) == 0) 470*57ef7aa9SRod Evans return (NULL); 4717c478bd9Sstevel@tonic-gate } 4727c478bd9Sstevel@tonic-gate obj = rent->e_obj; 473*57ef7aa9SRod Evans if ((obj->o_path = strdup(path)) == NULL) 474*57ef7aa9SRod Evans return (NULL); 4757c478bd9Sstevel@tonic-gate 4767c478bd9Sstevel@tonic-gate /* 4777c478bd9Sstevel@tonic-gate * Express the filename in terms of the full pathname. By reusing the 4787c478bd9Sstevel@tonic-gate * name within the full filename we can reduce the overall string table 4797c478bd9Sstevel@tonic-gate * size in the output configuration file. 4807c478bd9Sstevel@tonic-gate */ 4817c478bd9Sstevel@tonic-gate off = file - path; 4827c478bd9Sstevel@tonic-gate file = (char *)rent->e_key + off; 4837c478bd9Sstevel@tonic-gate 4847c478bd9Sstevel@tonic-gate /* 4857c478bd9Sstevel@tonic-gate * Create a entry for the individual file within this directory. 4867c478bd9Sstevel@tonic-gate */ 4877c478bd9Sstevel@tonic-gate if ((ent = get_hash(crle->c_strtbl, (Addr)file, dent->e_id, 488*57ef7aa9SRod Evans (HASH_FND_ENT | HASH_ADD_ENT))) == NULL) 489*57ef7aa9SRod Evans return (NULL); 4907c478bd9Sstevel@tonic-gate 4917c478bd9Sstevel@tonic-gate if (ent->e_id == 0) { 4927c478bd9Sstevel@tonic-gate if (_enterfile(crle, file, off, ent, rent, dent, obj) == 0) 493*57ef7aa9SRod Evans return (NULL); 4947c478bd9Sstevel@tonic-gate } 4957c478bd9Sstevel@tonic-gate return (ent); 4967c478bd9Sstevel@tonic-gate } 4977c478bd9Sstevel@tonic-gate 4987c478bd9Sstevel@tonic-gate 4997c478bd9Sstevel@tonic-gate /* 5007c478bd9Sstevel@tonic-gate * Establish a string hash entry for a file. 5017c478bd9Sstevel@tonic-gate */ 5027c478bd9Sstevel@tonic-gate static Hash_ent * 5037c478bd9Sstevel@tonic-gate enterfile(Crle_desc *crle, const char *opath, const char *ofile, Half flags, 5047c478bd9Sstevel@tonic-gate Hash_ent *odent, struct stat *status) 5057c478bd9Sstevel@tonic-gate { 5067c478bd9Sstevel@tonic-gate Hash_tbl *stbl = crle->c_strtbl; 5077c478bd9Sstevel@tonic-gate Hash_ent *ent, *rent, *ndent = odent; 5087c478bd9Sstevel@tonic-gate Hash_obj *obj; 5097c478bd9Sstevel@tonic-gate size_t size; 5107c478bd9Sstevel@tonic-gate char rpath[PATH_MAX], *npath, *nfile; 5117c478bd9Sstevel@tonic-gate int off; 5127c478bd9Sstevel@tonic-gate 5137c478bd9Sstevel@tonic-gate /* 5147c478bd9Sstevel@tonic-gate * Establish the files real name, this is the name that will be 5157c478bd9Sstevel@tonic-gate * recorded in the object identifier. 5167c478bd9Sstevel@tonic-gate */ 517*57ef7aa9SRod Evans if (realpath(opath, rpath) == NULL) 518*57ef7aa9SRod Evans return (NULL); 5197c478bd9Sstevel@tonic-gate 5207c478bd9Sstevel@tonic-gate if (strcmp(opath, rpath)) { 5217c478bd9Sstevel@tonic-gate npath = rpath; 5227c478bd9Sstevel@tonic-gate if (nfile = strrchr(npath, '/')) 5237c478bd9Sstevel@tonic-gate nfile++; 5247c478bd9Sstevel@tonic-gate else 5257c478bd9Sstevel@tonic-gate nfile = npath; 5267c478bd9Sstevel@tonic-gate 5277c478bd9Sstevel@tonic-gate /* 5287c478bd9Sstevel@tonic-gate * Determine if the real pathname has a different directory to 5297c478bd9Sstevel@tonic-gate * the original passed to us. 5307c478bd9Sstevel@tonic-gate */ 5317c478bd9Sstevel@tonic-gate size = nfile - npath; 5327c478bd9Sstevel@tonic-gate if (strncmp(opath, npath, size)) { 5337c478bd9Sstevel@tonic-gate char _npath[PATH_MAX]; 5347c478bd9Sstevel@tonic-gate struct stat _status; 5357c478bd9Sstevel@tonic-gate 5367c478bd9Sstevel@tonic-gate (void) strncpy(_npath, npath, size); 5377c478bd9Sstevel@tonic-gate _npath[size - 1] = '\0'; 5387c478bd9Sstevel@tonic-gate 5397c478bd9Sstevel@tonic-gate (void) stat(_npath, &_status); 5407c478bd9Sstevel@tonic-gate if ((ndent = enterdir(crle, _npath, flags, 541*57ef7aa9SRod Evans &_status)) == NULL) 542*57ef7aa9SRod Evans return (NULL); 5437c478bd9Sstevel@tonic-gate } 5447c478bd9Sstevel@tonic-gate } else { 5457c478bd9Sstevel@tonic-gate npath = (char *)opath; 5467c478bd9Sstevel@tonic-gate nfile = (char *)ofile; 5477c478bd9Sstevel@tonic-gate } 5487c478bd9Sstevel@tonic-gate 5497c478bd9Sstevel@tonic-gate /* 5507c478bd9Sstevel@tonic-gate * Establish an inode table entry, and the objects unique descriptor. 5517c478bd9Sstevel@tonic-gate */ 552*57ef7aa9SRod Evans if ((ent = enterino(crle, npath, status, flags)) == NULL) 553*57ef7aa9SRod Evans return (NULL); 5547c478bd9Sstevel@tonic-gate obj = ent->e_obj; 5557c478bd9Sstevel@tonic-gate 5567c478bd9Sstevel@tonic-gate /* 5577c478bd9Sstevel@tonic-gate * Create a string table entry for the full filename. 5587c478bd9Sstevel@tonic-gate */ 5597c478bd9Sstevel@tonic-gate if ((rent = get_hash(stbl, (Addr)npath, 0, 560*57ef7aa9SRod Evans (HASH_FND_ENT | HASH_ADD_ENT))) == NULL) 561*57ef7aa9SRod Evans return (NULL); 5627c478bd9Sstevel@tonic-gate if (rent->e_id == 0) { 5637c478bd9Sstevel@tonic-gate if (_enterfile(crle, npath, 0, rent, 0, ndent, obj) == 0) 564*57ef7aa9SRod Evans return (NULL); 5657c478bd9Sstevel@tonic-gate } 5667c478bd9Sstevel@tonic-gate 5677c478bd9Sstevel@tonic-gate /* 5687c478bd9Sstevel@tonic-gate * Identify this entry and its directory as real paths. If dldump(3dl) 5697c478bd9Sstevel@tonic-gate * processing is required this flag is checked, as we only need to dump 5707c478bd9Sstevel@tonic-gate * the real pathname. Many other objects may point to the same 5717c478bd9Sstevel@tonic-gate * alternative, but only one needs to be dumped. In addition, during 5727c478bd9Sstevel@tonic-gate * ld.so.1 validation, only this directory and file need be checked. 5737c478bd9Sstevel@tonic-gate */ 5747c478bd9Sstevel@tonic-gate rent->e_flags |= RTC_OBJ_REALPTH; 5757c478bd9Sstevel@tonic-gate ndent->e_flags |= RTC_OBJ_REALPTH; 5767c478bd9Sstevel@tonic-gate 5777c478bd9Sstevel@tonic-gate /* 5787c478bd9Sstevel@tonic-gate * Express the filename in terms of the full pathname. By reusing the 5797c478bd9Sstevel@tonic-gate * name within the full filename we can reduce the overall string table 5807c478bd9Sstevel@tonic-gate * size in the output configuration file. 5817c478bd9Sstevel@tonic-gate */ 5827c478bd9Sstevel@tonic-gate off = nfile - npath; 5837c478bd9Sstevel@tonic-gate nfile = (char *)rent->e_key + off; 5847c478bd9Sstevel@tonic-gate 5857c478bd9Sstevel@tonic-gate /* 5867c478bd9Sstevel@tonic-gate * Create a entry for the individual file within this directory. 5877c478bd9Sstevel@tonic-gate */ 5887c478bd9Sstevel@tonic-gate if ((ent = get_hash(stbl, (Addr)nfile, ndent->e_id, 589*57ef7aa9SRod Evans (HASH_FND_ENT | HASH_ADD_ENT))) == NULL) 590*57ef7aa9SRod Evans return (NULL); 5917c478bd9Sstevel@tonic-gate if (ent->e_id == 0) { 5927c478bd9Sstevel@tonic-gate if (_enterfile(crle, nfile, off, ent, rent, ndent, obj) == 0) 593*57ef7aa9SRod Evans return (NULL); 5947c478bd9Sstevel@tonic-gate } 5957c478bd9Sstevel@tonic-gate 5967c478bd9Sstevel@tonic-gate /* 5977c478bd9Sstevel@tonic-gate * If the original path name is not equivalent to the real path name, 5987c478bd9Sstevel@tonic-gate * then we had an alias (typically it's a symlink). Add the path name 5997c478bd9Sstevel@tonic-gate * to the string hash table and reference the object data structure. 6007c478bd9Sstevel@tonic-gate */ 6017c478bd9Sstevel@tonic-gate if (nfile == ofile) 6027c478bd9Sstevel@tonic-gate return (ent); 6037c478bd9Sstevel@tonic-gate 6047c478bd9Sstevel@tonic-gate /* 6057c478bd9Sstevel@tonic-gate * Establish an inode table entry, and the objects unique descriptor. 6067c478bd9Sstevel@tonic-gate */ 607*57ef7aa9SRod Evans if ((ent = enterino(crle, opath, status, 0)) == NULL) 608*57ef7aa9SRod Evans return (NULL); 6097c478bd9Sstevel@tonic-gate obj = ent->e_obj; 6107c478bd9Sstevel@tonic-gate 6117c478bd9Sstevel@tonic-gate /* 6127c478bd9Sstevel@tonic-gate * Create a string table entry for the full filename. 6137c478bd9Sstevel@tonic-gate */ 6147c478bd9Sstevel@tonic-gate if ((rent = get_hash(stbl, (Addr)opath, 0, 615*57ef7aa9SRod Evans (HASH_FND_ENT | HASH_ADD_ENT))) == NULL) 616*57ef7aa9SRod Evans return (NULL); 6177c478bd9Sstevel@tonic-gate if (rent->e_id == 0) { 6187c478bd9Sstevel@tonic-gate if (_enterfile(crle, opath, 0, rent, 0, odent, obj) == 0) 619*57ef7aa9SRod Evans return (NULL); 6207c478bd9Sstevel@tonic-gate } 6217c478bd9Sstevel@tonic-gate 6227c478bd9Sstevel@tonic-gate /* 6237c478bd9Sstevel@tonic-gate * Express the filename in terms of the full pathname. By reusing the 6247c478bd9Sstevel@tonic-gate * name within the full filename we can reduce the overall string table 6257c478bd9Sstevel@tonic-gate * size in the output configuration file. 6267c478bd9Sstevel@tonic-gate */ 6277c478bd9Sstevel@tonic-gate off = ofile - opath; 6287c478bd9Sstevel@tonic-gate ofile = (char *)rent->e_key + off; 6297c478bd9Sstevel@tonic-gate 6307c478bd9Sstevel@tonic-gate /* 6317c478bd9Sstevel@tonic-gate * Create a entry for the individual file within this directory. 6327c478bd9Sstevel@tonic-gate */ 6337c478bd9Sstevel@tonic-gate if ((ent = get_hash(stbl, (Addr)ofile, odent->e_id, 634*57ef7aa9SRod Evans (HASH_FND_ENT | HASH_ADD_ENT))) == NULL) 635*57ef7aa9SRod Evans return (NULL); 6367c478bd9Sstevel@tonic-gate if (ent->e_id == 0) { 6377c478bd9Sstevel@tonic-gate if (_enterfile(crle, ofile, off, ent, rent, odent, obj) == 0) 638*57ef7aa9SRod Evans return (NULL); 6397c478bd9Sstevel@tonic-gate } 6407c478bd9Sstevel@tonic-gate 6417c478bd9Sstevel@tonic-gate return (ent); 6427c478bd9Sstevel@tonic-gate } 6437c478bd9Sstevel@tonic-gate 6447c478bd9Sstevel@tonic-gate /* 6457c478bd9Sstevel@tonic-gate * Add a file to configuration information. 6467c478bd9Sstevel@tonic-gate */ 6477c478bd9Sstevel@tonic-gate static int 6487c478bd9Sstevel@tonic-gate inspect_file(Crle_desc *crle, const char *path, const char *file, Half flags, 6497c478bd9Sstevel@tonic-gate Hash_ent *dent, struct stat *status, int error) 6507c478bd9Sstevel@tonic-gate { 6517c478bd9Sstevel@tonic-gate Hash_ent *ent; 6527c478bd9Sstevel@tonic-gate Hash_obj *obj; 6537c478bd9Sstevel@tonic-gate int fd; 6547c478bd9Sstevel@tonic-gate Elf *elf; 6557c478bd9Sstevel@tonic-gate GElf_Ehdr ehdr; 6564899432aSab196087 GElf_Xword dyflags = 0; 657*57ef7aa9SRod Evans Aliste idx; 6587c478bd9Sstevel@tonic-gate Hash_tbl *tbl; 6597c478bd9Sstevel@tonic-gate Addr ino = (Addr)status->st_ino; 6607c478bd9Sstevel@tonic-gate 6617c478bd9Sstevel@tonic-gate /* 6627c478bd9Sstevel@tonic-gate * Determine whether this file (inode) has already been processed. 6637c478bd9Sstevel@tonic-gate */ 664*57ef7aa9SRod Evans for (APLIST_TRAVERSE(crle->c_inotbls, idx, tbl)) { 6657c478bd9Sstevel@tonic-gate if (tbl->t_ident != status->st_dev) 6667c478bd9Sstevel@tonic-gate continue; 6677c478bd9Sstevel@tonic-gate 668*57ef7aa9SRod Evans if ((ent = get_hash(tbl, ino, 0, HASH_FND_ENT)) == NULL) 6697c478bd9Sstevel@tonic-gate break; 6707c478bd9Sstevel@tonic-gate 6717c478bd9Sstevel@tonic-gate /* 6727c478bd9Sstevel@tonic-gate * This files inode object does exist, make sure it has a file 6737c478bd9Sstevel@tonic-gate * entry for this directory. 6747c478bd9Sstevel@tonic-gate */ 6757c478bd9Sstevel@tonic-gate if ((ent = enterfile(crle, path, file, flags, dent, 676*57ef7aa9SRod Evans status)) == NULL) 6777c478bd9Sstevel@tonic-gate return (error); 6787c478bd9Sstevel@tonic-gate obj = ent->e_obj; 6797c478bd9Sstevel@tonic-gate 6807c478bd9Sstevel@tonic-gate /* 6817c478bd9Sstevel@tonic-gate * If an alternative has been asked for, and one has not yet 6827c478bd9Sstevel@tonic-gate * been established, create one. 6837c478bd9Sstevel@tonic-gate */ 6847c478bd9Sstevel@tonic-gate if ((flags & RTC_OBJ_ALTER) && 6857c478bd9Sstevel@tonic-gate ((obj->o_flags & RTC_OBJ_NOALTER) == 0)) { 6867c478bd9Sstevel@tonic-gate if (enteralt(crle, path, file, flags, obj) == 0) 6877c478bd9Sstevel@tonic-gate return (error); 6887c478bd9Sstevel@tonic-gate } 6897c478bd9Sstevel@tonic-gate return (0); 6907c478bd9Sstevel@tonic-gate } 6917c478bd9Sstevel@tonic-gate 6927c478bd9Sstevel@tonic-gate /* 6937c478bd9Sstevel@tonic-gate * This is a new file, determine if it's a valid ELF file. 6947c478bd9Sstevel@tonic-gate */ 6957c478bd9Sstevel@tonic-gate if ((fd = open(path, O_RDONLY, 0)) == -1) { 6967c478bd9Sstevel@tonic-gate if (error) { 6977c478bd9Sstevel@tonic-gate int err = errno; 6987c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN), 6997c478bd9Sstevel@tonic-gate crle->c_name, path, strerror(err)); 7007c478bd9Sstevel@tonic-gate } 7017c478bd9Sstevel@tonic-gate return (error); 7027c478bd9Sstevel@tonic-gate } 7037c478bd9Sstevel@tonic-gate 7047c478bd9Sstevel@tonic-gate /* 7057c478bd9Sstevel@tonic-gate * Obtain an ELF descriptor and determine if we have a shared object. 7067c478bd9Sstevel@tonic-gate */ 7077c478bd9Sstevel@tonic-gate if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) { 7087c478bd9Sstevel@tonic-gate if (error) 7097c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ELF_BEGIN), 7107c478bd9Sstevel@tonic-gate crle->c_name, path, elf_errmsg(-1)); 7117c478bd9Sstevel@tonic-gate (void) close(fd); 7127c478bd9Sstevel@tonic-gate return (error); 7137c478bd9Sstevel@tonic-gate } 7147c478bd9Sstevel@tonic-gate if ((elf_kind(elf) != ELF_K_ELF) || 7157c478bd9Sstevel@tonic-gate (gelf_getehdr(elf, &ehdr) == NULL) || 7167c478bd9Sstevel@tonic-gate (!((ehdr.e_type == ET_EXEC) || (ehdr.e_type == ET_DYN))) || 717c13de8f6Sab196087 (!((ehdr.e_ident[EI_CLASS] == M_CLASS) || 718c13de8f6Sab196087 (ehdr.e_machine == M_MACH)))) { 7197c478bd9Sstevel@tonic-gate if (error) 7207c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ELF_TYPE), 7217c478bd9Sstevel@tonic-gate crle->c_name, path); 7227c478bd9Sstevel@tonic-gate (void) close(fd); 7237c478bd9Sstevel@tonic-gate (void) elf_end(elf); 7247c478bd9Sstevel@tonic-gate return (error); 7257c478bd9Sstevel@tonic-gate } 7267c478bd9Sstevel@tonic-gate 7277c478bd9Sstevel@tonic-gate (void) close(fd); 7287c478bd9Sstevel@tonic-gate 7297c478bd9Sstevel@tonic-gate /* 7307c478bd9Sstevel@tonic-gate * If we're generating alternative objects find this objects DT_FLAGS 7317c478bd9Sstevel@tonic-gate * to insure it isn't marked as non-dumpable (libdl.so.1 falls into 7327c478bd9Sstevel@tonic-gate * this category). 7337c478bd9Sstevel@tonic-gate */ 7344899432aSab196087 if (flags & RTC_OBJ_DUMP) 7354899432aSab196087 dyflags = _gelf_getdyndtflags_1(elf); 7367c478bd9Sstevel@tonic-gate 7377c478bd9Sstevel@tonic-gate /* 7387c478bd9Sstevel@tonic-gate * Dynamic executables can be examined to determine their dependencies, 7397c478bd9Sstevel@tonic-gate * dldump(3dl) their dependencies, and may even be dldump(3dl)'ed 7407c478bd9Sstevel@tonic-gate * themselves. 7417c478bd9Sstevel@tonic-gate * 7427c478bd9Sstevel@tonic-gate * If we come across an executable while searching a directory 7437c478bd9Sstevel@tonic-gate * (error == 0) it is ignored. 7447c478bd9Sstevel@tonic-gate */ 7457c478bd9Sstevel@tonic-gate if (ehdr.e_type == ET_EXEC) { 7467c478bd9Sstevel@tonic-gate if (error == 0) { 7477c478bd9Sstevel@tonic-gate (void) elf_end(elf); 7487c478bd9Sstevel@tonic-gate return (0); 7497c478bd9Sstevel@tonic-gate } 7507c478bd9Sstevel@tonic-gate 7517c478bd9Sstevel@tonic-gate /* 7527c478bd9Sstevel@tonic-gate * If we're not dumping the application itself, or we've not 7537c478bd9Sstevel@tonic-gate * asked to gather its dependencies then its rather useless. 7547c478bd9Sstevel@tonic-gate */ 7557c478bd9Sstevel@tonic-gate if ((flags & (RTC_OBJ_GROUP | RTC_OBJ_DUMP)) == 0) { 7567c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_GEN_INVFILE), 7577c478bd9Sstevel@tonic-gate crle->c_name, path); 7587c478bd9Sstevel@tonic-gate (void) elf_end(elf); 7597c478bd9Sstevel@tonic-gate return (error); 7607c478bd9Sstevel@tonic-gate } 7617c478bd9Sstevel@tonic-gate 7627c478bd9Sstevel@tonic-gate /* 7637c478bd9Sstevel@tonic-gate * If we're dumping the application under RTLD_REL_EXEC then the 7647c478bd9Sstevel@tonic-gate * configuration file becomes specific to this application, so 7657c478bd9Sstevel@tonic-gate * make sure we haven't been here before. 7667c478bd9Sstevel@tonic-gate */ 7677c478bd9Sstevel@tonic-gate if (crle->c_app && (flags & RTC_OBJ_DUMP) && 7687c478bd9Sstevel@tonic-gate (crle->c_dlflags & RTLD_REL_EXEC)) { 7697c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ARG_MODE), 7707c478bd9Sstevel@tonic-gate crle->c_name, crle->c_app, path); 7717c478bd9Sstevel@tonic-gate (void) elf_end(elf); 7727c478bd9Sstevel@tonic-gate return (error); 7737c478bd9Sstevel@tonic-gate } 7747c478bd9Sstevel@tonic-gate } 7757c478bd9Sstevel@tonic-gate 7767c478bd9Sstevel@tonic-gate /* 7777c478bd9Sstevel@tonic-gate * Enter the file in the string hash table. 7787c478bd9Sstevel@tonic-gate */ 779*57ef7aa9SRod Evans if ((ent = enterfile(crle, path, file, flags, dent, status)) == NULL) { 7807c478bd9Sstevel@tonic-gate (void) elf_end(elf); 7817c478bd9Sstevel@tonic-gate return (error); 7827c478bd9Sstevel@tonic-gate } 7837c478bd9Sstevel@tonic-gate obj = ent->e_obj; 7847c478bd9Sstevel@tonic-gate 7857c478bd9Sstevel@tonic-gate if (flags & RTC_OBJ_ALTER) { 7867c478bd9Sstevel@tonic-gate /* 7877c478bd9Sstevel@tonic-gate * If this object is marked as non-dumpable make sure we don't 7887c478bd9Sstevel@tonic-gate * create a dldump(3dl) alternative. A user requested 7897c478bd9Sstevel@tonic-gate * alternative is acceptable. 7907c478bd9Sstevel@tonic-gate */ 7917c478bd9Sstevel@tonic-gate if ((flags & RTC_OBJ_DUMP) && (dyflags & DF_1_NODUMP)) { 7927c478bd9Sstevel@tonic-gate obj->o_flags |= RTC_OBJ_NOALTER; 7937c478bd9Sstevel@tonic-gate obj->o_flags &= ~(RTC_OBJ_ALTER | RTC_OBJ_DUMP); 7947c478bd9Sstevel@tonic-gate } else { 7957c478bd9Sstevel@tonic-gate if (enteralt(crle, path, file, flags, obj) == 0) { 7967c478bd9Sstevel@tonic-gate (void) elf_end(elf); 7977c478bd9Sstevel@tonic-gate return (error); 7987c478bd9Sstevel@tonic-gate } 7997c478bd9Sstevel@tonic-gate } 8007c478bd9Sstevel@tonic-gate } 8017c478bd9Sstevel@tonic-gate 8027c478bd9Sstevel@tonic-gate /* 8037c478bd9Sstevel@tonic-gate * Executables are recorded in the configuration file either to allow 8047c478bd9Sstevel@tonic-gate * for the configuration files update, or may indicate that the 8057c478bd9Sstevel@tonic-gate * configuration file is specific to their use. 8067c478bd9Sstevel@tonic-gate */ 8077c478bd9Sstevel@tonic-gate if (ehdr.e_type == ET_EXEC) { 8087c478bd9Sstevel@tonic-gate obj->o_flags |= RTC_OBJ_EXEC; 8097c478bd9Sstevel@tonic-gate 8107c478bd9Sstevel@tonic-gate if ((flags & RTC_OBJ_DUMP) && 8117c478bd9Sstevel@tonic-gate (crle->c_dlflags & RTLD_REL_EXEC)) { 8127c478bd9Sstevel@tonic-gate /* 8137c478bd9Sstevel@tonic-gate * Get the reallocated pathname rather than using the 8147c478bd9Sstevel@tonic-gate * original (the original might be from an existing 8157c478bd9Sstevel@tonic-gate * configuration file being updated, in which case the 8167c478bd9Sstevel@tonic-gate * pointer will be unmapped before we get to use it). 8177c478bd9Sstevel@tonic-gate */ 8187c478bd9Sstevel@tonic-gate ent = get_hash(crle->c_strtbl, (Addr)path, 0, 8197c478bd9Sstevel@tonic-gate HASH_FND_ENT); 8207c478bd9Sstevel@tonic-gate 8217c478bd9Sstevel@tonic-gate obj->o_flags |= RTC_OBJ_APP; 8227c478bd9Sstevel@tonic-gate crle->c_app = (char *)ent->e_key; 8237c478bd9Sstevel@tonic-gate } 8247c478bd9Sstevel@tonic-gate } 8257c478bd9Sstevel@tonic-gate 8267c478bd9Sstevel@tonic-gate /* 8277c478bd9Sstevel@tonic-gate * If we've been asked to process this object as a group determine its 8287c478bd9Sstevel@tonic-gate * dependencies. 8297c478bd9Sstevel@tonic-gate */ 8307c478bd9Sstevel@tonic-gate if (flags & RTC_OBJ_GROUP) { 8317c478bd9Sstevel@tonic-gate if (depend(crle, path, flags, &ehdr)) { 8327c478bd9Sstevel@tonic-gate (void) elf_end(elf); 8337c478bd9Sstevel@tonic-gate return (error); 8347c478bd9Sstevel@tonic-gate } 8357c478bd9Sstevel@tonic-gate } 8367c478bd9Sstevel@tonic-gate 8377c478bd9Sstevel@tonic-gate (void) elf_end(elf); 8387c478bd9Sstevel@tonic-gate return (0); 8397c478bd9Sstevel@tonic-gate } 8407c478bd9Sstevel@tonic-gate 8417c478bd9Sstevel@tonic-gate /* 8427c478bd9Sstevel@tonic-gate * Add a directory to configuration information. 8437c478bd9Sstevel@tonic-gate */ 8447c478bd9Sstevel@tonic-gate static int 8457c478bd9Sstevel@tonic-gate inspect_dir(Crle_desc *crle, const char *name, Half flags, struct stat *status) 8467c478bd9Sstevel@tonic-gate { 8477c478bd9Sstevel@tonic-gate Hash_tbl *stbl = crle->c_strtbl; 8487c478bd9Sstevel@tonic-gate DIR *dir; 8497c478bd9Sstevel@tonic-gate struct dirent *dirent; 8507c478bd9Sstevel@tonic-gate Hash_ent *ent; 8517c478bd9Sstevel@tonic-gate int error = 0; 8527c478bd9Sstevel@tonic-gate struct stat _status; 8537c478bd9Sstevel@tonic-gate char path[PATH_MAX], * dst; 8547c478bd9Sstevel@tonic-gate const char *src; 8557c478bd9Sstevel@tonic-gate 8567c478bd9Sstevel@tonic-gate /* 8577c478bd9Sstevel@tonic-gate * Determine whether we've already visited this directory to process 8587c478bd9Sstevel@tonic-gate * all its entries. 8597c478bd9Sstevel@tonic-gate */ 860*57ef7aa9SRod Evans if ((ent = get_hash(stbl, (Addr)name, 0, HASH_FND_ENT)) != NULL) { 8617c478bd9Sstevel@tonic-gate if (ent->e_obj->o_flags & RTC_OBJ_ALLENTS) 8627c478bd9Sstevel@tonic-gate return (0); 8637c478bd9Sstevel@tonic-gate } else { 8647c478bd9Sstevel@tonic-gate /* 8657c478bd9Sstevel@tonic-gate * Create a directory hash entry. 8667c478bd9Sstevel@tonic-gate */ 8677c478bd9Sstevel@tonic-gate if ((ent = enterdir(crle, name, (flags | RTC_OBJ_ALLENTS), 868*57ef7aa9SRod Evans status)) == NULL) 8697c478bd9Sstevel@tonic-gate return (1); 8707c478bd9Sstevel@tonic-gate } 8717c478bd9Sstevel@tonic-gate ent->e_obj->o_flags |= RTC_OBJ_ALLENTS; 8727c478bd9Sstevel@tonic-gate 8737c478bd9Sstevel@tonic-gate /* 8747c478bd9Sstevel@tonic-gate * Establish the pathname buffer. 8757c478bd9Sstevel@tonic-gate */ 8767c478bd9Sstevel@tonic-gate for (dst = path, dst--, src = name; *src; src++) 8777c478bd9Sstevel@tonic-gate *++dst = *src; 8787c478bd9Sstevel@tonic-gate if (*dst++ != '/') 8797c478bd9Sstevel@tonic-gate *dst++ = '/'; 8807c478bd9Sstevel@tonic-gate 8817c478bd9Sstevel@tonic-gate /* 8827c478bd9Sstevel@tonic-gate * Access the directory in preparation for reading its entries. 8837c478bd9Sstevel@tonic-gate */ 884*57ef7aa9SRod Evans if ((dir = opendir(name)) == NULL) 8857c478bd9Sstevel@tonic-gate return (1); 8867c478bd9Sstevel@tonic-gate 8877c478bd9Sstevel@tonic-gate /* 8887c478bd9Sstevel@tonic-gate * Read each entry from the directory looking for ELF files. 8897c478bd9Sstevel@tonic-gate */ 8907c478bd9Sstevel@tonic-gate while ((dirent = readdir(dir)) != NULL) { 8917c478bd9Sstevel@tonic-gate const char *file = dirent->d_name; 8927c478bd9Sstevel@tonic-gate char *_dst; 8937c478bd9Sstevel@tonic-gate 8947c478bd9Sstevel@tonic-gate /* 8957c478bd9Sstevel@tonic-gate * Ignore "." and ".." entries. 8967c478bd9Sstevel@tonic-gate */ 8977c478bd9Sstevel@tonic-gate if ((file[0] == '.') && ((file[1] == '\0') || 8987c478bd9Sstevel@tonic-gate ((file[1] == '.') && (file[2] == '\0')))) 8997c478bd9Sstevel@tonic-gate continue; 9007c478bd9Sstevel@tonic-gate 9017c478bd9Sstevel@tonic-gate /* 9027c478bd9Sstevel@tonic-gate * Complete full pathname, and reassign file to the new path. 9037c478bd9Sstevel@tonic-gate */ 9047c478bd9Sstevel@tonic-gate for (_dst = dst, src = file, file = dst; *src; _dst++, src++) 9057c478bd9Sstevel@tonic-gate *_dst = *src; 9067c478bd9Sstevel@tonic-gate *_dst = '\0'; 9077c478bd9Sstevel@tonic-gate 9087c478bd9Sstevel@tonic-gate if (stat(path, &_status) == -1) 9097c478bd9Sstevel@tonic-gate continue; 9107c478bd9Sstevel@tonic-gate 9117c478bd9Sstevel@tonic-gate if ((_status.st_mode & S_IFMT) != S_IFREG) 9127c478bd9Sstevel@tonic-gate continue; 9137c478bd9Sstevel@tonic-gate 9147c478bd9Sstevel@tonic-gate if (inspect_file(crle, path, file, flags, ent, &_status, 0)) { 9157c478bd9Sstevel@tonic-gate error = 1; 9167c478bd9Sstevel@tonic-gate break; 9177c478bd9Sstevel@tonic-gate } 9187c478bd9Sstevel@tonic-gate } 9197c478bd9Sstevel@tonic-gate return (error); 9207c478bd9Sstevel@tonic-gate } 9217c478bd9Sstevel@tonic-gate 9227c478bd9Sstevel@tonic-gate /* 9237c478bd9Sstevel@tonic-gate * Inspect a file/dir name. A stat(name) results in the following actions: 9247c478bd9Sstevel@tonic-gate * 9257c478bd9Sstevel@tonic-gate * The name doesn't exist: 9267c478bd9Sstevel@tonic-gate * The name is assummed to be a non-existent directory and a directory 9277c478bd9Sstevel@tonic-gate * cache entry is created to indicate this. 9287c478bd9Sstevel@tonic-gate * 9297c478bd9Sstevel@tonic-gate * The name is a directory: 9307c478bd9Sstevel@tonic-gate * The directory is searched for appropriate files. 9317c478bd9Sstevel@tonic-gate * 9327c478bd9Sstevel@tonic-gate * The name is a file: 9337c478bd9Sstevel@tonic-gate * The file is processed and added to the cache if appropriate. 9347c478bd9Sstevel@tonic-gate */ 9357c478bd9Sstevel@tonic-gate int 9367c478bd9Sstevel@tonic-gate inspect(Crle_desc *crle, const char *name, Half flags) 9377c478bd9Sstevel@tonic-gate { 9387c478bd9Sstevel@tonic-gate Hash_ent *ent; 9397c478bd9Sstevel@tonic-gate const char *file, *dir; 9407c478bd9Sstevel@tonic-gate struct stat status; 9417c478bd9Sstevel@tonic-gate char _name[PATH_MAX], _dir[PATH_MAX]; 9427c478bd9Sstevel@tonic-gate Half nflags = flags & ~RTC_OBJ_CMDLINE; 9437c478bd9Sstevel@tonic-gate int noexist; 9447c478bd9Sstevel@tonic-gate 9457c478bd9Sstevel@tonic-gate /* 9467c478bd9Sstevel@tonic-gate * If this is the first time through here establish a string table 9477c478bd9Sstevel@tonic-gate * cache. 9487c478bd9Sstevel@tonic-gate */ 9497c478bd9Sstevel@tonic-gate if (crle->c_dirnum == 0) { 9507c478bd9Sstevel@tonic-gate if ((crle->c_strtbl = make_hash(crle->c_strbkts, 951*57ef7aa9SRod Evans HASH_STR, 0)) == NULL) 9527c478bd9Sstevel@tonic-gate return (1); 9537c478bd9Sstevel@tonic-gate crle->c_dirnum = 1; 9547c478bd9Sstevel@tonic-gate } 9557c478bd9Sstevel@tonic-gate 9567c478bd9Sstevel@tonic-gate if (crle->c_flags & CRLE_VERBOSE) 9577c478bd9Sstevel@tonic-gate (void) printf(MSG_INTL(MSG_DIA_INSPECT), name); 9587c478bd9Sstevel@tonic-gate 9597c478bd9Sstevel@tonic-gate /* 9607c478bd9Sstevel@tonic-gate * Determine whether the name exists. 9617c478bd9Sstevel@tonic-gate */ 9627c478bd9Sstevel@tonic-gate if ((noexist = stat(name, &status)) != 0) { 9637c478bd9Sstevel@tonic-gate if (errno != ENOENT) { 9647c478bd9Sstevel@tonic-gate int err = errno; 9657c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_STAT), 9667c478bd9Sstevel@tonic-gate crle->c_name, name, strerror(err)); 9677c478bd9Sstevel@tonic-gate return (1); 9687c478bd9Sstevel@tonic-gate } else { 9697c478bd9Sstevel@tonic-gate /* 9707c478bd9Sstevel@tonic-gate * If we've been asked to create an alternative object 9717c478bd9Sstevel@tonic-gate * assume the object is a file and create a valid 9727c478bd9Sstevel@tonic-gate * alternative entry. This allows the creation of 9737c478bd9Sstevel@tonic-gate * alternatives for files that might not yet be 9747c478bd9Sstevel@tonic-gate * installed. 9757c478bd9Sstevel@tonic-gate * 9767c478bd9Sstevel@tonic-gate * Otherwise we have no idea whether the name specified 9777c478bd9Sstevel@tonic-gate * is a file or directory, so we assume a directory and 9787c478bd9Sstevel@tonic-gate * establish an object descriptor to mark this as 9797c478bd9Sstevel@tonic-gate * non-existent. This allows us to mark things like 9807c478bd9Sstevel@tonic-gate * platform specific directories as non-existent. 9817c478bd9Sstevel@tonic-gate */ 9827c478bd9Sstevel@tonic-gate if ((flags & (RTC_OBJ_DUMP | RTC_OBJ_ALTER)) != 9837c478bd9Sstevel@tonic-gate RTC_OBJ_ALTER) { 984*57ef7aa9SRod Evans if ((ent = enternoexistdir(crle, name)) == NULL) 9857c478bd9Sstevel@tonic-gate return (1); 9867c478bd9Sstevel@tonic-gate ent->e_flags |= flags; 9877c478bd9Sstevel@tonic-gate return (0); 9887c478bd9Sstevel@tonic-gate } 9897c478bd9Sstevel@tonic-gate } 9907c478bd9Sstevel@tonic-gate } 9917c478bd9Sstevel@tonic-gate 9927c478bd9Sstevel@tonic-gate /* 9937c478bd9Sstevel@tonic-gate * Determine whether we're dealing with a directory or a file. 9947c478bd9Sstevel@tonic-gate */ 9957c478bd9Sstevel@tonic-gate if ((noexist == 0) && ((status.st_mode & S_IFMT) == S_IFDIR)) { 9967c478bd9Sstevel@tonic-gate /* 9977c478bd9Sstevel@tonic-gate * Process the directory name to collect its shared objects into 9987c478bd9Sstevel@tonic-gate * the configuration file. 9997c478bd9Sstevel@tonic-gate */ 10007c478bd9Sstevel@tonic-gate if (inspect_dir(crle, name, nflags, &status)) 10017c478bd9Sstevel@tonic-gate return (1); 10027c478bd9Sstevel@tonic-gate 10037c478bd9Sstevel@tonic-gate ent = get_hash(crle->c_strtbl, (Addr)name, 0, HASH_FND_ENT); 10047c478bd9Sstevel@tonic-gate ent->e_flags |= flags; 10057c478bd9Sstevel@tonic-gate return (0); 10067c478bd9Sstevel@tonic-gate } 10077c478bd9Sstevel@tonic-gate 10087c478bd9Sstevel@tonic-gate /* 10097c478bd9Sstevel@tonic-gate * If this isn't a regular file we might as well bail now. Note that 10107c478bd9Sstevel@tonic-gate * even if it is, we might still reject the file if it's not ELF later 10117c478bd9Sstevel@tonic-gate * in inspect_file(). 10127c478bd9Sstevel@tonic-gate */ 10137c478bd9Sstevel@tonic-gate if ((noexist == 0) && ((status.st_mode & S_IFMT) != S_IFREG)) { 10147c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_GEN_INVFILE), crle->c_name, 10157c478bd9Sstevel@tonic-gate name); 10167c478bd9Sstevel@tonic-gate return (1); 10177c478bd9Sstevel@tonic-gate } 10187c478bd9Sstevel@tonic-gate 10197c478bd9Sstevel@tonic-gate /* 10207c478bd9Sstevel@tonic-gate * Break the pathname into directory and filename components. 10217c478bd9Sstevel@tonic-gate */ 1022*57ef7aa9SRod Evans if ((file = strrchr(name, '/')) == NULL) { 10237c478bd9Sstevel@tonic-gate dir = MSG_ORIG(MSG_DIR_DOT); 10247c478bd9Sstevel@tonic-gate (void) strcpy(_name, MSG_ORIG(MSG_PTH_DOT)); 10257c478bd9Sstevel@tonic-gate (void) strcpy(&_name[MSG_PTH_DOT_SIZE], name); 10267c478bd9Sstevel@tonic-gate name = (const char *)_name; 10277c478bd9Sstevel@tonic-gate file = (const char *)&_name[MSG_PTH_DOT_SIZE]; 10287c478bd9Sstevel@tonic-gate } else { 10297c478bd9Sstevel@tonic-gate size_t off = file - name; 10307c478bd9Sstevel@tonic-gate 10317c478bd9Sstevel@tonic-gate if (file == name) 10327c478bd9Sstevel@tonic-gate dir = MSG_ORIG(MSG_DIR_ROOT); 10337c478bd9Sstevel@tonic-gate else { 10347c478bd9Sstevel@tonic-gate (void) strncpy(_dir, name, off); 10357c478bd9Sstevel@tonic-gate _dir[off] = '\0'; 10367c478bd9Sstevel@tonic-gate dir = (const char *)_dir; 10377c478bd9Sstevel@tonic-gate } 10387c478bd9Sstevel@tonic-gate file++; 10397c478bd9Sstevel@tonic-gate } 10407c478bd9Sstevel@tonic-gate 10417c478bd9Sstevel@tonic-gate /* 10427c478bd9Sstevel@tonic-gate * Determine whether we've already visited this directory and if not 10437c478bd9Sstevel@tonic-gate * create it. 10447c478bd9Sstevel@tonic-gate */ 1045*57ef7aa9SRod Evans if ((ent = get_hash(crle->c_strtbl, 1046*57ef7aa9SRod Evans (Addr)dir, 0, HASH_FND_ENT)) == NULL) { 10477c478bd9Sstevel@tonic-gate struct stat _status; 10487c478bd9Sstevel@tonic-gate 10497c478bd9Sstevel@tonic-gate if (stat(dir, &_status) != 0) { 10507c478bd9Sstevel@tonic-gate if (errno != ENOENT) { 10517c478bd9Sstevel@tonic-gate int err = errno; 10527c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_STAT), 10537c478bd9Sstevel@tonic-gate crle->c_name, name, strerror(err)); 10547c478bd9Sstevel@tonic-gate return (1); 10557c478bd9Sstevel@tonic-gate } else { 10567c478bd9Sstevel@tonic-gate /* 10577c478bd9Sstevel@tonic-gate * Note that this directory will be tagged as 10587c478bd9Sstevel@tonic-gate * having an alternative - not that the 10597c478bd9Sstevel@tonic-gate * directory does, but supposedly it contains 10607c478bd9Sstevel@tonic-gate * a file that does. 10617c478bd9Sstevel@tonic-gate */ 1062*57ef7aa9SRod Evans if ((ent = enternoexistdir(crle, dir)) == NULL) 10637c478bd9Sstevel@tonic-gate return (1); 10647c478bd9Sstevel@tonic-gate ent->e_flags |= nflags; 10657c478bd9Sstevel@tonic-gate } 10667c478bd9Sstevel@tonic-gate } else { 1067*57ef7aa9SRod Evans if ((ent = enterdir(crle, dir, nflags, 1068*57ef7aa9SRod Evans &_status)) == NULL) 10697c478bd9Sstevel@tonic-gate return (1); 10707c478bd9Sstevel@tonic-gate } 10717c478bd9Sstevel@tonic-gate } 10727c478bd9Sstevel@tonic-gate 10737c478bd9Sstevel@tonic-gate /* 10747c478bd9Sstevel@tonic-gate * Regardless of whether we've already processed this file (say from 10757c478bd9Sstevel@tonic-gate * an RTC_OBJ_ALLENTS which we could determine from the above), continue 10767c478bd9Sstevel@tonic-gate * to inspect the file. It may require alternatives or something that 10777c478bd9Sstevel@tonic-gate * hadn't be specified from the directory entry. 10787c478bd9Sstevel@tonic-gate */ 10797c478bd9Sstevel@tonic-gate if (noexist) { 1080*57ef7aa9SRod Evans if ((ent = enternoexistfile(crle, name, file, ent)) == NULL) 10817c478bd9Sstevel@tonic-gate return (1); 10827c478bd9Sstevel@tonic-gate ent->e_flags |= nflags; 10837c478bd9Sstevel@tonic-gate if (enteralt(crle, name, file, flags, ent->e_obj) == 0) 10847c478bd9Sstevel@tonic-gate return (1); 10857c478bd9Sstevel@tonic-gate } else { 10867c478bd9Sstevel@tonic-gate if (inspect_file(crle, name, file, nflags, ent, &status, 1)) 10877c478bd9Sstevel@tonic-gate return (1); 10887c478bd9Sstevel@tonic-gate } 10897c478bd9Sstevel@tonic-gate 10907c478bd9Sstevel@tonic-gate /* 10917c478bd9Sstevel@tonic-gate * Make sure to propagate any RTC_OBJ_CMDLINE flag. 10927c478bd9Sstevel@tonic-gate */ 10937c478bd9Sstevel@tonic-gate if (ent = get_hash(crle->c_strtbl, (Addr)name, 0, HASH_FND_ENT)) 10947c478bd9Sstevel@tonic-gate ent->e_flags |= (flags & RTC_OBJ_CMDLINE); 10957c478bd9Sstevel@tonic-gate 10967c478bd9Sstevel@tonic-gate return (0); 10977c478bd9Sstevel@tonic-gate } 1098