1 /* @(#)list.c	1.78 17/02/16 Copyright 1985, 1995, 2000-2016 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static	UConst char sccsid[] =
5 	"@(#)list.c	1.78 17/02/16 Copyright 1985, 1995, 2000-2016 J. Schilling";
6 #endif
7 /*
8  *	List the content of an archive
9  *
10  *	Copyright (c) 1985, 1995, 2000-2016 J. Schilling
11  */
12 /*
13  * The contents of this file are subject to the terms of the
14  * Common Development and Distribution License, Version 1.0 only
15  * (the "License").  You may not use this file except in compliance
16  * with the License.
17  *
18  * See the file CDDL.Schily.txt in this distribution for details.
19  * A copy of the CDDL is also available via the Internet at
20  * http://www.opensource.org/licenses/cddl1.txt
21  *
22  * When distributing Covered Code, include this CDDL HEADER in each
23  * file and include the License file CDDL.Schily.txt from this distribution.
24  */
25 
26 #include <schily/stdio.h>
27 #include <schily/dirent.h>
28 #include <schily/standard.h>
29 #include <schily/stdlib.h>
30 #include <schily/time.h>
31 #include <schily/string.h>
32 #include <schily/schily.h>
33 #ifdef	USE_FIND
34 #include <schily/walk.h>
35 #endif
36 #include <schily/strar.h>
37 
38 #include "table.h"
39 
40 /*
41  * Definitions for the t_mode field
42  */
43 #define	TSUID		04000	/* Set UID on execution */
44 #define	TSGID		02000	/* Set GID on execution */
45 #define	TSVTX		01000	/* On directories, restricted deletion flag */
46 #define	TUREAD		00400	/* Read by owner */
47 #define	TUWRITE		00200	/* Write by owner special */
48 #define	TUEXEC		00100	/* Execute/search by owner */
49 #define	TGREAD		00040	/* Read by group */
50 #define	TGWRITE		00020	/* Write by group */
51 #define	TGEXEC		00010	/* Execute/search by group */
52 #define	TOREAD		00004	/* Read by other */
53 #define	TOWRITE		00002	/* Write by other */
54 #define	TOEXEC		00001	/* Execute/search by other */
55 
56 #define	TALLMODES	07777	/* The low 12 bits mentioned in the standard */
57 
58 #define	is_dir(i)	((i)->f_rxftype == XT_DIR)
59 #define	is_symlink(i)	((i)->f_rxftype == XT_SLINK)
60 #define	is_link(i)	((i)->f_rxftype == XT_LINK)
61 #define	is_special(i)	((i)->f_rxftype > XT_DIR)
62 
63 
64 extern	FILE	*vpr;
65 extern	Llong	curblockno;
66 
67 extern	time_t	sixmonth;		/* 6 months before limit (ls)	*/
68 extern	time_t	now;			/* now limit (ls)		*/
69 
70 extern	BOOL	havepat;
71 extern	int	iftype;
72 extern	BOOL	paxls;
73 extern	int	xdebug;
74 extern	BOOL	numeric;
75 extern	int	verbose;
76 extern	BOOL	prblockno;
77 extern	BOOL	tpath;
78 extern	BOOL	cflag;
79 extern	BOOL	xflag;
80 extern	BOOL	interactive;
81 
82 extern	BOOL	acctime;
83 extern	BOOL	no_dirslash;
84 extern	BOOL	Ctime;
85 extern	BOOL	prinodes;
86 
87 extern	BOOL	listnew;
88 extern	BOOL	listnewf;
89 
90 extern	BOOL	do_subst;
91 
92 #ifdef	USE_FIND
93 extern	BOOL	dofind;
94 #endif
95 
96 /*--------------------------------------------------------------------------*/
97 #define	paxls		0
98 #define	tpath		0
99 #define	no_dirslash	0
100 #define	numeric		0
101 #define	acctime		0
102 #define	interactive	0
103 #define	prinodes	0
104 #define	list_file	strar_list_file
105 #define	vprint		strar_vprint
106 #define	vpr		info->f_list;
107 #define	cflag		(info->f_cmdflags & CMD_CREATE)
108 #define	xflag		(info->f_cmdflags & CMD_XTRACT)
109 #define	Ctime		(info->f_cmdflags & CMD_CTIME)
110 #define	verbose		(info->f_cmdflags & CMD_VERBOSE)
111 /*--------------------------------------------------------------------------*/
112 
113 LOCAL	void	modstr		__PR((FINFO *info, char *s, mode_t  mode));
114 EXPORT	void	list_file	__PR((FINFO *info));
115 EXPORT	void	vprint		__PR((FINFO *info));
116 
117 /*
118  * Convert POSIX.1 TAR mode/permission flags into string.
119  */
120 LOCAL void
121 #ifdef	PROTOTYPES
modstr(FINFO * info,char * s,register mode_t mode)122 modstr(FINFO *info, char *s, register mode_t  mode)
123 #else
124 modstr(info, s, mode)
125 		FINFO	*info;
126 		char	*s;
127 	register mode_t	mode;
128 #endif
129 {
130 	register char	*mstr = "xwrxwrxwr";
131 	register char	*str = s;
132 	register int	i;
133 
134 	for (i = 9; --i >= 0; ) {
135 		if (mode & (1 << i))
136 			*str++ = mstr[i];
137 		else
138 			*str++ = '-';
139 	}
140 #ifdef	USE_ACL
141 	*str++ = ' ';
142 #endif
143 #ifdef	USE_XATTR
144 	*str++ = '\0';				/* Don't claim space for '@' */
145 #endif
146 	*str = '\0';
147 	str = s;
148 	if (mode & TSVTX) {
149 		if (mode & TOEXEC) {
150 			str[8] = 't';		/* Sticky & exec. by others  */
151 		} else {
152 			str[8] = 'T';		/* Sticky but !exec. by oth  */
153 		}
154 	}
155 	if (mode & TSGID) {
156 		if (mode & TGEXEC) {
157 			str[5] = 's';		/* Sgid & executable by grp  */
158 		} else {
159 			if (is_dir(info))
160 				str[5] = 'S';	/* Sgid directory	    */
161 			else
162 				str[5] = 'l';	/* Mandatory lock file	    */
163 		}
164 	}
165 	if (mode & TSUID) {
166 		if (mode & TUEXEC)
167 			str[2] = 's';		/* Suid & executable by own. */
168 		else
169 			str[2] = 'S';		/* Suid but not executable   */
170 	}
171 	i = 9;
172 #ifdef	USE_ACL
173 	if ((info->f_xflags & (XF_ACL_ACCESS|XF_ACL_DEFAULT|XF_ACL_ACE)) != 0)
174 		str[i++] = '+';
175 #endif
176 #ifdef	USE_XATTR
177 	if ((info->f_xflags & XF_XATTR) != 0)
178 		str[i++] = '@';
179 #endif
180 	i++;	/* Make lint believe that we always use i. */
181 }
182 
183 EXPORT void
list_file(info)184 list_file(info)
185 	register FINFO	*info;
186 {
187 		FILE	*f;
188 		time_t	*tp;
189 		char	*tstr;
190 		char	mstr[12]; /* 9 UNIX chars + ACL '+' XATTR '@' + nul */
191 		char	lstr[22]; /* ' ' + link count as string - 64 bits */
192 	static	char	nuid[21]; /* uid as 64 bit long */
193 	static	char	ngid[21]; /* gid as 64 bit long */
194 		char	*add = "";
195 
196 	f = vpr;
197 	if (cflag)
198 		fprintf(f, "a ");
199 	else if (xflag)
200 		fprintf(f, "x ");
201 
202 	if (prinodes && info->f_ino > 0)
203 		fprintf(f, "%7llu ", (Llong)info->f_ino);
204 	if (cflag && is_dir(info) && !no_dirslash) {
205 		int	len = info->f_namelen;
206 
207 		if (len == 0)
208 			len = strlen(info->f_name);
209 		if (info->f_name[len-1] != '/')
210 			add = "/";
211 	}
212 	if (verbose) {
213 		register Uint	xft = info->f_xftype;
214 
215 		tp = acctime ? &info->f_atime :
216 				(Ctime ? &info->f_ctime : &info->f_mtime);
217 		tstr = ctime(tp);
218 		if (numeric || info->f_uname == NULL) {
219 			sprintf(nuid, "%lld", (Llong)info->f_uid);
220 			info->f_uname = nuid;
221 			info->f_umaxlen = sizeof (nuid)-1;
222 		}
223 		if (numeric || info->f_gname == NULL) {
224 			sprintf(ngid, "%lld", (Llong)info->f_gid);
225 			info->f_gname = ngid;
226 			info->f_gmaxlen = sizeof (ngid)-1;
227 		}
228 
229 		if (!paxls) {
230 			if (is_special(info))
231 				fprintf(f, "%3lu %3lu",
232 					info->f_rdevmaj, info->f_rdevmin);
233 			else
234 				fprintf(f, "%7llu", (Llong)info->f_size);
235 		}
236 		modstr(info, mstr, info->f_mode);
237 
238 		if (paxls && info->f_nlink == 0 && is_link(info)) {
239 			info->f_nlink = 2;
240 		}
241 		if (paxls || info->f_nlink > 0) {
242 			/*
243 			 * UNIX ls uses %3d for the link count
244 			 * and does not claim space for ACL '+'
245 			 */
246 			js_sprintf(lstr, " %2llu", (Ullong)info->f_nlink);
247 		} else {
248 			lstr[0] = 0;
249 		}
250 
251 		if (xft == XT_LINK)
252 			xft = info->f_rxftype;
253 		if (!paxls) {
254 			fprintf(f,
255 				" %s%s%s %3.*s/%-3.*s %.12s %4.4s ",
256 #ifdef	OLD
257 				typetab[info->f_filetype & 07],
258 #else
259 				XTTOSTR(xft),
260 #endif
261 				mstr,
262 				lstr,
263 				(int)info->f_umaxlen, info->f_uname,
264 				(int)info->f_gmaxlen, info->f_gname,
265 				&tstr[4], &tstr[20]);
266 		} else {
267 			fprintf(f,
268 				"%s%s%s %-8.*s %-8.*s ",
269 #ifdef	OLD
270 				typetab[info->f_filetype & 07],
271 #else
272 				XTTOSTR(xft),
273 #endif
274 				mstr,
275 				lstr,
276 				(int)info->f_umaxlen, info->f_uname,
277 				(int)info->f_gmaxlen, info->f_gname);
278 			if (is_special(info))
279 				fprintf(f, "%3lu %3lu",
280 					info->f_rdevmaj, info->f_rdevmin);
281 			else
282 				fprintf(f, "%7llu", (Llong)info->f_size);
283 			if ((*tp < sixmonth) || (*tp > now)) {
284 				fprintf(f, " %.6s  %4.4s ",
285 					&tstr[4], &tstr[20]);
286 			} else {
287 				fprintf(f, " %.12s ",
288 					&tstr[4]);
289 			}
290 		}
291 	}
292 	fprintf(f, "%s%s", info->f_name, add);
293 	if (tpath) {
294 		fprintf(f, "\n");
295 		return;
296 	}
297 	if (is_link(info)) {
298 		if (is_dir(info))
299 			fprintf(f, " directory");
300 		fprintf(f, " %s %s",
301 			paxls ? "==" : "link to",
302 			info->f_lname);
303 	}
304 	if (is_symlink(info))
305 		fprintf(f, " -> %s", info->f_lname);
306 	fprintf(f, "\n");
307 }
308 
309 EXPORT void
vprint(info)310 vprint(info)
311 	FINFO	*info;
312 {
313 		FILE	*f;
314 	char	*mode;
315 	char	*add = "";
316 
317 	if (verbose || interactive) {
318 		if (verbose > 1) {
319 			list_file(info);
320 			return;
321 		}
322 
323 		f = vpr;
324 
325 		if (cflag)
326 			mode = "a ";
327 		else if (xflag)
328 			mode = "x ";
329 		else
330 			mode = "";
331 
332 		if (cflag && is_dir(info) && !no_dirslash) {
333 			int	len = info->f_namelen;
334 
335 			if (len == 0)
336 				len = strlen(info->f_name);
337 			if (info->f_name[len-1] != '/')
338 				add = "/";
339 		}
340 		if (tpath) {
341 			fprintf(f, "%s%s\n", info->f_name, add);
342 			return;
343 		}
344 		if (is_dir(info)) {
345 			if (is_link(info)) {
346 				fprintf(f, "%s%s%s directory %s %s\n",
347 					mode, info->f_name, add,
348 					paxls ? "==" : "link to",
349 					info->f_lname);
350 			} else {
351 				fprintf(f, "%s%s%s directory\n", mode,
352 							info->f_name, add);
353 			}
354 		} else if (is_link(info)) {
355 			fprintf(f, "%s%s %s %s\n",
356 				mode, info->f_name,
357 				paxls ? "==" : "link to",
358 				info->f_lname);
359 		} else if (is_symlink(info)) {
360 			fprintf(f, "%s%s %s %s\n",
361 				mode, info->f_name,
362 				paxls ? "->" : "symbolic link to",
363 				info->f_lname);
364 		} else if (is_special(info)) {
365 			fprintf(f, "%s%s special\n", mode, info->f_name);
366 		} else {
367 			fprintf(f, "%s%s %lld bytes\n",
368 				mode, info->f_name, (Llong)info->f_size);
369 		}
370 	}
371 }
372