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*/
41 static int
visit_dir(const char * path,const struct stat * st,int file_type,struct FTW * ft)42 visit_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 
150 int
main(int argc,char * argv[])151 main(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