]>
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, |
68a1de3d | 117 | inode.i_uid, inode.i_gid, thislen, dirent->name); |
d056b991 TT |
118 | if (LINUX_S_ISDIR(inode.i_mode)) |
119 | fprintf(ls->f, "/"); | |
120 | else | |
0bd0e593 | 121 | fprintf(ls->f, "%lld/", EXT2_I_SIZE(&inode)); |
d056b991 | 122 | fprintf(ls->f, "\n"); |
68a1de3d | 123 | } else if (options & LONG_OPT) { |
e1018eea | 124 | if (ino) { |
68a1de3d | 125 | if (debugfs_read_inode(ino, &inode, "ls")) |
682720a4 | 126 | return 0; |
e1018eea TT |
127 | modtime = inode.i_mtime; |
128 | tm_p = localtime(&modtime); | |
129 | sprintf(datestr, "%2d-%s-%4d %02d:%02d", | |
130 | tm_p->tm_mday, monstr[tm_p->tm_mon], | |
131 | 1900 + tm_p->tm_year, tm_p->tm_hour, | |
132 | tm_p->tm_min); | |
133 | } else { | |
134 | strcpy(datestr, " "); | |
135 | memset(&inode, 0, sizeof(struct ext2_inode)); | |
136 | } | |
41bf5993 TT |
137 | fprintf(ls->f, "%c%6u%c %6o ", lbr, ino, rbr, inode.i_mode); |
138 | if (entry == DIRENT_CHECKSUM) { | |
139 | fprintf(ls->f, "(dirblock checksum: 0x%08x)\n", | |
140 | t->det_checksum); | |
141 | return 0; | |
142 | } | |
70f4632b JK |
143 | fprintf(ls->f, "(%d) %5d %5d ", |
144 | ext2fs_dirent_file_type(dirent), | |
5113a6e3 | 145 | inode_uid(inode), inode_gid(inode)); |
0bd0e593 | 146 | fprintf(ls->f, "%5llu", EXT2_I_SIZE(&inode)); |
f8dd9510 | 147 | fprintf(ls->f, " %s ", datestr); |
68a1de3d TT |
148 | print_filename(ls->f, dirent, options); |
149 | fputc('\n', ls->f); | |
e1018eea | 150 | } else { |
68a1de3d | 151 | if (entry == DIRENT_CHECKSUM) { |
41bf5993 TT |
152 | sprintf(tmp, "%c%u%c (dirblock checksum: 0x%08x) ", |
153 | lbr, dirent->inode, rbr, t->det_checksum); | |
68a1de3d TT |
154 | thislen = strlen(tmp); |
155 | if (ls->col + thislen > 80) { | |
156 | fputc('\n', ls->f); | |
157 | ls->col = 0; | |
158 | } | |
159 | fprintf(ls->f, "%s", tmp); | |
160 | ls->col += thislen; | |
161 | return 0; | |
162 | } | |
163 | sprintf(tmp, "%c%u%c (%d) ", lbr, dirent->inode, rbr, | |
164 | dirent->rec_len); | |
165 | thislen = strlen(tmp) + 3; | |
166 | thislen += print_filename(NULL, dirent, options); | |
e1018eea TT |
167 | |
168 | if (ls->col + thislen > 80) { | |
68a1de3d | 169 | fputc('\n', ls->f); |
e1018eea TT |
170 | ls->col = 0; |
171 | } | |
172 | fprintf(ls->f, "%s", tmp); | |
68a1de3d TT |
173 | print_filename(ls->f, dirent, options); |
174 | fputs(" ", ls->f); | |
e1018eea TT |
175 | ls->col += thislen; |
176 | } | |
521e3685 TT |
177 | return 0; |
178 | } | |
179 | ||
2fcbcb1b TT |
180 | void do_list_dir(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)), |
181 | void *infop EXT2FS_ATTR((unused))) | |
521e3685 | 182 | { |
68a1de3d TT |
183 | struct ext2_inode inode; |
184 | ext2_ino_t ino; | |
b044c2e0 | 185 | int retval; |
e1018eea | 186 | int c; |
41bf5993 | 187 | int flags = DIRENT_FLAG_INCLUDE_EMPTY; |
521e3685 | 188 | struct list_dir_struct ls; |
efc6f628 | 189 | |
521e3685 | 190 | ls.options = 0; |
68a1de3d | 191 | ls.state = 0; |
521e3685 TT |
192 | if (check_fs_open(argv[0])) |
193 | return; | |
194 | ||
88494bb6 | 195 | reset_getopt(); |
68a1de3d | 196 | while ((c = getopt (argc, argv, "cdlpr")) != EOF) { |
e1018eea | 197 | switch (c) { |
41bf5993 TT |
198 | case 'c': |
199 | flags |= DIRENT_FLAG_INCLUDE_CSUM; | |
200 | break; | |
e1018eea TT |
201 | case 'l': |
202 | ls.options |= LONG_OPT; | |
203 | break; | |
204 | case 'd': | |
41bf5993 | 205 | flags |= DIRENT_FLAG_INCLUDE_REMOVED; |
e1018eea | 206 | break; |
d056b991 TT |
207 | case 'p': |
208 | ls.options |= PARSE_OPT; | |
209 | break; | |
68a1de3d TT |
210 | case 'r': |
211 | ls.options |= RAW_OPT; | |
212 | break; | |
49c6b4e9 TT |
213 | default: |
214 | goto print_usage; | |
e1018eea TT |
215 | } |
216 | } | |
217 | ||
218 | if (argc > optind+1) { | |
49c6b4e9 | 219 | print_usage: |
7600aa0f | 220 | com_err(0, 0, "Usage: ls [-c] [-d] [-l] [-p] [-r] file"); |
e1018eea | 221 | return; |
521e3685 TT |
222 | } |
223 | ||
e1018eea | 224 | if (argc == optind) |
68a1de3d | 225 | ino = cwd; |
521e3685 | 226 | else |
68a1de3d TT |
227 | ino = string_to_inode(argv[optind]); |
228 | if (!ino) | |
521e3685 TT |
229 | return; |
230 | ||
231 | ls.f = open_pager(); | |
232 | ls.col = 0; | |
e1018eea | 233 | |
68a1de3d TT |
234 | if (debugfs_read_inode(ino, &inode, argv[0])) |
235 | return; | |
236 | ||
237 | if (inode.i_flags & EXT4_ENCRYPT_FL) | |
238 | ls.options |= ENCRYPT_OPT; | |
239 | ||
240 | retval = ext2fs_dir_iterate2(current_fs, ino, flags, | |
521e3685 TT |
241 | 0, list_dir_proc, &ls); |
242 | fprintf(ls.f, "\n"); | |
243 | close_pager(ls.f); | |
244 | if (retval) | |
9b9a780f | 245 | com_err(argv[1], retval, 0); |
521e3685 TT |
246 | |
247 | return; | |
248 | } | |
249 | ||
250 |