10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*1698Sab196087 * Common Development and Distribution License (the "License"). 6*1698Sab196087 * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 210Sstevel@tonic-gate /* 22*1698Sab196087 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 230Sstevel@tonic-gate * Use is subject to license terms. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 260Sstevel@tonic-gate 270Sstevel@tonic-gate /* 280Sstevel@tonic-gate * Routines to add file and directory entries into the internal configuration 290Sstevel@tonic-gate * information. This information is maintained in a number of hash tables which 300Sstevel@tonic-gate * after completion of input file processing will be processed and written to 310Sstevel@tonic-gate * the output configuration file. 320Sstevel@tonic-gate * 330Sstevel@tonic-gate * Each hash table is defined via a Hash_tbl structure. These are organized: 340Sstevel@tonic-gate * 350Sstevel@tonic-gate * c_strtbl contains a hash entry for every file, directory, pathname and 360Sstevel@tonic-gate * alternative path (dldump(3dl) image) processed. 370Sstevel@tonic-gate * c_strsize and c_objnum maintain the size and count of the 380Sstevel@tonic-gate * strings added to this table and are used to size the output 390Sstevel@tonic-gate * configuration file. 400Sstevel@tonic-gate * 410Sstevel@tonic-gate * c_inotbls contains a list of inode hash tables. Each element of the list 420Sstevel@tonic-gate * identifies a unique device. Thus, for each file processed its 430Sstevel@tonic-gate * st_dev and st_ino are used to assign its entry to the correct 440Sstevel@tonic-gate * hash table. 450Sstevel@tonic-gate * 460Sstevel@tonic-gate * Each directory processed is assigned a unique id (c_dirnum) 470Sstevel@tonic-gate * which insures each file also becomes uniquely identified. 480Sstevel@tonic-gate * 490Sstevel@tonic-gate * All file and directory additions come through the inspect() entry point. 500Sstevel@tonic-gate */ 510Sstevel@tonic-gate 520Sstevel@tonic-gate #include <sys/types.h> 530Sstevel@tonic-gate #include <sys/stat.h> 540Sstevel@tonic-gate #include <fcntl.h> 550Sstevel@tonic-gate #include <dirent.h> 56*1698Sab196087 #include <_libelf.h> 570Sstevel@tonic-gate #include <errno.h> 580Sstevel@tonic-gate #include <stdio.h> 590Sstevel@tonic-gate #include <string.h> 600Sstevel@tonic-gate #include <unistd.h> 610Sstevel@tonic-gate #include <limits.h> 620Sstevel@tonic-gate #include "machdep.h" 630Sstevel@tonic-gate #include "sgs.h" 640Sstevel@tonic-gate #include "rtc.h" 650Sstevel@tonic-gate #include "_crle.h" 660Sstevel@tonic-gate #include "msg.h" 670Sstevel@tonic-gate 680Sstevel@tonic-gate /* 690Sstevel@tonic-gate * Add an alternative pathname for an object. Although a configuration file 700Sstevel@tonic-gate * may contain several pathnames that resolve to the same real file, there can 710Sstevel@tonic-gate * only be one real file. Consequently, there can only be one alternative. 720Sstevel@tonic-gate * For multiple pathnames that resolve to the same real file, multiple alter- 730Sstevel@tonic-gate * natives may be specified. Always take the alternative for the real file 740Sstevel@tonic-gate * over any others. 750Sstevel@tonic-gate */ 760Sstevel@tonic-gate static int 770Sstevel@tonic-gate enteralt(Crle_desc * crle, const char *path, const char *file, Half flags, 780Sstevel@tonic-gate Hash_obj * obj) 790Sstevel@tonic-gate { 800Sstevel@tonic-gate const char *fmt; 810Sstevel@tonic-gate char alter[PATH_MAX]; 820Sstevel@tonic-gate size_t altsz; 830Sstevel@tonic-gate 840Sstevel@tonic-gate if (obj->o_alter) { 850Sstevel@tonic-gate /* 860Sstevel@tonic-gate * If an alternative has already been captured, only override 870Sstevel@tonic-gate * it if the specified file is the real file. 880Sstevel@tonic-gate */ 890Sstevel@tonic-gate if (strcmp(path, obj->o_path)) 900Sstevel@tonic-gate return (1); 910Sstevel@tonic-gate } 920Sstevel@tonic-gate 930Sstevel@tonic-gate /* 940Sstevel@tonic-gate * Create an alternative pathname from the file and object destination 950Sstevel@tonic-gate * directory. If we're dumping an alternative don't allow it to 960Sstevel@tonic-gate * override the original. 970Sstevel@tonic-gate */ 980Sstevel@tonic-gate if (flags & RTC_OBJ_DUMP) { 990Sstevel@tonic-gate char _alter[PATH_MAX]; 1000Sstevel@tonic-gate 1010Sstevel@tonic-gate (void) strcpy(_alter, crle->c_objdir); 1020Sstevel@tonic-gate (void) realpath(_alter, _alter); 1030Sstevel@tonic-gate (void) snprintf(alter, PATH_MAX, MSG_ORIG(MSG_FMT_PATH), 1040Sstevel@tonic-gate _alter, file); 1050Sstevel@tonic-gate if (strcmp(alter, obj->o_path) == 0) { 1060Sstevel@tonic-gate (void) printf(MSG_INTL(MSG_ARG_ALT), crle->c_name, 1070Sstevel@tonic-gate obj->o_path); 1080Sstevel@tonic-gate return (0); 1090Sstevel@tonic-gate } 1100Sstevel@tonic-gate obj->o_flags |= RTC_OBJ_DUMP; 1110Sstevel@tonic-gate } else 1120Sstevel@tonic-gate (void) snprintf(alter, PATH_MAX, MSG_ORIG(MSG_FMT_PATH), 1130Sstevel@tonic-gate crle->c_objdir, file); 1140Sstevel@tonic-gate obj->o_flags |= RTC_OBJ_ALTER; 1150Sstevel@tonic-gate 1160Sstevel@tonic-gate /* 1170Sstevel@tonic-gate * If we're overriding an existing alternative with the real path, free 1180Sstevel@tonic-gate * up any previous alternative. 1190Sstevel@tonic-gate */ 1200Sstevel@tonic-gate if (obj->o_alter) { 1210Sstevel@tonic-gate crle->c_strsize -= strlen(alter) + 1; 1220Sstevel@tonic-gate fmt = MSG_INTL(MSG_DIA_ALTUPDATE); 1230Sstevel@tonic-gate } else 1240Sstevel@tonic-gate fmt = MSG_INTL(MSG_DIA_ALTCREATE); 1250Sstevel@tonic-gate 1260Sstevel@tonic-gate /* 1270Sstevel@tonic-gate * Allocate the new alternative and update the string table size. 1280Sstevel@tonic-gate */ 1290Sstevel@tonic-gate altsz = strlen(alter) + 1; 1300Sstevel@tonic-gate if ((obj->o_alter = malloc(altsz)) == 0) 1310Sstevel@tonic-gate return (0); 1320Sstevel@tonic-gate (void) strcpy(obj->o_alter, alter); 1330Sstevel@tonic-gate 1340Sstevel@tonic-gate crle->c_strsize += altsz; 1350Sstevel@tonic-gate 1360Sstevel@tonic-gate if (crle->c_flags & CRLE_VERBOSE) 1370Sstevel@tonic-gate (void) printf(fmt, alter, obj->o_path); 1380Sstevel@tonic-gate 1390Sstevel@tonic-gate return (1); 1400Sstevel@tonic-gate } 1410Sstevel@tonic-gate 1420Sstevel@tonic-gate 1430Sstevel@tonic-gate /* 1440Sstevel@tonic-gate * Establish an inode hash entry, this is unique for each dev hash table, and 1450Sstevel@tonic-gate * establishes the unique object descriptor. 1460Sstevel@tonic-gate */ 1470Sstevel@tonic-gate static Hash_ent * 1480Sstevel@tonic-gate enterino(Crle_desc * crle, const char *name, struct stat *status, Half flags) 1490Sstevel@tonic-gate { 1500Sstevel@tonic-gate Hash_ent * ent; 1510Sstevel@tonic-gate Hash_obj * obj; 1520Sstevel@tonic-gate Hash_tbl * tbl; 1530Sstevel@tonic-gate Listnode * lnp = 0; 1540Sstevel@tonic-gate Addr ino = (Addr)status->st_ino; 1550Sstevel@tonic-gate ulong_t dev = status->st_dev; 1560Sstevel@tonic-gate Lword info; 1570Sstevel@tonic-gate 1580Sstevel@tonic-gate /* 1590Sstevel@tonic-gate * For configuration file verification we retain information about the 1600Sstevel@tonic-gate * file or directory. 1610Sstevel@tonic-gate */ 1620Sstevel@tonic-gate if (flags & RTC_OBJ_DIRENT) 1630Sstevel@tonic-gate info = (Lword)status->st_mtime; 1640Sstevel@tonic-gate else 1650Sstevel@tonic-gate info = (Lword)status->st_size; 1660Sstevel@tonic-gate 1670Sstevel@tonic-gate /* 1680Sstevel@tonic-gate * Determine the objects device number and establish a hash table for 1690Sstevel@tonic-gate * for this devices inodes. 1700Sstevel@tonic-gate */ 1710Sstevel@tonic-gate for (LIST_TRAVERSE(&crle->c_inotbls, lnp, tbl)) { 1720Sstevel@tonic-gate if (tbl->t_ident == dev) 1730Sstevel@tonic-gate break; 1740Sstevel@tonic-gate } 1750Sstevel@tonic-gate if (lnp == 0) { 1760Sstevel@tonic-gate if ((tbl = make_hash(crle->c_inobkts, HASH_INT, dev)) == 0) 1770Sstevel@tonic-gate return (0); 1780Sstevel@tonic-gate if (list_append(&crle->c_inotbls, tbl) == 0) 1790Sstevel@tonic-gate return (0); 1800Sstevel@tonic-gate } 1810Sstevel@tonic-gate 1820Sstevel@tonic-gate /* 1830Sstevel@tonic-gate * Reuse or add this new object to the inode hash table. 1840Sstevel@tonic-gate */ 1850Sstevel@tonic-gate if ((ent = get_hash(tbl, ino, 0, (HASH_FND_ENT | HASH_ADD_ENT))) == 0) 1860Sstevel@tonic-gate return (0); 1870Sstevel@tonic-gate 1880Sstevel@tonic-gate /* 1890Sstevel@tonic-gate * If an object descriptor doesn't yet exist create one. 1900Sstevel@tonic-gate */ 1910Sstevel@tonic-gate if ((obj = ent->e_obj) == 0) { 1920Sstevel@tonic-gate if ((obj = calloc(sizeof (Hash_obj), 1)) == 0) 1930Sstevel@tonic-gate return (0); 1940Sstevel@tonic-gate obj->o_tbl = tbl; 1950Sstevel@tonic-gate obj->o_flags = flags; 1960Sstevel@tonic-gate obj->o_info = info; 1970Sstevel@tonic-gate 1980Sstevel@tonic-gate /* 1990Sstevel@tonic-gate * Reallocate the objects name, as it might have been composed 2000Sstevel@tonic-gate * and passed to us on the stack. 2010Sstevel@tonic-gate */ 2020Sstevel@tonic-gate if ((obj->o_path = strdup(name)) == 0) 2030Sstevel@tonic-gate return (0); 2040Sstevel@tonic-gate 2050Sstevel@tonic-gate /* 2060Sstevel@tonic-gate * Assign this object to the original ino hash entry. 2070Sstevel@tonic-gate */ 2080Sstevel@tonic-gate ent->e_obj = obj; 2090Sstevel@tonic-gate } 2100Sstevel@tonic-gate return (ent); 2110Sstevel@tonic-gate } 2120Sstevel@tonic-gate 2130Sstevel@tonic-gate 2140Sstevel@tonic-gate /* 2150Sstevel@tonic-gate * Basic directory entry, establishes entry information, updated global counts 2160Sstevel@tonic-gate * and provides any diagnostics. 2170Sstevel@tonic-gate */ 2180Sstevel@tonic-gate static int 2190Sstevel@tonic-gate _enterdir(Crle_desc * crle, const char *dir, Hash_ent * ent, Hash_obj * obj) 2200Sstevel@tonic-gate { 2210Sstevel@tonic-gate size_t size = strlen(dir) + 1; 2220Sstevel@tonic-gate char *ndir; 2230Sstevel@tonic-gate 2240Sstevel@tonic-gate /* 2250Sstevel@tonic-gate * Establish this hash entries key (which is the directory name itself), 2260Sstevel@tonic-gate * assign the next available directory number, and its object. 2270Sstevel@tonic-gate */ 2280Sstevel@tonic-gate if ((ndir = malloc(size)) == 0) 2290Sstevel@tonic-gate return (0); 2300Sstevel@tonic-gate (void) strcpy(ndir, dir); 2310Sstevel@tonic-gate 2320Sstevel@tonic-gate ent->e_key = (Addr)ndir; 2330Sstevel@tonic-gate ent->e_id = crle->c_dirnum++; 2340Sstevel@tonic-gate ent->e_obj = obj; 2350Sstevel@tonic-gate 2360Sstevel@tonic-gate /* 2370Sstevel@tonic-gate * Update string table information. We add a dummy filename for each 2380Sstevel@tonic-gate * real directory so as to have a null terminated file table array for 2390Sstevel@tonic-gate * this directory. 2400Sstevel@tonic-gate */ 2410Sstevel@tonic-gate crle->c_strsize += size; 2420Sstevel@tonic-gate crle->c_hashstrnum++; 2430Sstevel@tonic-gate crle->c_filenum++; 2440Sstevel@tonic-gate 2450Sstevel@tonic-gate /* 2460Sstevel@tonic-gate * Provide any diagnostics. 2470Sstevel@tonic-gate */ 2480Sstevel@tonic-gate if (crle->c_flags & CRLE_VERBOSE) { 2490Sstevel@tonic-gate const char *fmt; 2500Sstevel@tonic-gate 2510Sstevel@tonic-gate if (obj->o_flags & RTC_OBJ_NOEXIST) 2520Sstevel@tonic-gate fmt = MSG_INTL(MSG_DIA_NOEXIST); 2530Sstevel@tonic-gate else 2540Sstevel@tonic-gate fmt = MSG_INTL(MSG_DIA_DIR); 2550Sstevel@tonic-gate 2560Sstevel@tonic-gate (void) printf(fmt, ent->e_id, dir); 2570Sstevel@tonic-gate } 2580Sstevel@tonic-gate return (1); 2590Sstevel@tonic-gate } 2600Sstevel@tonic-gate 2610Sstevel@tonic-gate 2620Sstevel@tonic-gate /* 2630Sstevel@tonic-gate * Establish a string hash entry for a directory. 2640Sstevel@tonic-gate */ 2650Sstevel@tonic-gate static Hash_ent * 2660Sstevel@tonic-gate enterdir(Crle_desc * crle, const char *odir, Half flags, struct stat *status) 2670Sstevel@tonic-gate { 2680Sstevel@tonic-gate Hash_tbl * stbl = crle->c_strtbl; 2690Sstevel@tonic-gate Hash_ent * ent; 2700Sstevel@tonic-gate Hash_obj * obj; 2710Sstevel@tonic-gate char rdir[PATH_MAX], * ndir; 2720Sstevel@tonic-gate 2730Sstevel@tonic-gate /* 2740Sstevel@tonic-gate * Establish the directories real name, this is the name that will be 2750Sstevel@tonic-gate * recorded in the object identifier. 2760Sstevel@tonic-gate */ 2770Sstevel@tonic-gate if (realpath(odir, rdir) == 0) 2780Sstevel@tonic-gate return (0); 2790Sstevel@tonic-gate 2800Sstevel@tonic-gate if (strcmp(odir, rdir)) 2810Sstevel@tonic-gate ndir = rdir; 2820Sstevel@tonic-gate else 2830Sstevel@tonic-gate ndir = (char *)odir; 2840Sstevel@tonic-gate 2850Sstevel@tonic-gate /* 2860Sstevel@tonic-gate * If we're not dealing with an all-entries directory (i.e., we're 2870Sstevel@tonic-gate * recording this directory because of its explicitly specified 2880Sstevel@tonic-gate * filename) leave off any filename specific attributes. 2890Sstevel@tonic-gate */ 2900Sstevel@tonic-gate if ((flags & RTC_OBJ_ALLENTS) == 0) 2910Sstevel@tonic-gate flags &= ~(RTC_OBJ_ALTER | RTC_OBJ_DUMP | RTC_OBJ_GROUP); 2920Sstevel@tonic-gate flags |= RTC_OBJ_DIRENT; 2930Sstevel@tonic-gate 2940Sstevel@tonic-gate /* 2950Sstevel@tonic-gate * Establish a inode table entry, and the objects unique descriptor. 2960Sstevel@tonic-gate */ 2970Sstevel@tonic-gate if ((ent = enterino(crle, ndir, status, flags)) == 0) 2980Sstevel@tonic-gate return (0); 2990Sstevel@tonic-gate obj = ent->e_obj; 3000Sstevel@tonic-gate 3010Sstevel@tonic-gate /* 3020Sstevel@tonic-gate * Create a string table entry for the real directory. 3030Sstevel@tonic-gate */ 3040Sstevel@tonic-gate if ((ent = get_hash(stbl, (Addr)ndir, 0, 3050Sstevel@tonic-gate (HASH_FND_ENT | HASH_ADD_ENT))) == 0) 3060Sstevel@tonic-gate return (0); 3070Sstevel@tonic-gate 3080Sstevel@tonic-gate /* 3090Sstevel@tonic-gate * If this is a new entry reassign the directory name and assign a 3100Sstevel@tonic-gate * unique directory id. 3110Sstevel@tonic-gate */ 3120Sstevel@tonic-gate if (ent->e_id == 0) { 3130Sstevel@tonic-gate if (_enterdir(crle, ndir, ent, obj) == 0) 3140Sstevel@tonic-gate return (0); 3150Sstevel@tonic-gate } 3160Sstevel@tonic-gate 3170Sstevel@tonic-gate /* 3180Sstevel@tonic-gate * If the directory name supplied is different than the real name we've 3190Sstevel@tonic-gate * just entered, continue to create an entry for it. 3200Sstevel@tonic-gate */ 3210Sstevel@tonic-gate if (ndir == odir) 3220Sstevel@tonic-gate return (ent); 3230Sstevel@tonic-gate 3240Sstevel@tonic-gate /* 3250Sstevel@tonic-gate * Create a string table entry for this real directory. 3260Sstevel@tonic-gate */ 3270Sstevel@tonic-gate if ((ent = get_hash(stbl, (Addr)odir, 0, 3280Sstevel@tonic-gate (HASH_FND_ENT | HASH_ADD_ENT))) == 0) 3290Sstevel@tonic-gate return (0); 3300Sstevel@tonic-gate 3310Sstevel@tonic-gate /* 3320Sstevel@tonic-gate * If this is a new entry reassign the directory name and assign a 3330Sstevel@tonic-gate * unique directory id. 3340Sstevel@tonic-gate */ 3350Sstevel@tonic-gate if (ent->e_id == 0) { 3360Sstevel@tonic-gate if (_enterdir(crle, odir, ent, obj) == 0) 3370Sstevel@tonic-gate return (0); 3380Sstevel@tonic-gate } 3390Sstevel@tonic-gate 3400Sstevel@tonic-gate return (ent); 3410Sstevel@tonic-gate } 3420Sstevel@tonic-gate 3430Sstevel@tonic-gate 3440Sstevel@tonic-gate /* 3450Sstevel@tonic-gate * Establish a non-existent directory entry. There is no inode entry created 3460Sstevel@tonic-gate * for this, just a directory and its associated object. 3470Sstevel@tonic-gate */ 3480Sstevel@tonic-gate static Hash_ent * 3490Sstevel@tonic-gate enternoexistdir(Crle_desc * crle, const char *dir) 3500Sstevel@tonic-gate { 3510Sstevel@tonic-gate Hash_ent * ent; 3520Sstevel@tonic-gate 3530Sstevel@tonic-gate /* 3540Sstevel@tonic-gate * Reuse or add this new non-existent directory to the string table. 3550Sstevel@tonic-gate */ 3560Sstevel@tonic-gate if ((ent = get_hash(crle->c_strtbl, (Addr)dir, 0, 3570Sstevel@tonic-gate (HASH_FND_ENT | HASH_ADD_ENT))) == 0) 3580Sstevel@tonic-gate return (0); 3590Sstevel@tonic-gate 3600Sstevel@tonic-gate /* 3610Sstevel@tonic-gate * If this is a new entry, assign both the object and the directory 3620Sstevel@tonic-gate * entry information. 3630Sstevel@tonic-gate */ 3640Sstevel@tonic-gate if (ent->e_id == 0) { 3650Sstevel@tonic-gate Hash_obj * obj; 3660Sstevel@tonic-gate 3670Sstevel@tonic-gate if ((obj = calloc(sizeof (Hash_obj), 1)) == 0) 3680Sstevel@tonic-gate return (0); 3690Sstevel@tonic-gate obj->o_flags = (RTC_OBJ_NOEXIST | RTC_OBJ_DIRENT); 3700Sstevel@tonic-gate 3710Sstevel@tonic-gate if (_enterdir(crle, dir, ent, obj) == 0) 3720Sstevel@tonic-gate return (0); 3730Sstevel@tonic-gate } 3740Sstevel@tonic-gate return (ent); 3750Sstevel@tonic-gate } 3760Sstevel@tonic-gate 3770Sstevel@tonic-gate 3780Sstevel@tonic-gate /* 3790Sstevel@tonic-gate * Basic file entry, establishes entry information, updated global counts 3800Sstevel@tonic-gate * and provides any diagnostics. 3810Sstevel@tonic-gate */ 3820Sstevel@tonic-gate static int 3830Sstevel@tonic-gate _enterfile(Crle_desc * crle, const char *file, int off, Hash_ent * fent, 3840Sstevel@tonic-gate Hash_ent * rent, Hash_ent * dent, Hash_obj * obj) 3850Sstevel@tonic-gate { 3860Sstevel@tonic-gate size_t size = strlen(file) + 1; 3870Sstevel@tonic-gate char *nfile; 3880Sstevel@tonic-gate 3890Sstevel@tonic-gate /* 3900Sstevel@tonic-gate * If this is a full file name reallocate it, as it might have been 3910Sstevel@tonic-gate * composed and passed to us on the stack. Otherwise reuse the original 3920Sstevel@tonic-gate * directory name to satisfy the filename, here we record the offset of 3930Sstevel@tonic-gate * the file in the directory name so that we can reduce the string table 3940Sstevel@tonic-gate * in the final configuration file. 3950Sstevel@tonic-gate */ 3960Sstevel@tonic-gate if (off == 0) { 3970Sstevel@tonic-gate if ((nfile = malloc(size)) == 0) 3980Sstevel@tonic-gate return (0); 3990Sstevel@tonic-gate (void) strcpy(nfile, file); 4000Sstevel@tonic-gate } else 4010Sstevel@tonic-gate nfile = (char *)file; 4020Sstevel@tonic-gate 4030Sstevel@tonic-gate fent->e_key = (Addr)nfile; 4040Sstevel@tonic-gate fent->e_off = off; 4050Sstevel@tonic-gate 4060Sstevel@tonic-gate /* 4070Sstevel@tonic-gate * Assign directory and directory id, and any real (full) path 4080Sstevel@tonic-gate * association. 4090Sstevel@tonic-gate */ 4100Sstevel@tonic-gate fent->e_dir = dent; 4110Sstevel@tonic-gate fent->e_id = dent->e_id; 4120Sstevel@tonic-gate fent->e_path = rent; 4130Sstevel@tonic-gate 4140Sstevel@tonic-gate /* 4150Sstevel@tonic-gate * Increment the file count for this directory. 4160Sstevel@tonic-gate */ 4170Sstevel@tonic-gate dent->e_cnt++; 4180Sstevel@tonic-gate 4190Sstevel@tonic-gate /* 4200Sstevel@tonic-gate * Assign this object to the new string hash entry. 4210Sstevel@tonic-gate */ 4220Sstevel@tonic-gate fent->e_obj = obj; 4230Sstevel@tonic-gate 4240Sstevel@tonic-gate /* 4250Sstevel@tonic-gate * Update string table information. 4260Sstevel@tonic-gate */ 4270Sstevel@tonic-gate crle->c_strsize += size; 4280Sstevel@tonic-gate crle->c_hashstrnum++; 4290Sstevel@tonic-gate crle->c_filenum++; 4300Sstevel@tonic-gate 4310Sstevel@tonic-gate /* 4320Sstevel@tonic-gate * Provide any diagnostics. 4330Sstevel@tonic-gate */ 4340Sstevel@tonic-gate if (crle->c_flags & CRLE_VERBOSE) 4350Sstevel@tonic-gate (void) printf(MSG_INTL(MSG_DIA_FILE), fent->e_id, nfile); 4360Sstevel@tonic-gate 4370Sstevel@tonic-gate return (1); 4380Sstevel@tonic-gate } 4390Sstevel@tonic-gate 4400Sstevel@tonic-gate 4410Sstevel@tonic-gate /* 4420Sstevel@tonic-gate * Establish a non-existent file entry. There is no inode entry created for 4430Sstevel@tonic-gate * this, just the files full and simple name, and its associated object. 4440Sstevel@tonic-gate */ 4450Sstevel@tonic-gate static Hash_ent * 4460Sstevel@tonic-gate enternoexistfile(Crle_desc * crle, const char *path, const char *file, 4470Sstevel@tonic-gate Hash_ent * dent) 4480Sstevel@tonic-gate { 4490Sstevel@tonic-gate Hash_ent * rent, * ent; 4500Sstevel@tonic-gate Hash_obj * obj; 4510Sstevel@tonic-gate int off; 4520Sstevel@tonic-gate 4530Sstevel@tonic-gate /* 4540Sstevel@tonic-gate * Create a string table entry for the full filename. 4550Sstevel@tonic-gate */ 4560Sstevel@tonic-gate if ((rent = get_hash(crle->c_strtbl, (Addr)path, 0, 4570Sstevel@tonic-gate (HASH_FND_ENT | HASH_ADD_ENT))) == 0) 4580Sstevel@tonic-gate return (0); 4590Sstevel@tonic-gate 4600Sstevel@tonic-gate /* 4610Sstevel@tonic-gate * If this is a new entry, assign both the object and the full filename 4620Sstevel@tonic-gate * entry information. 4630Sstevel@tonic-gate */ 4640Sstevel@tonic-gate if (rent->e_id == 0) { 4650Sstevel@tonic-gate if ((obj = calloc(sizeof (Hash_obj), 1)) == 0) 4660Sstevel@tonic-gate return (0); 4670Sstevel@tonic-gate obj->o_flags = RTC_OBJ_NOEXIST; 4680Sstevel@tonic-gate 4690Sstevel@tonic-gate if (_enterfile(crle, path, 0, rent, 0, dent, obj) == 0) 4700Sstevel@tonic-gate return (0); 4710Sstevel@tonic-gate } 4720Sstevel@tonic-gate obj = rent->e_obj; 4730Sstevel@tonic-gate if ((obj->o_path = strdup(path)) == 0) 4740Sstevel@tonic-gate return (0); 4750Sstevel@tonic-gate 4760Sstevel@tonic-gate /* 4770Sstevel@tonic-gate * Express the filename in terms of the full pathname. By reusing the 4780Sstevel@tonic-gate * name within the full filename we can reduce the overall string table 4790Sstevel@tonic-gate * size in the output configuration file. 4800Sstevel@tonic-gate */ 4810Sstevel@tonic-gate off = file - path; 4820Sstevel@tonic-gate file = (char *)rent->e_key + off; 4830Sstevel@tonic-gate 4840Sstevel@tonic-gate /* 4850Sstevel@tonic-gate * Create a entry for the individual file within this directory. 4860Sstevel@tonic-gate */ 4870Sstevel@tonic-gate if ((ent = get_hash(crle->c_strtbl, (Addr)file, dent->e_id, 4880Sstevel@tonic-gate (HASH_FND_ENT | HASH_ADD_ENT))) == 0) 4890Sstevel@tonic-gate return (0); 4900Sstevel@tonic-gate 4910Sstevel@tonic-gate if (ent->e_id == 0) { 4920Sstevel@tonic-gate if (_enterfile(crle, file, off, ent, rent, dent, obj) == 0) 4930Sstevel@tonic-gate return (0); 4940Sstevel@tonic-gate } 4950Sstevel@tonic-gate return (ent); 4960Sstevel@tonic-gate } 4970Sstevel@tonic-gate 4980Sstevel@tonic-gate 4990Sstevel@tonic-gate /* 5000Sstevel@tonic-gate * Establish a string hash entry for a file. 5010Sstevel@tonic-gate */ 5020Sstevel@tonic-gate static Hash_ent * 5030Sstevel@tonic-gate enterfile(Crle_desc * crle, const char *opath, const char *ofile, Half flags, 5040Sstevel@tonic-gate Hash_ent * odent, struct stat *status) 5050Sstevel@tonic-gate { 5060Sstevel@tonic-gate Hash_tbl * stbl = crle->c_strtbl; 5070Sstevel@tonic-gate Hash_ent * ent, * rent, * ndent = odent; 5080Sstevel@tonic-gate Hash_obj * obj; 5090Sstevel@tonic-gate size_t size; 5100Sstevel@tonic-gate char rpath[PATH_MAX], * npath, * nfile; 5110Sstevel@tonic-gate int off; 5120Sstevel@tonic-gate 5130Sstevel@tonic-gate /* 5140Sstevel@tonic-gate * Establish the files real name, this is the name that will be 5150Sstevel@tonic-gate * recorded in the object identifier. 5160Sstevel@tonic-gate */ 5170Sstevel@tonic-gate if (realpath(opath, rpath) == 0) 5180Sstevel@tonic-gate return (0); 5190Sstevel@tonic-gate 5200Sstevel@tonic-gate if (strcmp(opath, rpath)) { 5210Sstevel@tonic-gate npath = rpath; 5220Sstevel@tonic-gate if (nfile = strrchr(npath, '/')) 5230Sstevel@tonic-gate nfile++; 5240Sstevel@tonic-gate else 5250Sstevel@tonic-gate nfile = npath; 5260Sstevel@tonic-gate 5270Sstevel@tonic-gate /* 5280Sstevel@tonic-gate * Determine if the real pathname has a different directory to 5290Sstevel@tonic-gate * the original passed to us. 5300Sstevel@tonic-gate */ 5310Sstevel@tonic-gate size = nfile - npath; 5320Sstevel@tonic-gate if (strncmp(opath, npath, size)) { 5330Sstevel@tonic-gate char _npath[PATH_MAX]; 5340Sstevel@tonic-gate struct stat _status; 5350Sstevel@tonic-gate 5360Sstevel@tonic-gate (void) strncpy(_npath, npath, size); 5370Sstevel@tonic-gate _npath[size - 1] = '\0'; 5380Sstevel@tonic-gate 5390Sstevel@tonic-gate (void) stat(_npath, &_status); 5400Sstevel@tonic-gate if ((ndent = enterdir(crle, _npath, flags, 5410Sstevel@tonic-gate &_status)) == 0) 5420Sstevel@tonic-gate return (0); 5430Sstevel@tonic-gate } 5440Sstevel@tonic-gate } else { 5450Sstevel@tonic-gate npath = (char *)opath; 5460Sstevel@tonic-gate nfile = (char *)ofile; 5470Sstevel@tonic-gate } 5480Sstevel@tonic-gate 5490Sstevel@tonic-gate /* 5500Sstevel@tonic-gate * Establish an inode table entry, and the objects unique descriptor. 5510Sstevel@tonic-gate */ 5520Sstevel@tonic-gate if ((ent = enterino(crle, npath, status, flags)) == 0) 5530Sstevel@tonic-gate return (0); 5540Sstevel@tonic-gate obj = ent->e_obj; 5550Sstevel@tonic-gate 5560Sstevel@tonic-gate /* 5570Sstevel@tonic-gate * Create a string table entry for the full filename. 5580Sstevel@tonic-gate */ 5590Sstevel@tonic-gate if ((rent = get_hash(stbl, (Addr)npath, 0, 5600Sstevel@tonic-gate (HASH_FND_ENT | HASH_ADD_ENT))) == 0) 5610Sstevel@tonic-gate return (0); 5620Sstevel@tonic-gate if (rent->e_id == 0) { 5630Sstevel@tonic-gate if (_enterfile(crle, npath, 0, rent, 0, ndent, obj) == 0) 5640Sstevel@tonic-gate return (0); 5650Sstevel@tonic-gate } 5660Sstevel@tonic-gate 5670Sstevel@tonic-gate /* 5680Sstevel@tonic-gate * Identify this entry and its directory as real paths. If dldump(3dl) 5690Sstevel@tonic-gate * processing is required this flag is checked, as we only need to dump 5700Sstevel@tonic-gate * the real pathname. Many other objects may point to the same 5710Sstevel@tonic-gate * alternative, but only one needs to be dumped. In addition, during 5720Sstevel@tonic-gate * ld.so.1 validation, only this directory and file need be checked. 5730Sstevel@tonic-gate */ 5740Sstevel@tonic-gate rent->e_flags |= RTC_OBJ_REALPTH; 5750Sstevel@tonic-gate ndent->e_flags |= RTC_OBJ_REALPTH; 5760Sstevel@tonic-gate 5770Sstevel@tonic-gate /* 5780Sstevel@tonic-gate * Express the filename in terms of the full pathname. By reusing the 5790Sstevel@tonic-gate * name within the full filename we can reduce the overall string table 5800Sstevel@tonic-gate * size in the output configuration file. 5810Sstevel@tonic-gate */ 5820Sstevel@tonic-gate off = nfile - npath; 5830Sstevel@tonic-gate nfile = (char *)rent->e_key + off; 5840Sstevel@tonic-gate 5850Sstevel@tonic-gate /* 5860Sstevel@tonic-gate * Create a entry for the individual file within this directory. 5870Sstevel@tonic-gate */ 5880Sstevel@tonic-gate if ((ent = get_hash(stbl, (Addr)nfile, ndent->e_id, 5890Sstevel@tonic-gate (HASH_FND_ENT | HASH_ADD_ENT))) == 0) 5900Sstevel@tonic-gate return (0); 5910Sstevel@tonic-gate if (ent->e_id == 0) { 5920Sstevel@tonic-gate if (_enterfile(crle, nfile, off, ent, rent, ndent, obj) == 0) 5930Sstevel@tonic-gate return (0); 5940Sstevel@tonic-gate } 5950Sstevel@tonic-gate 5960Sstevel@tonic-gate /* 5970Sstevel@tonic-gate * If the original path name is not equivalent to the real path name, 5980Sstevel@tonic-gate * then we had an alias (typically it's a symlink). Add the path name 5990Sstevel@tonic-gate * to the string hash table and reference the object data structure. 6000Sstevel@tonic-gate */ 6010Sstevel@tonic-gate if (nfile == ofile) 6020Sstevel@tonic-gate return (ent); 6030Sstevel@tonic-gate 6040Sstevel@tonic-gate /* 6050Sstevel@tonic-gate * Establish an inode table entry, and the objects unique descriptor. 6060Sstevel@tonic-gate */ 6070Sstevel@tonic-gate if ((ent = enterino(crle, opath, status, 0)) == 0) 6080Sstevel@tonic-gate return (0); 6090Sstevel@tonic-gate obj = ent->e_obj; 6100Sstevel@tonic-gate 6110Sstevel@tonic-gate /* 6120Sstevel@tonic-gate * Create a string table entry for the full filename. 6130Sstevel@tonic-gate */ 6140Sstevel@tonic-gate if ((rent = get_hash(stbl, (Addr)opath, 0, 6150Sstevel@tonic-gate (HASH_FND_ENT | HASH_ADD_ENT))) == 0) 6160Sstevel@tonic-gate return (0); 6170Sstevel@tonic-gate if (rent->e_id == 0) { 6180Sstevel@tonic-gate if (_enterfile(crle, opath, 0, rent, 0, odent, obj) == 0) 6190Sstevel@tonic-gate return (0); 6200Sstevel@tonic-gate } 6210Sstevel@tonic-gate 6220Sstevel@tonic-gate /* 6230Sstevel@tonic-gate * Express the filename in terms of the full pathname. By reusing the 6240Sstevel@tonic-gate * name within the full filename we can reduce the overall string table 6250Sstevel@tonic-gate * size in the output configuration file. 6260Sstevel@tonic-gate */ 6270Sstevel@tonic-gate off = ofile - opath; 6280Sstevel@tonic-gate ofile = (char *)rent->e_key + off; 6290Sstevel@tonic-gate 6300Sstevel@tonic-gate /* 6310Sstevel@tonic-gate * Create a entry for the individual file within this directory. 6320Sstevel@tonic-gate */ 6330Sstevel@tonic-gate if ((ent = get_hash(stbl, (Addr)ofile, odent->e_id, 6340Sstevel@tonic-gate (HASH_FND_ENT | HASH_ADD_ENT))) == 0) 6350Sstevel@tonic-gate return (0); 6360Sstevel@tonic-gate if (ent->e_id == 0) { 6370Sstevel@tonic-gate if (_enterfile(crle, ofile, off, ent, rent, odent, obj) == 0) 6380Sstevel@tonic-gate return (0); 6390Sstevel@tonic-gate } 6400Sstevel@tonic-gate 6410Sstevel@tonic-gate return (ent); 6420Sstevel@tonic-gate } 6430Sstevel@tonic-gate 6440Sstevel@tonic-gate 6450Sstevel@tonic-gate /* 6460Sstevel@tonic-gate * Add a file to configuration information. 6470Sstevel@tonic-gate */ 6480Sstevel@tonic-gate static int 6490Sstevel@tonic-gate inspect_file(Crle_desc * crle, const char *path, const char *file, Half flags, 6500Sstevel@tonic-gate Hash_ent * dent, struct stat *status, int error) 6510Sstevel@tonic-gate { 6520Sstevel@tonic-gate Hash_ent * ent; 6530Sstevel@tonic-gate Hash_obj * obj; 6540Sstevel@tonic-gate int fd; 6550Sstevel@tonic-gate Elf * elf; 6560Sstevel@tonic-gate GElf_Ehdr ehdr; 657*1698Sab196087 GElf_Xword dyflags = 0; 6580Sstevel@tonic-gate Listnode * lnp; 6590Sstevel@tonic-gate Hash_tbl * tbl; 6600Sstevel@tonic-gate Addr ino = (Addr)status->st_ino; 6610Sstevel@tonic-gate 6620Sstevel@tonic-gate /* 6630Sstevel@tonic-gate * Determine whether this file (inode) has already been processed. 6640Sstevel@tonic-gate */ 6650Sstevel@tonic-gate for (LIST_TRAVERSE(&crle->c_inotbls, lnp, tbl)) { 6660Sstevel@tonic-gate if (tbl->t_ident != status->st_dev) 6670Sstevel@tonic-gate continue; 6680Sstevel@tonic-gate 6690Sstevel@tonic-gate if ((ent = get_hash(tbl, ino, 0, HASH_FND_ENT)) == 0) 6700Sstevel@tonic-gate break; 6710Sstevel@tonic-gate 6720Sstevel@tonic-gate /* 6730Sstevel@tonic-gate * This files inode object does exist, make sure it has a file 6740Sstevel@tonic-gate * entry for this directory. 6750Sstevel@tonic-gate */ 6760Sstevel@tonic-gate if ((ent = enterfile(crle, path, file, flags, dent, 6770Sstevel@tonic-gate status)) == 0) 6780Sstevel@tonic-gate return (error); 6790Sstevel@tonic-gate obj = ent->e_obj; 6800Sstevel@tonic-gate 6810Sstevel@tonic-gate /* 6820Sstevel@tonic-gate * If an alternative has been asked for, and one has not yet 6830Sstevel@tonic-gate * been established, create one. 6840Sstevel@tonic-gate */ 6850Sstevel@tonic-gate if ((flags & RTC_OBJ_ALTER) && 6860Sstevel@tonic-gate ((obj->o_flags & RTC_OBJ_NOALTER) == 0)) { 6870Sstevel@tonic-gate if (enteralt(crle, path, file, flags, obj) == 0) 6880Sstevel@tonic-gate return (error); 6890Sstevel@tonic-gate } 6900Sstevel@tonic-gate return (0); 6910Sstevel@tonic-gate } 6920Sstevel@tonic-gate 6930Sstevel@tonic-gate /* 6940Sstevel@tonic-gate * This is a new file, determine if it's a valid ELF file. 6950Sstevel@tonic-gate */ 6960Sstevel@tonic-gate if ((fd = open(path, O_RDONLY, 0)) == -1) { 6970Sstevel@tonic-gate if (error) { 6980Sstevel@tonic-gate int err = errno; 6990Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN), 7000Sstevel@tonic-gate crle->c_name, path, strerror(err)); 7010Sstevel@tonic-gate } 7020Sstevel@tonic-gate return (error); 7030Sstevel@tonic-gate } 7040Sstevel@tonic-gate 7050Sstevel@tonic-gate /* 7060Sstevel@tonic-gate * Obtain an ELF descriptor and determine if we have a shared object. 7070Sstevel@tonic-gate */ 7080Sstevel@tonic-gate if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) { 7090Sstevel@tonic-gate if (error) 7100Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ELF_BEGIN), 7110Sstevel@tonic-gate crle->c_name, path, elf_errmsg(-1)); 7120Sstevel@tonic-gate (void) close(fd); 7130Sstevel@tonic-gate return (error); 7140Sstevel@tonic-gate } 7150Sstevel@tonic-gate if ((elf_kind(elf) != ELF_K_ELF) || 7160Sstevel@tonic-gate (gelf_getehdr(elf, &ehdr) == NULL) || 7170Sstevel@tonic-gate (!((ehdr.e_type == ET_EXEC) || (ehdr.e_type == ET_DYN))) || 7180Sstevel@tonic-gate (!((ehdr.e_ident[EI_CLASS] == crle->c_class) || 7190Sstevel@tonic-gate (ehdr.e_machine == crle->c_machine)))) { 7200Sstevel@tonic-gate if (error) 7210Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ELF_TYPE), 7220Sstevel@tonic-gate crle->c_name, path); 7230Sstevel@tonic-gate (void) close(fd); 7240Sstevel@tonic-gate (void) elf_end(elf); 7250Sstevel@tonic-gate return (error); 7260Sstevel@tonic-gate } 7270Sstevel@tonic-gate 7280Sstevel@tonic-gate (void) close(fd); 7290Sstevel@tonic-gate 7300Sstevel@tonic-gate /* 7310Sstevel@tonic-gate * If we're generating alternative objects find this objects DT_FLAGS 7320Sstevel@tonic-gate * to insure it isn't marked as non-dumpable (libdl.so.1 falls into 7330Sstevel@tonic-gate * this category). 7340Sstevel@tonic-gate */ 735*1698Sab196087 if (flags & RTC_OBJ_DUMP) 736*1698Sab196087 dyflags = _gelf_getdyndtflags_1(elf); 7370Sstevel@tonic-gate 7380Sstevel@tonic-gate /* 7390Sstevel@tonic-gate * Dynamic executables can be examined to determine their dependencies, 7400Sstevel@tonic-gate * dldump(3dl) their dependencies, and may even be dldump(3dl)'ed 7410Sstevel@tonic-gate * themselves. 7420Sstevel@tonic-gate * 7430Sstevel@tonic-gate * If we come across an executable while searching a directory 7440Sstevel@tonic-gate * (error == 0) it is ignored. 7450Sstevel@tonic-gate */ 7460Sstevel@tonic-gate if (ehdr.e_type == ET_EXEC) { 7470Sstevel@tonic-gate if (error == 0) { 7480Sstevel@tonic-gate (void) elf_end(elf); 7490Sstevel@tonic-gate return (0); 7500Sstevel@tonic-gate } 7510Sstevel@tonic-gate 7520Sstevel@tonic-gate /* 7530Sstevel@tonic-gate * If we're not dumping the application itself, or we've not 7540Sstevel@tonic-gate * asked to gather its dependencies then its rather useless. 7550Sstevel@tonic-gate */ 7560Sstevel@tonic-gate if ((flags & (RTC_OBJ_GROUP | RTC_OBJ_DUMP)) == 0) { 7570Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_GEN_INVFILE), 7580Sstevel@tonic-gate crle->c_name, path); 7590Sstevel@tonic-gate (void) elf_end(elf); 7600Sstevel@tonic-gate return (error); 7610Sstevel@tonic-gate } 7620Sstevel@tonic-gate 7630Sstevel@tonic-gate /* 7640Sstevel@tonic-gate * If we're dumping the application under RTLD_REL_EXEC then the 7650Sstevel@tonic-gate * configuration file becomes specific to this application, so 7660Sstevel@tonic-gate * make sure we haven't been here before. 7670Sstevel@tonic-gate */ 7680Sstevel@tonic-gate if (crle->c_app && (flags & RTC_OBJ_DUMP) && 7690Sstevel@tonic-gate (crle->c_dlflags & RTLD_REL_EXEC)) { 7700Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ARG_MODE), 7710Sstevel@tonic-gate crle->c_name, crle->c_app, path); 7720Sstevel@tonic-gate (void) elf_end(elf); 7730Sstevel@tonic-gate return (error); 7740Sstevel@tonic-gate } 7750Sstevel@tonic-gate } 7760Sstevel@tonic-gate 7770Sstevel@tonic-gate /* 7780Sstevel@tonic-gate * Enter the file in the string hash table. 7790Sstevel@tonic-gate */ 7800Sstevel@tonic-gate if ((ent = enterfile(crle, path, file, flags, dent, status)) == 0) { 7810Sstevel@tonic-gate (void) elf_end(elf); 7820Sstevel@tonic-gate return (error); 7830Sstevel@tonic-gate } 7840Sstevel@tonic-gate obj = ent->e_obj; 7850Sstevel@tonic-gate 7860Sstevel@tonic-gate if (flags & RTC_OBJ_ALTER) { 7870Sstevel@tonic-gate /* 7880Sstevel@tonic-gate * If this object is marked as non-dumpable make sure we don't 7890Sstevel@tonic-gate * create a dldump(3dl) alternative. A user requested 7900Sstevel@tonic-gate * alternative is acceptable. 7910Sstevel@tonic-gate */ 7920Sstevel@tonic-gate if ((flags & RTC_OBJ_DUMP) && (dyflags & DF_1_NODUMP)) { 7930Sstevel@tonic-gate obj->o_flags |= RTC_OBJ_NOALTER; 7940Sstevel@tonic-gate obj->o_flags &= ~(RTC_OBJ_ALTER | RTC_OBJ_DUMP); 7950Sstevel@tonic-gate } else { 7960Sstevel@tonic-gate if (enteralt(crle, path, file, flags, obj) == 0) { 7970Sstevel@tonic-gate (void) elf_end(elf); 7980Sstevel@tonic-gate return (error); 7990Sstevel@tonic-gate } 8000Sstevel@tonic-gate } 8010Sstevel@tonic-gate } 8020Sstevel@tonic-gate 8030Sstevel@tonic-gate /* 8040Sstevel@tonic-gate * Executables are recorded in the configuration file either to allow 8050Sstevel@tonic-gate * for the configuration files update, or may indicate that the 8060Sstevel@tonic-gate * configuration file is specific to their use. 8070Sstevel@tonic-gate */ 8080Sstevel@tonic-gate if (ehdr.e_type == ET_EXEC) { 8090Sstevel@tonic-gate obj->o_flags |= RTC_OBJ_EXEC; 8100Sstevel@tonic-gate 8110Sstevel@tonic-gate if ((flags & RTC_OBJ_DUMP) && 8120Sstevel@tonic-gate (crle->c_dlflags & RTLD_REL_EXEC)) { 8130Sstevel@tonic-gate /* 8140Sstevel@tonic-gate * Get the reallocated pathname rather than using the 8150Sstevel@tonic-gate * original (the original might be from an existing 8160Sstevel@tonic-gate * configuration file being updated, in which case the 8170Sstevel@tonic-gate * pointer will be unmapped before we get to use it). 8180Sstevel@tonic-gate */ 8190Sstevel@tonic-gate ent = get_hash(crle->c_strtbl, (Addr)path, 0, 8200Sstevel@tonic-gate HASH_FND_ENT); 8210Sstevel@tonic-gate 8220Sstevel@tonic-gate obj->o_flags |= RTC_OBJ_APP; 8230Sstevel@tonic-gate crle->c_app = (char *)ent->e_key; 8240Sstevel@tonic-gate } 8250Sstevel@tonic-gate } 8260Sstevel@tonic-gate 8270Sstevel@tonic-gate /* 8280Sstevel@tonic-gate * If we've been asked to process this object as a group determine its 8290Sstevel@tonic-gate * dependencies. 8300Sstevel@tonic-gate */ 8310Sstevel@tonic-gate if (flags & RTC_OBJ_GROUP) { 8320Sstevel@tonic-gate if (depend(crle, path, flags, &ehdr)) { 8330Sstevel@tonic-gate (void) elf_end(elf); 8340Sstevel@tonic-gate return (error); 8350Sstevel@tonic-gate } 8360Sstevel@tonic-gate } 8370Sstevel@tonic-gate 8380Sstevel@tonic-gate (void) elf_end(elf); 8390Sstevel@tonic-gate return (0); 8400Sstevel@tonic-gate } 8410Sstevel@tonic-gate 8420Sstevel@tonic-gate 8430Sstevel@tonic-gate /* 8440Sstevel@tonic-gate * Add a directory to configuration information. 8450Sstevel@tonic-gate */ 8460Sstevel@tonic-gate static int 8470Sstevel@tonic-gate inspect_dir(Crle_desc * crle, const char *name, Half flags, struct stat *status) 8480Sstevel@tonic-gate { 8490Sstevel@tonic-gate Hash_tbl * stbl = crle->c_strtbl; 8500Sstevel@tonic-gate DIR * dir; 8510Sstevel@tonic-gate struct dirent *dirent; 8520Sstevel@tonic-gate Hash_ent * ent; 8530Sstevel@tonic-gate int error = 0; 8540Sstevel@tonic-gate struct stat _status; 8550Sstevel@tonic-gate char path[PATH_MAX], * dst; 8560Sstevel@tonic-gate const char *src; 8570Sstevel@tonic-gate 8580Sstevel@tonic-gate /* 8590Sstevel@tonic-gate * Determine whether we've already visited this directory to process 8600Sstevel@tonic-gate * all its entries. 8610Sstevel@tonic-gate */ 8620Sstevel@tonic-gate if ((ent = get_hash(stbl, (Addr)name, 0, HASH_FND_ENT)) != 0) { 8630Sstevel@tonic-gate if (ent->e_obj->o_flags & RTC_OBJ_ALLENTS) 8640Sstevel@tonic-gate return (0); 8650Sstevel@tonic-gate } else { 8660Sstevel@tonic-gate /* 8670Sstevel@tonic-gate * Create a directory hash entry. 8680Sstevel@tonic-gate */ 8690Sstevel@tonic-gate if ((ent = enterdir(crle, name, (flags | RTC_OBJ_ALLENTS), 8700Sstevel@tonic-gate status)) == 0) 8710Sstevel@tonic-gate return (1); 8720Sstevel@tonic-gate } 8730Sstevel@tonic-gate ent->e_obj->o_flags |= RTC_OBJ_ALLENTS; 8740Sstevel@tonic-gate 8750Sstevel@tonic-gate /* 8760Sstevel@tonic-gate * Establish the pathname buffer. 8770Sstevel@tonic-gate */ 8780Sstevel@tonic-gate for (dst = path, dst--, src = name; *src; src++) 8790Sstevel@tonic-gate *++dst = *src; 8800Sstevel@tonic-gate if (*dst++ != '/') 8810Sstevel@tonic-gate *dst++ = '/'; 8820Sstevel@tonic-gate 8830Sstevel@tonic-gate /* 8840Sstevel@tonic-gate * Access the directory in preparation for reading its entries. 8850Sstevel@tonic-gate */ 8860Sstevel@tonic-gate if ((dir = opendir(name)) == 0) 8870Sstevel@tonic-gate return (1); 8880Sstevel@tonic-gate 8890Sstevel@tonic-gate /* 8900Sstevel@tonic-gate * Read each entry from the directory looking for ELF files. 8910Sstevel@tonic-gate */ 8920Sstevel@tonic-gate while ((dirent = readdir(dir)) != NULL) { 8930Sstevel@tonic-gate const char *file = dirent->d_name; 8940Sstevel@tonic-gate char *_dst; 8950Sstevel@tonic-gate 8960Sstevel@tonic-gate /* 8970Sstevel@tonic-gate * Ignore "." and ".." entries. 8980Sstevel@tonic-gate */ 8990Sstevel@tonic-gate if ((file[0] == '.') && ((file[1] == '\0') || 9000Sstevel@tonic-gate ((file[1] == '.') && (file[2] == '\0')))) 9010Sstevel@tonic-gate continue; 9020Sstevel@tonic-gate 9030Sstevel@tonic-gate /* 9040Sstevel@tonic-gate * Complete full pathname, and reassign file to the new path. 9050Sstevel@tonic-gate */ 9060Sstevel@tonic-gate for (_dst = dst, src = file, file = dst; *src; _dst++, src++) 9070Sstevel@tonic-gate *_dst = *src; 9080Sstevel@tonic-gate *_dst = '\0'; 9090Sstevel@tonic-gate 9100Sstevel@tonic-gate if (stat(path, &_status) == -1) 9110Sstevel@tonic-gate continue; 9120Sstevel@tonic-gate 9130Sstevel@tonic-gate if ((_status.st_mode & S_IFMT) != S_IFREG) 9140Sstevel@tonic-gate continue; 9150Sstevel@tonic-gate 9160Sstevel@tonic-gate if (inspect_file(crle, path, file, flags, ent, &_status, 0)) { 9170Sstevel@tonic-gate error = 1; 9180Sstevel@tonic-gate break; 9190Sstevel@tonic-gate } 9200Sstevel@tonic-gate } 9210Sstevel@tonic-gate return (error); 9220Sstevel@tonic-gate } 9230Sstevel@tonic-gate 9240Sstevel@tonic-gate 9250Sstevel@tonic-gate /* 9260Sstevel@tonic-gate * Inspect a file/dir name. A stat(name) results in the following actions: 9270Sstevel@tonic-gate * 9280Sstevel@tonic-gate * The name doesn't exist: 9290Sstevel@tonic-gate * The name is assummed to be a non-existent directory and a directory 9300Sstevel@tonic-gate * cache entry is created to indicate this. 9310Sstevel@tonic-gate * 9320Sstevel@tonic-gate * The name is a directory: 9330Sstevel@tonic-gate * The directory is searched for appropriate files. 9340Sstevel@tonic-gate * 9350Sstevel@tonic-gate * The name is a file: 9360Sstevel@tonic-gate * The file is processed and added to the cache if appropriate. 9370Sstevel@tonic-gate */ 9380Sstevel@tonic-gate int 9390Sstevel@tonic-gate inspect(Crle_desc * crle, const char *name, Half flags) 9400Sstevel@tonic-gate { 9410Sstevel@tonic-gate Hash_ent * ent; 9420Sstevel@tonic-gate const char *file, * dir; 9430Sstevel@tonic-gate struct stat status; 9440Sstevel@tonic-gate char _name[PATH_MAX], _dir[PATH_MAX]; 9450Sstevel@tonic-gate Half nflags = flags & ~RTC_OBJ_CMDLINE; 9460Sstevel@tonic-gate int noexist; 9470Sstevel@tonic-gate 9480Sstevel@tonic-gate /* 9490Sstevel@tonic-gate * If this is the first time through here establish a string table 9500Sstevel@tonic-gate * cache. 9510Sstevel@tonic-gate */ 9520Sstevel@tonic-gate if (crle->c_dirnum == 0) { 9530Sstevel@tonic-gate if ((crle->c_strtbl = make_hash(crle->c_strbkts, 9540Sstevel@tonic-gate HASH_STR, 0)) == 0) 9550Sstevel@tonic-gate return (1); 9560Sstevel@tonic-gate crle->c_dirnum = 1; 9570Sstevel@tonic-gate } 9580Sstevel@tonic-gate 9590Sstevel@tonic-gate if (crle->c_flags & CRLE_VERBOSE) 9600Sstevel@tonic-gate (void) printf(MSG_INTL(MSG_DIA_INSPECT), name); 9610Sstevel@tonic-gate 9620Sstevel@tonic-gate /* 9630Sstevel@tonic-gate * Determine whether the name exists. 9640Sstevel@tonic-gate */ 9650Sstevel@tonic-gate if ((noexist = stat(name, &status)) != 0) { 9660Sstevel@tonic-gate if (errno != ENOENT) { 9670Sstevel@tonic-gate int err = errno; 9680Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_STAT), 9690Sstevel@tonic-gate crle->c_name, name, strerror(err)); 9700Sstevel@tonic-gate return (1); 9710Sstevel@tonic-gate } else { 9720Sstevel@tonic-gate /* 9730Sstevel@tonic-gate * If we've been asked to create an alternative object 9740Sstevel@tonic-gate * assume the object is a file and create a valid 9750Sstevel@tonic-gate * alternative entry. This allows the creation of 9760Sstevel@tonic-gate * alternatives for files that might not yet be 9770Sstevel@tonic-gate * installed. 9780Sstevel@tonic-gate * 9790Sstevel@tonic-gate * Otherwise we have no idea whether the name specified 9800Sstevel@tonic-gate * is a file or directory, so we assume a directory and 9810Sstevel@tonic-gate * establish an object descriptor to mark this as 9820Sstevel@tonic-gate * non-existent. This allows us to mark things like 9830Sstevel@tonic-gate * platform specific directories as non-existent. 9840Sstevel@tonic-gate */ 9850Sstevel@tonic-gate if ((flags & (RTC_OBJ_DUMP | RTC_OBJ_ALTER)) != 9860Sstevel@tonic-gate RTC_OBJ_ALTER) { 9870Sstevel@tonic-gate if ((ent = enternoexistdir(crle, name)) == 0) 9880Sstevel@tonic-gate return (1); 9890Sstevel@tonic-gate ent->e_flags |= flags; 9900Sstevel@tonic-gate return (0); 9910Sstevel@tonic-gate } 9920Sstevel@tonic-gate } 9930Sstevel@tonic-gate } 9940Sstevel@tonic-gate 9950Sstevel@tonic-gate /* 9960Sstevel@tonic-gate * Determine whether we're dealing with a directory or a file. 9970Sstevel@tonic-gate */ 9980Sstevel@tonic-gate if ((noexist == 0) && ((status.st_mode & S_IFMT) == S_IFDIR)) { 9990Sstevel@tonic-gate /* 10000Sstevel@tonic-gate * Process the directory name to collect its shared objects into 10010Sstevel@tonic-gate * the configuration file. 10020Sstevel@tonic-gate */ 10030Sstevel@tonic-gate if (inspect_dir(crle, name, nflags, &status)) 10040Sstevel@tonic-gate return (1); 10050Sstevel@tonic-gate 10060Sstevel@tonic-gate ent = get_hash(crle->c_strtbl, (Addr)name, 0, HASH_FND_ENT); 10070Sstevel@tonic-gate ent->e_flags |= flags; 10080Sstevel@tonic-gate return (0); 10090Sstevel@tonic-gate } 10100Sstevel@tonic-gate 10110Sstevel@tonic-gate /* 10120Sstevel@tonic-gate * If this isn't a regular file we might as well bail now. Note that 10130Sstevel@tonic-gate * even if it is, we might still reject the file if it's not ELF later 10140Sstevel@tonic-gate * in inspect_file(). 10150Sstevel@tonic-gate */ 10160Sstevel@tonic-gate if ((noexist == 0) && ((status.st_mode & S_IFMT) != S_IFREG)) { 10170Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_GEN_INVFILE), crle->c_name, 10180Sstevel@tonic-gate name); 10190Sstevel@tonic-gate return (1); 10200Sstevel@tonic-gate } 10210Sstevel@tonic-gate 10220Sstevel@tonic-gate /* 10230Sstevel@tonic-gate * Break the pathname into directory and filename components. 10240Sstevel@tonic-gate */ 10250Sstevel@tonic-gate if ((file = strrchr(name, '/')) == 0) { 10260Sstevel@tonic-gate dir = MSG_ORIG(MSG_DIR_DOT); 10270Sstevel@tonic-gate (void) strcpy(_name, MSG_ORIG(MSG_PTH_DOT)); 10280Sstevel@tonic-gate (void) strcpy(&_name[MSG_PTH_DOT_SIZE], name); 10290Sstevel@tonic-gate name = (const char *)_name; 10300Sstevel@tonic-gate file = (const char *)&_name[MSG_PTH_DOT_SIZE]; 10310Sstevel@tonic-gate } else { 10320Sstevel@tonic-gate size_t off = file - name; 10330Sstevel@tonic-gate 10340Sstevel@tonic-gate if (file == name) 10350Sstevel@tonic-gate dir = MSG_ORIG(MSG_DIR_ROOT); 10360Sstevel@tonic-gate else { 10370Sstevel@tonic-gate (void) strncpy(_dir, name, off); 10380Sstevel@tonic-gate _dir[off] = '\0'; 10390Sstevel@tonic-gate dir = (const char *)_dir; 10400Sstevel@tonic-gate } 10410Sstevel@tonic-gate file++; 10420Sstevel@tonic-gate } 10430Sstevel@tonic-gate 10440Sstevel@tonic-gate /* 10450Sstevel@tonic-gate * Determine whether we've already visited this directory and if not 10460Sstevel@tonic-gate * create it. 10470Sstevel@tonic-gate */ 10480Sstevel@tonic-gate if ((ent = get_hash(crle->c_strtbl, (Addr)dir, 0, HASH_FND_ENT)) == 0) { 10490Sstevel@tonic-gate struct stat _status; 10500Sstevel@tonic-gate 10510Sstevel@tonic-gate if (stat(dir, &_status) != 0) { 10520Sstevel@tonic-gate if (errno != ENOENT) { 10530Sstevel@tonic-gate int err = errno; 10540Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_STAT), 10550Sstevel@tonic-gate crle->c_name, name, strerror(err)); 10560Sstevel@tonic-gate return (1); 10570Sstevel@tonic-gate } else { 10580Sstevel@tonic-gate /* 10590Sstevel@tonic-gate * Note that this directory will be tagged as 10600Sstevel@tonic-gate * having an alternative - not that the 10610Sstevel@tonic-gate * directory does, but supposedly it contains 10620Sstevel@tonic-gate * a file that does. 10630Sstevel@tonic-gate */ 10640Sstevel@tonic-gate if ((ent = enternoexistdir(crle, dir)) == 0) 10650Sstevel@tonic-gate return (1); 10660Sstevel@tonic-gate ent->e_flags |= nflags; 10670Sstevel@tonic-gate } 10680Sstevel@tonic-gate } else { 10690Sstevel@tonic-gate if ((ent = enterdir(crle, dir, nflags, &_status)) == 0) 10700Sstevel@tonic-gate return (1); 10710Sstevel@tonic-gate } 10720Sstevel@tonic-gate } 10730Sstevel@tonic-gate 10740Sstevel@tonic-gate /* 10750Sstevel@tonic-gate * Regardless of whether we've already processed this file (say from 10760Sstevel@tonic-gate * an RTC_OBJ_ALLENTS which we could determine from the above), continue 10770Sstevel@tonic-gate * to inspect the file. It may require alternatives or something that 10780Sstevel@tonic-gate * hadn't be specified from the directory entry. 10790Sstevel@tonic-gate */ 10800Sstevel@tonic-gate if (noexist) { 10810Sstevel@tonic-gate if ((ent = enternoexistfile(crle, name, file, ent)) == 0) 10820Sstevel@tonic-gate return (1); 10830Sstevel@tonic-gate ent->e_flags |= nflags; 10840Sstevel@tonic-gate if (enteralt(crle, name, file, flags, ent->e_obj) == 0) 10850Sstevel@tonic-gate return (1); 10860Sstevel@tonic-gate } else { 10870Sstevel@tonic-gate if (inspect_file(crle, name, file, nflags, ent, &status, 1)) 10880Sstevel@tonic-gate return (1); 10890Sstevel@tonic-gate } 10900Sstevel@tonic-gate 10910Sstevel@tonic-gate /* 10920Sstevel@tonic-gate * Make sure to propagate any RTC_OBJ_CMDLINE flag. 10930Sstevel@tonic-gate */ 10940Sstevel@tonic-gate if (ent = get_hash(crle->c_strtbl, (Addr)name, 0, HASH_FND_ENT)) 10950Sstevel@tonic-gate ent->e_flags |= (flags & RTC_OBJ_CMDLINE); 10960Sstevel@tonic-gate 10970Sstevel@tonic-gate return (0); 10980Sstevel@tonic-gate } 1099