1 /*
2 * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3 * Copyright (c) 2020-2021 Huawei Device Co., Ltd. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this list of
9 * conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
12 * of conditions and the following disclaimer in the documentation and/or other materials
13 * provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its contributors may be used
16 * to endorse or promote products derived from this software without specific prior written
17 * permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
29 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include "los_config.h"
33
34 #include "los_task.h"
35 #include "shell.h"
36 #include "sys/stat.h"
37 #include "stdlib.h"
38 #include "unistd.h"
39 #include "fcntl.h"
40 #include "stdio.h"
41 #include "pthread.h"
42
43 #include "shcmd.h"
44 #include "securec.h"
45 #include "show.h"
46
47 #include <dirent.h>
48 #include <ctype.h>
49
50 #define VFS_ERROR OS_ERROR
51 #define SHOW_MAX_LEN CMD_MAX_LEN
52 #define TEMP_PATH_MAX (PATH_MAX + SHOW_MAX_LEN)
53
54 typedef enum {
55 RM_RECURSIVER,
56 RM_FILE,
57 RM_DIR,
58 CP_FILE,
59 CP_COUNT
60 } wildcard_type;
61
62 #define ERROR_OUT_IF(condition, message_function, handler) \
63 do { \
64 if (condition) { \
65 message_function; \
66 handler; \
67 } \
68 } while (0)
69
OsShellCmdDoChdir(const CHAR * path)70 INT32 OsShellCmdDoChdir(const CHAR *path)
71 {
72 CHAR *fullpath = NULL;
73 CHAR *fullpathBak = NULL;
74 DIR *dirent = NULL;
75 INT32 ret;
76 CHAR *shellWorkingDirectory = OsShellGetWorkingDirtectory();
77 if (shellWorkingDirectory == NULL) {
78 return -1;
79 }
80
81 if (path == NULL) {
82 LOS_TaskLock();
83 PRINTK("%s\n", shellWorkingDirectory);
84 LOS_TaskUnlock();
85 return 0;
86 }
87
88 ERROR_OUT_IF(strlen(path) > PATH_MAX, SetErr(ENOTDIR, "cd error"), return -1);
89
90 ret = VfsNormalizePath(shellWorkingDirectory, path, &fullpath);
91 ERROR_OUT_IF(ret < 0, SetErr(-ret, "cd error"), return -1);
92
93 fullpathBak = fullpath;
94 dirent = opendir(fullpath);
95 if (dirent == NULL) {
96 free(fullpathBak);
97 /* this is a not exist directory */
98 PRINTK("no such file or directory\n");
99 return -1;
100 }
101
102 /* close directory stream */
103 (VOID)closedir(dirent);
104
105 /* copy full path to working directory */
106 LOS_TaskLock();
107 ret = strncpy_s(shellWorkingDirectory, PATH_MAX, fullpath, strlen(fullpath));
108 if (ret != EOK) {
109 free(fullpathBak);
110 LOS_TaskUnlock();
111 return -1;
112 }
113 LOS_TaskUnlock();
114 /* release normalize directory path name */
115
116 free(fullpathBak);
117 return 0;
118 }
119
OsLsGetFullpath(const CHAR * path,struct dirent * pdirent)120 STATIC CHAR *OsLsGetFullpath(const CHAR *path, struct dirent *pdirent)
121 {
122 CHAR *fullpath = NULL;
123 INT32 ret;
124 size_t pathLen;
125
126 if (path[1] != '\0') {
127 pathLen = strlen(path) + strlen(pdirent->d_name) + 2; /* 2, path + '/' + d_name + '\0' */
128 fullpath = (CHAR *)malloc(pathLen);
129 if (fullpath == NULL) {
130 goto exit_with_nomem;
131 }
132
133 ret = snprintf_s(fullpath, pathLen, pathLen - 1, "%s/%s", path, pdirent->d_name);
134 if (ret < 0) {
135 free(fullpath);
136 return NULL;
137 }
138 } else {
139 pathLen = strlen(pdirent->d_name) + 2; /* 2, '/' + d_name + '\0' */
140 fullpath = (CHAR *)malloc(pathLen);
141 if (fullpath == NULL) {
142 goto exit_with_nomem;
143 }
144
145 ret = snprintf_s(fullpath, pathLen, pathLen, "/%s", pdirent->d_name);
146 if (ret < 0) {
147 free(fullpath);
148 return NULL;
149 }
150 }
151
152 return fullpath;
153 exit_with_nomem:
154 return (CHAR *)NULL;
155 }
156
OsLs(const CHAR * pathname)157 VOID OsLs(const CHAR *pathname)
158 {
159 struct dirent *pdirent = NULL;
160 CHAR *path = NULL;
161 CHAR *fullpath = NULL;
162 CHAR *fullpathBak = NULL;
163 INT32 ret;
164 struct stat statInfo = { 0 };
165 DIR *d = NULL;
166
167 /* list all directory and file */
168 if (pathname == NULL) {
169 path = strdup("/");
170 if (path == NULL) {
171 return;
172 }
173 } else {
174 ret = VfsNormalizePath(NULL, pathname, &path);
175 if (ret < 0) {
176 SetErrno(-ret);
177 return;
178 }
179 }
180
181 d = opendir(path);
182 if (d == NULL) {
183 PRINT_ERR("No such directory = %s\n", path);
184 free(path);
185 } else {
186 PRINTK("Directory %s:\n", path);
187 do {
188 pdirent = readdir(d);
189 if (pdirent != NULL) {
190 (VOID)memset_s(&statInfo, sizeof(struct stat), 0, sizeof(struct stat));
191 fullpath = OsLsGetFullpath(path, pdirent);
192 if (fullpath == NULL) {
193 free(path);
194 (VOID)closedir(d);
195 return;
196 }
197
198 fullpathBak = fullpath;
199 if (stat(fullpath, &statInfo) == 0) {
200 PRINTK("%-20s", pdirent->d_name);
201 if (S_ISDIR(statInfo.st_mode)) {
202 PRINTK(" %-25s\n", "<DIR>");
203 } else {
204 PRINTK(" %-25lu\n", statInfo.st_size);
205 }
206 } else {
207 PRINTK("BAD file: %s\n", pdirent->d_name);
208 }
209 free(fullpathBak);
210 }
211 } while (pdirent != NULL);
212
213 free(path);
214 (VOID)closedir(d);
215 }
216 }
217
OsShellCmdLs(INT32 argc,const CHAR ** argv)218 INT32 OsShellCmdLs(INT32 argc, const CHAR **argv)
219 {
220 CHAR *fullpath = NULL;
221 const CHAR *filename = NULL;
222 INT32 ret;
223 CHAR *shellWorkingDirectory = OsShellGetWorkingDirtectory();
224 if (shellWorkingDirectory == NULL) {
225 return -1;
226 }
227
228 ERROR_OUT_IF(argc > 1, PRINTK("ls or ls [DIRECTORY]\n"), return -1);
229
230 if (argc == 0) {
231 OsLs(shellWorkingDirectory);
232 return 0;
233 }
234
235 filename = argv[0];
236 ret = VfsNormalizePath(shellWorkingDirectory, filename, &fullpath);
237 ERROR_OUT_IF(ret < 0, SetErr(-ret, "ls error"), return -1);
238
239 OsLs(fullpath);
240 free(fullpath);
241
242 return 0;
243 }
244
OsShellCmdCd(INT32 argc,const CHAR ** argv)245 INT32 OsShellCmdCd(INT32 argc, const CHAR **argv)
246 {
247 if (argc == 0) {
248 (VOID)OsShellCmdDoChdir("/");
249 return 0;
250 }
251
252 OsShellCmdDoChdir(argv[0]);
253 return 0;
254 }
255
256 #define CAT_BUF_SIZE 512
257 #define CAT_TASK_PRIORITY 10
258 #define CAT_TASK_STACK_SIZE 0x3000
259 pthread_mutex_t g_mutex_cat = PTHREAD_MUTEX_INITIALIZER;
260
OsShellCmdCat(INT32 argc,const CHAR ** argv)261 INT32 OsShellCmdCat(INT32 argc, const CHAR **argv)
262 {
263 CHAR *fullpath = NULL;
264 INT32 ret;
265 CHAR buf[CAT_BUF_SIZE];
266 size_t size;
267
268 CHAR *shellWorkingDirectory = OsShellGetWorkingDirtectory();
269
270 if (shellWorkingDirectory == NULL) {
271 return -1;
272 }
273
274 ERROR_OUT_IF(argc != 1, PRINTK("cat [FILE]\n"), return -1);
275
276 ret = VfsNormalizePath(shellWorkingDirectory, argv[0], &fullpath);
277 ERROR_OUT_IF(ret < 0, SetErr(-ret, "cat error"), return -1);
278
279 INT32 fd = open(fullpath, O_RDONLY, 0666);
280
281 if (fd == -1) {
282 ret = -1;
283 free(fullpath);
284 return ret;
285 }
286
287 do {
288 (VOID)memset_s(buf, sizeof(buf), 0, CAT_BUF_SIZE);
289 size = read(fd, buf, CAT_BUF_SIZE - 1);
290 if ((INT32)size < 0) {
291 free(fullpath);
292 close(fd);
293 return -1;
294 }
295 PRINTK("%s", buf);
296 (VOID)LOS_TaskDelay(1);
297 } while (size == CAT_BUF_SIZE - 1);
298
299 free(fullpath);
300 close(fd);
301
302 return ret;
303 }
304
OsShellCmdMkdir(INT32 argc,const CHAR ** argv)305 INT32 OsShellCmdMkdir(INT32 argc, const CHAR **argv)
306 {
307 INT32 ret;
308 CHAR *fullpath = NULL;
309 const CHAR *filename = NULL;
310 CHAR *shellWorkingDirectory = OsShellGetWorkingDirtectory();
311 if (shellWorkingDirectory == NULL) {
312 return -1;
313 }
314
315 ERROR_OUT_IF(argc != 1, PRINTK("mkdir [DIRECTORY]\n"), return 0);
316
317 filename = argv[0];
318 ret = VfsNormalizePath(shellWorkingDirectory, filename, &fullpath);
319 ERROR_OUT_IF(ret < 0, SetErr(-ret, "mkdir error"), return -1);
320
321 ret = mkdir(fullpath, S_IRWXU | S_IRWXG | S_IRWXO);
322 if (ret == -1) {
323 perror("mkdir error");
324 }
325 free(fullpath);
326 return 0;
327 }
328
OsShellCmdPwd(INT32 argc,const CHAR ** argv)329 INT32 OsShellCmdPwd(INT32 argc, const CHAR **argv)
330 {
331 CHAR buf[SHOW_MAX_LEN] = {0};
332 CHAR *shellWorkingDirectory = OsShellGetWorkingDirtectory();
333 if (shellWorkingDirectory == NULL) {
334 return -1;
335 }
336
337 ERROR_OUT_IF(argc > 0, PRINTK("\nUsage: pwd\n"), return -1);
338
339 LOS_TaskLock();
340 if (strncpy_s(buf, SHOW_MAX_LEN, shellWorkingDirectory, SHOW_MAX_LEN - 1) != EOK) {
341 LOS_TaskUnlock();
342 PRINTK("pwd error: strncpy_s error!\n");
343 return -1;
344 }
345 LOS_TaskUnlock();
346
347 PRINTK("%s\n", buf);
348 return 0;
349 }
350
OsShellCmdTouch(INT32 argc,const CHAR ** argv)351 INT32 OsShellCmdTouch(INT32 argc, const CHAR **argv)
352 {
353 INT32 ret;
354 INT32 fd = -1;
355 CHAR *fullpath = NULL;
356 const CHAR *filename = NULL;
357 CHAR *shellWorkingDirectory = OsShellGetWorkingDirtectory();
358 if (shellWorkingDirectory == NULL) {
359 return -1;
360 }
361
362 ERROR_OUT_IF(argc != 1, PRINTK("touch [FILE]\n"), return -1);
363
364 filename = argv[0];
365 ret = VfsNormalizePath(shellWorkingDirectory, filename, &fullpath);
366 ERROR_OUT_IF(ret < 0, SetErr(-ret, "touch error"), return -1);
367
368 fd = open(fullpath, O_RDWR | O_CREAT, 0777);
369 free(fullpath);
370 if (fd == -1) {
371 perror("touch error");
372 return -1;
373 }
374
375 (VOID)close(fd);
376 return 0;
377 }
378
379 #define CP_BUF_SIZE 4096
380 pthread_mutex_t g_mutexCp = PTHREAD_MUTEX_INITIALIZER;
381
OsShellCmdDoCp(const CHAR * srcFilePath,const CHAR * dstFileName)382 STATIC INT32 OsShellCmdDoCp(const CHAR *srcFilePath, const CHAR *dstFileName)
383 {
384 INT32 ret;
385 CHAR *srcFullPath = NULL;
386 CHAR *drcFullPath = NULL;
387 const CHAR *srcFileName = NULL;
388 CHAR *dstFilePath = NULL;
389 CHAR *buf = NULL;
390 const CHAR *filename = NULL;
391 ssize_t rdSize, wrSize;
392 INT32 srcFd = -1;
393 INT32 dstFd = -1;
394 struct stat statBuf;
395 mode_t srcMode;
396 CHAR *shellWorkingDirectory = OsShellGetWorkingDirtectory();
397 if (shellWorkingDirectory == NULL) {
398 return -1;
399 }
400
401 buf = (CHAR *)malloc(CP_BUF_SIZE);
402 if (buf == NULL) {
403 PRINTK("cp error: Out of memory!\n");
404 return -1;
405 }
406
407 /* Get source fullpath. */
408 ret = VfsNormalizePath(shellWorkingDirectory, srcFilePath, &srcFullPath);
409 if (ret < 0) {
410 SetErrno(-ret);
411 PRINTK("cp error: %s\n", strerror(errno));
412 free(buf);
413 return -1;
414 }
415
416 /* Is source path exist? */
417 ret = stat(srcFullPath, &statBuf);
418 if (ret == -1) {
419 PRINTK("cp %s error: %s\n", srcFullPath, strerror(errno));
420 goto errout_with_srcpath;
421 }
422 srcMode = statBuf.st_mode;
423 /* Is source path a directory? */
424 if (S_ISDIR(statBuf.st_mode)) {
425 PRINTK("cp %s error: Source file can't be a directory.\n", srcFullPath);
426 goto errout_with_srcpath;
427 }
428
429 /* Get dest fullpath. */
430 drcFullPath = strdup(dstFileName);
431 if (drcFullPath == NULL) {
432 PRINTK("cp error: Out of memory.\n");
433 goto errout_with_srcpath;
434 }
435 /* Is dest path exist? */
436 ret = stat(drcFullPath, &statBuf);
437 if (ret == 0) {
438 /* Is dest path a directory? */
439 if (S_ISDIR(statBuf.st_mode)) {
440 /* Get source file name without '/'. */
441 srcFileName = srcFilePath;
442 while (1) {
443 filename = strchr(srcFileName, '/');
444 if (filename == NULL) {
445 break;
446 }
447 srcFileName = filename + 1;
448 }
449 /* Add the source file after dest path. */
450 ret = VfsNormalizePath(drcFullPath, srcFileName, &dstFilePath);
451 if (ret < 0) {
452 SetErrno(-ret);
453 PRINTK("cp error. %s.\n", strerror(errno));
454 goto errout_with_path;
455 }
456 free(drcFullPath);
457 drcFullPath = dstFilePath;
458 }
459 }
460
461 /* Is dest file same as source file? */
462 if (strcmp(srcFullPath, drcFullPath) == 0) {
463 PRINTK("cp error: '%s' and '%s' are the same file\n", srcFullPath, drcFullPath);
464 goto errout_with_path;
465 }
466
467 /* Copy begins. */
468 (VOID)pthread_mutex_lock(&g_mutexCp);
469 srcFd = open(srcFullPath, O_RDONLY);
470 if (srcFd < 0) {
471 PRINTK("cp error: can't open %s. %s.\n", srcFullPath, strerror(errno));
472 goto errout_with_mutex;
473 }
474
475 dstFd = open(drcFullPath, O_CREAT | O_WRONLY | O_TRUNC, srcMode);
476 if (dstFd < 0) {
477 PRINTK("cp error: can't create %s. %s.\n", drcFullPath, strerror(errno));
478 goto errout_with_srcfd;
479 }
480
481 do {
482 (VOID)memset_s(buf, CP_BUF_SIZE, 0, CP_BUF_SIZE);
483 rdSize = read(srcFd, buf, CP_BUF_SIZE);
484 if (rdSize < 0) {
485 PRINTK("cp %s %s failed. %s.\n", srcFullPath, drcFullPath, strerror(errno));
486 goto errout_with_fd;
487 }
488 wrSize = write(dstFd, buf, rdSize);
489 if (wrSize != rdSize) {
490 PRINTK("cp %s %s failed. %s.\n", srcFullPath, drcFullPath, strerror(errno));
491 goto errout_with_fd;
492 }
493 } while (rdSize == CP_BUF_SIZE);
494
495 /* Release resource. */
496 free(buf);
497 free(srcFullPath);
498 free(drcFullPath);
499 (VOID)close(srcFd);
500 (VOID)close(dstFd);
501 (VOID)pthread_mutex_unlock(&g_mutexCp);
502 return LOS_OK;
503
504 errout_with_fd:
505 (VOID)close(dstFd);
506 errout_with_srcfd:
507 (VOID)close(srcFd);
508 errout_with_mutex:
509 (VOID)pthread_mutex_unlock(&g_mutexCp);
510 errout_with_path:
511 free(drcFullPath);
512 errout_with_srcpath:
513 free(srcFullPath);
514 free(buf);
515 return -1;
516 }
517
518 /* The separator and EOF for a directory fullpath: '/'and '\0' */
519 #define SEPARATOR_EOF_LEN 2
520
OsShellCmdDoRmdir(const CHAR * pathname)521 STATIC INT32 OsShellCmdDoRmdir(const CHAR *pathname)
522 {
523 struct dirent *dirent = NULL;
524 struct stat statInfo;
525 DIR *d = NULL;
526 CHAR *fullpath = NULL;
527 INT32 ret;
528
529 (VOID)memset_s(&statInfo, sizeof(statInfo), 0, sizeof(struct stat));
530 if (stat(pathname, &statInfo) != 0) {
531 return -1;
532 }
533
534 if (S_ISREG(statInfo.st_mode) || S_ISLNK(statInfo.st_mode)) {
535 return remove(pathname);
536 }
537 d = opendir(pathname);
538 if (d == NULL) {
539 return -1;
540 }
541 while (1) {
542 dirent = readdir(d);
543 if (dirent == NULL) {
544 break;
545 }
546 if (strcmp(dirent->d_name, "..") && strcmp(dirent->d_name, ".")) {
547 size_t fullPathBufSize = strlen(pathname) + strlen(dirent->d_name) + SEPARATOR_EOF_LEN;
548 fullpath = (CHAR *)malloc(fullPathBufSize);
549 if (fullpath == NULL) {
550 PRINTK("malloc failure!\n");
551 (VOID)closedir(d);
552 return -1;
553 }
554 ret = snprintf_s(fullpath, fullPathBufSize, fullPathBufSize - 1, "%s/%s", pathname, dirent->d_name);
555 if (ret < 0) {
556 PRINTK("name is too long!\n");
557 free(fullpath);
558 (VOID)closedir(d);
559 return -1;
560 }
561 (VOID)OsShellCmdDoRmdir(fullpath);
562 free(fullpath);
563 }
564 }
565 (VOID)closedir(d);
566 return rmdir(pathname);
567 }
568
569 /* Wildcard matching operations */
OsWildcardMatch(const CHAR * src,const CHAR * filename)570 STATIC INT32 OsWildcardMatch(const CHAR *src, const CHAR *filename)
571 {
572 INT32 ret;
573
574 if (*src != '\0') {
575 if (*filename == '*') {
576 while ((*filename == '*') || (*filename == '?')) {
577 filename++;
578 }
579
580 if (*filename == '\0') {
581 return 0;
582 }
583
584 while (*src != '\0' && !(*src == *filename)) {
585 src++;
586 }
587
588 if (*src == '\0') {
589 return -1;
590 }
591
592 ret = OsWildcardMatch(src, filename);
593
594 while ((ret != 0) && (*(++src) != '\0')) {
595 if (*src == *filename) {
596 ret = OsWildcardMatch(src, filename);
597 }
598 }
599 return ret;
600 } else {
601 if ((*src == *filename) || (*filename == '?')) {
602 return OsWildcardMatch(++src, ++filename);
603 }
604 return -1;
605 }
606 }
607
608 while (*filename != '\0') {
609 if (*filename != '*') {
610 return -1;
611 }
612 filename++;
613 }
614 return 0;
615 }
616
617 /* To determine whether a wildcard character exists in a path */
OsIsContainersWildcard(const CHAR * filename)618 STATIC INT32 OsIsContainersWildcard(const CHAR *filename)
619 {
620 while (*filename != '\0') {
621 if ((*filename == '*') || (*filename == '?')) {
622 return 1;
623 }
624 filename++;
625 }
626 return 0;
627 }
628
629 /* Delete a matching file or directory */
630
OsWildcardDeleteFileOrDir(const CHAR * fullpath,wildcard_type mark)631 STATIC INT32 OsWildcardDeleteFileOrDir(const CHAR *fullpath, wildcard_type mark)
632 {
633 INT32 ret;
634
635 switch (mark) {
636 case RM_RECURSIVER:
637 ret = OsShellCmdDoRmdir(fullpath);
638 break;
639 case RM_FILE:
640 ret = unlink(fullpath);
641 break;
642 case RM_DIR:
643 ret = rmdir(fullpath);
644 break;
645 default:
646 return (INT32)VFS_ERROR;
647 }
648 if (ret == -1) {
649 PRINTK("%s ", fullpath);
650 perror("rm/rmdir error!");
651 return ret;
652 }
653
654 PRINTK("%s match successful!delete!\n", fullpath);
655 return 0;
656 }
657
658 /* Split the path with wildcard characters */
659
OsWildcardSplitPath(CHAR * fullpath,CHAR ** handle,CHAR ** wait)660 STATIC CHAR *OsWildcardSplitPath(CHAR *fullpath, CHAR **handle, CHAR **wait)
661 {
662 INT32 n;
663 INT32 a = 0;
664 INT32 b = 0;
665 INT32 len = strlen(fullpath);
666
667 for (n = 0; n < len; n++) {
668 if (fullpath[n] == '/') {
669 if (b != 0) {
670 fullpath[n] = '\0';
671 *wait = fullpath + n + 1;
672 break;
673 }
674 a = n;
675 } else if (fullpath[n] == '*' || fullpath[n] == '?') {
676 b = n;
677 fullpath[a] = '\0';
678 if (a == 0) {
679 *handle = fullpath + a + 1;
680 continue;
681 }
682 *handle = fullpath + a + 1;
683 }
684 }
685 return fullpath;
686 }
687
688 /* Handling entry of the path with wildcard characters */
689
OsWildcardExtractDirectory(CHAR * fullpath,VOID * dst,wildcard_type mark)690 STATIC INT32 OsWildcardExtractDirectory(CHAR *fullpath, VOID *dst, wildcard_type mark)
691 {
692 CHAR separator[] = "/";
693 CHAR src[PATH_MAX] = {0};
694 struct dirent *dirent = NULL;
695 CHAR *f = NULL;
696 CHAR *s = NULL;
697 CHAR *t = NULL;
698 INT32 ret = 0;
699 DIR *d = NULL;
700 struct stat statBuf;
701 INT32 deleteFlag = 0;
702
703 f = OsWildcardSplitPath(fullpath, &s, &t);
704
705 if (s == NULL) {
706 if (mark == CP_FILE) {
707 ret = OsShellCmdDoCp(fullpath, dst);
708 } else if (mark == CP_COUNT) {
709 ret = stat(fullpath, &statBuf);
710 if (ret == 0 && (S_ISREG(statBuf.st_mode) || S_ISLNK(statBuf.st_mode))) {
711 (*(INT32 *)dst)++;
712 }
713 } else {
714 ret = OsWildcardDeleteFileOrDir(fullpath, mark);
715 }
716 return ret;
717 }
718
719 d = (*f == '\0') ? opendir("/") : opendir(f);
720
721 if (d == NULL) {
722 perror("opendir error");
723 return (INT32)VFS_ERROR;
724 }
725
726 while (1) {
727 dirent = readdir(d);
728 if (dirent == NULL) {
729 break;
730 }
731
732 ret = strcpy_s(src, PATH_MAX, f);
733 if (ret != EOK) {
734 goto closedir_out;
735 }
736
737 ret = OsWildcardMatch(dirent->d_name, s);
738 if (ret == 0) {
739 ret = strcat_s(src, sizeof(src), separator);
740 if (ret != EOK) {
741 goto closedir_out;
742 }
743 ret = strcat_s(src, sizeof(src), dirent->d_name);
744 if (ret != EOK) {
745 goto closedir_out;
746 }
747 if (t == NULL) {
748 if (mark == CP_FILE) {
749 ret = OsShellCmdDoCp(src, dst);
750 } else if (mark == CP_COUNT) {
751 ret = stat(src, &statBuf);
752 if (ret == 0 && (S_ISREG(statBuf.st_mode) || S_ISLNK(statBuf.st_mode))) {
753 (*(INT32 *)dst)++;
754 if ((*(INT32 *)dst) > 1) {
755 break;
756 }
757 }
758 } else {
759 ret = OsWildcardDeleteFileOrDir(src, mark);
760 if (ret == 0) {
761 deleteFlag = 1;
762 }
763 }
764 } else {
765 ret = strcat_s(src, sizeof(src), separator);
766 if (ret != EOK) {
767 goto closedir_out;
768 }
769 ret = strcat_s(src, sizeof(src), t);
770 if (ret != EOK) {
771 goto closedir_out;
772 }
773 ret = OsWildcardExtractDirectory(src, dst, mark);
774 if (mark == CP_COUNT && (*(INT32 *)dst) > 1) {
775 break;
776 }
777 }
778 }
779 }
780 (VOID)closedir(d);
781 if (deleteFlag == 1) {
782 ret = 0;
783 }
784 return ret;
785 closedir_out:
786 (VOID)closedir(d);
787 return (INT32)VFS_ERROR;
788 }
789
OsShellCmdCp(INT32 argc,const CHAR ** argv)790 INT32 OsShellCmdCp(INT32 argc, const CHAR **argv)
791 {
792 INT32 ret;
793 const CHAR *src = NULL;
794 const CHAR *dst = NULL;
795 CHAR *srcFullPath = NULL;
796 CHAR *drcFullPath = NULL;
797 struct stat statBuf;
798 INT32 count = 0;
799 CHAR *shellWorkingDirectory = OsShellGetWorkingDirtectory();
800 if (shellWorkingDirectory == NULL) {
801 return -1;
802 }
803
804 ERROR_OUT_IF(argc < 2, PRINTK("cp [SOURCEFILE] [DESTFILE]\n"), return -1);
805
806 src = argv[0];
807 dst = argv[1];
808
809 /* Get source fullpath. */
810
811 ret = VfsNormalizePath(shellWorkingDirectory, src, &srcFullPath);
812 if (ret < 0) {
813 SetErrno(-ret);
814 PRINTK("cp error:%s\n", strerror(errno));
815 return -1;
816 }
817
818 if (src[strlen(src) - 1] == '/') {
819 PRINTK("cp %s error: Source file can't be a directory.\n", src);
820 goto errout_with_srcpath;
821 }
822
823 /* Get dest fullpath. */
824 ret = VfsNormalizePath(shellWorkingDirectory, dst, &drcFullPath);
825 if (ret < 0) {
826 SetErrno(-ret);
827 PRINTK("cp error: can't open %s. %s\n", dst, strerror(errno));
828 goto errout_with_srcpath;
829 }
830
831 /* Is dest path exist? */
832
833 ret = stat(drcFullPath, &statBuf);
834 if (ret < 0) {
835 /* Is dest path a directory? */
836 if (dst[strlen(dst) - 1] == '/') {
837 PRINTK("cp error: %s, %s.\n", drcFullPath, strerror(errno));
838 goto errout_with_path;
839 }
840 } else {
841 if ((S_ISREG(statBuf.st_mode) || S_ISLNK(statBuf.st_mode)) && dst[strlen(dst) - 1] == '/') {
842 PRINTK("cp error: %s is not a directory.\n", drcFullPath);
843 goto errout_with_path;
844 }
845 }
846
847 if (OsIsContainersWildcard(srcFullPath)) {
848 if (ret < 0 || S_ISREG(statBuf.st_mode) || S_ISLNK(statBuf.st_mode)) {
849 CHAR *srcCopy = strdup(srcFullPath);
850 if (srcCopy == NULL) {
851 PRINTK("cp error : Out of memory.\n");
852 goto errout_with_path;
853 }
854 (VOID)OsWildcardExtractDirectory(srcCopy, &count, CP_COUNT);
855 free(srcCopy);
856 if (count > 1) {
857 PRINTK("cp error : Can not copy two or more files.\n");
858 goto errout_with_path;
859 }
860 }
861 ret = OsWildcardExtractDirectory(srcFullPath, drcFullPath, CP_FILE);
862 } else {
863 ret = OsShellCmdDoCp(srcFullPath, drcFullPath);
864 }
865 free(drcFullPath);
866 free(srcFullPath);
867 return ret;
868
869 errout_with_path:
870 free(drcFullPath);
871 errout_with_srcpath:
872 free(srcFullPath);
873 return (INT32)VFS_ERROR;
874 }
875
PrintRmUsage(VOID)876 STATIC INLINE VOID PrintRmUsage(VOID)
877 {
878 PRINTK("rm [FILE] or rm [-r/-R] [FILE]\n");
879 }
880
OsShellCmdRm(INT32 argc,const CHAR ** argv)881 INT32 OsShellCmdRm(INT32 argc, const CHAR **argv)
882 {
883 INT32 ret;
884 CHAR *fullpath = NULL;
885 const CHAR *filename = NULL;
886 CHAR *shellWorkingDirectory = OsShellGetWorkingDirtectory();
887
888 if (shellWorkingDirectory == NULL) {
889 return -1;
890 }
891
892 ERROR_OUT_IF(argc != 1 && argc != 2, PrintRmUsage(), return -1);
893
894 if (argc == 2) {
895 ERROR_OUT_IF(strcmp(argv[0], "-r") != 0 && strcmp(argv[0], "-R") != 0, PrintRmUsage(), return -1);
896
897 filename = argv[1];
898 ret = VfsNormalizePath(shellWorkingDirectory, filename, &fullpath);
899 ERROR_OUT_IF(ret < 0, SetErr(-ret, "rm error"), return -1);
900
901 if (OsIsContainersWildcard(fullpath)) {
902 ret = OsWildcardExtractDirectory(fullpath, NULL, RM_RECURSIVER);
903 } else {
904 ret = OsShellCmdDoRmdir(fullpath);
905 }
906 } else {
907 filename = argv[0];
908 ret = VfsNormalizePath(shellWorkingDirectory, filename, &fullpath);
909 ERROR_OUT_IF(ret < 0, SetErr(-ret, "rm error"), return -1);
910
911 if (OsIsContainersWildcard(fullpath)) {
912 ret = OsWildcardExtractDirectory(fullpath, NULL, RM_FILE);
913 } else {
914 ret = unlink(fullpath);
915 }
916 }
917 if (ret == -1) {
918 perror("rm error");
919 }
920 free(fullpath);
921 return 0;
922 }
923
OsShellCmdRmdir(INT32 argc,const CHAR ** argv)924 INT32 OsShellCmdRmdir(INT32 argc, const CHAR **argv)
925 {
926 INT32 ret;
927 CHAR *fullpath = NULL;
928 const CHAR *filename = NULL;
929 CHAR *shellWorkingDirectory = OsShellGetWorkingDirtectory();
930 if (shellWorkingDirectory == NULL) {
931 return -1;
932 }
933
934 ERROR_OUT_IF(argc == 0, PRINTK("rmdir [DIRECTORY]\n"), return -1);
935
936 filename = argv[0];
937 ret = VfsNormalizePath(shellWorkingDirectory, filename, &fullpath);
938 ERROR_OUT_IF(ret < 0, SetErr(-ret, "rmdir error"), return -1);
939
940 if (OsIsContainersWildcard(fullpath)) {
941 ret = OsWildcardExtractDirectory(fullpath, NULL, RM_DIR);
942 } else {
943 ret = rmdir(fullpath);
944 }
945 if (ret == -1) {
946 PRINTK("rmdir %s failed. Error: %s.\n", fullpath, strerror(errno));
947 }
948 free(fullpath);
949
950 return 0;
951 }
952
953