4.4BSD/usr/src/contrib/sun.sharedlib/lang/rtld/ldconfig.c

Compare this file to the similar file:
Show the results in this format:

/*
 * This source code is a product of Sun Microsystems, Inc. and is provided
 * for unrestricted use provided that this legend is included on all tape
 * media and as a part of the software program in whole or part.  Users
 * may copy or modify this source code without charge, but are not authorized
 * to license or distribute it to anyone else except as part of a product or
 * program developed by the user.
 *
 * THIS PROGRAM CONTAINS SOURCE CODE COPYRIGHTED BY SUN MICROSYSTEMS, INC.
 * SUN MICROSYSTEMS, INC., MAKES NO REPRESENTATIONS ABOUT THE SUITABLITY
 * OF SUCH SOURCE CODE FOR ANY PURPOSE.  IT IS PROVIDED "AS IS" WITHOUT
 * EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  SUN MICROSYSTEMS, INC. DISCLAIMS
 * ALL WARRANTIES WITH REGARD TO SUCH SOURCE CODE, INCLUDING ALL IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  IN
 * NO EVENT SHALL SUN MICROSYSTEMS, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT,
 * INCIDENTAL, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
 * FROM USE OF SUCH SOURCE CODE, REGARDLESS OF THE THEORY OF LIABILITY.
 * 
 * This source code is provided with no support and without any obligation on
 * the part of Sun Microsystems, Inc. to assist in its use, correction, 
 * modification or enhancement.
 *
 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS
 * SOURCE CODE OR ANY PART THEREOF.
 *
 * Sun Microsystems, Inc.
 * 2550 Garcia Avenue
 * Mountain View, California 94043
 */

/* @(#)ldconfig.c 1.10 91/03/17 SMI */

/*
 * Copyright (c) 1991 by Sun Microsystems, Inc. */
 */

/*
 * ldconfig: build configuration information for ld.so.
 */

#include <stdio.h>			/* I/O */
#include <sys/mman.h>			/* memory management */
#include <sys/param.h>			/* general system definitions */
#include <sys/file.h>			/* file I/O bits */
#include <sys/exec.h>
#include <link.h>			/* link editor public */
#include "cache.h"			/* local caching information */

/*
 * Global storage and definitions.
 */
#define	MAX_DB	(1024 * 1024)		/* 1Mb database is the max */

int	fd;				/* descriptor on database */
caddr_t	db_base;			/* base address of last database */
caddr_t	heap_ptr;			/* current file allocation */
caddr_t heap_base;			/* base address of file mapping */
caddr_t heap_max;			/* maximum file to allocate */
void build_cache();			/* build a cache given directory */
int	first = 1;			/* true if no first entry yet */
struct	dbf *dbfp;			/* working cache file pointer */

/*
 * "Environmental" variables exported to the cache routines.
 */
extern	caddr_t malloc();		/* heap allocator */
caddr_t	mmap_alloc();			/* database allocator */
int	false();			/* says we're never secure */
int	use_cache = 0;			/* no previous database */

/*
 * List of directories which are always in the cache.  Note: these need
 * not be (nor are they) identical to the directories searched by default
 * by the loader.
 */
char *default_directories[] = {"/usr/lib", "/usr/5lib", 
	"/usr/lib/fsoft", "/usr/lib/f68881", "/usr/lib/ffpa",
	"/usr/lib/fswitch", 0};

/*
 * Build a database by building over all arguments.
 */
