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