]>
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); | |
9b965241 TT |
57 | else |
58 | return snprintf(NULL, 0, "<encrypted (%d)>", len); | |
68a1de3d TT |
59 | } |
60 | while (len--) { | |
61 | ch = *cp++; | |
9033a31e | 62 | if (ch < 32 || ch >= 127 || ch == '\\') { |
68a1de3d | 63 | if (f) |
9033a31e EB |
64 | fprintf(f, "\\x%02x", ch); |
65 | retlen += 4; | |
66 | } else { | |
68a1de3d | 67 | if (f) |
9033a31e | 68 | fputc(ch, f); |
68a1de3d TT |
69 | retlen++; |
70 | } | |
68a1de3d TT |
71 | } |
72 | return retlen; | |
73 | } | |
74 | ||
54434927 | 75 | static int list_dir_proc(ext2_ino_t dir EXT2FS_ATTR((unused)), |
e1018eea TT |
76 | int entry, |
77 | struct ext2_dir_entry *dirent, | |
54434927 TT |
78 | int offset EXT2FS_ATTR((unused)), |
79 | int blocksize EXT2FS_ATTR((unused)), | |
80 | char *buf EXT2FS_ATTR((unused)), | |
e1018eea | 81 | void *private) |
521e3685 TT |
82 | { |
83 | struct ext2_inode inode; | |
e1018eea | 84 | ext2_ino_t ino; |
521e3685 TT |
85 | struct tm *tm_p; |
86 | time_t modtime; | |
e1018eea | 87 | char tmp[EXT2_NAME_LEN + 16]; |
521e3685 | 88 | char datestr[80]; |
e1018eea TT |
89 | char lbr, rbr; |
90 | int thislen; | |
68a1de3d | 91 | int options; |
521e3685 | 92 | struct list_dir_struct *ls = (struct list_dir_struct *) private; |
41bf5993 | 93 | struct ext2_dir_entry_tail *t = (struct ext2_dir_entry_tail *) dirent; |
521e3685 | 94 | |
70f4632b | 95 | thislen = ext2fs_dirent_name_len(dirent); |
e1018eea | 96 | ino = dirent->inode; |
68a1de3d TT |
97 | options = ls->options; |
98 | if (ls->state < 2) { | |
99 | ls->state++; | |
100 | options |= RAW_OPT; | |
101 | } | |
e1018eea TT |
102 | |
103 | if (entry == DIRENT_DELETED_FILE) { | |
104 | lbr = '<'; | |
105 | rbr = '>'; | |
106 | ino = 0; | |
107 | } else { | |
108 | lbr = rbr = ' '; | |
109 | } | |
68a1de3d | 110 | if (options & PARSE_OPT) { |
d352f838 | 111 | if (ino) { |
68a1de3d | 112 | if (debugfs_read_inode(ino, &inode, "ls")) |
d352f838 ES |
113 | return 0; |
114 | } else | |
115 | memset(&inode, 0, sizeof(struct ext2_inode)); | |
b55571cd | 116 | fprintf(ls->f,"/%u/%06o/%d/%d/%.*s/", ino, inode.i_mode, |
37c2008f | 117 | inode_uid(inode), inode_gid(inode), thislen, dirent->name); |
d056b991 TT |
118 | if (LINUX_S_ISDIR(inode.i_mode)) |
119 | fprintf(ls->f, "/"); | |
120 | else | |
33b9a60c TT |
121 | fprintf(ls->f, "%llu/", |
122 | (unsigned long long) EXT2_I_SIZE(&inode)); | |
d056b991 | 123 | fprintf(ls->f, "\n"); |
68a1de3d | 124 | } else if (options & LONG_OPT) { |
e1018eea | 125 | if (ino) { |
68a1de3d | 126 | if (debugfs_read_inode(ino, &inode, "ls")) |
682720a4 | 127 | return 0; |
e1018eea TT |
128 | modtime = inode.i_mtime; |
129 | tm_p = localtime(&modtime); | |
130 | sprintf(datestr, "%2d-%s-%4d %02d:%02d", | |
131 | tm_p->tm_mday, monstr[tm_p->tm_mon], | |
132 | 1900 + tm_p->tm_year, tm_p->tm_hour, | |
133 | tm_p->tm_min); | |
134 | } else { | |
135 | strcpy(datestr, " "); | |
136 | memset(&inode, 0, sizeof(struct ext2_inode)); | |
137 | } | |
41bf5993 TT |
138 | fprintf(ls->f, "%c%6u%c %6o ", lbr, ino, rbr, inode.i_mode); |
139 | if (entry == DIRENT_CHECKSUM) { | |
140 | fprintf(ls->f, "(dirblock checksum: 0x%08x)\n", | |
141 | t->det_checksum); | |
142 | return 0; | |
143 | } | |
70f4632b JK |
144 | fprintf(ls->f, "(%d) %5d %5d ", |
145 | ext2fs_dirent_file_type(dirent), | |
5113a6e3 | 146 | inode_uid(inode), inode_gid(inode)); |
33b9a60c TT |
147 | fprintf(ls->f, "%5llu", |
148 | (unsigned long long) EXT2_I_SIZE(&inode)); | |
f8dd9510 | 149 | fprintf(ls->f, " %s ", datestr); |
68a1de3d TT |
150 | print_filename(ls->f, dirent, options); |
151 | fputc('\n', ls->f); | |
e1018eea | 152 | } else { |
68a1de3d | 153 | if (entry == DIRENT_CHECKSUM) { |
41bf5993 TT |
154 | sprintf(tmp, "%c%u%c (dirblock checksum: 0x%08x) ", |
155 | lbr, dirent->inode, rbr, t->det_checksum); | |
68a1de3d TT |
156 | thislen = strlen(tmp); |
157 | if (ls->col + thislen > 80) { | |
158 | fputc('\n', ls->f); | |
159 | ls->col = 0; | |
160 | } | |
161 | fprintf(ls->f, "%s", tmp); | |
162 | ls->col += thislen; | |
163 | return 0; | |
164 | } | |
165 | sprintf(tmp, "%c%u%c (%d) ", lbr, dirent->inode, rbr, | |
166 | dirent->rec_len); | |
167 | thislen = strlen(tmp) + 3; | |
168 | thislen += print_filename(NULL, dirent, options); | |
e1018eea TT |
169 | |
170 | if (ls->col + thislen > 80) { | |
68a1de3d | 171 | fputc('\n', ls->f); |
e1018eea TT |
172 | ls->col = 0; |
173 | } | |
174 | fprintf(ls->f, "%s", tmp); | |
68a1de3d TT |
175 | print_filename(ls->f, dirent, options); |
176 | fputs(" ", ls->f); | |
e1018eea TT |
177 | ls->col += thislen; |
178 | } | |
521e3685 TT |
179 | return 0; |
180 | } | |
181 | ||
49125d40 | 182 | void do_list_dir(int argc, ss_argv_t argv, int sci_idx EXT2FS_ATTR((unused)), |
2fcbcb1b | 183 | void *infop EXT2FS_ATTR((unused))) |
521e3685 | 184 | { |
68a1de3d TT |
185 | struct ext2_inode inode; |
186 | ext2_ino_t ino; | |
b044c2e0 | 187 | int retval; |
e1018eea | 188 | int c; |
41bf5993 | 189 | int flags = DIRENT_FLAG_INCLUDE_EMPTY; |
521e3685 | 190 | struct list_dir_struct ls; |
efc6f628 | 191 | |
521e3685 | 192 | ls.options = 0; |
68a1de3d | 193 | ls.state = 0; |
521e3685 TT |
194 | if (check_fs_open(argv[0])) |
195 | return; | |
196 | ||
88494bb6 | 197 | reset_getopt(); |
68a1de3d | 198 | while ((c = getopt (argc, argv, "cdlpr")) != EOF) { |
e1018eea | 199 | switch (c) { |
41bf5993 TT |
200 | case 'c': |
201 | flags |= DIRENT_FLAG_INCLUDE_CSUM; | |
202 | break; | |
e1018eea TT |
203 | case 'l': |
204 | ls.options |= LONG_OPT; | |
205 | break; | |
206 | case 'd': | |
41bf5993 | 207 | flags |= DIRENT_FLAG_INCLUDE_REMOVED; |
e1018eea | 208 | break; |
d056b991 TT |
209 | case 'p': |
210 | ls.options |= PARSE_OPT; | |
211 | break; | |
68a1de3d TT |
212 | case 'r': |
213 | ls.options |= RAW_OPT; | |
214 | break; | |
49c6b4e9 TT |
215 | default: |
216 | goto print_usage; | |
e1018eea TT |
217 | } |
218 | } | |
219 | ||
220 | if (argc > optind+1) { | |
49c6b4e9 | 221 | print_usage: |
7600aa0f | 222 | com_err(0, 0, "Usage: ls [-c] [-d] [-l] [-p] [-r] file"); |
e1018eea | 223 | return; |
521e3685 TT |
224 | } |
225 | ||
e1018eea | 226 | if (argc == optind) |
68a1de3d | 227 | ino = cwd; |
521e3685 | 228 | else |
68a1de3d TT |
229 | ino = string_to_inode(argv[optind]); |
230 | if (!ino) | |
521e3685 TT |
231 | return; |
232 | ||
233 | ls.f = open_pager(); | |
234 | ls.col = 0; | |
e1018eea | 235 | |
68a1de3d TT |
236 | if (debugfs_read_inode(ino, &inode, argv[0])) |
237 | return; | |
238 | ||
239 | if (inode.i_flags & EXT4_ENCRYPT_FL) | |
240 | ls.options |= ENCRYPT_OPT; | |
241 | ||
242 | retval = ext2fs_dir_iterate2(current_fs, ino, flags, | |
521e3685 TT |
243 | 0, list_dir_proc, &ls); |
244 | fprintf(ls.f, "\n"); | |
245 | close_pager(ls.f); | |
246 | if (retval) | |
9b9a780f | 247 | com_err(argv[1], retval, 0); |
521e3685 TT |
248 | |
249 | return; | |
250 | } | |
251 | ||
252 |