]> git.proxmox.com Git - grub2.git/blob - grub-core/commands/ls.c
Restructure pxe
[grub2.git] / grub-core / commands / ls.c
1 /* ls.c - command to list files and devices */
2 /*
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2003,2005,2007,2008,2009 Free Software Foundation, Inc.
5 *
6 * GRUB is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * GRUB 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
17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
18 */
19
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>
25 #include <grub/disk.h>
26 #include <grub/device.h>
27 #include <grub/term.h>
28 #include <grub/partition.h>
29 #include <grub/file.h>
30 #include <grub/normal.h>
31 #include <grub/extcmd.h>
32 #include <grub/datetime.h>
33 #include <grub/i18n.h>
34 #include <grub/net.h>
35
36 static const struct grub_arg_option options[] =
37 {
38 {"long", 'l', 0, N_("Show a long list with more detailed information."), 0, 0},
39 {"human-readable", 'h', 0, N_("Print sizes in a human readable format."), 0, 0},
40 {"all", 'a', 0, N_("List all files."), 0, 0},
41 {0, 0, 0, 0, 0, 0}
42 };
43
44 static const char grub_human_sizes[] = {' ', 'K', 'M', 'G', 'T'};
45
46 static grub_err_t
47 grub_ls_list_devices (int longlist)
48 {
49 grub_net_app_level_t proto;
50
51 auto int grub_ls_print_devices (const char *name);
52 int grub_ls_print_devices (const char *name)
53 {
54 if (longlist)
55 grub_normal_print_device_info (name);
56 else
57 grub_printf ("(%s) ", name);
58
59 return 0;
60 }
61
62 grub_device_iterate (grub_ls_print_devices);
63 grub_xputs ("\n");
64
65 grub_puts_ (N_ ("Network protocols:\n"));
66
67 FOR_NET_APP_LEVEL (proto)
68 {
69 grub_printf ("%s ", proto->name);
70 }
71
72 grub_xputs ("\n");
73
74 grub_refresh ();
75
76 return 0;
77 }
78
79 static grub_err_t
80 grub_ls_list_files (char *dirname, int longlist, int all, int human)
81 {
82 char *device_name;
83 grub_fs_t fs;
84 const char *path;
85 grub_device_t dev;
86
87 auto int print_files (const char *filename,
88 const struct grub_dirhook_info *info);
89 auto int print_files_long (const char *filename,
90 const struct grub_dirhook_info *info);
91
92 int print_files (const char *filename, const struct grub_dirhook_info *info)
93 {
94 if (all || filename[0] != '.')
95 grub_printf ("%s%s ", filename, info->dir ? "/" : "");
96
97 return 0;
98 }
99
100 int print_files_long (const char *filename,
101 const struct grub_dirhook_info *info)
102 {
103 if ((! all) && (filename[0] == '.'))
104 return 0;
105
106 if (! info->dir)
107 {
108 grub_file_t file;
109 char *pathname;
110
111 if (dirname[grub_strlen (dirname) - 1] == '/')
112 pathname = grub_xasprintf ("%s%s", dirname, filename);
113 else
114 pathname = grub_xasprintf ("%s/%s", dirname, filename);
115
116 if (!pathname)
117 return 1;
118
119 /* XXX: For ext2fs symlinks are detected as files while they
120 should be reported as directories. */
121 file = grub_file_open (pathname);
122 if (! file)
123 {
124 grub_errno = 0;
125 grub_free (pathname);
126 return 0;
127 }
128
129 if (! human)
130 grub_printf ("%-12llu", (unsigned long long) file->size);
131 else
132 {
133 grub_uint64_t fsize = file->size * 100ULL;
134 int fsz = file->size;
135 int units = 0;
136 char buf[20];
137
138 while (fsz / 1024)
139 {
140 fsize = (fsize + 512) / 1024;
141 fsz /= 1024;
142 units++;
143 }
144
145 if (units)
146 {
147 grub_uint32_t whole, fraction;
148
149 whole = grub_divmod64 (fsize, 100, &fraction);
150 grub_snprintf (buf, sizeof (buf),
151 "%u.%02u%c", whole, fraction,
152 grub_human_sizes[units]);
153 grub_printf ("%-12s", buf);
154 }
155 else
156 grub_printf ("%-12llu", (unsigned long long) file->size);
157
158 }
159 grub_file_close (file);
160 grub_free (pathname);
161 }
162 else
163 grub_printf ("%-12s", "DIR");
164
165 if (info->mtimeset)
166 {
167 struct grub_datetime datetime;
168 grub_unixtime2datetime (info->mtime, &datetime);
169 if (human)
170 grub_printf (" %d-%02d-%02d %02d:%02d:%02d %-11s ",
171 datetime.year, datetime.month, datetime.day,
172 datetime.hour, datetime.minute,
173 datetime.second,
174 grub_get_weekday_name (&datetime));
175 else
176 grub_printf (" %04d%02d%02d%02d%02d%02d ",
177 datetime.year, datetime.month,
178 datetime.day, datetime.hour,
179 datetime.minute, datetime.second);
180 }
181 grub_printf ("%s%s\n", filename, info->dir ? "/" : "");
182
183 return 0;
184 }
185
186 device_name = grub_file_get_device_name (dirname);
187 dev = grub_device_open (device_name);
188 if (! dev)
189 goto fail;
190
191 fs = grub_fs_probe (dev);
192 path = grub_strchr (dirname, ')');
193 if (! path)
194 path = dirname;
195 else
196 path++;
197
198 if (! path && ! device_name)
199 {
200 grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid argument");
201 goto fail;
202 }
203
204 if (! *path)
205 {
206 if (grub_errno == GRUB_ERR_UNKNOWN_FS)
207 grub_errno = GRUB_ERR_NONE;
208
209 grub_normal_print_device_info (device_name);
210 }
211 else if (fs)
212 {
213 if (longlist)
214 (fs->dir) (dev, path, print_files_long);
215 else
216 (fs->dir) (dev, path, print_files);
217
218 if (grub_errno == GRUB_ERR_BAD_FILE_TYPE
219 && path[grub_strlen (path) - 1] != '/')
220 {
221 /* PATH might be a regular file. */
222 char *p;
223 grub_file_t file;
224 struct grub_dirhook_info info;
225 grub_errno = 0;
226
227 file = grub_file_open (dirname);
228 if (! file)
229 goto fail;
230
231 grub_file_close (file);
232
233 p = grub_strrchr (dirname, '/') + 1;
234 dirname = grub_strndup (dirname, p - dirname);
235 if (! dirname)
236 goto fail;
237
238 all = 1;
239 grub_memset (&info, 0, sizeof (info));
240 if (longlist)
241 print_files_long (p, &info);
242 else
243 print_files (p, &info);
244
245 grub_free (dirname);
246 }
247
248 if (grub_errno == GRUB_ERR_NONE)
249 grub_xputs ("\n");
250
251 grub_refresh ();
252 }
253
254 fail:
255 if (dev)
256 grub_device_close (dev);
257
258 grub_free (device_name);
259
260 return 0;
261 }
262
263 static grub_err_t
264 grub_cmd_ls (grub_extcmd_t cmd, int argc, char **args)
265 {
266 struct grub_arg_list *state = cmd->state;
267
268 if (argc == 0)
269 grub_ls_list_devices (state[0].set);
270 else
271 grub_ls_list_files (args[0], state[0].set, state[2].set,
272 state[1].set);
273
274 return 0;
275 }
276
277 static grub_extcmd_t cmd;
278
279 GRUB_MOD_INIT(ls)
280 {
281 cmd = grub_register_extcmd ("ls", grub_cmd_ls, GRUB_COMMAND_FLAG_BOTH,
282 N_("[-l|-h|-a] [FILE]"),
283 N_("List devices and files."), options);
284 }
285
286 GRUB_MOD_FINI(ls)
287 {
288 grub_unregister_extcmd (cmd);
289 }