main(argc, argv)
	int argc;
	char *argv[];
{
	int i;				/* loop temporary */
	char *fnp;			/* temporary file name */
	char **cpp;			/* loop temporary */

	/*
	 * Initialize exported functions.
	 */
	db_malloc = mmap_alloc;
	heap_malloc = malloc;
	is_secure = false;

	/*
	 * Make a temporary file, map it in up to its maximum length.
	 */
	fnp = (char *)mktemp("/etc/ld.so.XXXXXX");
	if ((fd = open(fnp, O_CREAT|O_RDWR, 0644)) == -1) {
		perror("ldconfig: open temporary");
		exit(1);
	}
	if ((heap_base = mmap(0, MAX_DB, PROT_READ|PROT_WRITE, 
	    MAP_SHARED, fd, 0)) == (caddr_t)-1) {
		perror("ldconfig: mmap");
		exit(1);
	}
	db_base = heap_ptr = heap_max = heap_base;
	dbfp = (struct dbf *)(*db_malloc)(sizeof (struct dbf));
	dbfp->dbf_magic = LD_CACHE_MAGIC;
#if TARGET==SUN2
	dbfp->dbf_machtype = M_68010;
#endif
#if TARGET==SUN3
	dbfp->dbf_machtype = M_68020;
#endif
#if TARGET==SUN4
	dbfp->dbf_machtype = M_SPARC;
#endif
	dbfp->dbf_version = LD_CACHE_VERSION;

	/*
	 * For each argument, create a database.  
	 */
	for (i = 1; i < argc; i++) 
		build_cache(argv[i], 1);

	/*
	 * Build a database for each of the default directories.
	 * Note that it is not an error for these directories to
	 * fail (they may not exist in all installations).
	 */
	for (cpp = default_directories; *cpp; cpp++)
		build_cache(*cpp, 0);

	/*
	 * Database built.  Close file, and rename it to be the "real"
	 * database.  However, if nothing every actually got cached,
	 * delete it instead.
	 */
	(void) close(fd);
	if (first) {
		(void) unlink(fnp);
		exit(0);
	}
	if (rename(fnp, CACHE_FILE) == -1) {
		perror("ldconfig: rename");
		exit(1);
	}
	exit(0);
	/*NOTREACHED*/	
}

/*
 * Allocator for mmap arena.
 */
caddr_t
mmap_alloc(n)
	int n;
{
	caddr_t a;
	static u_int page_size = 0;

	/*
	 * Get value -- simply next address to allocate.
	 */
	a = heap_ptr;

	/*
	 * Architecture-dependent rounding.
	 */
#ifdef sparc
	n = round(n, sizeof (double));
#endif sparc
#ifdef mc68000
	n = round(n, sizeof (int));
#endif mc68000

	/*
	 * If block to be allocated requires file extension, do so.
	 */
	if ((heap_ptr + n) >= heap_max) {
		if (page_size == 0)
			page_size = getpagesize();
		heap_max = (caddr_t)roundup((u_int)heap_ptr + n, page_size);
		if ((heap_max - heap_base) > MAX_DB) {
			perror("ldconfig: data base overflow");
			exit(1);
		}
		if (ftruncate(fd, heap_max - heap_base) == -1) {
			perror("ldconfig: ftruncate");
			exit(1);
		}
	}

	/*
	 * Allocate full block, return starting address.
	 */
	heap_ptr += n;
	return (a);
}

/*
 * Call support routines to build a cache for the given directory.
 */
void
build_cache(cp, flag_error)
	char *cp;			/* directory to cache */
	int flag_error;			/* true if errors to be flagged */
{
	struct db *dbp;			/* working data base file */

	if ((dbp = lo_cache(cp)) == (struct db *)NULL) {
		if (flag_error)
			(void) fprintf(stderr,
			    "ldconfig: directory %s not cached\n", cp);
		return;
	}
	if (first) {
		dbfp->dbf_db = RELPTR(dbfp, dbp);
		db_base = (caddr_t) dbp = &AP(dbfp)[(int)dbfp->dbf_db];
		first = 0;
	}
	if (dbp->db_chain ==  0) {
		dbp->db_chain = (caddr_t)(heap_ptr - db_base);
		db_base = heap_ptr;
	}
}

/*
 * Dummy test to say we're never using security checks.
 */
int
false()
{

	return (0);
}

/*
 * Rounding function.
 */
round(v, r)
	int v;				/* value to be rounded */
	int r;				/* rounding point */
{

	v += --r;
	v &= ~r;
	return (v);
}