1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
#include "csapp.h"
#define DIRBUFSZ 256
static void print_mode(mode_t m) {
char t;
if (S_ISDIR(m))
t = 'd';
else if (S_ISCHR(m))
t = 'c';
else if (S_ISBLK(m))
t = 'b';
else if (S_ISREG(m))
t = '-';
else if (S_ISFIFO(m))
t = 'f';
else if (S_ISLNK(m))
t = 'l';
else if (S_ISSOCK(m))
t = 's';
else
t = '?';
char ur = (m & S_IRUSR) ? 'r' : '-';
char uw = (m & S_IWUSR) ? 'w' : '-';
char ux = (m & S_IXUSR) ? 'x' : '-';
char gr = (m & S_IRGRP) ? 'r' : '-';
char gw = (m & S_IWGRP) ? 'w' : '-';
char gx = (m & S_IXGRP) ? 'x' : '-';
char or = (m & S_IROTH) ? 'r' : '-';
char ow = (m & S_IWOTH) ? 'w' : '-';
char ox = (m & S_IXOTH) ? 'x' : '-';
/* TODO: Fix code to report set-uid/set-gid/sticky bit as 'ls' does. */
if (m & S_ISUID) ux = 's';
if (m & S_ISGID) gx = 's';
if (m & S_ISVTX) ox = 't';
printf("%c%c%c%c%c%c%c%c%c%c", t, ur, uw, ux, gr, gw, gx, or, ow, ox);
}
static void print_uid(uid_t uid) {
struct passwd *pw = getpwuid(uid);
if (pw)
printf(" %10s", pw->pw_name);
else
printf(" %10d", uid);
}
static void print_gid(gid_t gid) {
struct group *gr = getgrgid(gid);
if (gr)
printf(" %10s", gr->gr_name);
else
printf(" %10d", gid);
}
static void file_info(int dirfd, const char *name) {
struct stat sb[1];
/* TODO: Read file metadata. */
fstatat(dirfd, name, sb, AT_SYMLINK_NOFOLLOW);
print_mode(sb->st_mode);
printf("%4ld", sb->st_nlink);
print_uid(sb->st_uid);
print_gid(sb->st_gid);
/* TODO: For devices: print major/minor pair; for other files: size. */
if (S_ISCHR(sb->st_mode) || S_ISBLK(sb->st_mode)) {
int mi = minor(sb->st_rdev);
int ma = major(sb->st_rdev);
printf(" %d,\t%d", mi, ma);
}
else {
printf("\t%ld", sb->st_size);
}
char *now = ctime(&sb->st_mtime);
now[strlen(now) - 1] = '\0';
printf("%26s", now);
printf(" %s", name);
if (S_ISLNK(sb->st_mode)) {
/* TODO: Read where symlink points to and print '-> destination' string. */
char buf[300];
size_t len = readlinkat(dirfd, name, buf, sizeof(buf));
buf[len] = 0;
printf("-> %s", buf);
}
putchar('\n');
}
int main(int argc, char *argv[]) {
if (!argv[1])
argv[1] = ".";
int dirfd = Open(argv[1], O_RDONLY | O_DIRECTORY, 0);
char buf[DIRBUFSZ];
int n;
while ((n = Getdents(dirfd, (void *)buf, DIRBUFSZ))) {
struct linux_dirent *d;
/* TODO: Iterate over directory entries and call file_info on them. */
int offset = 0;
while (offset < n) {
d = (struct linux_dirent *)(buf + offset);
offset += d->d_reclen;
file_info(dirfd, d->d_name);
}
}
Close(dirfd);
return EXIT_SUCCESS;
}
|