1 /*
2 * Copyright (c) 2015 Travis Geiselbrecht
3 *
4 * Use of this source code is governed by a MIT-style
5 * license that can be found in the LICENSE file or at
6 * https://opensource.org/licenses/MIT
7 */
8
9 #include <lk/err.h>
10 #include <lk/debug.h>
11 #include <string.h>
12 #include <stdio.h>
13 #include <lk/trace.h>
14 #include <stdlib.h>
15 #include <platform.h>
16 #include <lk/console_cmd.h>
17 #include <lib/fs.h>
18
19 /* shell console hooks for manipulating the file system */
20
21 static char *cwd = NULL;
22
set_cwd(const char * path)23 static void set_cwd(const char *path) {
24 if (!path) {
25 free(cwd);
26 cwd = NULL;
27 return;
28 }
29
30 size_t len = strlen(path) + 1;
31 char *new_cwd = realloc(cwd, len);
32 if (new_cwd) {
33 cwd = new_cwd;
34 memcpy(cwd, path, len);
35 }
36 }
37
get_cwd(void)38 static const char *get_cwd(void) {
39 if (!cwd)
40 return "/";
41 return cwd;
42 }
43
prepend_cwd(char * path,size_t len,const char * arg)44 static char *prepend_cwd(char *path, size_t len, const char *arg) {
45 path[0] = '\0';
46
47 if (!arg || arg[0] != '/') {
48 strlcat(path, get_cwd(), len);
49 if (arg && path[strlen(path) - 1] != '/')
50 strlcat(path, "/", len);
51 }
52 if (arg) {
53 strlcat(path, arg, len);
54 }
55
56 return path;
57 }
58
cmd_ls(int argc,const console_cmd_args * argv)59 static int cmd_ls(int argc, const console_cmd_args *argv) {
60 status_t status = NO_ERROR;
61
62 // construct the path
63 char *path = malloc(FS_MAX_PATH_LEN);
64 prepend_cwd(path, FS_MAX_PATH_LEN, (argc >= 2) ? argv[1].str : NULL);
65
66 dirhandle *dhandle;
67 status = fs_open_dir(path, &dhandle);
68 if (status < 0) {
69 printf("error %d opening dir '%s'\n", status, path);
70 goto err;
71 }
72
73 size_t pathlen = strlen(path);
74
75 status_t err;
76 struct dirent ent;
77 while ((err = fs_read_dir(dhandle, &ent)) >= 0) {
78 struct file_stat stat;
79 filehandle *handle;
80
81 // append our filename to the path
82 strlcat(path, "/", FS_MAX_PATH_LEN);
83 strlcat(path, ent.name, FS_MAX_PATH_LEN);
84
85 err = fs_open_file(path, &handle);
86
87 // restore the old path
88 path[pathlen] = '\0';
89
90 if (err < 0) {
91 printf("error %d opening file '%s'\n", err, path);
92 continue;
93 }
94
95 // stat the file
96 err = fs_stat_file(handle, &stat);
97 fs_close_file(handle);
98 if (err < 0) {
99 printf("error %d statting file\n", err);
100 continue;
101 }
102
103 printf("%c %16llu %s\n", stat.is_dir ? 'd' : ' ', stat.size, ent.name);
104 }
105
106 fs_close_dir(dhandle);
107
108 err:
109 free(path);
110 return status;;
111 }
112
cmd_cd(int argc,const console_cmd_args * argv)113 static int cmd_cd(int argc, const console_cmd_args *argv) {
114 if (argc < 2) {
115 set_cwd(NULL);
116 } else {
117 char *path = malloc(FS_MAX_PATH_LEN);
118 prepend_cwd(path, FS_MAX_PATH_LEN, (argc >= 2) ? argv[1].str : NULL);
119 fs_normalize_path(path);
120
121 if (strlen(path) == 0) {
122 set_cwd(NULL);
123 } else {
124 set_cwd(path);
125 }
126 free(path);
127 }
128 puts(get_cwd());
129
130 return 0;
131 }
132
cmd_pwd(int argc,const console_cmd_args * argv)133 static int cmd_pwd(int argc, const console_cmd_args *argv) {
134 puts(get_cwd());
135
136 return 0;
137 }
138
cmd_mkdir(int argc,const console_cmd_args * argv)139 static int cmd_mkdir(int argc, const console_cmd_args *argv) {
140 if (argc < 2) {
141 printf("not enough arguments\n");
142 printf("usage: %s <path>\n", argv[0].str);
143 return -1;
144 }
145
146 char *path = malloc(FS_MAX_PATH_LEN);
147
148 int status = fs_make_dir(prepend_cwd(path, FS_MAX_PATH_LEN, argv[1].str));
149 if (status < 0) {
150 printf("error %d making directory '%s'\n", status, path);
151 }
152
153 free(path);
154 return status;
155 }
156
cmd_mkfile(int argc,const console_cmd_args * argv)157 static int cmd_mkfile(int argc, const console_cmd_args *argv) {
158 if (argc < 2) {
159 printf("not enough arguments\n");
160 printf("usage: %s <path> [length]\n", argv[0].str);
161 return -1;
162 }
163
164 char *path = malloc(FS_MAX_PATH_LEN);
165 prepend_cwd(path, FS_MAX_PATH_LEN, argv[1].str);
166
167 filehandle *handle;
168 status_t status = fs_create_file(path, &handle, (argc >= 2) ? argv[2].u : 0);
169 if (status < 0) {
170 printf("error %d making file '%s'\n", status, path);
171 goto err;
172 }
173
174 fs_close_file(handle);
175
176 err:
177 free(path);
178 return status;
179 }
180
cmd_rm(int argc,const console_cmd_args * argv)181 static int cmd_rm(int argc, const console_cmd_args *argv) {
182 if (argc < 2) {
183 printf("not enough arguments\n");
184 printf("usage: %s <path>\n", argv[0].str);
185 return -1;
186 }
187
188 char *path = malloc(FS_MAX_PATH_LEN);
189 prepend_cwd(path, FS_MAX_PATH_LEN, argv[1].str);
190
191 status_t err = fs_remove_file(path);
192 if (err < 0) {
193 printf("error %d removing file '%s'\n", err, path);
194 return err;
195 }
196
197 return 0;
198 }
199
cmd_stat(int argc,const console_cmd_args * argv)200 static int cmd_stat(int argc, const console_cmd_args *argv) {
201 if (argc < 2) {
202 printf("not enough arguments\n");
203 printf("usage: %s <path>\n", argv[0].str);
204 return -1;
205 }
206
207 int status;
208 struct file_stat stat;
209 filehandle *handle;
210
211 char *path = malloc(FS_MAX_PATH_LEN);
212 prepend_cwd(path, FS_MAX_PATH_LEN, argv[1].str);
213
214 status = fs_open_file(path, &handle);
215 if (status < 0) {
216 printf("error %d opening file '%s'\n", status, path);
217 goto err;
218 }
219
220 status = fs_stat_file(handle, &stat);
221
222 fs_close_file(handle);
223
224 if (status < 0) {
225 printf("error %d statting file\n", status);
226 goto err;
227 }
228
229 printf("stat successful:\n");
230 printf("\tis_dir: %d\n", stat.is_dir ? 1 : 0);
231 printf("\tsize: %lld\n", stat.size);
232
233
234 err:
235 free(path);
236 return status;
237 }
238
cmd_cat(int argc,const console_cmd_args * argv)239 static int cmd_cat(int argc, const console_cmd_args *argv) {
240 status_t status = NO_ERROR;
241
242 if (argc < 2) {
243 printf("not enough arguments\n");
244 printf("usage: %s <path>\n", argv[0].str);
245 return -1;
246 }
247
248 char *path = malloc(FS_MAX_PATH_LEN);
249 prepend_cwd(path, FS_MAX_PATH_LEN, argv[1].str);
250
251 filehandle *handle;
252 status = fs_open_file(path, &handle);
253 if (status < 0) {
254 printf("error %d opening file '%s'\n", status, path);
255 goto err;
256 }
257
258 char buf[64];
259 ssize_t read_len;
260 off_t offset = 0;
261 while ((read_len = fs_read_file(handle, buf, offset, sizeof(buf))) > 0) {
262 for (int i = 0; i < read_len; i++) {
263 putchar(buf[i]);
264 }
265
266 offset += read_len;
267 }
268
269 fs_close_file(handle);
270
271 err:
272 free(path);
273 return status;
274 }
275
276 STATIC_COMMAND_START
277 STATIC_COMMAND("ls", "dir listing", &cmd_ls)
278 STATIC_COMMAND("cd", "change dir", &cmd_cd)
279 STATIC_COMMAND("pwd", "print working dir", &cmd_pwd)
280 STATIC_COMMAND("mkdir", "make dir", &cmd_mkdir)
281 STATIC_COMMAND("mkfile", "make file", &cmd_mkfile)
282 STATIC_COMMAND("rm", "remove file", &cmd_rm)
283 STATIC_COMMAND("stat", "stat file", &cmd_stat)
284 STATIC_COMMAND("cat", "cat file", &cmd_cat)
285 STATIC_COMMAND_END(fs_shell);
286