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