]> git.proxmox.com Git - grub2.git/blob - commands/ls.c
2005-11-13 Marco Gerards <mgerards@xs4all.nl>
[grub2.git] / commands / ls.c
1 /* ls.c - command to list files and devices */
2 /*
3 * GRUB -- GRand Unified Bootloader
4 * Copyright (C) 2003,2005 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 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
17 * along with GRUB; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
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>
31 #include <grub/partition.h>
32 #include <grub/file.h>
33
34 static const struct grub_arg_option options[] =
35 {
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},
39 {0, 0, 0, 0, 0, 0}
40 };
41
42 static const char grub_human_sizes[] = {' ', 'K', 'M', 'G', 'T'};
43
44 static grub_err_t
45 grub_ls_list_devices (int longlist)
46 {
47 auto int grub_ls_print_devices (const char *name);
48 int grub_ls_print_devices (const char *name)
49 {
50 if (longlist)
51 grub_normal_print_device_info (name);
52 else
53 grub_printf ("(%s) ", name);
54
55 return 0;
56 }
57
58 grub_device_iterate (grub_ls_print_devices);
59 grub_putchar ('\n');
60 grub_refresh ();
61
62 return 0;
63 }
64
65 static grub_err_t
66 grub_ls_list_files (char *dirname, int longlist, int all, int human)
67 {
68 char *device_name;
69 grub_fs_t fs;
70 const char *path;
71 grub_device_t dev;
72 auto int print_files (const char *filename, int dir);
73 auto int print_files_long (const char *filename, int dir);
74
75 int print_files (const char *filename, int dir)
76 {
77 if (all || filename[0] != '.')
78 grub_printf ("%s%s ", filename, dir ? "/" : "");
79
80 return 0;
81 }
82
83 int print_files_long (const char *filename, int dir)
84 {
85 char pathname[grub_strlen (dirname) + grub_strlen (filename) + 1];
86
87 if ((! all) && (filename[0] == '.'))
88 return 0;
89
90 if (! dir)
91 {
92 grub_file_t file;
93
94 if (dirname[grub_strlen (dirname) - 1] == '/')
95 grub_sprintf (pathname, "%s%s", dirname, filename);
96 else
97 grub_sprintf (pathname, "%s/%s", dirname, filename);
98
99 /* XXX: For ext2fs symlinks are detected as files while they
100 should be reported as directories. */
101 file = grub_file_open (pathname);
102 if (! file)
103 {
104 grub_errno = 0;
105 return 0;
106 }
107
108 if (! human)
109 grub_printf ("%-12d", file->size);
110 else
111 {
112 float fsize = file->size;
113 int fsz = file->size;
114 int units = 0;
115 char buf[20];
116
117 while (fsz / 1024)
118 {
119 fsize /= 1024;
120 fsz /= 1024;
121 units++;
122 }
123
124 if (units)
125 {
126 grub_sprintf (buf, "%0.2f%c", fsize, grub_human_sizes[units]);
127 grub_printf ("%-12s", buf);
128 }
129 else
130 grub_printf ("%-12d", file->size);
131
132 }
133 grub_file_close (file);
134 }
135 else
136 grub_printf ("%-12s", "DIR");
137
138 grub_printf ("%s%s\n", filename, dir ? "/" : "");
139
140 return 0;
141 }
142
143 device_name = grub_file_get_device_name (dirname);
144 dev = grub_device_open (device_name);
145 if (! dev)
146 goto fail;
147
148 fs = grub_fs_probe (dev);
149 path = grub_strchr (dirname, ')');
150 if (! path)
151 path = dirname;
152 else
153 path++;
154
155 if (! path && ! device_name)
156 {
157 grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid argument");
158 goto fail;
159 }
160
161 if (! *path)
162 {
163 if (grub_errno == GRUB_ERR_UNKNOWN_FS)
164 grub_errno = GRUB_ERR_NONE;
165
166 grub_normal_print_device_info (device_name);
167 }
168 else if (fs)
169 {
170 if (longlist)
171 (fs->dir) (dev, path, print_files_long);
172 else
173 (fs->dir) (dev, path, print_files);
174
175 if (grub_errno == GRUB_ERR_BAD_FILE_TYPE
176 && path[grub_strlen (path) - 1] != '/')
177 {
178 /* PATH might be a regular file. */
179 char *p;
180 grub_file_t file;
181
182 grub_errno = 0;
183
184 file = grub_file_open (dirname);
185 if (! file)
186 goto fail;
187
188 grub_file_close (file);
189
190 p = grub_strrchr (dirname, '/') + 1;
191 dirname = grub_strndup (dirname, p - dirname);
192 if (! dirname)
193 goto fail;
194
195 all = 1;
196 if (longlist)
197 print_files_long (p, 0);
198 else
199 print_files (p, 0);
200
201 grub_free (dirname);
202 }
203
204 if (grub_errno == GRUB_ERR_NONE)
205 grub_putchar ('\n');
206
207 grub_refresh ();
208 }
209
210 fail:
211 if (dev)
212 grub_device_close (dev);
213
214 grub_free (device_name);
215
216 return 0;
217 }
218
219 static grub_err_t
220 grub_cmd_ls (struct grub_arg_list *state, int argc, char **args)
221 {
222 if (argc == 0)
223 grub_ls_list_devices (state[0].set);
224 else
225 grub_ls_list_files (args[0], state[0].set, state[2].set,
226 state[1].set);
227
228 return 0;
229 }
230
231 GRUB_MOD_INIT(ls)
232 {
233 (void)mod; /* To stop warning. */
234 grub_register_command ("ls", grub_cmd_ls, GRUB_COMMAND_FLAG_BOTH,
235 "ls [-l|-h|-a] [FILE]",
236 "List devices and files.", options);
237 }
238
239 GRUB_MOD_FINI(ls)
240 {
241 grub_unregister_command ("ls");
242 }