File: find_list.c

package info (click to toggle)
sfind 1.2-1
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 3,404 kB
  • ctags: 2,727
  • sloc: ansic: 16,006; sh: 3,297; makefile: 106
file content (294 lines) | stat: -rw-r--r-- 6,757 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
/* @(#)find_list.c	1.13 06/09/15 Copyright 1985, 1995, 2000-2005 J. Schilling*/
#ifndef lint
static	char sccsid[] =
	"@(#)find_list.c	1.13 06/09/15 Copyright 1985, 1995, 2000-2005 J. Schilling";
#endif
/*
 *	List a file
 *
 *	Copyright (c) 1985, 1995, 2000-2005 J. Schilling
 */
/*
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * See the file CDDL.Schily.txt in this distribution for details.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file CDDL.Schily.txt from this distribution.
 */

#include <schily/mconfig.h>
#include <stdio.h>
#include <schily/unistd.h>
#include <schily/utypes.h>
#include <schily/dirent.h>
#include <schily/time.h>
#include <schily/standard.h>
#include <schily/string.h>
#include <schily/schily.h>
#include <schily/device.h>
#include <schily/nlsdefs.h>

#ifdef	HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#ifndef	DEV_BSIZE
#define	DEV_BSIZE	512
#endif

#include "walk.h"
#include "find.h"
#include "find_list.h"
#include "find_misc.h"

#define	K_DIV	(1024/DEV_BSIZE)

EXPORT	time_t	find_sixmonth;		/* 6 months before limit (ls)	*/
EXPORT	time_t	find_now;		/* now limit (ls)		*/

#define	paxls	TRUE
extern	BOOL	numeric;
extern	int	verbose;

LOCAL	void	modstr		__PR((struct stat *fs, char *s, Ulong  mode, char *name, char *sname, struct WALK *state));
EXPORT	void	find_list	__PR((struct stat *fs, char *name, char *sname, struct WALK *state));

/*--------------------------------------------------------------------------*/
extern	BOOL	nameuid	__PR((char *name, int namelen, uid_t uid));
extern	BOOL	namegid	__PR((char *name, int namelen, gid_t gid));
/*--------------------------------------------------------------------------*/

/*
 * Convert POSIX.1 mode/permission flags into string.
 */
LOCAL void
modstr(fs, s, mode, name, sname, state)
	struct stat	*fs;
		char	*s;
	register Ulong	mode;
		char	*name;
		char	*sname;
	struct WALK	*state;
{
	register char	*mstr = "xwrxwrxwr";
	register char	*str = s;
	register int	i;

	for (i = 9; --i >= 0; ) {
		if (mode & (1 << i))
			*str++ = mstr[i];
		else
			*str++ = '-';
	}
#ifdef	USE_ACL
	*str++ = ' ';
#endif
#ifdef	USE_XATTR
	*str++ = '\0';				/* Don't claim space for '@' */
#endif
	*str = '\0';
	str = s;
	if (mode & S_ISVTX) {
		if (mode &  S_IXOTH) {
			str[8] = 't';		/* Sticky & exec. by others  */
		} else {
			str[8] = 'T';		/* Sticky but !exec. by oth  */
		}
	}
	if (mode & S_ISGID) {
		if (mode & S_IXGRP) {
			str[5] = 's';		/* Sgid & executable by grp  */
		} else {
			if (S_ISDIR(fs->st_mode))
				str[5] = 'S';	/* Sgid directory	    */
			else
				str[5] = 'l';	/* Mandatory lock file	    */
		}
	}
	if (mode & S_ISUID) {
		if (mode & S_IXUSR)
			str[2] = 's';		/* Suid & executable by own. */
		else
			str[2] = 'S';		/* Suid but not executable   */
	}
	i = 9;
#ifdef	USE_ACL
	if (state->pflags & PF_ACL) {
		if (state->pflags & PF_HAS_ACL)
			str[i++] = '+';
	} else
	if (has_acl(name, sname, fs))
		str[i++] = '+';
#endif
#ifdef	USE_XATTR
	if (state->pflags & PF_XATTR) {
		if (state->pflags & PF_HAS_XATTR)
			str[i++] = '@';
	} else
	if (has_xattr(sname))
		str[i++] = '@';
#endif
	i++;	/* Make lint believe that we always use i. */
}

