OpenSolaris_b135/tools/protolist/protolist.c

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

/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/mkdev.h>
#include <ftw.h>
#include <strings.h>
#include <stdlib.h>
#include "stdusers.h"

#define	MAX_DEPTH	50

/*ARGSUSED2*/
static int
visit_dir(const char *path, const struct stat *st,
	int file_type, struct FTW *ft)
{
	const char	*uid, *gid;
	char	ftype;
	char	symsrc[MAXPATHLEN];
	char	buffer[MAXPATHLEN];
	char	*abs_name;
	char	name[MAXPATHLEN];
	char	maj[10], min[10];
	char	*p;
	int	c;
	static int first_time = 1;
	int	inum;

	/*
	 * The first directory is the current directory '.',
	 * this is relevant in our protolist, so I throw it out.
	 */
	if (first_time) {
		first_time = 0;
		if ((path[0] == '.') && (path[1] == '\0'))
			return (0);
	}

	abs_name = (char *)(path + 2);
	maj[0] = min[0] = symsrc[0] = '-';
	maj[1] = min[1] = symsrc[1] = '\0';

	(void) strcpy(name, abs_name);
	/*
	 * is this a relocatable object?  if so set
	 * the symsrc appropriately.
	 *
	 * All relocatable objects start with /sun or /i86
	 *
	 * eg:
	 *    /sun4d/kadb == kadb
	 *    /i86pc/kadb == kadb
	 */
#if defined(sparc)
#define	ARCH_STR "sun"
#elif defined(i386)
#define	ARCH_STR "i86"
#elif defined(__ppc)
#define	ARCH_STR "prep"
#else
#error "Unknown instruction set"
#endif
	if (strncmp(abs_name, ARCH_STR, 3) == 0) {
		if (((st->st_mode & S_IFMT) == S_IFDIR) ||
		    ((st->st_mode & S_IFMT) == S_IFLNK))
			return (0);

		(void) strcpy(buffer, abs_name);
		if (p = index(buffer, '/')) {
			(void) strcpy(symsrc, abs_name);
			*p++ = '\0';
			(void) strcpy(name, p);
		}
	}

	switch (st->st_mode & S_IFMT) {
	case S_IFCHR:
		(void) sprintf(maj, "%ld", major(st->st_rdev));
		(void) sprintf(min, "%ld", minor(st->st_rdev));
		ftype = 'c';
		break;
	case S_IFDIR:
		ftype = 'd';
		break;
	case S_IFBLK:
		(void) sprintf(maj, "%ld", major(st->st_rdev));
		(void) sprintf(min, "%ld", minor(st->st_rdev));
		ftype = 'b';
		break;
	case S_IFREG:
		ftype = 'f';
		break;
	case S_IFLNK:
		if ((c = readlink(path, symsrc, MAXPATHLEN)) == -1)
			perror("readlink");
		symsrc[c] = '\0';
		ftype = 's';
		break;
	default:
		ftype = '?';
		break;
	}

	uid = stdfindbyvalue(st->st_uid, usernames);
	if (uid == NULL)
		uid = "NO_SUCH_UID";

	gid = stdfindbyvalue(st->st_gid, groupnames);
	if (gid == NULL)
		gid = "NO_SUCH_GID";
	if (st->st_nlink == 1)
		inum = 0;
	else
		inum = st->st_ino;

	(void) printf("%c %-30s %-20s %4lo %-5s %-5s %6d %2ld %2s %2s\n",
	    ftype, name, symsrc, st->st_mode % 010000, uid, gid,
	    inum, st->st_nlink, maj, min);
	return (0);
}

int
main(int argc, char *argv[])
{

	if (argc != 2) {
		(void) fprintf(stderr, "usage: protolist <protodir>\n");
		exit(1);
	}

	if (chdir(argv[1]) < 0) {
		perror("chdir");
		exit(1);
	}

	if (nftw(".", visit_dir, MAX_DEPTH, FTW_PHYS) != 0) {
		perror("nftw");
		exit(1);
	}

	return (0);
}