1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27#include <stdio.h>
28#include <sys/stat.h>
29#include <unistd.h>
30#include <sys/param.h>
31#include <sys/types.h>
32#include <sys/mkdev.h>
33#include <ftw.h>
34#include <strings.h>
35#include <stdlib.h>
36#include "stdusers.h"
37
38#define	MAX_DEPTH	50
39
40/*ARGSUSED2*/
41static int
42visit_dir(const char *path, const struct stat *st,
43	int file_type, struct FTW *ft)
44{
45	const char	*uid, *gid;
46	char	ftype;
47	char	symsrc[MAXPATHLEN];
48	char	buffer[MAXPATHLEN];
49	char	*abs_name;
50	char	name[MAXPATHLEN];
51	char	maj[10], min[10];
52	char	*p;
53	int	c;
54	static int first_time = 1;
55	int	inum;
56
57	/*
58	 * The first directory is the current directory '.',
59	 * this is relevant in our protolist, so I throw it out.
60	 */
61	if (first_time) {
62		first_time = 0;
63		if ((path[0] == '.') && (path[1] == '\0'))
64			return (0);
65	}
66
67	abs_name = (char *)(path + 2);
68	maj[0] = min[0] = symsrc[0] = '-';
69	maj[1] = min[1] = symsrc[1] = '\0';
70
71	(void) strcpy(name, abs_name);
72	/*
73	 * is this a relocatable object?  if so set
74	 * the symsrc appropriately.
75	 *
76	 * All relocatable objects start with /sun or /i86
77	 *
78	 * eg:
79	 *    /sun4d/kadb == kadb
80	 *    /i86pc/kadb == kadb
81	 */
82#if defined(sparc)
83#define	ARCH_STR "sun"
84#elif defined(i386)
85#define	ARCH_STR "i86"
86#elif defined(__ppc)
87#define	ARCH_STR "prep"
88#else
89#error "Unknown instruction set"
90#endif
91	if (strncmp(abs_name, ARCH_STR, 3) == 0) {
92		if (((st->st_mode & S_IFMT) == S_IFDIR) ||
93		    ((st->st_mode & S_IFMT) == S_IFLNK))
94			return (0);
95
96		(void) strcpy(buffer, abs_name);
97		if (p = index(buffer, '/')) {
98			(void) strcpy(symsrc, abs_name);
99			*p++ = '\0';
100			(void) strcpy(name, p);
101		}
102	}
103
104	switch (st->st_mode & S_IFMT) {
105	case S_IFCHR:
106		(void) sprintf(maj, "%ld", major(st->st_rdev));
107		(void) sprintf(min, "%ld", minor(st->st_rdev));
108		ftype = 'c';
109		break;
110	case S_IFDIR:
111		ftype = 'd';
112		break;
113	case S_IFBLK:
114		(void) sprintf(maj, "%ld", major(st->st_rdev));
115		(void) sprintf(min, "%ld", minor(st->st_rdev));
116		ftype = 'b';
117		break;
118	case S_IFREG:
119		ftype = 'f';
120		break;
121	case S_IFLNK:
122		if ((c = readlink(path, symsrc, MAXPATHLEN)) == -1)
123			perror("readlink");
124		symsrc[c] = '\0';
125		ftype = 's';
126		break;
127	default:
128		ftype = '?';
129		break;
130	}
131
132	uid = stdfindbyvalue(st->st_uid, usernames);
133	if (uid == NULL)
134		uid = "NO_SUCH_UID";
135
136	gid = stdfindbyvalue(st->st_gid, groupnames);
137	if (gid == NULL)
138		gid = "NO_SUCH_GID";
139	if (st->st_nlink == 1)
140		inum = 0;
141	else
142		inum = st->st_ino;
143
144	(void) printf("%c %-30s %-20s %4lo %-5s %-5s %6d %2ld %2s %2s\n",
145	    ftype, name, symsrc, st->st_mode % 010000, uid, gid,
146	    inum, st->st_nlink, maj, min);
147	return (0);
148}
149
150int
151main(int argc, char *argv[])
152{
153
154	if (argc != 2) {
155		(void) fprintf(stderr, "usage: protolist <protodir>\n");
156		exit(1);
157	}
158
159	if (chdir(argv[1]) < 0) {
160		perror("chdir");
161		exit(1);
162	}
163
164	if (nftw(".", visit_dir, MAX_DEPTH, FTW_PHYS) != 0) {
165		perror("nftw");
166		exit(1);
167	}
168
169	return (0);
170}
171