blob: 1dbd6de8719ef28996a0f84872e334b6436ab64c [file] [log] [blame]
rjw1f884582022-01-06 17:20:42 +08001/*
2 * Copyright (c) 2015 Travis Geiselbrecht
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files
6 * (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify, merge,
8 * publish, distribute, sublicense, and/or sell copies of the Software,
9 * and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23
24#include <err.h>
25#include <debug.h>
26#include <string.h>
27#include <stdio.h>
28#include <trace.h>
29#include <stdlib.h>
30#include <platform.h>
31#include <lib/console.h>
32#include <lib/fs.h>
33
34/* shell console hooks for manipulating the file system */
35
36#if WITH_LIB_CONSOLE
37
38static char *cwd = NULL;
39
40static void set_cwd(const char *path)
41{
42 if (!path) {
43 free(cwd);
44 cwd = NULL;
45 return;
46 }
47
48 size_t len = strlen(path) + 1;
49 char *new_cwd = realloc(cwd, len);
50 if (new_cwd) {
51 cwd = new_cwd;
52 memcpy(cwd, path, len);
53 }
54}
55
56static const char *get_cwd(void)
57{
58 if (!cwd)
59 return "/";
60 return cwd;
61}
62
63static char *prepend_cwd(char *path, size_t len, const char *arg)
64{
65 path[0] = '\0';
66
67 if (!arg || arg[0] != '/') {
68 strlcat(path, get_cwd(), len);
69 if (arg && path[strlen(path) - 1] != '/')
70 strlcat(path, "/", len);
71 }
72 if (arg) {
73 strlcat(path, arg, len);
74 }
75
76 return path;
77}
78
79static int cmd_ls(int argc, const cmd_args *argv)
80{
81 status_t status = NO_ERROR;
82
83 // construct the path
84 char *path = malloc(FS_MAX_PATH_LEN);
85 prepend_cwd(path, FS_MAX_PATH_LEN, (argc >= 2) ? argv[1].str : NULL);
86
87 dirhandle *dhandle;
88 status = fs_open_dir(path, &dhandle);
89 if (status < 0) {
90 printf("error %d opening dir '%s'\n", status, path);
91 goto err;
92 }
93
94 size_t pathlen = strlen(path);
95
96 status_t err;
97 struct dirent ent;
98 while ((err = fs_read_dir(dhandle, &ent)) >= 0) {
99 struct file_stat stat;
100 filehandle *handle;
101
102 // append our filename to the path
103 strlcat(path, "/", FS_MAX_PATH_LEN);
104 strlcat(path, ent.name, FS_MAX_PATH_LEN);
105
106 err = fs_open_file(path, &handle);
107
108 // restore the old path
109 path[pathlen] = '\0';
110
111 if (err < 0) {
112 printf("error %d opening file '%s'\n", err, path);
113 continue;
114 }
115
116 // stat the file
117 err = fs_stat_file(handle, &stat);
118 fs_close_file(handle);
119 if (err < 0) {
120 printf("error %d statting file\n", err);
121 continue;
122 }
123
124 printf("%c %16llu %s\n", stat.is_dir ? 'd' : ' ', stat.size, ent.name);
125 }
126
127 fs_close_dir(dhandle);
128
129err:
130 free(path);
131 return status;;
132}
133
134static int cmd_cd(int argc, const cmd_args *argv)
135{
136 if (argc < 2) {
137 set_cwd(NULL);
138 } else {
139 char *path = malloc(FS_MAX_PATH_LEN);
140 prepend_cwd(path, FS_MAX_PATH_LEN, (argc >= 2) ? argv[1].str : NULL);
141 fs_normalize_path(path);
142
143 if (strlen(path) == 0) {
144 set_cwd(NULL);
145 } else {
146 set_cwd(path);
147 }
148 free(path);
149 }
150 puts(get_cwd());
151
152 return 0;
153}
154
155static int cmd_pwd(int argc, const cmd_args *argv)
156{
157 puts(get_cwd());
158
159 return 0;
160}
161
162static int cmd_mkdir(int argc, const cmd_args *argv)
163{
164 if (argc < 2) {
165 printf("not enough arguments\n");
166 printf("usage: %s <path>\n", argv[0].str);
167 return -1;
168 }
169
170 char *path = malloc(FS_MAX_PATH_LEN);
171
172 int status = fs_make_dir(prepend_cwd(path, FS_MAX_PATH_LEN, argv[1].str));
173 if (status < 0) {
174 printf("error %d making directory '%s'\n", status, path);
175 }
176
177 free(path);
178 return status;
179}
180
181static int cmd_mkfile(int argc, const cmd_args *argv)
182{
183 if (argc < 2) {
184 printf("not enough arguments\n");
185 printf("usage: %s <path> [length]\n", argv[0].str);
186 return -1;
187 }
188
189 char *path = malloc(FS_MAX_PATH_LEN);
190 prepend_cwd(path, FS_MAX_PATH_LEN, argv[1].str);
191
192 filehandle *handle;
193 status_t status = fs_create_file(path, &handle, (argc >= 2) ? argv[2].u : 0);
194 if (status < 0) {
195 printf("error %d making file '%s'\n", status, path);
196 goto err;
197 }
198
199 fs_close_file(handle);
200
201err:
202 free(path);
203 return status;
204}
205
206static int cmd_rm(int argc, const cmd_args *argv)
207{
208 if (argc < 2) {
209 printf("not enough arguments\n");
210 printf("usage: %s <path>\n", argv[0].str);
211 return -1;
212 }
213
214 char *path = malloc(FS_MAX_PATH_LEN);
215 prepend_cwd(path, FS_MAX_PATH_LEN, argv[1].str);
216
217 status_t err = fs_remove_file(path);
218 if (err < 0) {
219 printf("error %d removing file '%s'\n", err, path);
220 return err;
221 }
222
223 return 0;
224}
225
226static int cmd_stat(int argc, const cmd_args *argv)
227{
228 if (argc < 2) {
229 printf("not enough arguments\n");
230 printf("usage: %s <path>\n", argv[0].str);
231 return -1;
232 }
233
234 int status;
235 struct file_stat stat;
236 filehandle *handle;
237
238 char *path = malloc(FS_MAX_PATH_LEN);
239 prepend_cwd(path, FS_MAX_PATH_LEN, argv[1].str);
240
241 status = fs_open_file(path, &handle);
242 if (status < 0) {
243 printf("error %d opening file '%s'\n", status, path);
244 goto err;
245 }
246
247 status = fs_stat_file(handle, &stat);
248
249 fs_close_file(handle);
250
251 if (status < 0) {
252 printf("error %d statting file\n", status);
253 goto err;
254 }
255
256 printf("stat successful:\n");
257 printf("\tis_dir: %d\n", stat.is_dir ? 1 : 0);
258 printf("\tsize: %lld\n", stat.size);
259
260
261err:
262 free(path);
263 return status;
264}
265
266static int cmd_cat(int argc, const cmd_args *argv)
267{
268 status_t status = NO_ERROR;
269
270 if (argc < 2) {
271 printf("not enough arguments\n");
272 printf("usage: %s <path>\n", argv[0].str);
273 return -1;
274 }
275
276 char *path = malloc(FS_MAX_PATH_LEN);
277 prepend_cwd(path, FS_MAX_PATH_LEN, argv[1].str);
278
279 filehandle *handle;
280 status = fs_open_file(path, &handle);
281 if (status < 0) {
282 printf("error %d opening file '%s'\n", status, path);
283 goto err;
284 }
285
286 char buf[64];
287 ssize_t read_len;
288 off_t offset = 0;
289 while ((read_len = fs_read_file(handle, buf, offset, sizeof(buf))) > 0) {
290 for (int i = 0; i < read_len; i++) {
291 putchar(buf[i]);
292 }
293
294 offset += read_len;
295 }
296
297 fs_close_file(handle);
298
299err:
300 free(path);
301 return status;
302}
303
304STATIC_COMMAND_START
305STATIC_COMMAND("ls", "dir listing", &cmd_ls)
306STATIC_COMMAND("cd", "change dir", &cmd_cd)
307STATIC_COMMAND("pwd", "print working dir", &cmd_pwd)
308STATIC_COMMAND("mkdir", "make dir", &cmd_mkdir)
309STATIC_COMMAND("mkfile", "make file", &cmd_mkfile)
310STATIC_COMMAND("rm", "remove file", &cmd_rm)
311STATIC_COMMAND("stat", "stat file", &cmd_stat)
312STATIC_COMMAND("cat", "cat file", &cmd_cat)
313STATIC_COMMAND_END(fs_shell);
314
315#endif
316