Contents of /tags/mkinitrd-6_3_3/klibc/usr/utils/ls.c
Parent Directory | Revision Log
Revision 1182 -
(show annotations)
(download)
Wed Dec 15 21:43:57 2010 UTC (13 years, 6 months ago) by niro
File MIME type: text/plain
File size: 4425 byte(s)
Wed Dec 15 21:43:57 2010 UTC (13 years, 6 months ago) by niro
File MIME type: text/plain
File size: 4425 byte(s)
tagged 'mkinitrd-6_3_3'
1 | #include <stdio.h> |
2 | #include <stdlib.h> |
3 | #include <dirent.h> |
4 | #include <unistd.h> |
5 | #include <sys/stat.h> |
6 | #include <sys/types.h> |
7 | #include <sys/sysmacros.h> |
8 | |
9 | #define STAT_ISSET(mode, mask) (((mode) & mask) == mask) |
10 | |
11 | static size_t max_linksiz = 128; |
12 | static int max_nlinks = 1; |
13 | static int max_size = 1; |
14 | static int max_uid = 1; |
15 | static int max_gid = 1; |
16 | static int max_min = 1; |
17 | static int max_maj = 1; |
18 | |
19 | static void do_preformat(const struct stat *st) |
20 | { |
21 | int bytes; |
22 | |
23 | if ((bytes = snprintf(NULL, 0, "%ju", (uintmax_t) st->st_nlink)) > max_nlinks) |
24 | max_nlinks = bytes; |
25 | |
26 | if ((bytes = snprintf(NULL, 0, "%ju", (uintmax_t) st->st_uid)) > max_uid) |
27 | max_uid = bytes; |
28 | |
29 | if ((bytes = snprintf(NULL, 0, "%ju", (uintmax_t) st->st_gid)) > max_gid) |
30 | max_gid = bytes; |
31 | |
32 | if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) { |
33 | if ((bytes = snprintf(NULL, 0, "%u", major(st->st_rdev))) > max_maj) |
34 | max_maj = bytes; |
35 | |
36 | if ((bytes = snprintf(NULL, 0, "%u", minor(st->st_rdev))) > max_min) |
37 | max_min = bytes; |
38 | |
39 | max_size = max_maj + max_min + 1; |
40 | } |
41 | else { |
42 | if ((bytes = snprintf(NULL, 0, "%ju", (uintmax_t) st->st_size)) > max_size) |
43 | max_size = bytes; |
44 | } |
45 | return; |
46 | } |
47 | |
48 | static void do_stat(const struct stat *st, const char *path) |
49 | { |
50 | char *fmt, *link_name; |
51 | int rc; |
52 | |
53 | switch (st->st_mode & S_IFMT) { |
54 | case S_IFBLK: putchar('b'); break; |
55 | case S_IFCHR: putchar('c'); break; |
56 | case S_IFDIR: putchar('d'); break; |
57 | case S_IFIFO: putchar('p'); break; |
58 | case S_IFLNK: putchar('l'); break; |
59 | case S_IFSOCK: putchar('s'); break; |
60 | case S_IFREG: putchar('-'); break; |
61 | default: putchar('?'); break; |
62 | } |
63 | putchar(STAT_ISSET(st->st_mode, S_IRUSR) ? 'r' : '-'); |
64 | putchar(STAT_ISSET(st->st_mode, S_IWUSR) ? 'w' : '-'); |
65 | |
66 | !STAT_ISSET(st->st_mode, S_ISUID) ? |
67 | putchar(STAT_ISSET(st->st_mode, S_IXUSR) ? 'x' : '-') : |
68 | putchar('S'); |
69 | |
70 | putchar(STAT_ISSET(st->st_mode, S_IRGRP) ? 'r' : '-'); |
71 | putchar(STAT_ISSET(st->st_mode, S_IWGRP) ? 'w' : '-'); |
72 | |
73 | !STAT_ISSET(st->st_mode, S_ISGID) ? |
74 | putchar(STAT_ISSET(st->st_mode, S_IXGRP) ? 'x' : '-') : |
75 | putchar('S'); |
76 | |
77 | putchar(STAT_ISSET(st->st_mode, S_IROTH) ? 'r' : '-'); |
78 | putchar(STAT_ISSET(st->st_mode, S_IWOTH) ? 'w' : '-'); |
79 | |
80 | !STAT_ISSET(st->st_mode, S_ISVTX) ? |
81 | putchar(STAT_ISSET(st->st_mode, S_IXOTH) ? 'x' : '-') : |
82 | putchar(S_ISDIR(st->st_mode) ? 't' : 'T'); |
83 | |
84 | if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) { |
85 | rc = asprintf(&fmt," %%%dju %%%dju %%%dju %%%du,%%%du %%s", |
86 | max_nlinks, max_uid, max_gid, max_maj, max_min); |
87 | if (rc == -1) { |
88 | perror("asprintf"); |
89 | exit(1); |
90 | } |
91 | fprintf(stdout, fmt, |
92 | (uintmax_t) st->st_nlink, |
93 | (uintmax_t) st->st_uid, |
94 | (uintmax_t) st->st_gid, |
95 | major(st->st_rdev), |
96 | minor(st->st_rdev), |
97 | path); |
98 | } |
99 | else { |
100 | rc = asprintf(&fmt," %%%dju %%%dju %%%dju %%%dju %%s", |
101 | max_nlinks, max_uid, max_gid, max_size); |
102 | if (rc == -1) { |
103 | perror("asprintf"); |
104 | exit(1); |
105 | } |
106 | fprintf(stdout, fmt, |
107 | (uintmax_t) st->st_nlink, |
108 | (uintmax_t) st->st_uid, |
109 | (uintmax_t) st->st_gid, |
110 | (uintmax_t) st->st_size, |
111 | path); |
112 | } |
113 | free(fmt); |
114 | |
115 | if (S_ISLNK(st->st_mode)) { |
116 | if ((link_name = malloc(max_linksiz)) == NULL) { |
117 | perror("malloc"); |
118 | exit(1); |
119 | } |
120 | if ((rc = readlink(path, link_name, max_linksiz)) == -1) { |
121 | free(link_name); |
122 | perror("readlink"); |
123 | exit(1); |
124 | } |
125 | link_name[rc] = '\0'; |
126 | fprintf(stdout, " -> %s", link_name); |
127 | free(link_name); |
128 | } |
129 | |
130 | putchar('\n'); |
131 | return; |
132 | } |
133 | |
134 | static void do_dir(const char *path, int preformat) |
135 | { |
136 | DIR *dir; |
137 | struct dirent *dent; |
138 | struct stat st; |
139 | |
140 | if (chdir(path) == -1) { |
141 | perror(path); |
142 | exit(1); |
143 | } |
144 | |
145 | if ((dir = opendir(path)) == NULL) { |
146 | perror(path); |
147 | exit(1); |
148 | } |
149 | |
150 | while ((dent = readdir(dir)) != NULL) { |
151 | if (lstat(dent->d_name, &st)) { |
152 | perror(dent->d_name); |
153 | exit(1); |
154 | } |
155 | (preformat) ? |
156 | do_preformat(&st) : |
157 | do_stat(&st, dent->d_name); |
158 | } |
159 | |
160 | closedir(dir); |
161 | } |
162 | |
163 | int main(int argc, char *argv[]) |
164 | { |
165 | int i; |
166 | struct stat st; |
167 | |
168 | if (argc == 1) { |
169 | do_dir(".", 1); |
170 | do_dir(".", 0); |
171 | return 0; |
172 | } |
173 | |
174 | for (i = 1; i < argc; i++) { |
175 | if (argv[i][0] == '-' && argv[i][1] == 'h') { |
176 | fprintf(stdout, "Usage: ls [-h] [FILE ...]\n"); |
177 | return 0; |
178 | } |
179 | |
180 | if (lstat(argv[i], &st)) { |
181 | perror(argv[i]); |
182 | exit(1); |
183 | } |
184 | |
185 | S_ISDIR(st.st_mode) ? |
186 | do_dir(argv[i], 1) : |
187 | do_preformat(&st); |
188 | } |
189 | |
190 | for (i = 1; i < argc; i++) { |
191 | if (lstat(argv[i], &st)) { |
192 | perror(argv[i]); |
193 | exit(1); |
194 | } |
195 | |
196 | S_ISDIR(st.st_mode) ? |
197 | do_dir(argv[i], 0) : |
198 | do_stat(&st, argv[i]); |
199 | } |
200 | |
201 | return 0; |
202 | } |