]>
Commit | Line | Data |
---|---|---|
521e3685 TT |
1 | /* |
2 | * ls.c --- list directories | |
efc6f628 | 3 | * |
521e3685 TT |
4 | * Copyright (C) 1997 Theodore Ts'o. This file may be redistributed |
5 | * under the terms of the GNU Public License. | |
6 | */ | |
7 | ||
d1154eb4 | 8 | #include "config.h" |
521e3685 TT |
9 | #include <stdio.h> |
10 | #include <unistd.h> | |
11 | #include <stdlib.h> | |
12 | #include <ctype.h> | |
13 | #include <string.h> | |
14 | #include <time.h> | |
15 | #ifdef HAVE_ERRNO_H | |
16 | #include <errno.h> | |
17 | #endif | |
18 | #include <sys/types.h> | |
e1018eea TT |
19 | #ifdef HAVE_GETOPT_H |
20 | #include <getopt.h> | |
efc6f628 | 21 | #else |
e1018eea TT |
22 | extern int optind; |
23 | extern char *optarg; | |
24 | #endif | |
521e3685 TT |
25 | |
26 | #include "debugfs.h" | |
27 | ||
28 | /* | |
29 | * list directory | |
30 | */ | |
31 | ||
32 | #define LONG_OPT 0x0001 | |
41bf5993 | 33 | #define PARSE_OPT 0x0002 |
68a1de3d TT |
34 | #define RAW_OPT 0x0004 |
35 | #define ENCRYPT_OPT 0x8000 | |
521e3685 TT |
36 | |
37 | struct list_dir_struct { | |
38 | FILE *f; | |
39 | int col; | |
40 | int options; | |
68a1de3d | 41 | int state; |
521e3685 TT |
42 | }; |
43 | ||
44 | static const char *monstr[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", | |
45 | "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; | |
efc6f628 | 46 | |
68a1de3d TT |
47 | static int print_filename(FILE *f, struct ext2_dir_entry *dirent, int options) |
48 | { | |
49 | unsigned char ch; | |
50 | const char *cp = dirent->name; | |
51 | int len = ext2fs_dirent_name_len(dirent); | |
52 | int retlen = 0; | |
53 | ||
54 | if ((options & ENCRYPT_OPT) && !(options & RAW_OPT)) { | |
55 | if (f) | |
56 | return fprintf(f, "<encrypted (%d)>", len); | |
57 | else { | |
58 | char tmp[1]; | |
59 | return snprintf(tmp, sizeof(tmp), | |
60 | "<encrypted (%d)>", len); | |
61 | } | |
62 | } | |
63 | while (len--) { | |
64 | ch = *cp++; | |
9033a31e | 65 | if (ch < 32 || ch >= 127 || ch == '\\') { |
68a1de3d | 66 | if (f) |
9033a31e EB |
67 | fprintf(f, "\\x%02x", ch); |
68 | retlen += 4; | |
69 | } else { | |
68a1de3d | 70 | if (f) |
9033a31e | 71 | fputc(ch, f); |
68a1de3d TT |
72 | retlen++; |
73 | } | |
68a1de3d TT |
74 | } |
75 | return retlen; | |
76 | } | |
77 | ||
54434927 | 78 | static int list_dir_proc(ext2_ino_t dir EXT2FS_ATTR((unused)), |
e1018eea TT |
79 | int entry, |
80 | struct ext2_dir_entry *dirent, | |
54434927 TT |
81 | int offset EXT2FS_ATTR((unused)), |
82 | int blocksize EXT2FS_ATTR((unused)), | |
83 | char *buf EXT2FS_ATTR((unused)), | |
e1018eea | 84 | void *private) |
521e3685 TT |
85 | { |
86 | struct ext2_inode inode; | |
e1018eea | 87 | ext2_ino_t ino; |
521e3685 TT |
88 | struct tm *tm_p; |
89 | time_t modtime; | |
e1018eea | 90 | char tmp[EXT2_NAME_LEN + 16]; |
521e3685 | 91 | char datestr[80]; |
e1018eea TT |
92 | char lbr, rbr; |
93 | int thislen; | |
68a1de3d | 94 | int options; |
521e3685 | 95 | struct list_dir_struct *ls = (struct list_dir_struct *) private; |
41bf5993 | 96 | struct ext2_dir_entry_tail *t = (struct ext2_dir_entry_tail *) dirent; |
521e3685 | 97 | |
70f4632b | 98 | thislen = ext2fs_dirent_name_len(dirent); |
e1018eea | 99 | ino = dirent->inode; |
68a1de3d TT |
100 | options = ls->options; |
101 | if (ls->state < 2) { | |
102 | ls->state++; | |
103 | options |= RAW_OPT; | |
104 | } | |
e1018eea TT |
105 | |
106 | if (entry == DIRENT_DELETED_FILE) { | |
107 | lbr = '<'; | |
108 | rbr = '>'; | |
109 | ino = 0; | |
110 | } else { | |
111 | lbr = rbr = ' '; | |
112 | } | |
68a1de3d | 113 | if (options & PARSE_OPT) { |
d352f838 | 114 | if (ino) { |
68a1de3d | 115 | if (debugfs_read_inode(ino, &inode, "ls")) |
d352f838 ES |
116 | return 0; |
117 | } else | |
118 | memset(&inode, 0, sizeof(struct ext2_inode)); | |
b55571cd | 119 | fprintf(ls->f,"/%u/%06o/%d/%d/%.*s/", ino, inode.i_mode, |
68a1de3d | 120 | inode.i_uid, inode.i_gid, thislen, dirent->name); |
d056b991 TT |
121 | if (LINUX_S_ISDIR(inode.i_mode)) |
122 | fprintf(ls->f, "/"); | |
123 | else | |
0bd0e593 | 124 | fprintf(ls->f, "%lld/", EXT2_I_SIZE(&inode)); |
d056b991 | 125 | fprintf(ls->f, "\n"); |
68a1de3d | 126 | } else if (options & LONG_OPT) { |
e1018eea | 127 | if (ino) { |
68a1de3d | 128 | if (debugfs_read_inode(ino, &inode, "ls")) |
682720a4 | 129 | return 0; |
e1018eea TT |
130 | modtime = inode.i_mtime; |
131 | tm_p = localtime(&modtime); | |
132 | sprintf(datestr, "%2d-%s-%4d %02d:%02d", | |
133 | tm_p->tm_mday, monstr[tm_p->tm_mon], | |
134 | 1900 + tm_p->tm_year, tm_p->tm_hour, | |
135 | tm_p->tm_min); | |
136 | } else { | |
137 | strcpy(datestr, " "); | |
138 | memset(&inode, 0, sizeof(struct ext2_inode)); | |
139 | } | |
41bf5993 TT |
140 | fprintf(ls->f, "%c%6u%c %6o ", lbr, ino, rbr, inode.i_mode); |
141 | if (entry == DIRENT_CHECKSUM) { | |
142 | fprintf(ls->f, "(dirblock checksum: 0x%08x)\n", | |
143 | t->det_checksum); | |
144 | return 0; | |
145 | } | |
70f4632b JK |
146 | fprintf(ls->f, "(%d) %5d %5d ", |
147 | ext2fs_dirent_file_type(dirent), | |
5113a6e3 | 148 | inode_uid(inode), inode_gid(inode)); |
0bd0e593 | 149 | fprintf(ls->f, "%5llu", EXT2_I_SIZE(&inode)); |
f8dd9510 | 150 | fprintf(ls->f, " %s ", datestr); |
68a1de3d TT |
151 | print_filename(ls->f, dirent, options); |
152 | fputc('\n', ls->f); | |
e1018eea | 153 | } else { |
68a1de3d | 154 | if (entry == DIRENT_CHECKSUM) { |
41bf5993 TT |
155 | sprintf(tmp, "%c%u%c (dirblock checksum: 0x%08x) ", |
156 | lbr, dirent->inode, rbr, t->det_checksum); | |
68a1de3d TT |
157 | thislen = strlen(tmp); |
158 | if (ls->col + thislen > 80) { | |
159 | fputc('\n', ls->f); | |
160 | ls->col = 0; | |
161 | } | |
162 | fprintf(ls->f, "%s", tmp); | |
163 | ls->col += thislen; | |
164 | return 0; | |
165 | } | |
166 | sprintf(tmp, "%c%u%c (%d) ", lbr, dirent->inode, rbr, | |
167 | dirent->rec_len); | |
168 | thislen = strlen(tmp) + 3; | |
169 | thislen += print_filename(NULL, dirent, options); | |
e1018eea TT |
170 | |
171 | if (ls->col + thislen > 80) { | |
68a1de3d | 172 | fputc('\n', ls->f); |
e1018eea TT |
173 | ls->col = 0; |
174 | } | |
175 | fprintf(ls->f, "%s", tmp); | |
68a1de3d TT |
176 | print_filename(ls->f, dirent, options); |
177 | fputs(" ", ls->f); | |
e1018eea TT |
178 | ls->col += thislen; |
179 | } | |
521e3685 TT |
180 | return 0; |
181 | } | |
182 | ||
2fcbcb1b TT |
183 | void do_list_dir(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), |
184 | void *infop EXT2FS_ATTR((unused))) | |
521e3685 | 185 | { |
68a1de3d TT |
186 | struct ext2_inode inode; |
187 | ext2_ino_t ino; | |
b044c2e0 | 188 | int retval; |
e1018eea | 189 | int c; |
41bf5993 | 190 | int flags = DIRENT_FLAG_INCLUDE_EMPTY; |
521e3685 | 191 | struct list_dir_struct ls; |
efc6f628 | 192 | |
521e3685 | 193 | ls.options = 0; |
68a1de3d | 194 | ls.state = 0; |
521e3685 TT |
195 | if (check_fs_open(argv[0])) |
196 | return; | |
197 | ||
88494bb6 | 198 | reset_getopt(); |
68a1de3d | 199 | while ((c = getopt (argc, argv, "cdlpr")) != EOF) { |
e1018eea | 200 | switch (c) { |
41bf5993 TT |
201 | case 'c': |
202 | flags |= DIRENT_FLAG_INCLUDE_CSUM; | |
203 | break; | |
e1018eea TT |
204 | case 'l': |
205 | ls.options |= LONG_OPT; | |
206 | break; | |
207 | case 'd': | |
41bf5993 | 208 | flags |= DIRENT_FLAG_INCLUDE_REMOVED; |
e1018eea | 209 | break; |
d056b991 TT |
210 | case 'p': |
211 | ls.options |= PARSE_OPT; | |
212 | break; | |
68a1de3d TT |
213 | case 'r': |
214 | ls.options |= RAW_OPT; | |
215 | break; | |
49c6b4e9 TT |
216 | default: |
217 | goto print_usage; | |
e1018eea TT |
218 | } |
219 | } | |
220 | ||
221 | if (argc > optind+1) { | |
49c6b4e9 | 222 | print_usage: |
7600aa0f | 223 | com_err(0, 0, "Usage: ls [-c] [-d] [-l] [-p] [-r] file"); |
e1018eea | 224 | return; |
521e3685 TT |
225 | } |
226 | ||
e1018eea | 227 | if (argc == optind) |
68a1de3d | 228 | ino = cwd; |
521e3685 | 229 | else |
68a1de3d TT |
230 | ino = string_to_inode(argv[optind]); |
231 | if (!ino) | |
521e3685 TT |
232 | return; |
233 | ||
234 | ls.f = open_pager(); | |
235 | ls.col = 0; | |
e1018eea | 236 | |
68a1de3d TT |
237 | if (debugfs_read_inode(ino, &inode, argv[0])) |
238 | return; | |
239 | ||
240 | if (inode.i_flags & EXT4_ENCRYPT_FL) | |
241 | ls.options |= ENCRYPT_OPT; | |
242 | ||
243 | retval = ext2fs_dir_iterate2(current_fs, ino, flags, | |
521e3685 TT |
244 | 0, list_dir_proc, &ls); |
245 | fprintf(ls.f, "\n"); | |
246 | close_pager(ls.f); | |
247 | if (retval) | |
9b9a780f | 248 | com_err(argv[1], retval, 0); |
521e3685 TT |
249 | |
250 | return; | |
251 | } | |
252 | ||
253 |