Blame


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