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 5*4899432aSab196087 * Common Development and Distribution License (the "License"). 6*4899432aSab196087 * 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*4899432aSab196087 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate /* 287c478bd9Sstevel@tonic-gate * Routines to add file and directory entries into the internal configuration 297c478bd9Sstevel@tonic-gate * information. This information is maintained in a number of hash tables which 307c478bd9Sstevel@tonic-gate * after completion of input file processing will be processed and written to 317c478bd9Sstevel@tonic-gate * the output configuration file. 327c478bd9Sstevel@tonic-gate * 337c478bd9Sstevel@tonic-gate * Each hash table is defined via a Hash_tbl structure. These are organized: 347c478bd9Sstevel@tonic-gate * 357c478bd9Sstevel@tonic-gate * c_strtbl contains a hash entry for every file, directory, pathname and 367c478bd9Sstevel@tonic-gate * alternative path (dldump(3dl) image) processed. 377c478bd9Sstevel@tonic-gate * c_strsize and c_objnum maintain the size and count of the 387c478bd9Sstevel@tonic-gate * strings added to this table and are used to size the output 397c478bd9Sstevel@tonic-gate * configuration file. 407c478bd9Sstevel@tonic-gate * 417c478bd9Sstevel@tonic-gate * c_inotbls contains a list of inode hash tables. Each element of the list 427c478bd9Sstevel@tonic-gate * identifies a unique device. Thus, for each file processed its 437c478bd9Sstevel@tonic-gate * st_dev and st_ino are used to assign its entry to the correct 447c478bd9Sstevel@tonic-gate * hash table. 457c478bd9Sstevel@tonic-gate * 467c478bd9Sstevel@tonic-gate * Each directory processed is assigned a unique id (c_dirnum) 477c478bd9Sstevel@tonic-gate * which insures each file also becomes uniquely identified. 487c478bd9Sstevel@tonic-gate * 497c478bd9Sstevel@tonic-gate * All file and directory additions come through the inspect() entry point. 507c478bd9Sstevel@tonic-gate */ 517c478bd9Sstevel@tonic-gate 527c478bd9Sstevel@tonic-gate #include <sys/types.h> 537c478bd9Sstevel@tonic-gate #include <sys/stat.h> 547c478bd9Sstevel@tonic-gate #include <fcntl.h> 557c478bd9Sstevel@tonic-gate #include <dirent.h> 56*4899432aSab196087 #include <_libelf.h> 577c478bd9Sstevel@tonic-gate #include <errno.h> 587c478bd9Sstevel@tonic-gate #include <stdio.h> 597c478bd9Sstevel@tonic-gate #include <string.h> 607c478bd9Sstevel@tonic-gate #include <unistd.h> 617c478bd9Sstevel@tonic-gate #include <limits.h> 627c478bd9Sstevel@tonic-gate #include "machdep.h" 637c478bd9Sstevel@tonic-gate #include "sgs.h" 647c478bd9Sstevel@tonic-gate #include "rtc.h" 657c478bd9Sstevel@tonic-gate #include "_crle.h" 667c478bd9Sstevel@tonic-gate #include "msg.h" 677c478bd9Sstevel@tonic-gate 687c478bd9Sstevel@tonic-gate /* 697c478bd9Sstevel@tonic-gate * Add an alternative pathname for an object. Although a configuration file 707c478bd9Sstevel@tonic-gate * may contain several pathnames that resolve to the same real file, there can 717c478bd9Sstevel@tonic-gate * only be one real file. Consequently, there can only be one alternative. 727c478bd9Sstevel@tonic-gate * For multiple pathnames that resolve to the same real file, multiple alter- 737c478bd9Sstevel@tonic-gate * natives may be specified. Always take the alternative for the real file 747c478bd9Sstevel@tonic-gate * over any others. 757c478bd9Sstevel@tonic-gate */ 767c478bd9Sstevel@tonic-gate static int 777c478bd9Sstevel@tonic-gate enteralt(Crle_desc * crle, const char *path, const char *file, Half flags, 787c478bd9Sstevel@tonic-gate Hash_obj * obj) 797c478bd9Sstevel@tonic-gate { 807c478bd9Sstevel@tonic-gate const char *fmt; 817c478bd9Sstevel@tonic-gate char alter[PATH_MAX]; 827c478bd9Sstevel@tonic-gate size_t altsz; 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate if (obj->o_alter) { 857c478bd9Sstevel@tonic-gate /* 867c478bd9Sstevel@tonic-gate * If an alternative has already been captured, only override 877c478bd9Sstevel@tonic-gate * it if the specified file is the real file. 887c478bd9Sstevel@tonic-gate */ 897c478bd9Sstevel@tonic-gate if (strcmp(path, obj->o_path)) 907c478bd9Sstevel@tonic-gate return (1); 917c478bd9Sstevel@tonic-gate } 927c478bd9Sstevel@tonic-gate 937c478bd9Sstevel@tonic-gate /* 947c478bd9Sstevel@tonic-gate * Create an alternative pathname from the file and object destination 957c478bd9Sstevel@tonic-gate * directory. If we're dumping an alternative don't allow it to 967c478bd9Sstevel@tonic-gate * override the original. 977c478bd9Sstevel@tonic-gate */ 987c478bd9Sstevel@tonic-gate if (flags & RTC_OBJ_DUMP) { 997c478bd9Sstevel@tonic-gate char _alter[PATH_MAX]; 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate (void) strcpy(_alter, crle->c_objdir); 1027c478bd9Sstevel@tonic-gate (void) realpath(_alter, _alter); 1037c478bd9Sstevel@tonic-gate (void) snprintf(alter, PATH_MAX, MSG_ORIG(MSG_FMT_PATH), 1047c478bd9Sstevel@tonic-gate _alter, file); 1057c478bd9Sstevel@tonic-gate if (strcmp(alter, obj->o_path) == 0) { 1067c478bd9Sstevel@tonic-gate (void) printf(MSG_INTL(MSG_ARG_ALT), crle->c_name, 1077c478bd9Sstevel@tonic-gate obj->o_path); 1087c478bd9Sstevel@tonic-gate return (0); 1097c478bd9Sstevel@tonic-gate } 1107c478bd9Sstevel@tonic-gate obj->o_flags |= RTC_OBJ_DUMP; 1117c478bd9Sstevel@tonic-gate } else 1127c478bd9Sstevel@tonic-gate (void) snprintf(alter, PATH_MAX, MSG_ORIG(MSG_FMT_PATH), 1137c478bd9Sstevel@tonic-gate crle->c_objdir, file); 1147c478bd9Sstevel@tonic-gate obj->o_flags |= RTC_OBJ_ALTER; 1157c478bd9Sstevel@tonic-gate 1167c478bd9Sstevel@tonic-gate /* 1177c478bd9Sstevel@tonic-gate * If we're overriding an existing alternative with the real path, free 1187c478bd9Sstevel@tonic-gate * up any previous alternative. 1197c478bd9Sstevel@tonic-gate */ 1207c478bd9Sstevel@tonic-gate if (obj->o_alter) { 1217c478bd9Sstevel@tonic-gate crle->c_strsize -= strlen(alter) + 1; 1227c478bd9Sstevel@tonic-gate fmt = MSG_INTL(MSG_DIA_ALTUPDATE); 1237c478bd9Sstevel@tonic-gate } else 1247c478bd9Sstevel@tonic-gate fmt = MSG_INTL(MSG_DIA_ALTCREATE); 1257c478bd9Sstevel@tonic-gate 1267c478bd9Sstevel@tonic-gate /* 1277c478bd9Sstevel@tonic-gate * Allocate the new alternative and update the string table size. 1287c478bd9Sstevel@tonic-gate */ 1297c478bd9Sstevel@tonic-gate altsz = strlen(alter) + 1; 1307c478bd9Sstevel@tonic-gate if ((obj->o_alter = malloc(altsz)) == 0) 1317c478bd9Sstevel@tonic-gate return (0); 1327c478bd9Sstevel@tonic-gate (void) strcpy(obj->o_alter, alter); 1337c478bd9Sstevel@tonic-gate 1347c478bd9Sstevel@tonic-gate crle->c_strsize += altsz; 1357c478bd9Sstevel@tonic-gate 1367c478bd9Sstevel@tonic-gate if (crle->c_flags & CRLE_VERBOSE) 1377c478bd9Sstevel@tonic-gate (void) printf(fmt, alter, obj->o_path); 1387c478bd9Sstevel@tonic-gate 1397c478bd9Sstevel@tonic-gate return (1); 1407c478bd9Sstevel@tonic-gate } 1417c478bd9Sstevel@tonic-gate 1427c478bd9Sstevel@tonic-gate 1437c478bd9Sstevel@tonic-gate /* 1447c478bd9Sstevel@tonic-gate * Establish an inode hash entry, this is unique for each dev hash table, and 1457c478bd9Sstevel@tonic-gate * establishes the unique object descriptor. 1467c478bd9Sstevel@tonic-gate */ 1477c478bd9Sstevel@tonic-gate static Hash_ent * 1487c478bd9Sstevel@tonic-gate enterino(Crle_desc * crle, const char *name, struct stat *status, Half flags) 1497c478bd9Sstevel@tonic-gate { 1507c478bd9Sstevel@tonic-gate Hash_ent * ent; 1517c478bd9Sstevel@tonic-gate Hash_obj * obj; 1527c478bd9Sstevel@tonic-gate Hash_tbl * tbl; 1537c478bd9Sstevel@tonic-gate Listnode * lnp = 0; 1547c478bd9Sstevel@tonic-gate Addr ino = (Addr)status->st_ino; 1557c478bd9Sstevel@tonic-gate ulong_t dev = status->st_dev; 1567c478bd9Sstevel@tonic-gate Lword info; 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 */ 1717c478bd9Sstevel@tonic-gate for (LIST_TRAVERSE(&crle->c_inotbls, lnp, tbl)) { 1727c478bd9Sstevel@tonic-gate if (tbl->t_ident == dev) 1737c478bd9Sstevel@tonic-gate break; 1747c478bd9Sstevel@tonic-gate } 1757c478bd9Sstevel@tonic-gate if (lnp == 0) { 1767c478bd9Sstevel@tonic-gate if ((tbl = make_hash(crle->c_inobkts, HASH_INT, dev)) == 0) 1777c478bd9Sstevel@tonic-gate return (0); 1787c478bd9Sstevel@tonic-gate if (list_append(&crle->c_inotbls, tbl) == 0) 1797c478bd9Sstevel@tonic-gate return (0); 1807c478bd9Sstevel@tonic-gate } 1817c478bd9Sstevel@tonic-gate 1827c478bd9Sstevel@tonic-gate /* 1837c478bd9Sstevel@tonic-gate * Reuse or add this new object to the inode hash table. 1847c478bd9Sstevel@tonic-gate */ 1857c478bd9Sstevel@tonic-gate if ((ent = get_hash(tbl, ino, 0, (HASH_FND_ENT | HASH_ADD_ENT))) == 0) 1867c478bd9Sstevel@tonic-gate return (0); 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate /* 1897c478bd9Sstevel@tonic-gate * If an object descriptor doesn't yet exist create one. 1907c478bd9Sstevel@tonic-gate */ 1917c478bd9Sstevel@tonic-gate if ((obj = ent->e_obj) == 0) { 1927c478bd9Sstevel@tonic-gate if ((obj = calloc(sizeof (Hash_obj), 1)) == 0) 1937c478bd9Sstevel@tonic-gate return (0); 1947c478bd9Sstevel@tonic-gate obj->o_tbl = tbl; 1957c478bd9Sstevel@tonic-gate obj->o_flags = flags; 1967c478bd9Sstevel@tonic-gate obj->o_info = info; 1977c478bd9Sstevel@tonic-gate 1987c478bd9Sstevel@tonic-gate /* 1997c478bd9Sstevel@tonic-gate * Reallocate the objects name, as it might have been composed 2007c478bd9Sstevel@tonic-gate * and passed to us on the stack. 2017c478bd9Sstevel@tonic-gate */ 2027c478bd9Sstevel@tonic-gate if ((obj->o_path = strdup(name)) == 0) 2037c478bd9Sstevel@tonic-gate return (0); 2047c478bd9Sstevel@tonic-gate 2057c478bd9Sstevel@tonic-gate /* 2067c478bd9Sstevel@tonic-gate * Assign this object to the original ino hash entry. 2077c478bd9Sstevel@tonic-gate */ 2087c478bd9Sstevel@tonic-gate ent->e_obj = obj; 2097c478bd9Sstevel@tonic-gate } 2107c478bd9Sstevel@tonic-gate return (ent); 2117c478bd9Sstevel@tonic-gate } 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate 2147c478bd9Sstevel@tonic-gate /* 2157c478bd9Sstevel@tonic-gate * Basic directory entry, establishes entry information, updated global counts 2167c478bd9Sstevel@tonic-gate * and provides any diagnostics. 2177c478bd9Sstevel@tonic-gate */ 2187c478bd9Sstevel@tonic-gate static int 2197c478bd9Sstevel@tonic-gate _enterdir(Crle_desc * crle, const char *dir, Hash_ent * ent, Hash_obj * obj) 2207c478bd9Sstevel@tonic-gate { 2217c478bd9Sstevel@tonic-gate size_t size = strlen(dir) + 1; 2227c478bd9Sstevel@tonic-gate char *ndir; 2237c478bd9Sstevel@tonic-gate 2247c478bd9Sstevel@tonic-gate /* 2257c478bd9Sstevel@tonic-gate * Establish this hash entries key (which is the directory name itself), 2267c478bd9Sstevel@tonic-gate * assign the next available directory number, and its object. 2277c478bd9Sstevel@tonic-gate */ 2287c478bd9Sstevel@tonic-gate if ((ndir = malloc(size)) == 0) 2297c478bd9Sstevel@tonic-gate return (0); 2307c478bd9Sstevel@tonic-gate (void) strcpy(ndir, dir); 2317c478bd9Sstevel@tonic-gate 2327c478bd9Sstevel@tonic-gate ent->e_key = (Addr)ndir; 2337c478bd9Sstevel@tonic-gate ent->e_id = crle->c_dirnum++; 2347c478bd9Sstevel@tonic-gate ent->e_obj = obj; 2357c478bd9Sstevel@tonic-gate 2367c478bd9Sstevel@tonic-gate /* 2377c478bd9Sstevel@tonic-gate * Update string table information. We add a dummy filename for each 2387c478bd9Sstevel@tonic-gate * real directory so as to have a null terminated file table array for 2397c478bd9Sstevel@tonic-gate * this directory. 2407c478bd9Sstevel@tonic-gate */ 2417c478bd9Sstevel@tonic-gate crle->c_strsize += size; 2427c478bd9Sstevel@tonic-gate crle->c_hashstrnum++; 2437c478bd9Sstevel@tonic-gate crle->c_filenum++; 2447c478bd9Sstevel@tonic-gate 2457c478bd9Sstevel@tonic-gate /* 2467c478bd9Sstevel@tonic-gate * Provide any diagnostics. 2477c478bd9Sstevel@tonic-gate */ 2487c478bd9Sstevel@tonic-gate if (crle->c_flags & CRLE_VERBOSE) { 2497c478bd9Sstevel@tonic-gate const char *fmt; 2507c478bd9Sstevel@tonic-gate 2517c478bd9Sstevel@tonic-gate if (obj->o_flags & RTC_OBJ_NOEXIST) 2527c478bd9Sstevel@tonic-gate fmt = MSG_INTL(MSG_DIA_NOEXIST); 2537c478bd9Sstevel@tonic-gate else 2547c478bd9Sstevel@tonic-gate fmt = MSG_INTL(MSG_DIA_DIR); 2557c478bd9Sstevel@tonic-gate 2567c478bd9Sstevel@tonic-gate (void) printf(fmt, ent->e_id, dir); 2577c478bd9Sstevel@tonic-gate } 2587c478bd9Sstevel@tonic-gate return (1); 2597c478bd9Sstevel@tonic-gate } 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate 2627c478bd9Sstevel@tonic-gate /* 2637c478bd9Sstevel@tonic-gate * Establish a string hash entry for a directory. 2647c478bd9Sstevel@tonic-gate */ 2657c478bd9Sstevel@tonic-gate static Hash_ent * 2667c478bd9Sstevel@tonic-gate enterdir(Crle_desc * crle, const char *odir, Half flags, struct stat *status) 2677c478bd9Sstevel@tonic-gate { 2687c478bd9Sstevel@tonic-gate Hash_tbl * stbl = crle->c_strtbl; 2697c478bd9Sstevel@tonic-gate Hash_ent * ent; 2707c478bd9Sstevel@tonic-gate Hash_obj * obj; 2717c478bd9Sstevel@tonic-gate char rdir[PATH_MAX], * ndir; 2727c478bd9Sstevel@tonic-gate 2737c478bd9Sstevel@tonic-gate /* 2747c478bd9Sstevel@tonic-gate * Establish the directories real name, this is the name that will be 2757c478bd9Sstevel@tonic-gate * recorded in the object identifier. 2767c478bd9Sstevel@tonic-gate */ 2777c478bd9Sstevel@tonic-gate if (realpath(odir, rdir) == 0) 2787c478bd9Sstevel@tonic-gate return (0); 2797c478bd9Sstevel@tonic-gate 2807c478bd9Sstevel@tonic-gate if (strcmp(odir, rdir)) 2817c478bd9Sstevel@tonic-gate ndir = rdir; 2827c478bd9Sstevel@tonic-gate else 2837c478bd9Sstevel@tonic-gate ndir = (char *)odir; 2847c478bd9Sstevel@tonic-gate 2857c478bd9Sstevel@tonic-gate /* 2867c478bd9Sstevel@tonic-gate * If we're not dealing with an all-entries directory (i.e., we're 2877c478bd9Sstevel@tonic-gate * recording this directory because of its explicitly specified 2887c478bd9Sstevel@tonic-gate * filename) leave off any filename specific attributes. 2897c478bd9Sstevel@tonic-gate */ 2907c478bd9Sstevel@tonic-gate if ((flags & RTC_OBJ_ALLENTS) == 0) 2917c478bd9Sstevel@tonic-gate flags &= ~(RTC_OBJ_ALTER | RTC_OBJ_DUMP | RTC_OBJ_GROUP); 2927c478bd9Sstevel@tonic-gate flags |= RTC_OBJ_DIRENT; 2937c478bd9Sstevel@tonic-gate 2947c478bd9Sstevel@tonic-gate /* 2957c478bd9Sstevel@tonic-gate * Establish a inode table entry, and the objects unique descriptor. 2967c478bd9Sstevel@tonic-gate */ 2977c478bd9Sstevel@tonic-gate if ((ent = enterino(crle, ndir, status, flags)) == 0) 2987c478bd9Sstevel@tonic-gate return (0); 2997c478bd9Sstevel@tonic-gate obj = ent->e_obj; 3007c478bd9Sstevel@tonic-gate 3017c478bd9Sstevel@tonic-gate /* 3027c478bd9Sstevel@tonic-gate * Create a string table entry for the real directory. 3037c478bd9Sstevel@tonic-gate */ 3047c478bd9Sstevel@tonic-gate if ((ent = get_hash(stbl, (Addr)ndir, 0, 3057c478bd9Sstevel@tonic-gate (HASH_FND_ENT | HASH_ADD_ENT))) == 0) 3067c478bd9Sstevel@tonic-gate return (0); 3077c478bd9Sstevel@tonic-gate 3087c478bd9Sstevel@tonic-gate /* 3097c478bd9Sstevel@tonic-gate * If this is a new entry reassign the directory name and assign a 3107c478bd9Sstevel@tonic-gate * unique directory id. 3117c478bd9Sstevel@tonic-gate */ 3127c478bd9Sstevel@tonic-gate if (ent->e_id == 0) { 3137c478bd9Sstevel@tonic-gate if (_enterdir(crle, ndir, ent, obj) == 0) 3147c478bd9Sstevel@tonic-gate return (0); 3157c478bd9Sstevel@tonic-gate } 3167c478bd9Sstevel@tonic-gate 3177c478bd9Sstevel@tonic-gate /* 3187c478bd9Sstevel@tonic-gate * If the directory name supplied is different than the real name we've 3197c478bd9Sstevel@tonic-gate * just entered, continue to create an entry for it. 3207c478bd9Sstevel@tonic-gate */ 3217c478bd9Sstevel@tonic-gate if (ndir == odir) 3227c478bd9Sstevel@tonic-gate return (ent); 3237c478bd9Sstevel@tonic-gate 3247c478bd9Sstevel@tonic-gate /* 3257c478bd9Sstevel@tonic-gate * Create a string table entry for this real directory. 3267c478bd9Sstevel@tonic-gate */ 3277c478bd9Sstevel@tonic-gate if ((ent = get_hash(stbl, (Addr)odir, 0, 3287c478bd9Sstevel@tonic-gate (HASH_FND_ENT | HASH_ADD_ENT))) == 0) 3297c478bd9Sstevel@tonic-gate return (0); 3307c478bd9Sstevel@tonic-gate 3317c478bd9Sstevel@tonic-gate /* 3327c478bd9Sstevel@tonic-gate * If this is a new entry reassign the directory name and assign a 3337c478bd9Sstevel@tonic-gate * unique directory id. 3347c478bd9Sstevel@tonic-gate */ 3357c478bd9Sstevel@tonic-gate if (ent->e_id == 0) { 3367c478bd9Sstevel@tonic-gate if (_enterdir(crle, odir, ent, obj) == 0) 3377c478bd9Sstevel@tonic-gate return (0); 3387c478bd9Sstevel@tonic-gate } 3397c478bd9Sstevel@tonic-gate 3407c478bd9Sstevel@tonic-gate return (ent); 3417c478bd9Sstevel@tonic-gate } 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, 3577c478bd9Sstevel@tonic-gate (HASH_FND_ENT | HASH_ADD_ENT))) == 0) 3587c478bd9Sstevel@tonic-gate return (0); 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 3677c478bd9Sstevel@tonic-gate if ((obj = calloc(sizeof (Hash_obj), 1)) == 0) 3687c478bd9Sstevel@tonic-gate return (0); 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) 3727c478bd9Sstevel@tonic-gate return (0); 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) { 3977c478bd9Sstevel@tonic-gate if ((nfile = malloc(size)) == 0) 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, 4577c478bd9Sstevel@tonic-gate (HASH_FND_ENT | HASH_ADD_ENT))) == 0) 4587c478bd9Sstevel@tonic-gate return (0); 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) { 4657c478bd9Sstevel@tonic-gate if ((obj = calloc(sizeof (Hash_obj), 1)) == 0) 4667c478bd9Sstevel@tonic-gate return (0); 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) 4707c478bd9Sstevel@tonic-gate return (0); 4717c478bd9Sstevel@tonic-gate } 4727c478bd9Sstevel@tonic-gate obj = rent->e_obj; 4737c478bd9Sstevel@tonic-gate if ((obj->o_path = strdup(path)) == 0) 4747c478bd9Sstevel@tonic-gate return (0); 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, 4887c478bd9Sstevel@tonic-gate (HASH_FND_ENT | HASH_ADD_ENT))) == 0) 4897c478bd9Sstevel@tonic-gate return (0); 4907c478bd9Sstevel@tonic-gate 4917c478bd9Sstevel@tonic-gate if (ent->e_id == 0) { 4927c478bd9Sstevel@tonic-gate if (_enterfile(crle, file, off, ent, rent, dent, obj) == 0) 4937c478bd9Sstevel@tonic-gate return (0); 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 */ 5177c478bd9Sstevel@tonic-gate if (realpath(opath, rpath) == 0) 5187c478bd9Sstevel@tonic-gate return (0); 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, 5417c478bd9Sstevel@tonic-gate &_status)) == 0) 5427c478bd9Sstevel@tonic-gate return (0); 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 */ 5527c478bd9Sstevel@tonic-gate if ((ent = enterino(crle, npath, status, flags)) == 0) 5537c478bd9Sstevel@tonic-gate return (0); 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, 5607c478bd9Sstevel@tonic-gate (HASH_FND_ENT | HASH_ADD_ENT))) == 0) 5617c478bd9Sstevel@tonic-gate return (0); 5627c478bd9Sstevel@tonic-gate if (rent->e_id == 0) { 5637c478bd9Sstevel@tonic-gate if (_enterfile(crle, npath, 0, rent, 0, ndent, obj) == 0) 5647c478bd9Sstevel@tonic-gate return (0); 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, 5897c478bd9Sstevel@tonic-gate (HASH_FND_ENT | HASH_ADD_ENT))) == 0) 5907c478bd9Sstevel@tonic-gate return (0); 5917c478bd9Sstevel@tonic-gate if (ent->e_id == 0) { 5927c478bd9Sstevel@tonic-gate if (_enterfile(crle, nfile, off, ent, rent, ndent, obj) == 0) 5937c478bd9Sstevel@tonic-gate return (0); 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 */ 6077c478bd9Sstevel@tonic-gate if ((ent = enterino(crle, opath, status, 0)) == 0) 6087c478bd9Sstevel@tonic-gate return (0); 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, 6157c478bd9Sstevel@tonic-gate (HASH_FND_ENT | HASH_ADD_ENT))) == 0) 6167c478bd9Sstevel@tonic-gate return (0); 6177c478bd9Sstevel@tonic-gate if (rent->e_id == 0) { 6187c478bd9Sstevel@tonic-gate if (_enterfile(crle, opath, 0, rent, 0, odent, obj) == 0) 6197c478bd9Sstevel@tonic-gate return (0); 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, 6347c478bd9Sstevel@tonic-gate (HASH_FND_ENT | HASH_ADD_ENT))) == 0) 6357c478bd9Sstevel@tonic-gate return (0); 6367c478bd9Sstevel@tonic-gate if (ent->e_id == 0) { 6377c478bd9Sstevel@tonic-gate if (_enterfile(crle, ofile, off, ent, rent, odent, obj) == 0) 6387c478bd9Sstevel@tonic-gate return (0); 6397c478bd9Sstevel@tonic-gate } 6407c478bd9Sstevel@tonic-gate 6417c478bd9Sstevel@tonic-gate return (ent); 6427c478bd9Sstevel@tonic-gate } 6437c478bd9Sstevel@tonic-gate 6447c478bd9Sstevel@tonic-gate 6457c478bd9Sstevel@tonic-gate /* 6467c478bd9Sstevel@tonic-gate * Add a file to configuration information. 6477c478bd9Sstevel@tonic-gate */ 6487c478bd9Sstevel@tonic-gate static int 6497c478bd9Sstevel@tonic-gate inspect_file(Crle_desc * crle, const char *path, const char *file, Half flags, 6507c478bd9Sstevel@tonic-gate Hash_ent * dent, struct stat *status, int error) 6517c478bd9Sstevel@tonic-gate { 6527c478bd9Sstevel@tonic-gate Hash_ent * ent; 6537c478bd9Sstevel@tonic-gate Hash_obj * obj; 6547c478bd9Sstevel@tonic-gate int fd; 6557c478bd9Sstevel@tonic-gate Elf * elf; 6567c478bd9Sstevel@tonic-gate GElf_Ehdr ehdr; 657*4899432aSab196087 GElf_Xword dyflags = 0; 6587c478bd9Sstevel@tonic-gate Listnode * lnp; 6597c478bd9Sstevel@tonic-gate Hash_tbl * tbl; 6607c478bd9Sstevel@tonic-gate Addr ino = (Addr)status->st_ino; 6617c478bd9Sstevel@tonic-gate 6627c478bd9Sstevel@tonic-gate /* 6637c478bd9Sstevel@tonic-gate * Determine whether this file (inode) has already been processed. 6647c478bd9Sstevel@tonic-gate */ 6657c478bd9Sstevel@tonic-gate for (LIST_TRAVERSE(&crle->c_inotbls, lnp, tbl)) { 6667c478bd9Sstevel@tonic-gate if (tbl->t_ident != status->st_dev) 6677c478bd9Sstevel@tonic-gate continue; 6687c478bd9Sstevel@tonic-gate 6697c478bd9Sstevel@tonic-gate if ((ent = get_hash(tbl, ino, 0, HASH_FND_ENT)) == 0) 6707c478bd9Sstevel@tonic-gate break; 6717c478bd9Sstevel@tonic-gate 6727c478bd9Sstevel@tonic-gate /* 6737c478bd9Sstevel@tonic-gate * This files inode object does exist, make sure it has a file 6747c478bd9Sstevel@tonic-gate * entry for this directory. 6757c478bd9Sstevel@tonic-gate */ 6767c478bd9Sstevel@tonic-gate if ((ent = enterfile(crle, path, file, flags, dent, 6777c478bd9Sstevel@tonic-gate status)) == 0) 6787c478bd9Sstevel@tonic-gate return (error); 6797c478bd9Sstevel@tonic-gate obj = ent->e_obj; 6807c478bd9Sstevel@tonic-gate 6817c478bd9Sstevel@tonic-gate /* 6827c478bd9Sstevel@tonic-gate * If an alternative has been asked for, and one has not yet 6837c478bd9Sstevel@tonic-gate * been established, create one. 6847c478bd9Sstevel@tonic-gate */ 6857c478bd9Sstevel@tonic-gate if ((flags & RTC_OBJ_ALTER) && 6867c478bd9Sstevel@tonic-gate ((obj->o_flags & RTC_OBJ_NOALTER) == 0)) { 6877c478bd9Sstevel@tonic-gate if (enteralt(crle, path, file, flags, obj) == 0) 6887c478bd9Sstevel@tonic-gate return (error); 6897c478bd9Sstevel@tonic-gate } 6907c478bd9Sstevel@tonic-gate return (0); 6917c478bd9Sstevel@tonic-gate } 6927c478bd9Sstevel@tonic-gate 6937c478bd9Sstevel@tonic-gate /* 6947c478bd9Sstevel@tonic-gate * This is a new file, determine if it's a valid ELF file. 6957c478bd9Sstevel@tonic-gate */ 6967c478bd9Sstevel@tonic-gate if ((fd = open(path, O_RDONLY, 0)) == -1) { 6977c478bd9Sstevel@tonic-gate if (error) { 6987c478bd9Sstevel@tonic-gate int err = errno; 6997c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN), 7007c478bd9Sstevel@tonic-gate crle->c_name, path, strerror(err)); 7017c478bd9Sstevel@tonic-gate } 7027c478bd9Sstevel@tonic-gate return (error); 7037c478bd9Sstevel@tonic-gate } 7047c478bd9Sstevel@tonic-gate 7057c478bd9Sstevel@tonic-gate /* 7067c478bd9Sstevel@tonic-gate * Obtain an ELF descriptor and determine if we have a shared object. 7077c478bd9Sstevel@tonic-gate */ 7087c478bd9Sstevel@tonic-gate if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) { 7097c478bd9Sstevel@tonic-gate if (error) 7107c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ELF_BEGIN), 7117c478bd9Sstevel@tonic-gate crle->c_name, path, elf_errmsg(-1)); 7127c478bd9Sstevel@tonic-gate (void) close(fd); 7137c478bd9Sstevel@tonic-gate return (error); 7147c478bd9Sstevel@tonic-gate } 7157c478bd9Sstevel@tonic-gate if ((elf_kind(elf) != ELF_K_ELF) || 7167c478bd9Sstevel@tonic-gate (gelf_getehdr(elf, &ehdr) == NULL) || 7177c478bd9Sstevel@tonic-gate (!((ehdr.e_type == ET_EXEC) || (ehdr.e_type == ET_DYN))) || 7187c478bd9Sstevel@tonic-gate (!((ehdr.e_ident[EI_CLASS] == crle->c_class) || 7197c478bd9Sstevel@tonic-gate (ehdr.e_machine == crle->c_machine)))) { 7207c478bd9Sstevel@tonic-gate if (error) 7217c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ELF_TYPE), 7227c478bd9Sstevel@tonic-gate crle->c_name, path); 7237c478bd9Sstevel@tonic-gate (void) close(fd); 7247c478bd9Sstevel@tonic-gate (void) elf_end(elf); 7257c478bd9Sstevel@tonic-gate return (error); 7267c478bd9Sstevel@tonic-gate } 7277c478bd9Sstevel@tonic-gate 7287c478bd9Sstevel@tonic-gate (void) close(fd); 7297c478bd9Sstevel@tonic-gate 7307c478bd9Sstevel@tonic-gate /* 7317c478bd9Sstevel@tonic-gate * If we're generating alternative objects find this objects DT_FLAGS 7327c478bd9Sstevel@tonic-gate * to insure it isn't marked as non-dumpable (libdl.so.1 falls into 7337c478bd9Sstevel@tonic-gate * this category). 7347c478bd9Sstevel@tonic-gate */ 735*4899432aSab196087 if (flags & RTC_OBJ_DUMP) 736*4899432aSab196087 dyflags = _gelf_getdyndtflags_1(elf); 7377c478bd9Sstevel@tonic-gate 7387c478bd9Sstevel@tonic-gate /* 7397c478bd9Sstevel@tonic-gate * Dynamic executables can be examined to determine their dependencies, 7407c478bd9Sstevel@tonic-gate * dldump(3dl) their dependencies, and may even be dldump(3dl)'ed 7417c478bd9Sstevel@tonic-gate * themselves. 7427c478bd9Sstevel@tonic-gate * 7437c478bd9Sstevel@tonic-gate * If we come across an executable while searching a directory 7447c478bd9Sstevel@tonic-gate * (error == 0) it is ignored. 7457c478bd9Sstevel@tonic-gate */ 7467c478bd9Sstevel@tonic-gate if (ehdr.e_type == ET_EXEC) { 7477c478bd9Sstevel@tonic-gate if (error == 0) { 7487c478bd9Sstevel@tonic-gate (void) elf_end(elf); 7497c478bd9Sstevel@tonic-gate return (0); 7507c478bd9Sstevel@tonic-gate } 7517c478bd9Sstevel@tonic-gate 7527c478bd9Sstevel@tonic-gate /* 7537c478bd9Sstevel@tonic-gate * If we're not dumping the application itself, or we've not 7547c478bd9Sstevel@tonic-gate * asked to gather its dependencies then its rather useless. 7557c478bd9Sstevel@tonic-gate */ 7567c478bd9Sstevel@tonic-gate if ((flags & (RTC_OBJ_GROUP | RTC_OBJ_DUMP)) == 0) { 7577c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_GEN_INVFILE), 7587c478bd9Sstevel@tonic-gate crle->c_name, path); 7597c478bd9Sstevel@tonic-gate (void) elf_end(elf); 7607c478bd9Sstevel@tonic-gate return (error); 7617c478bd9Sstevel@tonic-gate } 7627c478bd9Sstevel@tonic-gate 7637c478bd9Sstevel@tonic-gate /* 7647c478bd9Sstevel@tonic-gate * If we're dumping the application under RTLD_REL_EXEC then the 7657c478bd9Sstevel@tonic-gate * configuration file becomes specific to this application, so 7667c478bd9Sstevel@tonic-gate * make sure we haven't been here before. 7677c478bd9Sstevel@tonic-gate */ 7687c478bd9Sstevel@tonic-gate if (crle->c_app && (flags & RTC_OBJ_DUMP) && 7697c478bd9Sstevel@tonic-gate (crle->c_dlflags & RTLD_REL_EXEC)) { 7707c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ARG_MODE), 7717c478bd9Sstevel@tonic-gate crle->c_name, crle->c_app, path); 7727c478bd9Sstevel@tonic-gate (void) elf_end(elf); 7737c478bd9Sstevel@tonic-gate return (error); 7747c478bd9Sstevel@tonic-gate } 7757c478bd9Sstevel@tonic-gate } 7767c478bd9Sstevel@tonic-gate 7777c478bd9Sstevel@tonic-gate /* 7787c478bd9Sstevel@tonic-gate * Enter the file in the string hash table. 7797c478bd9Sstevel@tonic-gate */ 7807c478bd9Sstevel@tonic-gate if ((ent = enterfile(crle, path, file, flags, dent, status)) == 0) { 7817c478bd9Sstevel@tonic-gate (void) elf_end(elf); 7827c478bd9Sstevel@tonic-gate return (error); 7837c478bd9Sstevel@tonic-gate } 7847c478bd9Sstevel@tonic-gate obj = ent->e_obj; 7857c478bd9Sstevel@tonic-gate 7867c478bd9Sstevel@tonic-gate if (flags & RTC_OBJ_ALTER) { 7877c478bd9Sstevel@tonic-gate /* 7887c478bd9Sstevel@tonic-gate * If this object is marked as non-dumpable make sure we don't 7897c478bd9Sstevel@tonic-gate * create a dldump(3dl) alternative. A user requested 7907c478bd9Sstevel@tonic-gate * alternative is acceptable. 7917c478bd9Sstevel@tonic-gate */ 7927c478bd9Sstevel@tonic-gate if ((flags & RTC_OBJ_DUMP) && (dyflags & DF_1_NODUMP)) { 7937c478bd9Sstevel@tonic-gate obj->o_flags |= RTC_OBJ_NOALTER; 7947c478bd9Sstevel@tonic-gate obj->o_flags &= ~(RTC_OBJ_ALTER | RTC_OBJ_DUMP); 7957c478bd9Sstevel@tonic-gate } else { 7967c478bd9Sstevel@tonic-gate if (enteralt(crle, path, file, flags, obj) == 0) { 7977c478bd9Sstevel@tonic-gate (void) elf_end(elf); 7987c478bd9Sstevel@tonic-gate return (error); 7997c478bd9Sstevel@tonic-gate } 8007c478bd9Sstevel@tonic-gate } 8017c478bd9Sstevel@tonic-gate } 8027c478bd9Sstevel@tonic-gate 8037c478bd9Sstevel@tonic-gate /* 8047c478bd9Sstevel@tonic-gate * Executables are recorded in the configuration file either to allow 8057c478bd9Sstevel@tonic-gate * for the configuration files update, or may indicate that the 8067c478bd9Sstevel@tonic-gate * configuration file is specific to their use. 8077c478bd9Sstevel@tonic-gate */ 8087c478bd9Sstevel@tonic-gate if (ehdr.e_type == ET_EXEC) { 8097c478bd9Sstevel@tonic-gate obj->o_flags |= RTC_OBJ_EXEC; 8107c478bd9Sstevel@tonic-gate 8117c478bd9Sstevel@tonic-gate if ((flags & RTC_OBJ_DUMP) && 8127c478bd9Sstevel@tonic-gate (crle->c_dlflags & RTLD_REL_EXEC)) { 8137c478bd9Sstevel@tonic-gate /* 8147c478bd9Sstevel@tonic-gate * Get the reallocated pathname rather than using the 8157c478bd9Sstevel@tonic-gate * original (the original might be from an existing 8167c478bd9Sstevel@tonic-gate * configuration file being updated, in which case the 8177c478bd9Sstevel@tonic-gate * pointer will be unmapped before we get to use it). 8187c478bd9Sstevel@tonic-gate */ 8197c478bd9Sstevel@tonic-gate ent = get_hash(crle->c_strtbl, (Addr)path, 0, 8207c478bd9Sstevel@tonic-gate HASH_FND_ENT); 8217c478bd9Sstevel@tonic-gate 8227c478bd9Sstevel@tonic-gate obj->o_flags |= RTC_OBJ_APP; 8237c478bd9Sstevel@tonic-gate crle->c_app = (char *)ent->e_key; 8247c478bd9Sstevel@tonic-gate } 8257c478bd9Sstevel@tonic-gate } 8267c478bd9Sstevel@tonic-gate 8277c478bd9Sstevel@tonic-gate /* 8287c478bd9Sstevel@tonic-gate * If we've been asked to process this object as a group determine its 8297c478bd9Sstevel@tonic-gate * dependencies. 8307c478bd9Sstevel@tonic-gate */ 8317c478bd9Sstevel@tonic-gate if (flags & RTC_OBJ_GROUP) { 8327c478bd9Sstevel@tonic-gate if (depend(crle, path, flags, &ehdr)) { 8337c478bd9Sstevel@tonic-gate (void) elf_end(elf); 8347c478bd9Sstevel@tonic-gate return (error); 8357c478bd9Sstevel@tonic-gate } 8367c478bd9Sstevel@tonic-gate } 8377c478bd9Sstevel@tonic-gate 8387c478bd9Sstevel@tonic-gate (void) elf_end(elf); 8397c478bd9Sstevel@tonic-gate return (0); 8407c478bd9Sstevel@tonic-gate } 8417c478bd9Sstevel@tonic-gate 8427c478bd9Sstevel@tonic-gate 8437c478bd9Sstevel@tonic-gate /* 8447c478bd9Sstevel@tonic-gate * Add a directory to configuration information. 8457c478bd9Sstevel@tonic-gate */ 8467c478bd9Sstevel@tonic-gate static int 8477c478bd9Sstevel@tonic-gate inspect_dir(Crle_desc * crle, const char *name, Half flags, struct stat *status) 8487c478bd9Sstevel@tonic-gate { 8497c478bd9Sstevel@tonic-gate Hash_tbl * stbl = crle->c_strtbl; 8507c478bd9Sstevel@tonic-gate DIR * dir; 8517c478bd9Sstevel@tonic-gate struct dirent *dirent; 8527c478bd9Sstevel@tonic-gate Hash_ent * ent; 8537c478bd9Sstevel@tonic-gate int error = 0; 8547c478bd9Sstevel@tonic-gate struct stat _status; 8557c478bd9Sstevel@tonic-gate char path[PATH_MAX], * dst; 8567c478bd9Sstevel@tonic-gate const char *src; 8577c478bd9Sstevel@tonic-gate 8587c478bd9Sstevel@tonic-gate /* 8597c478bd9Sstevel@tonic-gate * Determine whether we've already visited this directory to process 8607c478bd9Sstevel@tonic-gate * all its entries. 8617c478bd9Sstevel@tonic-gate */ 8627c478bd9Sstevel@tonic-gate if ((ent = get_hash(stbl, (Addr)name, 0, HASH_FND_ENT)) != 0) { 8637c478bd9Sstevel@tonic-gate if (ent->e_obj->o_flags & RTC_OBJ_ALLENTS) 8647c478bd9Sstevel@tonic-gate return (0); 8657c478bd9Sstevel@tonic-gate } else { 8667c478bd9Sstevel@tonic-gate /* 8677c478bd9Sstevel@tonic-gate * Create a directory hash entry. 8687c478bd9Sstevel@tonic-gate */ 8697c478bd9Sstevel@tonic-gate if ((ent = enterdir(crle, name, (flags | RTC_OBJ_ALLENTS), 8707c478bd9Sstevel@tonic-gate status)) == 0) 8717c478bd9Sstevel@tonic-gate return (1); 8727c478bd9Sstevel@tonic-gate } 8737c478bd9Sstevel@tonic-gate ent->e_obj->o_flags |= RTC_OBJ_ALLENTS; 8747c478bd9Sstevel@tonic-gate 8757c478bd9Sstevel@tonic-gate /* 8767c478bd9Sstevel@tonic-gate * Establish the pathname buffer. 8777c478bd9Sstevel@tonic-gate */ 8787c478bd9Sstevel@tonic-gate for (dst = path, dst--, src = name; *src; src++) 8797c478bd9Sstevel@tonic-gate *++dst = *src; 8807c478bd9Sstevel@tonic-gate if (*dst++ != '/') 8817c478bd9Sstevel@tonic-gate *dst++ = '/'; 8827c478bd9Sstevel@tonic-gate 8837c478bd9Sstevel@tonic-gate /* 8847c478bd9Sstevel@tonic-gate * Access the directory in preparation for reading its entries. 8857c478bd9Sstevel@tonic-gate */ 8867c478bd9Sstevel@tonic-gate if ((dir = opendir(name)) == 0) 8877c478bd9Sstevel@tonic-gate return (1); 8887c478bd9Sstevel@tonic-gate 8897c478bd9Sstevel@tonic-gate /* 8907c478bd9Sstevel@tonic-gate * Read each entry from the directory looking for ELF files. 8917c478bd9Sstevel@tonic-gate */ 8927c478bd9Sstevel@tonic-gate while ((dirent = readdir(dir)) != NULL) { 8937c478bd9Sstevel@tonic-gate const char *file = dirent->d_name; 8947c478bd9Sstevel@tonic-gate char *_dst; 8957c478bd9Sstevel@tonic-gate 8967c478bd9Sstevel@tonic-gate /* 8977c478bd9Sstevel@tonic-gate * Ignore "." and ".." entries. 8987c478bd9Sstevel@tonic-gate */ 8997c478bd9Sstevel@tonic-gate if ((file[0] == '.') && ((file[1] == '\0') || 9007c478bd9Sstevel@tonic-gate ((file[1] == '.') && (file[2] == '\0')))) 9017c478bd9Sstevel@tonic-gate continue; 9027c478bd9Sstevel@tonic-gate 9037c478bd9Sstevel@tonic-gate /* 9047c478bd9Sstevel@tonic-gate * Complete full pathname, and reassign file to the new path. 9057c478bd9Sstevel@tonic-gate */ 9067c478bd9Sstevel@tonic-gate for (_dst = dst, src = file, file = dst; *src; _dst++, src++) 9077c478bd9Sstevel@tonic-gate *_dst = *src; 9087c478bd9Sstevel@tonic-gate *_dst = '\0'; 9097c478bd9Sstevel@tonic-gate 9107c478bd9Sstevel@tonic-gate if (stat(path, &_status) == -1) 9117c478bd9Sstevel@tonic-gate continue; 9127c478bd9Sstevel@tonic-gate 9137c478bd9Sstevel@tonic-gate if ((_status.st_mode & S_IFMT) != S_IFREG) 9147c478bd9Sstevel@tonic-gate continue; 9157c478bd9Sstevel@tonic-gate 9167c478bd9Sstevel@tonic-gate if (inspect_file(crle, path, file, flags, ent, &_status, 0)) { 9177c478bd9Sstevel@tonic-gate error = 1; 9187c478bd9Sstevel@tonic-gate break; 9197c478bd9Sstevel@tonic-gate } 9207c478bd9Sstevel@tonic-gate } 9217c478bd9Sstevel@tonic-gate return (error); 9227c478bd9Sstevel@tonic-gate } 9237c478bd9Sstevel@tonic-gate 9247c478bd9Sstevel@tonic-gate 9257c478bd9Sstevel@tonic-gate /* 9267c478bd9Sstevel@tonic-gate * Inspect a file/dir name. A stat(name) results in the following actions: 9277c478bd9Sstevel@tonic-gate * 9287c478bd9Sstevel@tonic-gate * The name doesn't exist: 9297c478bd9Sstevel@tonic-gate * The name is assummed to be a non-existent directory and a directory 9307c478bd9Sstevel@tonic-gate * cache entry is created to indicate this. 9317c478bd9Sstevel@tonic-gate * 9327c478bd9Sstevel@tonic-gate * The name is a directory: 9337c478bd9Sstevel@tonic-gate * The directory is searched for appropriate files. 9347c478bd9Sstevel@tonic-gate * 9357c478bd9Sstevel@tonic-gate * The name is a file: 9367c478bd9Sstevel@tonic-gate * The file is processed and added to the cache if appropriate. 9377c478bd9Sstevel@tonic-gate */ 9387c478bd9Sstevel@tonic-gate int 9397c478bd9Sstevel@tonic-gate inspect(Crle_desc * crle, const char *name, Half flags) 9407c478bd9Sstevel@tonic-gate { 9417c478bd9Sstevel@tonic-gate Hash_ent * ent; 9427c478bd9Sstevel@tonic-gate const char *file, * dir; 9437c478bd9Sstevel@tonic-gate struct stat status; 9447c478bd9Sstevel@tonic-gate char _name[PATH_MAX], _dir[PATH_MAX]; 9457c478bd9Sstevel@tonic-gate Half nflags = flags & ~RTC_OBJ_CMDLINE; 9467c478bd9Sstevel@tonic-gate int noexist; 9477c478bd9Sstevel@tonic-gate 9487c478bd9Sstevel@tonic-gate /* 9497c478bd9Sstevel@tonic-gate * If this is the first time through here establish a string table 9507c478bd9Sstevel@tonic-gate * cache. 9517c478bd9Sstevel@tonic-gate */ 9527c478bd9Sstevel@tonic-gate if (crle->c_dirnum == 0) { 9537c478bd9Sstevel@tonic-gate if ((crle->c_strtbl = make_hash(crle->c_strbkts, 9547c478bd9Sstevel@tonic-gate HASH_STR, 0)) == 0) 9557c478bd9Sstevel@tonic-gate return (1); 9567c478bd9Sstevel@tonic-gate crle->c_dirnum = 1; 9577c478bd9Sstevel@tonic-gate } 9587c478bd9Sstevel@tonic-gate 9597c478bd9Sstevel@tonic-gate if (crle->c_flags & CRLE_VERBOSE) 9607c478bd9Sstevel@tonic-gate (void) printf(MSG_INTL(MSG_DIA_INSPECT), name); 9617c478bd9Sstevel@tonic-gate 9627c478bd9Sstevel@tonic-gate /* 9637c478bd9Sstevel@tonic-gate * Determine whether the name exists. 9647c478bd9Sstevel@tonic-gate */ 9657c478bd9Sstevel@tonic-gate if ((noexist = stat(name, &status)) != 0) { 9667c478bd9Sstevel@tonic-gate if (errno != ENOENT) { 9677c478bd9Sstevel@tonic-gate int err = errno; 9687c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_STAT), 9697c478bd9Sstevel@tonic-gate crle->c_name, name, strerror(err)); 9707c478bd9Sstevel@tonic-gate return (1); 9717c478bd9Sstevel@tonic-gate } else { 9727c478bd9Sstevel@tonic-gate /* 9737c478bd9Sstevel@tonic-gate * If we've been asked to create an alternative object 9747c478bd9Sstevel@tonic-gate * assume the object is a file and create a valid 9757c478bd9Sstevel@tonic-gate * alternative entry. This allows the creation of 9767c478bd9Sstevel@tonic-gate * alternatives for files that might not yet be 9777c478bd9Sstevel@tonic-gate * installed. 9787c478bd9Sstevel@tonic-gate * 9797c478bd9Sstevel@tonic-gate * Otherwise we have no idea whether the name specified 9807c478bd9Sstevel@tonic-gate * is a file or directory, so we assume a directory and 9817c478bd9Sstevel@tonic-gate * establish an object descriptor to mark this as 9827c478bd9Sstevel@tonic-gate * non-existent. This allows us to mark things like 9837c478bd9Sstevel@tonic-gate * platform specific directories as non-existent. 9847c478bd9Sstevel@tonic-gate */ 9857c478bd9Sstevel@tonic-gate if ((flags & (RTC_OBJ_DUMP | RTC_OBJ_ALTER)) != 9867c478bd9Sstevel@tonic-gate RTC_OBJ_ALTER) { 9877c478bd9Sstevel@tonic-gate if ((ent = enternoexistdir(crle, name)) == 0) 9887c478bd9Sstevel@tonic-gate return (1); 9897c478bd9Sstevel@tonic-gate ent->e_flags |= flags; 9907c478bd9Sstevel@tonic-gate return (0); 9917c478bd9Sstevel@tonic-gate } 9927c478bd9Sstevel@tonic-gate } 9937c478bd9Sstevel@tonic-gate } 9947c478bd9Sstevel@tonic-gate 9957c478bd9Sstevel@tonic-gate /* 9967c478bd9Sstevel@tonic-gate * Determine whether we're dealing with a directory or a file. 9977c478bd9Sstevel@tonic-gate */ 9987c478bd9Sstevel@tonic-gate if ((noexist == 0) && ((status.st_mode & S_IFMT) == S_IFDIR)) { 9997c478bd9Sstevel@tonic-gate /* 10007c478bd9Sstevel@tonic-gate * Process the directory name to collect its shared objects into 10017c478bd9Sstevel@tonic-gate * the configuration file. 10027c478bd9Sstevel@tonic-gate */ 10037c478bd9Sstevel@tonic-gate if (inspect_dir(crle, name, nflags, &status)) 10047c478bd9Sstevel@tonic-gate return (1); 10057c478bd9Sstevel@tonic-gate 10067c478bd9Sstevel@tonic-gate ent = get_hash(crle->c_strtbl, (Addr)name, 0, HASH_FND_ENT); 10077c478bd9Sstevel@tonic-gate ent->e_flags |= flags; 10087c478bd9Sstevel@tonic-gate return (0); 10097c478bd9Sstevel@tonic-gate } 10107c478bd9Sstevel@tonic-gate 10117c478bd9Sstevel@tonic-gate /* 10127c478bd9Sstevel@tonic-gate * If this isn't a regular file we might as well bail now. Note that 10137c478bd9Sstevel@tonic-gate * even if it is, we might still reject the file if it's not ELF later 10147c478bd9Sstevel@tonic-gate * in inspect_file(). 10157c478bd9Sstevel@tonic-gate */ 10167c478bd9Sstevel@tonic-gate if ((noexist == 0) && ((status.st_mode & S_IFMT) != S_IFREG)) { 10177c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_GEN_INVFILE), crle->c_name, 10187c478bd9Sstevel@tonic-gate name); 10197c478bd9Sstevel@tonic-gate return (1); 10207c478bd9Sstevel@tonic-gate } 10217c478bd9Sstevel@tonic-gate 10227c478bd9Sstevel@tonic-gate /* 10237c478bd9Sstevel@tonic-gate * Break the pathname into directory and filename components. 10247c478bd9Sstevel@tonic-gate */ 10257c478bd9Sstevel@tonic-gate if ((file = strrchr(name, '/')) == 0) { 10267c478bd9Sstevel@tonic-gate dir = MSG_ORIG(MSG_DIR_DOT); 10277c478bd9Sstevel@tonic-gate (void) strcpy(_name, MSG_ORIG(MSG_PTH_DOT)); 10287c478bd9Sstevel@tonic-gate (void) strcpy(&_name[MSG_PTH_DOT_SIZE], name); 10297c478bd9Sstevel@tonic-gate name = (const char *)_name; 10307c478bd9Sstevel@tonic-gate file = (const char *)&_name[MSG_PTH_DOT_SIZE]; 10317c478bd9Sstevel@tonic-gate } else { 10327c478bd9Sstevel@tonic-gate size_t off = file - name; 10337c478bd9Sstevel@tonic-gate 10347c478bd9Sstevel@tonic-gate if (file == name) 10357c478bd9Sstevel@tonic-gate dir = MSG_ORIG(MSG_DIR_ROOT); 10367c478bd9Sstevel@tonic-gate else { 10377c478bd9Sstevel@tonic-gate (void) strncpy(_dir, name, off); 10387c478bd9Sstevel@tonic-gate _dir[off] = '\0'; 10397c478bd9Sstevel@tonic-gate dir = (const char *)_dir; 10407c478bd9Sstevel@tonic-gate } 10417c478bd9Sstevel@tonic-gate file++; 10427c478bd9Sstevel@tonic-gate } 10437c478bd9Sstevel@tonic-gate 10447c478bd9Sstevel@tonic-gate /* 10457c478bd9Sstevel@tonic-gate * Determine whether we've already visited this directory and if not 10467c478bd9Sstevel@tonic-gate * create it. 10477c478bd9Sstevel@tonic-gate */ 10487c478bd9Sstevel@tonic-gate if ((ent = get_hash(crle->c_strtbl, (Addr)dir, 0, HASH_FND_ENT)) == 0) { 10497c478bd9Sstevel@tonic-gate struct stat _status; 10507c478bd9Sstevel@tonic-gate 10517c478bd9Sstevel@tonic-gate if (stat(dir, &_status) != 0) { 10527c478bd9Sstevel@tonic-gate if (errno != ENOENT) { 10537c478bd9Sstevel@tonic-gate int err = errno; 10547c478bd9Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_STAT), 10557c478bd9Sstevel@tonic-gate crle->c_name, name, strerror(err)); 10567c478bd9Sstevel@tonic-gate return (1); 10577c478bd9Sstevel@tonic-gate } else { 10587c478bd9Sstevel@tonic-gate /* 10597c478bd9Sstevel@tonic-gate * Note that this directory will be tagged as 10607c478bd9Sstevel@tonic-gate * having an alternative - not that the 10617c478bd9Sstevel@tonic-gate * directory does, but supposedly it contains 10627c478bd9Sstevel@tonic-gate * a file that does. 10637c478bd9Sstevel@tonic-gate */ 10647c478bd9Sstevel@tonic-gate if ((ent = enternoexistdir(crle, dir)) == 0) 10657c478bd9Sstevel@tonic-gate return (1); 10667c478bd9Sstevel@tonic-gate ent->e_flags |= nflags; 10677c478bd9Sstevel@tonic-gate } 10687c478bd9Sstevel@tonic-gate } else { 10697c478bd9Sstevel@tonic-gate if ((ent = enterdir(crle, dir, nflags, &_status)) == 0) 10707c478bd9Sstevel@tonic-gate return (1); 10717c478bd9Sstevel@tonic-gate } 10727c478bd9Sstevel@tonic-gate } 10737c478bd9Sstevel@tonic-gate 10747c478bd9Sstevel@tonic-gate /* 10757c478bd9Sstevel@tonic-gate * Regardless of whether we've already processed this file (say from 10767c478bd9Sstevel@tonic-gate * an RTC_OBJ_ALLENTS which we could determine from the above), continue 10777c478bd9Sstevel@tonic-gate * to inspect the file. It may require alternatives or something that 10787c478bd9Sstevel@tonic-gate * hadn't be specified from the directory entry. 10797c478bd9Sstevel@tonic-gate */ 10807c478bd9Sstevel@tonic-gate if (noexist) { 10817c478bd9Sstevel@tonic-gate if ((ent = enternoexistfile(crle, name, file, ent)) == 0) 10827c478bd9Sstevel@tonic-gate return (1); 10837c478bd9Sstevel@tonic-gate ent->e_flags |= nflags; 10847c478bd9Sstevel@tonic-gate if (enteralt(crle, name, file, flags, ent->e_obj) == 0) 10857c478bd9Sstevel@tonic-gate return (1); 10867c478bd9Sstevel@tonic-gate } else { 10877c478bd9Sstevel@tonic-gate if (inspect_file(crle, name, file, nflags, ent, &status, 1)) 10887c478bd9Sstevel@tonic-gate return (1); 10897c478bd9Sstevel@tonic-gate } 10907c478bd9Sstevel@tonic-gate 10917c478bd9Sstevel@tonic-gate /* 10927c478bd9Sstevel@tonic-gate * Make sure to propagate any RTC_OBJ_CMDLINE flag. 10937c478bd9Sstevel@tonic-gate */ 10947c478bd9Sstevel@tonic-gate if (ent = get_hash(crle->c_strtbl, (Addr)name, 0, HASH_FND_ENT)) 10957c478bd9Sstevel@tonic-gate ent->e_flags |= (flags & RTC_OBJ_CMDLINE); 10967c478bd9Sstevel@tonic-gate 10977c478bd9Sstevel@tonic-gate return (0); 10987c478bd9Sstevel@tonic-gate } 1099