Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
script3r
GitHub Repository: script3r/os161
Path: blob/master/user/bin/ls/ls.c
734 views
1
/*
2
* Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
3
* The President and Fellows of Harvard College.
4
*
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
7
* are met:
8
* 1. Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer.
10
* 2. Redistributions in binary form must reproduce the above copyright
11
* notice, this list of conditions and the following disclaimer in the
12
* documentation and/or other materials provided with the distribution.
13
* 3. Neither the name of the University nor the names of its contributors
14
* may be used to endorse or promote products derived from this software
15
* without specific prior written permission.
16
*
17
* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
18
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
21
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
* SUCH DAMAGE.
28
*/
29
30
#include <sys/types.h>
31
#include <sys/stat.h>
32
#include <stdio.h>
33
#include <unistd.h>
34
#include <string.h>
35
#include <errno.h>
36
#include <err.h>
37
38
/*
39
* ls - list files.
40
* Usage: ls [-adlRs] [files]
41
* -a Show files whose names begin with a dot.
42
* -d Don't list contents of directories specified on the command line.
43
* -l Long format listing.
44
* -R Recurse into subdirectories found.
45
* -s (with -l) Show block counts.
46
*/
47
48
/* Flags for which options we're using. */
49
static int aopt=0;
50
static int dopt=0;
51
static int lopt=0;
52
static int Ropt=0;
53
static int sopt=0;
54
55
/* Process an option character. */
56
static
57
void
58
option(int ch)
59
{
60
switch (ch) {
61
case 'a': aopt=1; break;
62
case 'd': dopt=1; break;
63
case 'l': lopt=1; break;
64
case 'R': Ropt=1; break;
65
case 's': sopt=1; break;
66
default:
67
errx(1, "Unknown option -%c", ch);
68
}
69
}
70
71
/*
72
* Utility function to find the non-directory part of a pathname.
73
*/
74
static
75
const char *
76
basename(const char *path)
77
{
78
const char *s;
79
80
s = strrchr(path, '/');
81
if (s) {
82
return s+1;
83
}
84
return path;
85
}
86
87
/*
88
* Utility function to check if a name refers to a directory.
89
*/
90
static
91
int
92
isdir(const char *path)
93
{
94
struct stat buf;
95
int fd;
96
97
/* Assume stat() may not be implemented; use fstat */
98
fd = open(path, O_RDONLY);
99
if (fd<0) {
100
err(1, "%s", path);
101
}
102
if (fstat(fd, &buf)<0) {
103
err(1, "%s: fstat", path);
104
}
105
close(fd);
106
107
return S_ISDIR(buf.st_mode);
108
}
109
110
/*
111
* When listing one of several subdirectories, show the name of the
112
* directory.
113
*/
114
static
115
void
116
printheader(const char *file)
117
{
118
/* No blank line before the first header */
119
static int first=1;
120
if (first) {
121
first = 0;
122
}
123
else {
124
printf("\n");
125
}
126
printf("%s:\n", file);
127
}
128
129
/*
130
* Show a single file.
131
* We don't do the neat multicolumn listing that Unix ls does.
132
*/
133
static
134
void
135
print(const char *path)
136
{
137
struct stat statbuf;
138
const char *file;
139
int typech;
140
141
if (lopt || sopt) {
142
int fd;
143
144
fd = open(path, O_RDONLY);
145
if (fd<0) {
146
err(1, "%s", path);
147
}
148
if (fstat(fd, &statbuf)<0) {
149
err(1, "%s: fstat", path);
150
}
151
close(fd);
152
}
153
154
file = basename(path);
155
156
if (sopt) {
157
printf("%3d ", statbuf.st_blocks);
158
}
159
160
if (lopt) {
161
if (S_ISREG(statbuf.st_mode)) {
162
typech = '-';
163
}
164
else if (S_ISDIR(statbuf.st_mode)) {
165
typech = 'd';
166
}
167
else if (S_ISLNK(statbuf.st_mode)) {
168
typech = 'l';
169
}
170
else if (S_ISCHR(statbuf.st_mode)) {
171
typech = 'c';
172
}
173
else if (S_ISBLK(statbuf.st_mode)) {
174
typech = 'b';
175
}
176
else {
177
typech = '?';
178
}
179
180
printf("%crwx------ %2d root %-8llu",
181
typech,
182
statbuf.st_nlink,
183
statbuf.st_size);
184
}
185
printf("%s\n", file);
186
}
187
188
/*
189
* List a directory.
190
*/
191
static
192
void
193
listdir(const char *path, int showheader)
194
{
195
int fd;
196
char buf[1024];
197
char newpath[1024];
198
int len;
199
200
if (showheader) {
201
printheader(path);
202
}
203
204
/*
205
* Open it.
206
*/
207
fd = open(path, O_RDONLY);
208
if (fd<0) {
209
err(1, "%s", path);
210
}
211
212
/*
213
* List the directory.
214
*/
215
while ((len = getdirentry(fd, buf, sizeof(buf)-1)) > 0) {
216
buf[len] = 0;
217
218
/* Assemble the full name of the new item */
219
snprintf(newpath, sizeof(newpath), "%s/%s", path, buf);
220
221
if (aopt || buf[0]!='.') {
222
/* Print it */
223
print(newpath);
224
}
225
}
226
if (len<0) {
227
err(1, "%s: getdirentry", path);
228
}
229
230
/* Done */
231
close(fd);
232
}
233
234
static
235
void
236
recursedir(const char *path)
237
{
238
int fd;
239
char buf[1024];
240
char newpath[1024];
241
int len;
242
243
/*
244
* Open it.
245
*/
246
fd = open(path, O_RDONLY);
247
if (fd<0) {
248
err(1, "%s", path);
249
}
250
251
/*
252
* List the directory.
253
*/
254
while ((len = getdirentry(fd, buf, sizeof(buf)-1)) > 0) {
255
buf[len] = 0;
256
257
/* Assemble the full name of the new item */
258
snprintf(newpath, sizeof(newpath), "%s/%s", path, buf);
259
260
if (!aopt && buf[0]=='.') {
261
/* skip this one */
262
continue;
263
}
264
265
if (!strcmp(buf, ".") || !strcmp(buf, "..")) {
266
/* always skip these */
267
continue;
268
}
269
270
if (!isdir(newpath)) {
271
continue;
272
}
273
274
listdir(newpath, 1 /*showheader*/);
275
if (Ropt) {
276
recursedir(newpath);
277
}
278
}
279
if (len<0) {
280
err(1, "%s", path);
281
}
282
283
close(fd);
284
}
285
286
static
287
void
288
listitem(const char *path, int showheader)
289
{
290
if (!dopt && isdir(path)) {
291
listdir(path, showheader || Ropt);
292
if (Ropt) {
293
recursedir(path);
294
}
295
}
296
else {
297
print(path);
298
}
299
}
300
301
int
302
main(int argc, char *argv[])
303
{
304
int i,j, items=0;
305
306
/*
307
* Go through the arguments and count how many non-option args.
308
*/
309
for (i=1; i<argc; i++) {
310
if (argv[i][0]!='-') {
311
items++;
312
}
313
}
314
315
/*
316
* Now go through the options for real, processing them.
317
*/
318
for (i=1; i<argc; i++) {
319
if (argv[i][0]=='-') {
320
/*
321
* This word is an option.
322
* Process all the option characters in it.
323
*/
324
for (j=1; argv[i][j]; j++) {
325
option(argv[i][j]);
326
}
327
}
328
else {
329
/*
330
* This word isn't an option; list it.
331
*/
332
listitem(argv[i], items>1);
333
}
334
}
335
336
/*
337
* If no filenames were specified to list, list the current
338
* directory.
339
*/
340
if (items==0) {
341
listitem(".", 0);
342
}
343
344
return 0;
345
}
346
347