Blame


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