EXPORT void
find_list(fs, name, sname, state)
	struct stat	*fs;
	char		*name;
	char		*sname;
	struct WALK	*state;
{
		time_t	*tp;
		char	*tstr;
		char	mstr[12]; /* 9 UNIX chars + ACL '+' XATTR '@' + nul */
		char	lstr[11]; /* contains link count as string */
	static	char	nuid[32+1];
	static	char	ngid[32+1];
		char	*add = "";
char	lname[8192];
char	*lnamep = lname;
		int	lsize;

#define	verbose	1
	if (verbose) {
		char	*uname;
		char	*gname;
		int	umaxlen;
		int	gmaxlen;
		char	ft;

		tp = state->walkflags & WALK_LS_ATIME ? &fs->st_atime :
				(state->walkflags & WALK_LS_CTIME ?
					&fs->st_ctime : &fs->st_mtime);
		tstr = ctime(tp);

		if (nameuid(nuid, sizeof (nuid), fs->st_uid)) {
			uname = nuid;
			umaxlen = sizeof (nuid)-1;
		} else {
			sprintf(nuid, "%llu", (Llong)fs->st_uid);
			uname = nuid;
			umaxlen = sizeof (nuid)-1;
		}

		if (namegid(ngid, sizeof (ngid), fs->st_gid)) {
			gname = ngid;
			gmaxlen = sizeof (ngid)-1;
		} else {
			sprintf(ngid, "%llu", (Llong)fs->st_gid);
			gname = ngid;
			gmaxlen = sizeof (ngid)-1;
		}

		{
			printf("%7llu ", (Llong)fs->st_ino);
#ifdef	HAVE_ST_BLOCKS
			printf("%4llu ", (Llong)fs->st_blocks/K_DIV);
#else
			printf("%4llu ", (Llong)(fs->st_size+1023)/1024);
#endif
		}
		if (!paxls) {
			if (S_ISBLK(fs->st_mode) || S_ISCHR(fs->st_mode))
				printf("%3lu %3lu",
					(long)major(fs->st_rdev), (long)minor(fs->st_rdev));
			else
				printf("%7llu", (Llong)fs->st_size);
		}
		modstr(fs, mstr, fs->st_mode, name, sname, state);

		if (paxls || fs->st_nlink > 0) {
			/*
			 * UNIX ls uses %3d for the link count
			 * and does not claim space for ACL '+'
			 */
			js_sprintf(lstr, " %2ld", (long)fs->st_nlink);
		} else {
			lstr[0] = 0;
		}

		switch (fs->st_mode & S_IFMT) {

		case S_IFREG:	ft = '-'; break;
		case S_IFLNK:	ft = 'l';
				if (state->lname != NULL) {
					lnamep = state->lname;
					break;
				}
				lname[0] = '\0';
				lsize = readlink(sname, lname, sizeof (lname));
				if (lsize < 0)
					errmsg(
					gettext("Cannot read link '%s'.\n"),
						name);
				lname[sizeof (lname)-1] = '\0';
				if (lsize >= 0)
					lname[lsize] = '\0';
				break;
		case S_IFDIR:	ft = 'd'; break;
		case S_IFBLK:	ft = 'b'; break;
		case S_IFCHR:	ft = 'c'; break;
		case S_IFIFO:	ft = 'p'; break;
#ifdef	S_IFDOOR
		case S_IFDOOR:	ft = 'D'; break;
#endif
#ifdef	S_IFSOCK
		case S_IFSOCK:	ft = 's'; break;
#endif
#ifdef	S_IFNAM
		case S_IFNAM:	switch (fs->st_rdev) {
				case S_INSEM:
					ft = 's';
					break;
				case S_INSHD:
					ft = 'm';
					break;
				default:
					ft = '-';
					break;
				}
#endif

		default:	ft = '?'; break;
		}

		if (!paxls) {
			printf(" %c%s%s %3.*s/%-3.*s %.12s %4.4s ",
				ft,
				mstr,
				lstr,
				umaxlen, uname,
				gmaxlen, gname,
				&tstr[4], &tstr[20]);
		} else {
			printf("%c%s%s %-8.*s %-8.*s ",
				ft,
				mstr,
				lstr,
				umaxlen, uname,
				gmaxlen, gname);
			if (S_ISBLK(fs->st_mode) || S_ISCHR(fs->st_mode))
/*				printf("%3lu %3lu",*/
/* XXXXXXXXXXXXXX */		printf("%3lu, %3lu",
					(long)major(fs->st_rdev), (long)minor(fs->st_rdev));
			else
				printf("%7llu", (Llong)fs->st_size);
			if ((*tp < find_sixmonth) || (*tp > find_now)) {
				printf(" %.6s  %4.4s ",
					&tstr[4], &tstr[20]);
			} else {
				printf(" %.12s ",
					&tstr[4]);
			}
		}
	}
	printf("%s%s", name, add);

	if (S_ISLNK(fs->st_mode))
		printf(" -> %s", lnamep);

	printf("\n");
}