]>
Commit | Line | Data |
---|---|---|
db1771cf | 1 | /* ls.c - command to list files and devices */ |
2 | /* | |
4b13b216 | 3 | * GRUB -- GRand Unified Bootloader |
7224189a | 4 | * Copyright (C) 2003,2005 Free Software Foundation, Inc. |
db1771cf | 5 | * |
4b13b216 | 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 |
8 | * the Free Software Foundation; either version 2 of the License, or | |
9 | * (at your option) any later version. | |
10 | * | |
11 | * This program is distributed in the hope that it will be useful, | |
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 | |
4b13b216 | 17 | * along with GRUB; if not, write to the Free Software |
db1771cf | 18 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
19 | */ | |
20 | ||
4b13b216 | 21 | #include <grub/types.h> |
22 | #include <grub/misc.h> | |
23 | #include <grub/mm.h> | |
24 | #include <grub/err.h> | |
25 | #include <grub/dl.h> | |
26 | #include <grub/normal.h> | |
27 | #include <grub/arg.h> | |
28 | #include <grub/disk.h> | |
29 | #include <grub/device.h> | |
30 | #include <grub/term.h> | |
3f1578fe | 31 | #include <grub/partition.h> |
4b13b216 | 32 | #include <grub/file.h> |
db1771cf | 33 | |
4b13b216 | 34 | static const struct grub_arg_option options[] = |
db1771cf | 35 | { |
502c87e8 | 36 | {"long", 'l', 0, "show a long list with more detailed information", 0, 0}, |
37 | {"human-readable", 'h', 0, "print sizes in a human readable format", 0, 0}, | |
38 | {"all", 'a', 0, "list all files", 0, 0}, | |
db1771cf | 39 | {0, 0, 0, 0, 0, 0} |
40 | }; | |
41 | ||
4b13b216 | 42 | static const char grub_human_sizes[] = {' ', 'K', 'M', 'G', 'T'}; |
db1771cf | 43 | |
4b13b216 | 44 | static grub_err_t |
45 | grub_ls_list_disks (int longlist) | |
db1771cf | 46 | { |
4b13b216 | 47 | auto int grub_ls_print_disks (const char *name); |
48 | int grub_ls_print_disks (const char *name) | |
db1771cf | 49 | { |
4b13b216 | 50 | grub_device_t dev; |
51 | auto int print_partition (const grub_partition_t p); | |
db1771cf | 52 | |
4b13b216 | 53 | int print_partition (const grub_partition_t p) |
db1771cf | 54 | { |
4b13b216 | 55 | char *pname = grub_partition_get_name (p); |
db1771cf | 56 | |
57 | if (pname) | |
58 | { | |
59 | if (longlist) | |
4b13b216 | 60 | grub_print_partinfo (dev, pname); |
db1771cf | 61 | else |
4b13b216 | 62 | grub_printf ("(%s,%s) ", name, pname); |
db1771cf | 63 | } |
64 | ||
65 | return 0; | |
66 | } | |
67 | ||
4b13b216 | 68 | dev = grub_device_open (name); |
69 | grub_errno = GRUB_ERR_NONE; | |
db1771cf | 70 | |
71 | if (dev) | |
72 | { | |
73 | if (longlist) | |
5f3607e0 | 74 | { |
75 | grub_printf ("Device: %s", name); | |
76 | ||
77 | if (! dev->disk || ! dev->disk->has_partitions) | |
78 | { | |
79 | grub_fs_t fs; | |
80 | char *label; | |
81 | ||
82 | fs = grub_fs_probe (dev); | |
83 | grub_errno = GRUB_ERR_NONE; | |
84 | ||
85 | grub_printf (", Filesystem type %s", | |
ea409713 | 86 | fs ? fs->name : "unknown"); |
87 | ||
88 | if (fs && fs->label) | |
5f3607e0 | 89 | { |
ea409713 | 90 | (fs->label) (dev, &label); |
91 | if (grub_errno == GRUB_ERR_NONE) | |
92 | { | |
93 | if (label && grub_strlen (label)) | |
94 | grub_printf (", Label: %s", label); | |
95 | grub_free (label); | |
96 | } | |
97 | else | |
98 | grub_errno = GRUB_ERR_NONE; | |
5f3607e0 | 99 | } |
5f3607e0 | 100 | } |
101 | ||
102 | grub_putchar ('\n'); | |
103 | } | |
db1771cf | 104 | else |
4b13b216 | 105 | grub_printf ("(%s) ", name); |
db1771cf | 106 | |
107 | if (dev->disk && dev->disk->has_partitions) | |
108 | { | |
4b13b216 | 109 | grub_partition_iterate (dev->disk, print_partition); |
110 | grub_errno = GRUB_ERR_NONE; | |
db1771cf | 111 | } |
112 | ||
4b13b216 | 113 | grub_device_close (dev); |
db1771cf | 114 | } |
115 | ||
116 | return 0; | |
117 | } | |
118 | ||
4b13b216 | 119 | grub_disk_dev_iterate (grub_ls_print_disks); |
120 | grub_putchar ('\n'); | |
121 | grub_refresh (); | |
db1771cf | 122 | |
db1771cf | 123 | return 0; |
124 | } | |
125 | ||
4b13b216 | 126 | static grub_err_t |
5f968e1e | 127 | grub_ls_list_files (char *dirname, int longlist, int all, int human) |
db1771cf | 128 | { |
129 | char *device_name; | |
4b13b216 | 130 | grub_fs_t fs; |
8a572cd7 | 131 | const char *path; |
4b13b216 | 132 | grub_device_t dev; |
5f968e1e | 133 | auto int print_files (const char *filename, int dir); |
134 | auto int print_files_long (const char *filename, int dir); | |
135 | ||
136 | int print_files (const char *filename, int dir) | |
db1771cf | 137 | { |
138 | if (all || filename[0] != '.') | |
4b13b216 | 139 | grub_printf ("%s%s ", filename, dir ? "/" : ""); |
db1771cf | 140 | |
141 | return 0; | |
142 | } | |
143 | ||
5f968e1e | 144 | int print_files_long (const char *filename, int dir) |
db1771cf | 145 | { |
4b13b216 | 146 | char pathname[grub_strlen (dirname) + grub_strlen (filename) + 1]; |
db1771cf | 147 | |
148 | if ((! all) && (filename[0] == '.')) | |
149 | return 0; | |
150 | ||
151 | if (! dir) | |
152 | { | |
4b13b216 | 153 | grub_file_t file; |
db1771cf | 154 | |
4b13b216 | 155 | if (dirname[grub_strlen (dirname) - 1] == '/') |
156 | grub_sprintf (pathname, "%s%s", dirname, filename); | |
db1771cf | 157 | else |
4b13b216 | 158 | grub_sprintf (pathname, "%s/%s", dirname, filename); |
db1771cf | 159 | |
160 | /* XXX: For ext2fs symlinks are detected as files while they | |
161 | should be reported as directories. */ | |
4b13b216 | 162 | file = grub_file_open (pathname); |
db1771cf | 163 | if (! file) |
164 | { | |
4b13b216 | 165 | grub_errno = 0; |
db1771cf | 166 | return 0; |
167 | } | |
168 | ||
169 | if (! human) | |
4b13b216 | 170 | grub_printf ("%-12d", file->size); |
db1771cf | 171 | else |
172 | { | |
173 | float fsize = file->size; | |
174 | int fsz = file->size; | |
175 | int units = 0; | |
176 | char buf[20]; | |
177 | ||
178 | while (fsz / 1024) | |
179 | { | |
180 | fsize /= 1024; | |
181 | fsz /= 1024; | |
182 | units++; | |
183 | } | |
184 | ||
185 | if (units) | |
186 | { | |
4b13b216 | 187 | grub_sprintf (buf, "%0.2f%c", fsize, grub_human_sizes[units]); |
188 | grub_printf ("%-12s", buf); | |
db1771cf | 189 | } |
190 | else | |
4b13b216 | 191 | grub_printf ("%-12d", file->size); |
db1771cf | 192 | |
193 | } | |
194 | (fs->close) (file); | |
195 | } | |
196 | else | |
4b13b216 | 197 | grub_printf ("%-12s", "DIR"); |
db1771cf | 198 | |
4b13b216 | 199 | grub_printf ("%s%s\n", filename, dir ? "/" : ""); |
db1771cf | 200 | |
201 | return 0; | |
202 | } | |
203 | ||
4b13b216 | 204 | device_name = grub_file_get_device_name (dirname); |
205 | dev = grub_device_open (device_name); | |
db1771cf | 206 | if (! dev) |
207 | goto fail; | |
208 | ||
4b13b216 | 209 | fs = grub_fs_probe (dev); |
8a572cd7 | 210 | path = grub_strchr (dirname, ')'); |
211 | if (! path) | |
212 | path = dirname; | |
213 | else | |
214 | path++; | |
215 | ||
db1771cf | 216 | if (! path && ! device_name) |
217 | { | |
4b13b216 | 218 | grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid argument"); |
db1771cf | 219 | goto fail; |
220 | } | |
221 | ||
7224189a | 222 | if (! *path) |
db1771cf | 223 | { |
4b13b216 | 224 | if (grub_errno == GRUB_ERR_UNKNOWN_FS) |
225 | grub_errno = GRUB_ERR_NONE; | |
db1771cf | 226 | |
ea409713 | 227 | grub_printf ("(%s): Filesystem is %s", |
db1771cf | 228 | device_name, fs ? fs->name : "unknown"); |
ea409713 | 229 | |
230 | if (fs && fs->label) | |
231 | { | |
232 | char *label; | |
233 | ||
234 | (fs->label) (dev, &label); | |
235 | if (grub_errno == GRUB_ERR_NONE) | |
236 | { | |
237 | if (label && grub_strlen (label)) | |
238 | grub_printf (", Label: %s", label); | |
239 | grub_free (label); | |
240 | } | |
241 | else | |
242 | grub_errno = GRUB_ERR_NONE; | |
243 | } | |
244 | ||
245 | grub_putchar ('\n'); | |
db1771cf | 246 | } |
247 | else if (fs) | |
248 | { | |
249 | if (longlist) | |
250 | (fs->dir) (dev, path, print_files_long); | |
251 | else | |
252 | (fs->dir) (dev, path, print_files); | |
5f968e1e | 253 | |
254 | if (grub_errno == GRUB_ERR_BAD_FILE_TYPE | |
255 | && path[grub_strlen (path) - 1] != '/') | |
256 | { | |
257 | /* PATH might be a regular file. */ | |
258 | char *p; | |
259 | grub_file_t file; | |
260 | ||
261 | grub_errno = 0; | |
262 | ||
263 | file = grub_file_open (dirname); | |
264 | if (! file) | |
265 | goto fail; | |
266 | ||
267 | grub_file_close (file); | |
268 | ||
269 | p = grub_strrchr (dirname, '/') + 1; | |
270 | dirname = grub_strndup (dirname, p - dirname); | |
271 | if (! dirname) | |
272 | goto fail; | |
273 | ||
274 | all = 1; | |
275 | if (longlist) | |
276 | print_files_long (p, 0); | |
277 | else | |
278 | print_files (p, 0); | |
279 | ||
280 | grub_free (dirname); | |
281 | } | |
282 | ||
283 | if (grub_errno == GRUB_ERR_NONE) | |
284 | grub_putchar ('\n'); | |
285 | ||
4b13b216 | 286 | grub_refresh (); |
db1771cf | 287 | } |
288 | ||
289 | fail: | |
290 | if (dev) | |
4b13b216 | 291 | grub_device_close (dev); |
db1771cf | 292 | |
4b13b216 | 293 | grub_free (device_name); |
db1771cf | 294 | |
295 | return 0; | |
296 | } | |
297 | ||
4b13b216 | 298 | static grub_err_t |
299 | grub_cmd_ls (struct grub_arg_list *state, int argc, char **args) | |
db1771cf | 300 | { |
db1771cf | 301 | if (argc == 0) |
7224189a | 302 | grub_ls_list_disks (state[0].set); |
db1771cf | 303 | else |
4b13b216 | 304 | grub_ls_list_files (args[0], state[0].set, state[2].set, |
db1771cf | 305 | state[1].set); |
306 | ||
307 | return 0; | |
308 | } | |
309 | ||
4b13b216 | 310 | #ifdef GRUB_UTIL |
db1771cf | 311 | void |
4b13b216 | 312 | grub_ls_init (void) |
db1771cf | 313 | { |
4b13b216 | 314 | grub_register_command ("ls", grub_cmd_ls, GRUB_COMMAND_FLAG_BOTH, |
502c87e8 | 315 | "ls [-l|-h|-a] [FILE]", |
316 | "List devices and files.", options); | |
db1771cf | 317 | } |
318 | ||
319 | void | |
4b13b216 | 320 | grub_ls_fini (void) |
db1771cf | 321 | { |
4b13b216 | 322 | grub_unregister_command ("ls"); |
db1771cf | 323 | } |
4b13b216 | 324 | #else /* ! GRUB_UTIL */ |
325 | GRUB_MOD_INIT | |
db1771cf | 326 | { |
327 | (void)mod; /* To stop warning. */ | |
4b13b216 | 328 | grub_register_command ("ls", grub_cmd_ls, GRUB_COMMAND_FLAG_BOTH, |
502c87e8 | 329 | "ls [-l|-h|-a] [FILE]", |
330 | "List devices and files.", options); | |
db1771cf | 331 | } |
332 | ||
4b13b216 | 333 | GRUB_MOD_FINI |
db1771cf | 334 | { |
4b13b216 | 335 | grub_unregister_command ("ls"); |
db1771cf | 336 | } |
4b13b216 | 337 | #endif /* ! GRUB_UTIL */ |