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
51698Sab196087 * Common Development and Distribution License (the "License").
61698Sab196087 * 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*9131SRod.Evans@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23*9131SRod.Evans@Sun.COM * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate /*
270Sstevel@tonic-gate * Routines to add file and directory entries into the internal configuration
280Sstevel@tonic-gate * information. This information is maintained in a number of hash tables which
290Sstevel@tonic-gate * after completion of input file processing will be processed and written to
300Sstevel@tonic-gate * the output configuration file.
310Sstevel@tonic-gate *
320Sstevel@tonic-gate * Each hash table is defined via a Hash_tbl structure. These are organized:
330Sstevel@tonic-gate *
340Sstevel@tonic-gate * c_strtbl contains a hash entry for every file, directory, pathname and
350Sstevel@tonic-gate * alternative path (dldump(3dl) image) processed.
360Sstevel@tonic-gate * c_strsize and c_objnum maintain the size and count of the
370Sstevel@tonic-gate * strings added to this table and are used to size the output
380Sstevel@tonic-gate * configuration file.
390Sstevel@tonic-gate *
400Sstevel@tonic-gate * c_inotbls contains a list of inode hash tables. Each element of the list
410Sstevel@tonic-gate * identifies a unique device. Thus, for each file processed its
420Sstevel@tonic-gate * st_dev and st_ino are used to assign its entry to the correct
430Sstevel@tonic-gate * hash table.
440Sstevel@tonic-gate *
450Sstevel@tonic-gate * Each directory processed is assigned a unique id (c_dirnum)
460Sstevel@tonic-gate * which insures each file also becomes uniquely identified.
470Sstevel@tonic-gate *
480Sstevel@tonic-gate * All file and directory additions come through the inspect() entry point.
490Sstevel@tonic-gate */
500Sstevel@tonic-gate
510Sstevel@tonic-gate #include <sys/types.h>
520Sstevel@tonic-gate #include <sys/stat.h>
530Sstevel@tonic-gate #include <fcntl.h>
540Sstevel@tonic-gate #include <dirent.h>
551698Sab196087 #include <_libelf.h>
560Sstevel@tonic-gate #include <errno.h>
570Sstevel@tonic-gate #include <stdio.h>
580Sstevel@tonic-gate #include <string.h>
590Sstevel@tonic-gate #include <unistd.h>
600Sstevel@tonic-gate #include <limits.h>
610Sstevel@tonic-gate #include "machdep.h"
620Sstevel@tonic-gate #include "sgs.h"
630Sstevel@tonic-gate #include "rtc.h"
640Sstevel@tonic-gate #include "_crle.h"
650Sstevel@tonic-gate #include "msg.h"
660Sstevel@tonic-gate
670Sstevel@tonic-gate /*
680Sstevel@tonic-gate * Add an alternative pathname for an object. Although a configuration file
690Sstevel@tonic-gate * may contain several pathnames that resolve to the same real file, there can
700Sstevel@tonic-gate * only be one real file. Consequently, there can only be one alternative.
710Sstevel@tonic-gate * For multiple pathnames that resolve to the same real file, multiple alter-
720Sstevel@tonic-gate * natives may be specified. Always take the alternative for the real file
730Sstevel@tonic-gate * over any others.
740Sstevel@tonic-gate */
750Sstevel@tonic-gate static int
enteralt(Crle_desc * crle,const char * path,const char * file,Half flags,Hash_obj * obj)76*9131SRod.Evans@Sun.COM enteralt(Crle_desc *crle, const char *path, const char *file, Half flags,
77*9131SRod.Evans@Sun.COM Hash_obj *obj)
780Sstevel@tonic-gate {
790Sstevel@tonic-gate const char *fmt;
800Sstevel@tonic-gate char alter[PATH_MAX];
810Sstevel@tonic-gate size_t altsz;
820Sstevel@tonic-gate
830Sstevel@tonic-gate if (obj->o_alter) {
840Sstevel@tonic-gate /*
850Sstevel@tonic-gate * If an alternative has already been captured, only override
860Sstevel@tonic-gate * it if the specified file is the real file.
870Sstevel@tonic-gate */
880Sstevel@tonic-gate if (strcmp(path, obj->o_path))
890Sstevel@tonic-gate return (1);
900Sstevel@tonic-gate }
910Sstevel@tonic-gate
920Sstevel@tonic-gate /*
930Sstevel@tonic-gate * Create an alternative pathname from the file and object destination
940Sstevel@tonic-gate * directory. If we're dumping an alternative don't allow it to
950Sstevel@tonic-gate * override the original.
960Sstevel@tonic-gate */
970Sstevel@tonic-gate if (flags & RTC_OBJ_DUMP) {
980Sstevel@tonic-gate char _alter[PATH_MAX];
990Sstevel@tonic-gate
1000Sstevel@tonic-gate (void) strcpy(_alter, crle->c_objdir);
1010Sstevel@tonic-gate (void) realpath(_alter, _alter);
1020Sstevel@tonic-gate (void) snprintf(alter, PATH_MAX, MSG_ORIG(MSG_FMT_PATH),
1030Sstevel@tonic-gate _alter, file);
1040Sstevel@tonic-gate if (strcmp(alter, obj->o_path) == 0) {
1050Sstevel@tonic-gate (void) printf(MSG_INTL(MSG_ARG_ALT), crle->c_name,
1060Sstevel@tonic-gate obj->o_path);
1070Sstevel@tonic-gate return (0);
1080Sstevel@tonic-gate }
1090Sstevel@tonic-gate obj->o_flags |= RTC_OBJ_DUMP;
1100Sstevel@tonic-gate } else
1110Sstevel@tonic-gate (void) snprintf(alter, PATH_MAX, MSG_ORIG(MSG_FMT_PATH),
1120Sstevel@tonic-gate crle->c_objdir, file);
1130Sstevel@tonic-gate obj->o_flags |= RTC_OBJ_ALTER;
1140Sstevel@tonic-gate
1150Sstevel@tonic-gate /*
1160Sstevel@tonic-gate * If we're overriding an existing alternative with the real path, free
1170Sstevel@tonic-gate * up any previous alternative.
1180Sstevel@tonic-gate */
1190Sstevel@tonic-gate if (obj->o_alter) {
1200Sstevel@tonic-gate crle->c_strsize -= strlen(alter) + 1;
1210Sstevel@tonic-gate fmt = MSG_INTL(MSG_DIA_ALTUPDATE);
1220Sstevel@tonic-gate } else
1230Sstevel@tonic-gate fmt = MSG_INTL(MSG_DIA_ALTCREATE);
1240Sstevel@tonic-gate
1250Sstevel@tonic-gate /*
1260Sstevel@tonic-gate * Allocate the new alternative and update the string table size.
1270Sstevel@tonic-gate */
1280Sstevel@tonic-gate altsz = strlen(alter) + 1;
129*9131SRod.Evans@Sun.COM if ((obj->o_alter = malloc(altsz)) == NULL)
1300Sstevel@tonic-gate return (0);
1310Sstevel@tonic-gate (void) strcpy(obj->o_alter, alter);
1320Sstevel@tonic-gate
1330Sstevel@tonic-gate crle->c_strsize += altsz;
1340Sstevel@tonic-gate
1350Sstevel@tonic-gate if (crle->c_flags & CRLE_VERBOSE)
1360Sstevel@tonic-gate (void) printf(fmt, alter, obj->o_path);
1370Sstevel@tonic-gate
1380Sstevel@tonic-gate return (1);
1390Sstevel@tonic-gate }
1400Sstevel@tonic-gate
1410Sstevel@tonic-gate
1420Sstevel@tonic-gate /*
1430Sstevel@tonic-gate * Establish an inode hash entry, this is unique for each dev hash table, and
1440Sstevel@tonic-gate * establishes the unique object descriptor.
1450Sstevel@tonic-gate */
1460Sstevel@tonic-gate static Hash_ent *
enterino(Crle_desc * crle,const char * name,struct stat * status,Half flags)147*9131SRod.Evans@Sun.COM enterino(Crle_desc *crle, const char *name, struct stat *status, Half flags)
1480Sstevel@tonic-gate {
149*9131SRod.Evans@Sun.COM Hash_ent *ent;
150*9131SRod.Evans@Sun.COM Hash_obj *obj;
151*9131SRod.Evans@Sun.COM Hash_tbl *tbl;
152*9131SRod.Evans@Sun.COM Aliste idx;
1530Sstevel@tonic-gate Addr ino = (Addr)status->st_ino;
1540Sstevel@tonic-gate ulong_t dev = status->st_dev;
1550Sstevel@tonic-gate Lword info;
156*9131SRod.Evans@Sun.COM int found = 0;
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 */
171*9131SRod.Evans@Sun.COM for (APLIST_TRAVERSE(crle->c_inotbls, idx, tbl)) {
172*9131SRod.Evans@Sun.COM if (tbl->t_ident == dev) {
173*9131SRod.Evans@Sun.COM found = 1;
1740Sstevel@tonic-gate break;
175*9131SRod.Evans@Sun.COM }
1760Sstevel@tonic-gate }
177*9131SRod.Evans@Sun.COM if (found == 0) {
178*9131SRod.Evans@Sun.COM if ((tbl = make_hash(crle->c_inobkts, HASH_INT, dev)) == NULL)
179*9131SRod.Evans@Sun.COM return (NULL);
180*9131SRod.Evans@Sun.COM if (aplist_append(&crle->c_inotbls, tbl, AL_CNT_CRLE) == NULL)
181*9131SRod.Evans@Sun.COM return (NULL);
1820Sstevel@tonic-gate }
1830Sstevel@tonic-gate
1840Sstevel@tonic-gate /*
1850Sstevel@tonic-gate * Reuse or add this new object to the inode hash table.
1860Sstevel@tonic-gate */
187*9131SRod.Evans@Sun.COM if ((ent = get_hash(tbl, ino, 0,
188*9131SRod.Evans@Sun.COM (HASH_FND_ENT | HASH_ADD_ENT))) == NULL)
189*9131SRod.Evans@Sun.COM return (NULL);
1900Sstevel@tonic-gate
1910Sstevel@tonic-gate /*
1920Sstevel@tonic-gate * If an object descriptor doesn't yet exist create one.
1930Sstevel@tonic-gate */
194*9131SRod.Evans@Sun.COM if ((obj = ent->e_obj) == NULL) {
195*9131SRod.Evans@Sun.COM if ((obj = calloc(sizeof (Hash_obj), 1)) == NULL)
196*9131SRod.Evans@Sun.COM return (NULL);
1970Sstevel@tonic-gate obj->o_tbl = tbl;
1980Sstevel@tonic-gate obj->o_flags = flags;
1990Sstevel@tonic-gate obj->o_info = info;
2000Sstevel@tonic-gate
2010Sstevel@tonic-gate /*
2020Sstevel@tonic-gate * Reallocate the objects name, as it might have been composed
2030Sstevel@tonic-gate * and passed to us on the stack.
2040Sstevel@tonic-gate */
205*9131SRod.Evans@Sun.COM if ((obj->o_path = strdup(name)) == NULL)
206*9131SRod.Evans@Sun.COM return (NULL);
2070Sstevel@tonic-gate
2080Sstevel@tonic-gate /*
2090Sstevel@tonic-gate * Assign this object to the original ino hash entry.
2100Sstevel@tonic-gate */
2110Sstevel@tonic-gate ent->e_obj = obj;
2120Sstevel@tonic-gate }
2130Sstevel@tonic-gate return (ent);
2140Sstevel@tonic-gate }
2150Sstevel@tonic-gate
2160Sstevel@tonic-gate /*
2170Sstevel@tonic-gate * Basic directory entry, establishes entry information, updated global counts
2180Sstevel@tonic-gate * and provides any diagnostics.
2190Sstevel@tonic-gate */
2200Sstevel@tonic-gate static int
_enterdir(Crle_desc * crle,const char * dir,Hash_ent * ent,Hash_obj * obj)221*9131SRod.Evans@Sun.COM _enterdir(Crle_desc *crle, const char *dir, Hash_ent *ent, Hash_obj *obj)
2220Sstevel@tonic-gate {
2230Sstevel@tonic-gate size_t size = strlen(dir) + 1;
2240Sstevel@tonic-gate char *ndir;
2250Sstevel@tonic-gate
2260Sstevel@tonic-gate /*
2270Sstevel@tonic-gate * Establish this hash entries key (which is the directory name itself),
2280Sstevel@tonic-gate * assign the next available directory number, and its object.
2290Sstevel@tonic-gate */
230*9131SRod.Evans@Sun.COM if ((ndir = malloc(size)) == NULL)
2310Sstevel@tonic-gate return (0);
2320Sstevel@tonic-gate (void) strcpy(ndir, dir);
2330Sstevel@tonic-gate
2340Sstevel@tonic-gate ent->e_key = (Addr)ndir;
2350Sstevel@tonic-gate ent->e_id = crle->c_dirnum++;
2360Sstevel@tonic-gate ent->e_obj = obj;
2370Sstevel@tonic-gate
2380Sstevel@tonic-gate /*
2390Sstevel@tonic-gate * Update string table information. We add a dummy filename for each
2400Sstevel@tonic-gate * real directory so as to have a null terminated file table array for
2410Sstevel@tonic-gate * this directory.
2420Sstevel@tonic-gate */
2430Sstevel@tonic-gate crle->c_strsize += size;
2440Sstevel@tonic-gate crle->c_hashstrnum++;
2450Sstevel@tonic-gate crle->c_filenum++;
2460Sstevel@tonic-gate
2470Sstevel@tonic-gate /*
2480Sstevel@tonic-gate * Provide any diagnostics.
2490Sstevel@tonic-gate */
2500Sstevel@tonic-gate if (crle->c_flags & CRLE_VERBOSE) {
2510Sstevel@tonic-gate const char *fmt;
2520Sstevel@tonic-gate
2530Sstevel@tonic-gate if (obj->o_flags & RTC_OBJ_NOEXIST)
2540Sstevel@tonic-gate fmt = MSG_INTL(MSG_DIA_NOEXIST);
2550Sstevel@tonic-gate else
2560Sstevel@tonic-gate fmt = MSG_INTL(MSG_DIA_DIR);
2570Sstevel@tonic-gate
2580Sstevel@tonic-gate (void) printf(fmt, ent->e_id, dir);
2590Sstevel@tonic-gate }
2600Sstevel@tonic-gate return (1);
2610Sstevel@tonic-gate }
2620Sstevel@tonic-gate
2630Sstevel@tonic-gate /*
2640Sstevel@tonic-gate * Establish a string hash entry for a directory.
2650Sstevel@tonic-gate */
2660Sstevel@tonic-gate static Hash_ent *
enterdir(Crle_desc * crle,const char * odir,Half flags,struct stat * status)267*9131SRod.Evans@Sun.COM enterdir(Crle_desc *crle, const char *odir, Half flags, struct stat *status)
2680Sstevel@tonic-gate {
269*9131SRod.Evans@Sun.COM Hash_tbl *stbl = crle->c_strtbl;
270*9131SRod.Evans@Sun.COM Hash_ent *ent;
271*9131SRod.Evans@Sun.COM Hash_obj *obj;
272*9131SRod.Evans@Sun.COM char rdir[PATH_MAX], *ndir;
2730Sstevel@tonic-gate
2740Sstevel@tonic-gate /*
2750Sstevel@tonic-gate * Establish the directories real name, this is the name that will be
2760Sstevel@tonic-gate * recorded in the object identifier.
2770Sstevel@tonic-gate */
278*9131SRod.Evans@Sun.COM if (realpath(odir, rdir) == NULL)
279*9131SRod.Evans@Sun.COM return (NULL);
2800Sstevel@tonic-gate
2810Sstevel@tonic-gate if (strcmp(odir, rdir))
2820Sstevel@tonic-gate ndir = rdir;
2830Sstevel@tonic-gate else
2840Sstevel@tonic-gate ndir = (char *)odir;
2850Sstevel@tonic-gate
2860Sstevel@tonic-gate /*
2870Sstevel@tonic-gate * If we're not dealing with an all-entries directory (i.e., we're
2880Sstevel@tonic-gate * recording this directory because of its explicitly specified
2890Sstevel@tonic-gate * filename) leave off any filename specific attributes.
2900Sstevel@tonic-gate */
2910Sstevel@tonic-gate if ((flags & RTC_OBJ_ALLENTS) == 0)
2920Sstevel@tonic-gate flags &= ~(RTC_OBJ_ALTER | RTC_OBJ_DUMP | RTC_OBJ_GROUP);
2930Sstevel@tonic-gate flags |= RTC_OBJ_DIRENT;
2940Sstevel@tonic-gate
2950Sstevel@tonic-gate /*
2960Sstevel@tonic-gate * Establish a inode table entry, and the objects unique descriptor.
2970Sstevel@tonic-gate */
298*9131SRod.Evans@Sun.COM if ((ent = enterino(crle, ndir, status, flags)) == NULL)
299*9131SRod.Evans@Sun.COM return (NULL);
3000Sstevel@tonic-gate obj = ent->e_obj;
3010Sstevel@tonic-gate
3020Sstevel@tonic-gate /*
3030Sstevel@tonic-gate * Create a string table entry for the real directory.
3040Sstevel@tonic-gate */
3050Sstevel@tonic-gate if ((ent = get_hash(stbl, (Addr)ndir, 0,
306*9131SRod.Evans@Sun.COM (HASH_FND_ENT | HASH_ADD_ENT))) == NULL)
307*9131SRod.Evans@Sun.COM return (NULL);
3080Sstevel@tonic-gate
3090Sstevel@tonic-gate /*
3100Sstevel@tonic-gate * If this is a new entry reassign the directory name and assign a
3110Sstevel@tonic-gate * unique directory id.
3120Sstevel@tonic-gate */
3130Sstevel@tonic-gate if (ent->e_id == 0) {
3140Sstevel@tonic-gate if (_enterdir(crle, ndir, ent, obj) == 0)
315*9131SRod.Evans@Sun.COM return (NULL);
3160Sstevel@tonic-gate }
3170Sstevel@tonic-gate
3180Sstevel@tonic-gate /*
3190Sstevel@tonic-gate * If the directory name supplied is different than the real name we've
3200Sstevel@tonic-gate * just entered, continue to create an entry for it.
3210Sstevel@tonic-gate */
3220Sstevel@tonic-gate if (ndir == odir)
3230Sstevel@tonic-gate return (ent);
3240Sstevel@tonic-gate
3250Sstevel@tonic-gate /*
3260Sstevel@tonic-gate * Create a string table entry for this real directory.
3270Sstevel@tonic-gate */
3280Sstevel@tonic-gate if ((ent = get_hash(stbl, (Addr)odir, 0,
329*9131SRod.Evans@Sun.COM (HASH_FND_ENT | HASH_ADD_ENT))) == NULL)
330*9131SRod.Evans@Sun.COM return (NULL);
3310Sstevel@tonic-gate
3320Sstevel@tonic-gate /*
3330Sstevel@tonic-gate * If this is a new entry reassign the directory name and assign a
3340Sstevel@tonic-gate * unique directory id.
3350Sstevel@tonic-gate */
3360Sstevel@tonic-gate if (ent->e_id == 0) {
3370Sstevel@tonic-gate if (_enterdir(crle, odir, ent, obj) == 0)
338*9131SRod.Evans@Sun.COM return (NULL);
3390Sstevel@tonic-gate }
3400Sstevel@tonic-gate
3410Sstevel@tonic-gate return (ent);
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 *
enternoexistdir(Crle_desc * crle,const char * dir)349*9131SRod.Evans@Sun.COM enternoexistdir(Crle_desc *crle, const char *dir)
3500Sstevel@tonic-gate {
351*9131SRod.Evans@Sun.COM 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,
357*9131SRod.Evans@Sun.COM (HASH_FND_ENT | HASH_ADD_ENT))) == NULL)
358*9131SRod.Evans@Sun.COM return (NULL);
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
367*9131SRod.Evans@Sun.COM if ((obj = calloc(sizeof (Hash_obj), 1)) == NULL)
368*9131SRod.Evans@Sun.COM return (NULL);
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)
372*9131SRod.Evans@Sun.COM return (NULL);
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
_enterfile(Crle_desc * crle,const char * file,int off,Hash_ent * fent,Hash_ent * rent,Hash_ent * dent,Hash_obj * obj)383*9131SRod.Evans@Sun.COM _enterfile(Crle_desc *crle, const char *file, int off, Hash_ent *fent,
384*9131SRod.Evans@Sun.COM 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) {
397*9131SRod.Evans@Sun.COM if ((nfile = malloc(size)) == NULL)
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 *
enternoexistfile(Crle_desc * crle,const char * path,const char * file,Hash_ent * dent)446*9131SRod.Evans@Sun.COM enternoexistfile(Crle_desc *crle, const char *path, const char *file,
447*9131SRod.Evans@Sun.COM Hash_ent *dent)
4480Sstevel@tonic-gate {
449*9131SRod.Evans@Sun.COM Hash_ent *rent, *ent;
450*9131SRod.Evans@Sun.COM 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,
457*9131SRod.Evans@Sun.COM (HASH_FND_ENT | HASH_ADD_ENT))) == NULL)
458*9131SRod.Evans@Sun.COM return (NULL);
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) {
465*9131SRod.Evans@Sun.COM if ((obj = calloc(sizeof (Hash_obj), 1)) == NULL)
466*9131SRod.Evans@Sun.COM return (NULL);
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)
470*9131SRod.Evans@Sun.COM return (NULL);
4710Sstevel@tonic-gate }
4720Sstevel@tonic-gate obj = rent->e_obj;
473*9131SRod.Evans@Sun.COM if ((obj->o_path = strdup(path)) == NULL)
474*9131SRod.Evans@Sun.COM return (NULL);
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,
488*9131SRod.Evans@Sun.COM (HASH_FND_ENT | HASH_ADD_ENT))) == NULL)
489*9131SRod.Evans@Sun.COM return (NULL);
4900Sstevel@tonic-gate
4910Sstevel@tonic-gate if (ent->e_id == 0) {
4920Sstevel@tonic-gate if (_enterfile(crle, file, off, ent, rent, dent, obj) == 0)
493*9131SRod.Evans@Sun.COM return (NULL);
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 *
enterfile(Crle_desc * crle,const char * opath,const char * ofile,Half flags,Hash_ent * odent,struct stat * status)503*9131SRod.Evans@Sun.COM enterfile(Crle_desc *crle, const char *opath, const char *ofile, Half flags,
504*9131SRod.Evans@Sun.COM Hash_ent *odent, struct stat *status)
5050Sstevel@tonic-gate {
506*9131SRod.Evans@Sun.COM Hash_tbl *stbl = crle->c_strtbl;
507*9131SRod.Evans@Sun.COM Hash_ent *ent, *rent, *ndent = odent;
508*9131SRod.Evans@Sun.COM Hash_obj *obj;
5090Sstevel@tonic-gate size_t size;
510*9131SRod.Evans@Sun.COM 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 */
517*9131SRod.Evans@Sun.COM if (realpath(opath, rpath) == NULL)
518*9131SRod.Evans@Sun.COM return (NULL);
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,
541*9131SRod.Evans@Sun.COM &_status)) == NULL)
542*9131SRod.Evans@Sun.COM return (NULL);
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 */
552*9131SRod.Evans@Sun.COM if ((ent = enterino(crle, npath, status, flags)) == NULL)
553*9131SRod.Evans@Sun.COM return (NULL);
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,
560*9131SRod.Evans@Sun.COM (HASH_FND_ENT | HASH_ADD_ENT))) == NULL)
561*9131SRod.Evans@Sun.COM return (NULL);
5620Sstevel@tonic-gate if (rent->e_id == 0) {
5630Sstevel@tonic-gate if (_enterfile(crle, npath, 0, rent, 0, ndent, obj) == 0)
564*9131SRod.Evans@Sun.COM return (NULL);
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,
589*9131SRod.Evans@Sun.COM (HASH_FND_ENT | HASH_ADD_ENT))) == NULL)
590*9131SRod.Evans@Sun.COM return (NULL);
5910Sstevel@tonic-gate if (ent->e_id == 0) {
5920Sstevel@tonic-gate if (_enterfile(crle, nfile, off, ent, rent, ndent, obj) == 0)
593*9131SRod.Evans@Sun.COM return (NULL);
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 */
607*9131SRod.Evans@Sun.COM if ((ent = enterino(crle, opath, status, 0)) == NULL)
608*9131SRod.Evans@Sun.COM return (NULL);
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,
615*9131SRod.Evans@Sun.COM (HASH_FND_ENT | HASH_ADD_ENT))) == NULL)
616*9131SRod.Evans@Sun.COM return (NULL);
6170Sstevel@tonic-gate if (rent->e_id == 0) {
6180Sstevel@tonic-gate if (_enterfile(crle, opath, 0, rent, 0, odent, obj) == 0)
619*9131SRod.Evans@Sun.COM return (NULL);
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,
634*9131SRod.Evans@Sun.COM (HASH_FND_ENT | HASH_ADD_ENT))) == NULL)
635*9131SRod.Evans@Sun.COM return (NULL);
6360Sstevel@tonic-gate if (ent->e_id == 0) {
6370Sstevel@tonic-gate if (_enterfile(crle, ofile, off, ent, rent, odent, obj) == 0)
638*9131SRod.Evans@Sun.COM return (NULL);
6390Sstevel@tonic-gate }
6400Sstevel@tonic-gate
6410Sstevel@tonic-gate return (ent);
6420Sstevel@tonic-gate }
6430Sstevel@tonic-gate
6440Sstevel@tonic-gate /*
6450Sstevel@tonic-gate * Add a file to configuration information.
6460Sstevel@tonic-gate */
6470Sstevel@tonic-gate static int
inspect_file(Crle_desc * crle,const char * path,const char * file,Half flags,Hash_ent * dent,struct stat * status,int error)648*9131SRod.Evans@Sun.COM inspect_file(Crle_desc *crle, const char *path, const char *file, Half flags,
649*9131SRod.Evans@Sun.COM Hash_ent *dent, struct stat *status, int error)
6500Sstevel@tonic-gate {
651*9131SRod.Evans@Sun.COM Hash_ent *ent;
652*9131SRod.Evans@Sun.COM Hash_obj *obj;
6530Sstevel@tonic-gate int fd;
654*9131SRod.Evans@Sun.COM Elf *elf;
6550Sstevel@tonic-gate GElf_Ehdr ehdr;
6561698Sab196087 GElf_Xword dyflags = 0;
657*9131SRod.Evans@Sun.COM Aliste idx;
658*9131SRod.Evans@Sun.COM Hash_tbl *tbl;
6590Sstevel@tonic-gate Addr ino = (Addr)status->st_ino;
6600Sstevel@tonic-gate
6610Sstevel@tonic-gate /*
6620Sstevel@tonic-gate * Determine whether this file (inode) has already been processed.
6630Sstevel@tonic-gate */
664*9131SRod.Evans@Sun.COM for (APLIST_TRAVERSE(crle->c_inotbls, idx, tbl)) {
6650Sstevel@tonic-gate if (tbl->t_ident != status->st_dev)
6660Sstevel@tonic-gate continue;
6670Sstevel@tonic-gate
668*9131SRod.Evans@Sun.COM if ((ent = get_hash(tbl, ino, 0, HASH_FND_ENT)) == NULL)
6690Sstevel@tonic-gate break;
6700Sstevel@tonic-gate
6710Sstevel@tonic-gate /*
6720Sstevel@tonic-gate * This files inode object does exist, make sure it has a file
6730Sstevel@tonic-gate * entry for this directory.
6740Sstevel@tonic-gate */
6750Sstevel@tonic-gate if ((ent = enterfile(crle, path, file, flags, dent,
676*9131SRod.Evans@Sun.COM status)) == NULL)
6770Sstevel@tonic-gate return (error);
6780Sstevel@tonic-gate obj = ent->e_obj;
6790Sstevel@tonic-gate
6800Sstevel@tonic-gate /*
6810Sstevel@tonic-gate * If an alternative has been asked for, and one has not yet
6820Sstevel@tonic-gate * been established, create one.
6830Sstevel@tonic-gate */
6840Sstevel@tonic-gate if ((flags & RTC_OBJ_ALTER) &&
6850Sstevel@tonic-gate ((obj->o_flags & RTC_OBJ_NOALTER) == 0)) {
6860Sstevel@tonic-gate if (enteralt(crle, path, file, flags, obj) == 0)
6870Sstevel@tonic-gate return (error);
6880Sstevel@tonic-gate }
6890Sstevel@tonic-gate return (0);
6900Sstevel@tonic-gate }
6910Sstevel@tonic-gate
6920Sstevel@tonic-gate /*
6930Sstevel@tonic-gate * This is a new file, determine if it's a valid ELF file.
6940Sstevel@tonic-gate */
6950Sstevel@tonic-gate if ((fd = open(path, O_RDONLY, 0)) == -1) {
6960Sstevel@tonic-gate if (error) {
6970Sstevel@tonic-gate int err = errno;
6980Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_OPEN),
6990Sstevel@tonic-gate crle->c_name, path, strerror(err));
7000Sstevel@tonic-gate }
7010Sstevel@tonic-gate return (error);
7020Sstevel@tonic-gate }
7030Sstevel@tonic-gate
7040Sstevel@tonic-gate /*
7050Sstevel@tonic-gate * Obtain an ELF descriptor and determine if we have a shared object.
7060Sstevel@tonic-gate */
7070Sstevel@tonic-gate if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
7080Sstevel@tonic-gate if (error)
7090Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ELF_BEGIN),
7100Sstevel@tonic-gate crle->c_name, path, elf_errmsg(-1));
7110Sstevel@tonic-gate (void) close(fd);
7120Sstevel@tonic-gate return (error);
7130Sstevel@tonic-gate }
7140Sstevel@tonic-gate if ((elf_kind(elf) != ELF_K_ELF) ||
7150Sstevel@tonic-gate (gelf_getehdr(elf, &ehdr) == NULL) ||
7160Sstevel@tonic-gate (!((ehdr.e_type == ET_EXEC) || (ehdr.e_type == ET_DYN))) ||
7171976Sab196087 (!((ehdr.e_ident[EI_CLASS] == M_CLASS) ||
7181976Sab196087 (ehdr.e_machine == M_MACH)))) {
7190Sstevel@tonic-gate if (error)
7200Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ELF_TYPE),
7210Sstevel@tonic-gate crle->c_name, path);
7220Sstevel@tonic-gate (void) close(fd);
7230Sstevel@tonic-gate (void) elf_end(elf);
7240Sstevel@tonic-gate return (error);
7250Sstevel@tonic-gate }
7260Sstevel@tonic-gate
7270Sstevel@tonic-gate (void) close(fd);
7280Sstevel@tonic-gate
7290Sstevel@tonic-gate /*
7300Sstevel@tonic-gate * If we're generating alternative objects find this objects DT_FLAGS
7310Sstevel@tonic-gate * to insure it isn't marked as non-dumpable (libdl.so.1 falls into
7320Sstevel@tonic-gate * this category).
7330Sstevel@tonic-gate */
7341698Sab196087 if (flags & RTC_OBJ_DUMP)
7351698Sab196087 dyflags = _gelf_getdyndtflags_1(elf);
7360Sstevel@tonic-gate
7370Sstevel@tonic-gate /*
7380Sstevel@tonic-gate * Dynamic executables can be examined to determine their dependencies,
7390Sstevel@tonic-gate * dldump(3dl) their dependencies, and may even be dldump(3dl)'ed
7400Sstevel@tonic-gate * themselves.
7410Sstevel@tonic-gate *
7420Sstevel@tonic-gate * If we come across an executable while searching a directory
7430Sstevel@tonic-gate * (error == 0) it is ignored.
7440Sstevel@tonic-gate */
7450Sstevel@tonic-gate if (ehdr.e_type == ET_EXEC) {
7460Sstevel@tonic-gate if (error == 0) {
7470Sstevel@tonic-gate (void) elf_end(elf);
7480Sstevel@tonic-gate return (0);
7490Sstevel@tonic-gate }
7500Sstevel@tonic-gate
7510Sstevel@tonic-gate /*
7520Sstevel@tonic-gate * If we're not dumping the application itself, or we've not
7530Sstevel@tonic-gate * asked to gather its dependencies then its rather useless.
7540Sstevel@tonic-gate */
7550Sstevel@tonic-gate if ((flags & (RTC_OBJ_GROUP | RTC_OBJ_DUMP)) == 0) {
7560Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_GEN_INVFILE),
7570Sstevel@tonic-gate crle->c_name, path);
7580Sstevel@tonic-gate (void) elf_end(elf);
7590Sstevel@tonic-gate return (error);
7600Sstevel@tonic-gate }
7610Sstevel@tonic-gate
7620Sstevel@tonic-gate /*
7630Sstevel@tonic-gate * If we're dumping the application under RTLD_REL_EXEC then the
7640Sstevel@tonic-gate * configuration file becomes specific to this application, so
7650Sstevel@tonic-gate * make sure we haven't been here before.
7660Sstevel@tonic-gate */
7670Sstevel@tonic-gate if (crle->c_app && (flags & RTC_OBJ_DUMP) &&
7680Sstevel@tonic-gate (crle->c_dlflags & RTLD_REL_EXEC)) {
7690Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_ARG_MODE),
7700Sstevel@tonic-gate crle->c_name, crle->c_app, path);
7710Sstevel@tonic-gate (void) elf_end(elf);
7720Sstevel@tonic-gate return (error);
7730Sstevel@tonic-gate }
7740Sstevel@tonic-gate }
7750Sstevel@tonic-gate
7760Sstevel@tonic-gate /*
7770Sstevel@tonic-gate * Enter the file in the string hash table.
7780Sstevel@tonic-gate */
779*9131SRod.Evans@Sun.COM if ((ent = enterfile(crle, path, file, flags, dent, status)) == NULL) {
7800Sstevel@tonic-gate (void) elf_end(elf);
7810Sstevel@tonic-gate return (error);
7820Sstevel@tonic-gate }
7830Sstevel@tonic-gate obj = ent->e_obj;
7840Sstevel@tonic-gate
7850Sstevel@tonic-gate if (flags & RTC_OBJ_ALTER) {
7860Sstevel@tonic-gate /*
7870Sstevel@tonic-gate * If this object is marked as non-dumpable make sure we don't
7880Sstevel@tonic-gate * create a dldump(3dl) alternative. A user requested
7890Sstevel@tonic-gate * alternative is acceptable.
7900Sstevel@tonic-gate */
7910Sstevel@tonic-gate if ((flags & RTC_OBJ_DUMP) && (dyflags & DF_1_NODUMP)) {
7920Sstevel@tonic-gate obj->o_flags |= RTC_OBJ_NOALTER;
7930Sstevel@tonic-gate obj->o_flags &= ~(RTC_OBJ_ALTER | RTC_OBJ_DUMP);
7940Sstevel@tonic-gate } else {
7950Sstevel@tonic-gate if (enteralt(crle, path, file, flags, obj) == 0) {
7960Sstevel@tonic-gate (void) elf_end(elf);
7970Sstevel@tonic-gate return (error);
7980Sstevel@tonic-gate }
7990Sstevel@tonic-gate }
8000Sstevel@tonic-gate }
8010Sstevel@tonic-gate
8020Sstevel@tonic-gate /*
8030Sstevel@tonic-gate * Executables are recorded in the configuration file either to allow
8040Sstevel@tonic-gate * for the configuration files update, or may indicate that the
8050Sstevel@tonic-gate * configuration file is specific to their use.
8060Sstevel@tonic-gate */
8070Sstevel@tonic-gate if (ehdr.e_type == ET_EXEC) {
8080Sstevel@tonic-gate obj->o_flags |= RTC_OBJ_EXEC;
8090Sstevel@tonic-gate
8100Sstevel@tonic-gate if ((flags & RTC_OBJ_DUMP) &&
8110Sstevel@tonic-gate (crle->c_dlflags & RTLD_REL_EXEC)) {
8120Sstevel@tonic-gate /*
8130Sstevel@tonic-gate * Get the reallocated pathname rather than using the
8140Sstevel@tonic-gate * original (the original might be from an existing
8150Sstevel@tonic-gate * configuration file being updated, in which case the
8160Sstevel@tonic-gate * pointer will be unmapped before we get to use it).
8170Sstevel@tonic-gate */
8180Sstevel@tonic-gate ent = get_hash(crle->c_strtbl, (Addr)path, 0,
8190Sstevel@tonic-gate HASH_FND_ENT);
8200Sstevel@tonic-gate
8210Sstevel@tonic-gate obj->o_flags |= RTC_OBJ_APP;
8220Sstevel@tonic-gate crle->c_app = (char *)ent->e_key;
8230Sstevel@tonic-gate }
8240Sstevel@tonic-gate }
8250Sstevel@tonic-gate
8260Sstevel@tonic-gate /*
8270Sstevel@tonic-gate * If we've been asked to process this object as a group determine its
8280Sstevel@tonic-gate * dependencies.
8290Sstevel@tonic-gate */
8300Sstevel@tonic-gate if (flags & RTC_OBJ_GROUP) {
8310Sstevel@tonic-gate if (depend(crle, path, flags, &ehdr)) {
8320Sstevel@tonic-gate (void) elf_end(elf);
8330Sstevel@tonic-gate return (error);
8340Sstevel@tonic-gate }
8350Sstevel@tonic-gate }
8360Sstevel@tonic-gate
8370Sstevel@tonic-gate (void) elf_end(elf);
8380Sstevel@tonic-gate return (0);
8390Sstevel@tonic-gate }
8400Sstevel@tonic-gate
8410Sstevel@tonic-gate /*
8420Sstevel@tonic-gate * Add a directory to configuration information.
8430Sstevel@tonic-gate */
8440Sstevel@tonic-gate static int
inspect_dir(Crle_desc * crle,const char * name,Half flags,struct stat * status)845*9131SRod.Evans@Sun.COM inspect_dir(Crle_desc *crle, const char *name, Half flags, struct stat *status)
8460Sstevel@tonic-gate {
847*9131SRod.Evans@Sun.COM Hash_tbl *stbl = crle->c_strtbl;
848*9131SRod.Evans@Sun.COM DIR *dir;
8490Sstevel@tonic-gate struct dirent *dirent;
850*9131SRod.Evans@Sun.COM Hash_ent *ent;
8510Sstevel@tonic-gate int error = 0;
8520Sstevel@tonic-gate struct stat _status;
8530Sstevel@tonic-gate char path[PATH_MAX], * dst;
8540Sstevel@tonic-gate const char *src;
8550Sstevel@tonic-gate
8560Sstevel@tonic-gate /*
8570Sstevel@tonic-gate * Determine whether we've already visited this directory to process
8580Sstevel@tonic-gate * all its entries.
8590Sstevel@tonic-gate */
860*9131SRod.Evans@Sun.COM if ((ent = get_hash(stbl, (Addr)name, 0, HASH_FND_ENT)) != NULL) {
8610Sstevel@tonic-gate if (ent->e_obj->o_flags & RTC_OBJ_ALLENTS)
8620Sstevel@tonic-gate return (0);
8630Sstevel@tonic-gate } else {
8640Sstevel@tonic-gate /*
8650Sstevel@tonic-gate * Create a directory hash entry.
8660Sstevel@tonic-gate */
8670Sstevel@tonic-gate if ((ent = enterdir(crle, name, (flags | RTC_OBJ_ALLENTS),
868*9131SRod.Evans@Sun.COM status)) == NULL)
8690Sstevel@tonic-gate return (1);
8700Sstevel@tonic-gate }
8710Sstevel@tonic-gate ent->e_obj->o_flags |= RTC_OBJ_ALLENTS;
8720Sstevel@tonic-gate
8730Sstevel@tonic-gate /*
8740Sstevel@tonic-gate * Establish the pathname buffer.
8750Sstevel@tonic-gate */
8760Sstevel@tonic-gate for (dst = path, dst--, src = name; *src; src++)
8770Sstevel@tonic-gate *++dst = *src;
8780Sstevel@tonic-gate if (*dst++ != '/')
8790Sstevel@tonic-gate *dst++ = '/';
8800Sstevel@tonic-gate
8810Sstevel@tonic-gate /*
8820Sstevel@tonic-gate * Access the directory in preparation for reading its entries.
8830Sstevel@tonic-gate */
884*9131SRod.Evans@Sun.COM if ((dir = opendir(name)) == NULL)
8850Sstevel@tonic-gate return (1);
8860Sstevel@tonic-gate
8870Sstevel@tonic-gate /*
8880Sstevel@tonic-gate * Read each entry from the directory looking for ELF files.
8890Sstevel@tonic-gate */
8900Sstevel@tonic-gate while ((dirent = readdir(dir)) != NULL) {
8910Sstevel@tonic-gate const char *file = dirent->d_name;
8920Sstevel@tonic-gate char *_dst;
8930Sstevel@tonic-gate
8940Sstevel@tonic-gate /*
8950Sstevel@tonic-gate * Ignore "." and ".." entries.
8960Sstevel@tonic-gate */
8970Sstevel@tonic-gate if ((file[0] == '.') && ((file[1] == '\0') ||
8980Sstevel@tonic-gate ((file[1] == '.') && (file[2] == '\0'))))
8990Sstevel@tonic-gate continue;
9000Sstevel@tonic-gate
9010Sstevel@tonic-gate /*
9020Sstevel@tonic-gate * Complete full pathname, and reassign file to the new path.
9030Sstevel@tonic-gate */
9040Sstevel@tonic-gate for (_dst = dst, src = file, file = dst; *src; _dst++, src++)
9050Sstevel@tonic-gate *_dst = *src;
9060Sstevel@tonic-gate *_dst = '\0';
9070Sstevel@tonic-gate
9080Sstevel@tonic-gate if (stat(path, &_status) == -1)
9090Sstevel@tonic-gate continue;
9100Sstevel@tonic-gate
9110Sstevel@tonic-gate if ((_status.st_mode & S_IFMT) != S_IFREG)
9120Sstevel@tonic-gate continue;
9130Sstevel@tonic-gate
9140Sstevel@tonic-gate if (inspect_file(crle, path, file, flags, ent, &_status, 0)) {
9150Sstevel@tonic-gate error = 1;
9160Sstevel@tonic-gate break;
9170Sstevel@tonic-gate }
9180Sstevel@tonic-gate }
9190Sstevel@tonic-gate return (error);
9200Sstevel@tonic-gate }
9210Sstevel@tonic-gate
9220Sstevel@tonic-gate /*
9230Sstevel@tonic-gate * Inspect a file/dir name. A stat(name) results in the following actions:
9240Sstevel@tonic-gate *
9250Sstevel@tonic-gate * The name doesn't exist:
9260Sstevel@tonic-gate * The name is assummed to be a non-existent directory and a directory
9270Sstevel@tonic-gate * cache entry is created to indicate this.
9280Sstevel@tonic-gate *
9290Sstevel@tonic-gate * The name is a directory:
9300Sstevel@tonic-gate * The directory is searched for appropriate files.
9310Sstevel@tonic-gate *
9320Sstevel@tonic-gate * The name is a file:
9330Sstevel@tonic-gate * The file is processed and added to the cache if appropriate.
9340Sstevel@tonic-gate */
9350Sstevel@tonic-gate int
inspect(Crle_desc * crle,const char * name,Half flags)936*9131SRod.Evans@Sun.COM inspect(Crle_desc *crle, const char *name, Half flags)
9370Sstevel@tonic-gate {
938*9131SRod.Evans@Sun.COM Hash_ent *ent;
939*9131SRod.Evans@Sun.COM const char *file, *dir;
9400Sstevel@tonic-gate struct stat status;
9410Sstevel@tonic-gate char _name[PATH_MAX], _dir[PATH_MAX];
9420Sstevel@tonic-gate Half nflags = flags & ~RTC_OBJ_CMDLINE;
9430Sstevel@tonic-gate int noexist;
9440Sstevel@tonic-gate
9450Sstevel@tonic-gate /*
9460Sstevel@tonic-gate * If this is the first time through here establish a string table
9470Sstevel@tonic-gate * cache.
9480Sstevel@tonic-gate */
9490Sstevel@tonic-gate if (crle->c_dirnum == 0) {
9500Sstevel@tonic-gate if ((crle->c_strtbl = make_hash(crle->c_strbkts,
951*9131SRod.Evans@Sun.COM HASH_STR, 0)) == NULL)
9520Sstevel@tonic-gate return (1);
9530Sstevel@tonic-gate crle->c_dirnum = 1;
9540Sstevel@tonic-gate }
9550Sstevel@tonic-gate
9560Sstevel@tonic-gate if (crle->c_flags & CRLE_VERBOSE)
9570Sstevel@tonic-gate (void) printf(MSG_INTL(MSG_DIA_INSPECT), name);
9580Sstevel@tonic-gate
9590Sstevel@tonic-gate /*
9600Sstevel@tonic-gate * Determine whether the name exists.
9610Sstevel@tonic-gate */
9620Sstevel@tonic-gate if ((noexist = stat(name, &status)) != 0) {
9630Sstevel@tonic-gate if (errno != ENOENT) {
9640Sstevel@tonic-gate int err = errno;
9650Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_STAT),
9660Sstevel@tonic-gate crle->c_name, name, strerror(err));
9670Sstevel@tonic-gate return (1);
9680Sstevel@tonic-gate } else {
9690Sstevel@tonic-gate /*
9700Sstevel@tonic-gate * If we've been asked to create an alternative object
9710Sstevel@tonic-gate * assume the object is a file and create a valid
9720Sstevel@tonic-gate * alternative entry. This allows the creation of
9730Sstevel@tonic-gate * alternatives for files that might not yet be
9740Sstevel@tonic-gate * installed.
9750Sstevel@tonic-gate *
9760Sstevel@tonic-gate * Otherwise we have no idea whether the name specified
9770Sstevel@tonic-gate * is a file or directory, so we assume a directory and
9780Sstevel@tonic-gate * establish an object descriptor to mark this as
9790Sstevel@tonic-gate * non-existent. This allows us to mark things like
9800Sstevel@tonic-gate * platform specific directories as non-existent.
9810Sstevel@tonic-gate */
9820Sstevel@tonic-gate if ((flags & (RTC_OBJ_DUMP | RTC_OBJ_ALTER)) !=
9830Sstevel@tonic-gate RTC_OBJ_ALTER) {
984*9131SRod.Evans@Sun.COM if ((ent = enternoexistdir(crle, name)) == NULL)
9850Sstevel@tonic-gate return (1);
9860Sstevel@tonic-gate ent->e_flags |= flags;
9870Sstevel@tonic-gate return (0);
9880Sstevel@tonic-gate }
9890Sstevel@tonic-gate }
9900Sstevel@tonic-gate }
9910Sstevel@tonic-gate
9920Sstevel@tonic-gate /*
9930Sstevel@tonic-gate * Determine whether we're dealing with a directory or a file.
9940Sstevel@tonic-gate */
9950Sstevel@tonic-gate if ((noexist == 0) && ((status.st_mode & S_IFMT) == S_IFDIR)) {
9960Sstevel@tonic-gate /*
9970Sstevel@tonic-gate * Process the directory name to collect its shared objects into
9980Sstevel@tonic-gate * the configuration file.
9990Sstevel@tonic-gate */
10000Sstevel@tonic-gate if (inspect_dir(crle, name, nflags, &status))
10010Sstevel@tonic-gate return (1);
10020Sstevel@tonic-gate
10030Sstevel@tonic-gate ent = get_hash(crle->c_strtbl, (Addr)name, 0, HASH_FND_ENT);
10040Sstevel@tonic-gate ent->e_flags |= flags;
10050Sstevel@tonic-gate return (0);
10060Sstevel@tonic-gate }
10070Sstevel@tonic-gate
10080Sstevel@tonic-gate /*
10090Sstevel@tonic-gate * If this isn't a regular file we might as well bail now. Note that
10100Sstevel@tonic-gate * even if it is, we might still reject the file if it's not ELF later
10110Sstevel@tonic-gate * in inspect_file().
10120Sstevel@tonic-gate */
10130Sstevel@tonic-gate if ((noexist == 0) && ((status.st_mode & S_IFMT) != S_IFREG)) {
10140Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_GEN_INVFILE), crle->c_name,
10150Sstevel@tonic-gate name);
10160Sstevel@tonic-gate return (1);
10170Sstevel@tonic-gate }
10180Sstevel@tonic-gate
10190Sstevel@tonic-gate /*
10200Sstevel@tonic-gate * Break the pathname into directory and filename components.
10210Sstevel@tonic-gate */
1022*9131SRod.Evans@Sun.COM if ((file = strrchr(name, '/')) == NULL) {
10230Sstevel@tonic-gate dir = MSG_ORIG(MSG_DIR_DOT);
10240Sstevel@tonic-gate (void) strcpy(_name, MSG_ORIG(MSG_PTH_DOT));
10250Sstevel@tonic-gate (void) strcpy(&_name[MSG_PTH_DOT_SIZE], name);
10260Sstevel@tonic-gate name = (const char *)_name;
10270Sstevel@tonic-gate file = (const char *)&_name[MSG_PTH_DOT_SIZE];
10280Sstevel@tonic-gate } else {
10290Sstevel@tonic-gate size_t off = file - name;
10300Sstevel@tonic-gate
10310Sstevel@tonic-gate if (file == name)
10320Sstevel@tonic-gate dir = MSG_ORIG(MSG_DIR_ROOT);
10330Sstevel@tonic-gate else {
10340Sstevel@tonic-gate (void) strncpy(_dir, name, off);
10350Sstevel@tonic-gate _dir[off] = '\0';
10360Sstevel@tonic-gate dir = (const char *)_dir;
10370Sstevel@tonic-gate }
10380Sstevel@tonic-gate file++;
10390Sstevel@tonic-gate }
10400Sstevel@tonic-gate
10410Sstevel@tonic-gate /*
10420Sstevel@tonic-gate * Determine whether we've already visited this directory and if not
10430Sstevel@tonic-gate * create it.
10440Sstevel@tonic-gate */
1045*9131SRod.Evans@Sun.COM if ((ent = get_hash(crle->c_strtbl,
1046*9131SRod.Evans@Sun.COM (Addr)dir, 0, HASH_FND_ENT)) == NULL) {
10470Sstevel@tonic-gate struct stat _status;
10480Sstevel@tonic-gate
10490Sstevel@tonic-gate if (stat(dir, &_status) != 0) {
10500Sstevel@tonic-gate if (errno != ENOENT) {
10510Sstevel@tonic-gate int err = errno;
10520Sstevel@tonic-gate (void) fprintf(stderr, MSG_INTL(MSG_SYS_STAT),
10530Sstevel@tonic-gate crle->c_name, name, strerror(err));
10540Sstevel@tonic-gate return (1);
10550Sstevel@tonic-gate } else {
10560Sstevel@tonic-gate /*
10570Sstevel@tonic-gate * Note that this directory will be tagged as
10580Sstevel@tonic-gate * having an alternative - not that the
10590Sstevel@tonic-gate * directory does, but supposedly it contains
10600Sstevel@tonic-gate * a file that does.
10610Sstevel@tonic-gate */
1062*9131SRod.Evans@Sun.COM if ((ent = enternoexistdir(crle, dir)) == NULL)
10630Sstevel@tonic-gate return (1);
10640Sstevel@tonic-gate ent->e_flags |= nflags;
10650Sstevel@tonic-gate }
10660Sstevel@tonic-gate } else {
1067*9131SRod.Evans@Sun.COM if ((ent = enterdir(crle, dir, nflags,
1068*9131SRod.Evans@Sun.COM &_status)) == NULL)
10690Sstevel@tonic-gate return (1);
10700Sstevel@tonic-gate }
10710Sstevel@tonic-gate }
10720Sstevel@tonic-gate
10730Sstevel@tonic-gate /*
10740Sstevel@tonic-gate * Regardless of whether we've already processed this file (say from
10750Sstevel@tonic-gate * an RTC_OBJ_ALLENTS which we could determine from the above), continue
10760Sstevel@tonic-gate * to inspect the file. It may require alternatives or something that
10770Sstevel@tonic-gate * hadn't be specified from the directory entry.
10780Sstevel@tonic-gate */
10790Sstevel@tonic-gate if (noexist) {
1080*9131SRod.Evans@Sun.COM if ((ent = enternoexistfile(crle, name, file, ent)) == NULL)
10810Sstevel@tonic-gate return (1);
10820Sstevel@tonic-gate ent->e_flags |= nflags;
10830Sstevel@tonic-gate if (enteralt(crle, name, file, flags, ent->e_obj) == 0)
10840Sstevel@tonic-gate return (1);
10850Sstevel@tonic-gate } else {
10860Sstevel@tonic-gate if (inspect_file(crle, name, file, nflags, ent, &status, 1))
10870Sstevel@tonic-gate return (1);
10880Sstevel@tonic-gate }
10890Sstevel@tonic-gate
10900Sstevel@tonic-gate /*
10910Sstevel@tonic-gate * Make sure to propagate any RTC_OBJ_CMDLINE flag.
10920Sstevel@tonic-gate */
10930Sstevel@tonic-gate if (ent = get_hash(crle->c_strtbl, (Addr)name, 0, HASH_FND_ENT))
10940Sstevel@tonic-gate ent->e_flags |= (flags & RTC_OBJ_CMDLINE);
10950Sstevel@tonic-gate
10960Sstevel@tonic-gate return (0);
10970Sstevel@tonic-gate }
1098