Introduction
Introduction Statistics Contact Development Disclaimer Help
ls.c - 9base - revived minimalist port of Plan 9 userland to Unix
git clone git://git.suckless.org/9base
Log
Files
Refs
README
LICENSE
---
ls.c (5449B)
---
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4
5 #define dirbuf p9dirbuf /* avoid conflict on sun */
6
7 typedef struct NDir NDir;
8 struct NDir
9 {
10 Dir *d;
11 char *prefix;
12 };
13
14 int errs = 0;
15 int dflag;
16 int lflag;
17 int mflag;
18 int nflag;
19 int pflag;
20 int qflag;
21 int Qflag;
22 int rflag;
23 int sflag;
24 int tflag;
25 int uflag;
26 int Fflag;
27 int ndirbuf;
28 int ndir;
29 NDir* dirbuf;
30 int ls(char*, int);
31 int compar(NDir*, NDir*);
32 char* asciitime(long);
33 char* darwx(long);
34 void rwx(long, char*);
35 void growto(long);
36 void dowidths(Dir*);
37 void format(Dir*, char*);
38 void output(void);
39 ulong clk;
40 int swidth; /* max width of -s size */
41 int qwidth; /* max width of -q version */
42 int vwidth; /* max width of dev */
43 int uwidth; /* max width of userid */
44 int mwidth; /* max width of muid */
45 int glwidth; /* max width of groupid and length */
46 Biobuf bin;
47
48 void
49 main(int argc, char *argv[])
50 {
51 int i;
52
53 Binit(&bin, 1, OWRITE);
54 ARGBEGIN{
55 case 'F': Fflag++; break;
56 case 'd': dflag++; break;
57 case 'l': lflag++; break;
58 case 'm': mflag++; break;
59 case 'n': nflag++; break;
60 case 'p': pflag++; break;
61 case 'q': qflag++; break;
62 case 'Q': Qflag++; break;
63 case 'r': rflag++; break;
64 case 's': sflag++; break;
65 case 't': tflag++; break;
66 case 'u': uflag++; break;
67 default: fprint(2, "usage: ls [-dlmnpqrstuFQ] [file ...]\…
68 exits("usage");
69 }ARGEND
70
71 doquote = needsrcquote;
72 quotefmtinstall();
73 fmtinstall('M', dirmodefmt);
74
75 if(lflag)
76 clk = time(0);
77 if(argc == 0)
78 errs = ls(".", 0);
79 else for(i=0; i<argc; i++)
80 errs |= ls(argv[i], 1);
81 output();
82 exits(errs? "errors" : 0);
83 }
84
85 int
86 ls(char *s, int multi)
87 {
88 int fd;
89 long i, n;
90 char *p;
91 Dir *db;
92
93 for(;;) {
94 p = utfrrune(s, '/');
95 if(p == 0 || p[1] != 0 || p == s)
96 break;
97 *p = 0;
98 }
99 db = dirstat(s);
100 if(db == nil){
101 error:
102 fprint(2, "ls: %s: %r\n", s);
103 return 1;
104 }
105 if(db->qid.type&QTDIR && dflag==0){
106 free(db);
107 db = nil;
108 output();
109 fd = open(s, OREAD);
110 if(fd == -1)
111 goto error;
112 n = dirreadall(fd, &db);
113 if(n < 0)
114 goto error;
115 growto(ndir+n);
116 for(i=0; i<n; i++){
117 dirbuf[ndir+i].d = db+i;
118 dirbuf[ndir+i].prefix = multi? s : 0;
119 }
120 ndir += n;
121 close(fd);
122 output();
123 }else{
124 growto(ndir+1);
125 dirbuf[ndir].d = db;
126 dirbuf[ndir].prefix = 0;
127 p = utfrrune(s, '/');
128 if(p){
129 dirbuf[ndir].prefix = s;
130 *p = 0;
131 /* restore original name; don't use result of st…
132 dirbuf[ndir].d->name = strdup(p+1);
133 }
134 ndir++;
135 }
136 return 0;
137 }
138
139 void
140 output(void)
141 {
142 int i;
143 char buf[4096];
144 char *s;
145
146 if(!nflag)
147 qsort(dirbuf, ndir, sizeof dirbuf[0], (int (*)(const voi…
148 for(i=0; i<ndir; i++)
149 dowidths(dirbuf[i].d);
150 for(i=0; i<ndir; i++) {
151 if(!pflag && (s = dirbuf[i].prefix)) {
152 if(strcmp(s, "/") ==0) /* / is a special …
153 s = "";
154 sprint(buf, "%s/%s", s, dirbuf[i].d->name);
155 format(dirbuf[i].d, buf);
156 } else
157 format(dirbuf[i].d, dirbuf[i].d->name);
158 }
159 ndir = 0;
160 Bflush(&bin);
161 }
162
163 void
164 dowidths(Dir *db)
165 {
166 char buf[256];
167 int n;
168
169 if(sflag) {
170 n = sprint(buf, "%llud", (db->length+1023)/1024);
171 if(n > swidth)
172 swidth = n;
173 }
174 if(qflag) {
175 n = sprint(buf, "%lud", db->qid.vers);
176 if(n > qwidth)
177 qwidth = n;
178 }
179 if(mflag) {
180 n = snprint(buf, sizeof buf, "[%s]", db->muid);
181 if(n > mwidth)
182 mwidth = n;
183 }
184 if(lflag) {
185 n = sprint(buf, "%ud", db->dev);
186 if(n > vwidth)
187 vwidth = n;
188 n = strlen(db->uid);
189 if(n > uwidth)
190 uwidth = n;
191 n = sprint(buf, "%llud", db->length);
192 n += strlen(db->gid);
193 if(n > glwidth)
194 glwidth = n;
195 }
196 }
197
198 char*
199 fileflag(Dir *db)
200 {
201 if(Fflag == 0)
202 return "";
203 if(QTDIR & db->qid.type)
204 return "/";
205 if(0111 & db->mode)
206 return "*";
207 return "";
208 }
209
210 void
211 format(Dir *db, char *name)
212 {
213 int i;
214
215 if(sflag)
216 Bprint(&bin, "%*llud ",
217 swidth, (db->length+1023)/1024);
218 if(mflag){
219 Bprint(&bin, "[%s] ", db->muid);
220 for(i=2+strlen(db->muid); i<mwidth; i++)
221 Bprint(&bin, " ");
222 }
223 if(qflag)
224 Bprint(&bin, "(%.16llux %*lud %.2ux) ",
225 db->qid.path,
226 qwidth, db->qid.vers,
227 db->qid.type);
228 if(lflag)
229 Bprint(&bin,
230 "%M %C %*ud %*s %s %*llud %s ",
231 db->mode, db->type,
232 vwidth, db->dev,
233 -uwidth, db->uid,
234 db->gid,
235 (int)(glwidth-strlen(db->gid)), db->length,
236 asciitime(uflag? db->atime : db->mtime));
237 Bprint(&bin,
238 Qflag? "%s%s\n" : "%q%s\n",
239 name, fileflag(db));
240 }
241
242 void
243 growto(long n)
244 {
245 if(n <= ndirbuf)
246 return;
247 ndirbuf = n;
248 dirbuf=(NDir *)realloc(dirbuf, ndirbuf*sizeof(NDir));
249 if(dirbuf == 0){
250 fprint(2, "ls: malloc fail\n");
251 exits("malloc fail");
252 }
253 }
254
255 int
256 compar(NDir *a, NDir *b)
257 {
258 long i;
259 Dir *ad, *bd;
260
261 ad = a->d;
262 bd = b->d;
263
264 if(tflag){
265 if(uflag)
266 i = bd->atime-ad->atime;
267 else
268 i = bd->mtime-ad->mtime;
269 }else{
270 if(a->prefix && b->prefix){
271 i = strcmp(a->prefix, b->prefix);
272 if(i == 0)
273 i = strcmp(ad->name, bd->name);
274 }else if(a->prefix){
275 i = strcmp(a->prefix, bd->name);
276 if(i == 0)
277 i = 1; /* a is longer than b */
278 }else if(b->prefix){
279 i = strcmp(ad->name, b->prefix);
280 if(i == 0)
281 i = -1; /* b is longer than a */
282 }else
283 i = strcmp(ad->name, bd->name);
284 }
285 if(i == 0)
286 i = (ad<bd? -1 : 1);
287 if(rflag)
288 i = -i;
289 return i;
290 }
291
292 char*
293 asciitime(long l)
294 {
295 static char buf[32];
296 char *t;
297
298 t = ctime(l);
299 /* 6 months in the past or a day in the future */
300 if(l<clk-180L*24*60*60 || clk+24L*60*60<l){
301 memmove(buf, t+4, 7); /* month and day */
302 memmove(buf+7, t+23, 5); /* year */
303 }else
304 memmove(buf, t+4, 12); /* skip day of wee…
305 buf[12] = 0;
306 return buf;
307 }
308
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.