]>
Commit | Line | Data |
---|---|---|
db1771cf | 1 | /* ls.c - command to list files and devices */ |
2 | /* | |
4b13b216 | 3 | * GRUB -- GRand Unified Bootloader |
58bc8bd5 | 4 | * Copyright (C) 2003,2005,2007,2008,2009 Free Software Foundation, Inc. |
db1771cf | 5 | * |
5a79f472 | 6 | * GRUB is free software: you can redistribute it and/or modify |
db1771cf | 7 | * it under the terms of the GNU General Public License as published by |
5a79f472 | 8 | * the Free Software Foundation, either version 3 of the License, or |
db1771cf | 9 | * (at your option) any later version. |
10 | * | |
5a79f472 | 11 | * GRUB is distributed in the hope that it will be useful, |
db1771cf | 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | * GNU General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License | |
5a79f472 | 17 | * along with GRUB. If not, see <http://www.gnu.org/licenses/>. |
db1771cf | 18 | */ |
19 | ||
4b13b216 | 20 | #include <grub/types.h> |
21 | #include <grub/misc.h> | |
22 | #include <grub/mm.h> | |
23 | #include <grub/err.h> | |
24 | #include <grub/dl.h> | |
4b13b216 | 25 | #include <grub/disk.h> |
26 | #include <grub/device.h> | |
27 | #include <grub/term.h> | |
3f1578fe | 28 | #include <grub/partition.h> |
4b13b216 | 29 | #include <grub/file.h> |
b1b797cb | 30 | #include <grub/normal.h> |
31 | #include <grub/extcmd.h> | |
05aaebfb | 32 | #include <grub/datetime.h> |
77a79592 | 33 | #include <grub/i18n.h> |
03b17064 | 34 | #include <grub/net.h> |
db1771cf | 35 | |
e745cf0c VS |
36 | GRUB_MOD_LICENSE ("GPLv3+"); |
37 | ||
4b13b216 | 38 | static const struct grub_arg_option options[] = |
db1771cf | 39 | { |
77a79592 | 40 | {"long", 'l', 0, N_("Show a long list with more detailed information."), 0, 0}, |
41 | {"human-readable", 'h', 0, N_("Print sizes in a human readable format."), 0, 0}, | |
42 | {"all", 'a', 0, N_("List all files."), 0, 0}, | |
db1771cf | 43 | {0, 0, 0, 0, 0, 0} |
44 | }; | |
45 | ||
25239370 CW |
46 | /* Helper for grub_ls_list_devices. */ |
47 | static int | |
48 | grub_ls_print_devices (const char *name, void *data) | |
db1771cf | 49 | { |
25239370 | 50 | int *longlist = data; |
b39f9d20 | 51 | |
7d8848f3 | 52 | if (*longlist) |
25239370 CW |
53 | grub_normal_print_device_info (name); |
54 | else | |
55 | grub_printf ("(%s) ", name); | |
b39f9d20 | 56 | |
25239370 CW |
57 | return 0; |
58 | } | |
59 | ||
60 | static grub_err_t | |
61 | grub_ls_list_devices (int longlist) | |
62 | { | |
63 | grub_device_iterate (grub_ls_print_devices, &longlist); | |
dfed5c6b | 64 | grub_xputs ("\n"); |
03b17064 | 65 | |
54853fd7 | 66 | #if 0 |
03b17064 | 67 | { |
eea84144 VS |
68 | grub_net_app_level_t proto; |
69 | int first = 1; | |
70 | FOR_NET_APP_LEVEL (proto) | |
71 | { | |
72 | if (first) | |
73 | grub_puts_ (N_ ("Network protocols:")); | |
74 | first = 0; | |
75 | grub_printf ("%s ", proto->name); | |
76 | } | |
77 | grub_xputs ("\n"); | |
03b17064 | 78 | } |
eea84144 | 79 | #endif |
03b17064 | 80 | |
4b13b216 | 81 | grub_refresh (); |
db1771cf | 82 | |
db1771cf | 83 | return 0; |
84 | } | |
85 | ||
fc524edf CW |
86 | /* Context for grub_ls_list_files. */ |
87 | struct grub_ls_list_files_ctx | |
db1771cf | 88 | { |
fc524edf CW |
89 | char *dirname; |
90 | int all; | |
91 | int human; | |
92 | }; | |
93 | ||
94 | /* Helper for grub_ls_list_files. */ | |
95 | static int | |
96 | print_files (const char *filename, const struct grub_dirhook_info *info, | |
97 | void *data) | |
98 | { | |
99 | struct grub_ls_list_files_ctx *ctx = data; | |
05aaebfb | 100 | |
fc524edf CW |
101 | if (ctx->all || filename[0] != '.') |
102 | grub_printf ("%s%s ", filename, info->dir ? "/" : ""); | |
b39f9d20 | 103 | |
fc524edf CW |
104 | return 0; |
105 | } | |
b39f9d20 | 106 | |
fc524edf CW |
107 | /* Helper for grub_ls_list_files. */ |
108 | static int | |
109 | print_files_long (const char *filename, const struct grub_dirhook_info *info, | |
110 | void *data) | |
111 | { | |
112 | struct grub_ls_list_files_ctx *ctx = data; | |
113 | ||
114 | if ((! ctx->all) && (filename[0] == '.')) | |
115 | return 0; | |
b39f9d20 | 116 | |
fc524edf | 117 | if (! info->dir) |
db1771cf | 118 | { |
fc524edf CW |
119 | grub_file_t file; |
120 | char *pathname; | |
db1771cf | 121 | |
fc524edf CW |
122 | if (ctx->dirname[grub_strlen (ctx->dirname) - 1] == '/') |
123 | pathname = grub_xasprintf ("%s%s", ctx->dirname, filename); | |
124 | else | |
125 | pathname = grub_xasprintf ("%s/%s", ctx->dirname, filename); | |
b39f9d20 | 126 | |
fc524edf CW |
127 | if (!pathname) |
128 | return 1; | |
8b442f3f | 129 | |
fc524edf CW |
130 | /* XXX: For ext2fs symlinks are detected as files while they |
131 | should be reported as directories. */ | |
ca0a4f68 VS |
132 | file = grub_file_open (pathname, GRUB_FILE_TYPE_GET_SIZE |
133 | | GRUB_FILE_TYPE_NO_DECOMPRESS); | |
fc524edf CW |
134 | if (! file) |
135 | { | |
136 | grub_errno = 0; | |
137 | grub_free (pathname); | |
138 | return 0; | |
139 | } | |
db1771cf | 140 | |
fc524edf CW |
141 | if (! ctx->human) |
142 | grub_printf ("%-12llu", (unsigned long long) file->size); | |
143 | else | |
fa292343 B |
144 | grub_printf ("%-12s", grub_get_human_size (file->size, |
145 | GRUB_HUMAN_SIZE_SHORT)); | |
fc524edf CW |
146 | grub_file_close (file); |
147 | grub_free (pathname); | |
148 | } | |
149 | else | |
150 | grub_printf ("%-12s", _("DIR")); | |
db1771cf | 151 | |
fc524edf CW |
152 | if (info->mtimeset) |
153 | { | |
154 | struct grub_datetime datetime; | |
155 | grub_unixtime2datetime (info->mtime, &datetime); | |
156 | if (ctx->human) | |
157 | grub_printf (" %d-%02d-%02d %02d:%02d:%02d %-11s ", | |
158 | datetime.year, datetime.month, datetime.day, | |
159 | datetime.hour, datetime.minute, | |
160 | datetime.second, | |
161 | grub_get_weekday_name (&datetime)); | |
162 | else | |
163 | grub_printf (" %04d%02d%02d%02d%02d%02d ", | |
164 | datetime.year, datetime.month, | |
165 | datetime.day, datetime.hour, | |
166 | datetime.minute, datetime.second); | |
db1771cf | 167 | } |
fc524edf CW |
168 | grub_printf ("%s%s\n", filename, info->dir ? "/" : ""); |
169 | ||
170 | return 0; | |
171 | } | |
172 | ||
173 | static grub_err_t | |
174 | grub_ls_list_files (char *dirname, int longlist, int all, int human) | |
175 | { | |
176 | char *device_name; | |
177 | grub_fs_t fs; | |
178 | const char *path; | |
179 | grub_device_t dev; | |
db1771cf | 180 | |
4b13b216 | 181 | device_name = grub_file_get_device_name (dirname); |
182 | dev = grub_device_open (device_name); | |
db1771cf | 183 | if (! dev) |
184 | goto fail; | |
185 | ||
4b13b216 | 186 | fs = grub_fs_probe (dev); |
8a572cd7 | 187 | path = grub_strchr (dirname, ')'); |
188 | if (! path) | |
189 | path = dirname; | |
190 | else | |
191 | path++; | |
b39f9d20 | 192 | |
db1771cf | 193 | if (! path && ! device_name) |
194 | { | |
4b13b216 | 195 | grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid argument"); |
db1771cf | 196 | goto fail; |
197 | } | |
b39f9d20 | 198 | |
7224189a | 199 | if (! *path) |
db1771cf | 200 | { |
4b13b216 | 201 | if (grub_errno == GRUB_ERR_UNKNOWN_FS) |
202 | grub_errno = GRUB_ERR_NONE; | |
992ffbbe | 203 | |
3d8df86d ES |
204 | #ifdef GRUB_MACHINE_IEEE1275 |
205 | /* | |
206 | * Close device to prevent a double open in grub_normal_print_device_info(). | |
207 | * Otherwise it may lead to hangs on some IEEE 1275 platforms. | |
208 | */ | |
209 | grub_device_close (dev); | |
210 | dev = NULL; | |
211 | #endif | |
212 | ||
992ffbbe | 213 | grub_normal_print_device_info (device_name); |
db1771cf | 214 | } |
215 | else if (fs) | |
216 | { | |
fc524edf CW |
217 | struct grub_ls_list_files_ctx ctx = { |
218 | .dirname = dirname, | |
219 | .all = all, | |
220 | .human = human | |
221 | }; | |
222 | ||
db1771cf | 223 | if (longlist) |
ad4bfeec | 224 | (fs->fs_dir) (dev, path, print_files_long, &ctx); |
db1771cf | 225 | else |
ad4bfeec | 226 | (fs->fs_dir) (dev, path, print_files, &ctx); |
5f968e1e | 227 | |
228 | if (grub_errno == GRUB_ERR_BAD_FILE_TYPE | |
229 | && path[grub_strlen (path) - 1] != '/') | |
230 | { | |
231 | /* PATH might be a regular file. */ | |
232 | char *p; | |
233 | grub_file_t file; | |
05aaebfb | 234 | struct grub_dirhook_info info; |
5f968e1e | 235 | grub_errno = 0; |
b39f9d20 | 236 | |
ca0a4f68 VS |
237 | file = grub_file_open (dirname, GRUB_FILE_TYPE_GET_SIZE |
238 | | GRUB_FILE_TYPE_NO_DECOMPRESS); | |
5f968e1e | 239 | if (! file) |
240 | goto fail; | |
b39f9d20 | 241 | |
5f968e1e | 242 | grub_file_close (file); |
b39f9d20 | 243 | |
5f968e1e | 244 | p = grub_strrchr (dirname, '/') + 1; |
245 | dirname = grub_strndup (dirname, p - dirname); | |
246 | if (! dirname) | |
247 | goto fail; | |
248 | ||
249 | all = 1; | |
05aaebfb | 250 | grub_memset (&info, 0, sizeof (info)); |
5f968e1e | 251 | if (longlist) |
fc524edf | 252 | print_files_long (p, &info, &ctx); |
5f968e1e | 253 | else |
fc524edf | 254 | print_files (p, &info, &ctx); |
5f968e1e | 255 | |
256 | grub_free (dirname); | |
257 | } | |
258 | ||
259 | if (grub_errno == GRUB_ERR_NONE) | |
dfed5c6b | 260 | grub_xputs ("\n"); |
b39f9d20 | 261 | |
4b13b216 | 262 | grub_refresh (); |
db1771cf | 263 | } |
264 | ||
265 | fail: | |
266 | if (dev) | |
4b13b216 | 267 | grub_device_close (dev); |
b39f9d20 | 268 | |
4b13b216 | 269 | grub_free (device_name); |
db1771cf | 270 | |
271 | return 0; | |
272 | } | |
273 | ||
4b13b216 | 274 | static grub_err_t |
28be0e94 | 275 | grub_cmd_ls (grub_extcmd_context_t ctxt, int argc, char **args) |
db1771cf | 276 | { |
28be0e94 | 277 | struct grub_arg_list *state = ctxt->state; |
84fb3b3d | 278 | int i; |
b1b797cb | 279 | |
db1771cf | 280 | if (argc == 0) |
6a85ce79 | 281 | grub_ls_list_devices (state[0].set); |
db1771cf | 282 | else |
84fb3b3d VS |
283 | for (i = 0; i < argc; i++) |
284 | grub_ls_list_files (args[i], state[0].set, state[2].set, | |
285 | state[1].set); | |
db1771cf | 286 | |
287 | return 0; | |
288 | } | |
289 | ||
b1b797cb | 290 | static grub_extcmd_t cmd; |
291 | ||
6d099807 | 292 | GRUB_MOD_INIT(ls) |
db1771cf | 293 | { |
ed80f7d5 | 294 | cmd = grub_register_extcmd ("ls", grub_cmd_ls, 0, |
e5bfc130 | 295 | N_("[-l|-h|-a] [FILE ...]"), |
77a79592 | 296 | N_("List devices and files."), options); |
db1771cf | 297 | } |
298 | ||
6d099807 | 299 | GRUB_MOD_FINI(ls) |
db1771cf | 300 | { |
b1b797cb | 301 | grub_unregister_extcmd (cmd); |
db1771cf | 302 | } |