• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     } else {
185         PRINTK("Directory %s:\n", path);
186         do {
187             pdirent = readdir(d);
188             if (pdirent != NULL) {
189                 (VOID)memset_s(&statInfo, sizeof(struct stat), 0, sizeof(struct stat));
190                 fullpath = OsLsGetFullpath(path, pdirent);
191                 if (fullpath == NULL) {
192                     free(path);
193                     (VOID)closedir(d);
194                     return;
195                 }
196 
197                 fullpathBak = fullpath;
198                 if (stat(fullpath, &statInfo) == 0) {
199                     PRINTK("%-20s", pdirent->d_name);
200                     if (S_ISDIR(statInfo.st_mode)) {
201                         PRINTK(" %-25s\n", "<DIR>");
202                     } else {
203                         PRINTK(" %-25lu\n", statInfo.st_size);
204                     }
205                 } else {
206                     PRINTK("BAD file: %s\n", pdirent->d_name);
207                 }
208                 free(fullpathBak);
209             }
210         } while (pdirent != NULL);
211 
212         free(path);
213         (VOID)closedir(d);
214     }
215 }
216 
OsShellCmdLs(INT32 argc,const CHAR ** argv)217 INT32 OsShellCmdLs(INT32 argc, const CHAR **argv)
218 {
219     CHAR *fullpath = NULL;
220     const CHAR *filename = NULL;
221     INT32 ret;
222     CHAR *shellWorkingDirectory = OsShellGetWorkingDirtectory();
223     if (shellWorkingDirectory == NULL) {
224         return -1;
225     }
226 
227     ERROR_OUT_IF(argc > 1, PRINTK("ls or ls [DIRECTORY]\n"), return -1);
228 
229     if (argc == 0) {
230         OsLs(shellWorkingDirectory);
231         return 0;
232     }
233 
234     filename = argv[0];
235     ret = VfsNormalizePath(shellWorkingDirectory, filename, &fullpath);
236     ERROR_OUT_IF(ret < 0, SetErr(-ret, "ls error"), return -1);
237 
238     OsLs(fullpath);
239     free(fullpath);
240 
241     return 0;
242 }
243 
OsShellCmdCd(INT32 argc,const CHAR ** argv)244 INT32 OsShellCmdCd(INT32 argc, const CHAR **argv)
245 {
246     if (argc == 0) {
247         (VOID)OsShellCmdDoChdir("/");
248         return 0;
249     }
250 
251     OsShellCmdDoChdir(argv[0]);
252     return 0;
253 }
254 
255 #define CAT_BUF_SIZE  512
256 #define CAT_TASK_PRIORITY  10
257 #define CAT_TASK_STACK_SIZE  0x3000
258 pthread_mutex_t g_mutex_cat = PTHREAD_MUTEX_INITIALIZER;
259 
OsShellCmdCat(INT32 argc,const CHAR ** argv)260 INT32 OsShellCmdCat(INT32 argc, const CHAR **argv)
261 {
262     CHAR *fullpath = NULL;
263     INT32 ret;
264     CHAR buf[CAT_BUF_SIZE];
265     size_t size;
266 
267     CHAR *shellWorkingDirectory = OsShellGetWorkingDirtectory();
268 
269     if (shellWorkingDirectory == NULL) {
270         return -1;
271     }
272 
273     ERROR_OUT_IF(argc != 1, PRINTK("cat [FILE]\n"), return -1);
274 
275     ret = VfsNormalizePath(shellWorkingDirectory, argv[0], &fullpath);
276     ERROR_OUT_IF(ret < 0, SetErr(-ret, "cat error"), return -1);
277 
278     INT32 fd = open(fullpath, O_RDONLY, 0666);
279 
280     if (fd == -1) {
281         ret = -1;
282         free(fullpath);
283         return ret;
284     }
285 
286     do {
287         (VOID)memset_s(buf, sizeof(buf), 0, CAT_BUF_SIZE);
288         size = read(fd, buf, CAT_BUF_SIZE - 1);
289         if ((INT32)size < 0) {
290             free(fullpath);
291             close(fd);
292             return -1;
293         }
294         PRINTK("%s", buf);
295         (VOID)LOS_TaskDelay(1);
296     } while (size == CAT_BUF_SIZE - 1);
297 
298     free(fullpath);
299     close(fd);
300 
301     return ret;
302 }
303 
OsShellCmdMkdir(INT32 argc,const CHAR ** argv)304 INT32 OsShellCmdMkdir(INT32 argc, const CHAR **argv)
305 {
306     INT32 ret;
307     CHAR *fullpath = NULL;
308     const CHAR *filename = NULL;
309     CHAR *shellWorkingDirectory = OsShellGetWorkingDirtectory();
310     if (shellWorkingDirectory == NULL) {
311         return -1;
312     }
313 
314     ERROR_OUT_IF(argc != 1, PRINTK("mkdir [DIRECTORY]\n"), return 0);
315 
316     filename = argv[0];
317     ret = VfsNormalizePath(shellWorkingDirectory, filename, &fullpath);
318     ERROR_OUT_IF(ret < 0, SetErr(-ret, "mkdir error"), return -1);
319 
320     ret = mkdir(fullpath, S_IRWXU | S_IRWXG | S_IRWXO);
321     if (ret == -1) {
322         perror("mkdir error");
323     }
324     free(fullpath);
325     return 0;
326 }
327 
OsShellCmdPwd(INT32 argc,const CHAR ** argv)328 INT32 OsShellCmdPwd(INT32 argc, const CHAR **argv)
329 {
330     CHAR buf[SHOW_MAX_LEN] = {0};
331     CHAR *shellWorkingDirectory = OsShellGetWorkingDirtectory();
332     if (shellWorkingDirectory == NULL) {
333         return -1;
334     }
335 
336     ERROR_OUT_IF(argc > 0, PRINTK("\nUsage: pwd\n"), return -1);
337 
338     LOS_TaskLock();
339     if (strncpy_s(buf, SHOW_MAX_LEN, shellWorkingDirectory, SHOW_MAX_LEN - 1) != EOK) {
340         LOS_TaskUnlock();
341         PRINTK("pwd error: strncpy_s error!\n");
342         return -1;
343     }
344     LOS_TaskUnlock();
345 
346     PRINTK("%s\n", buf);
347     return 0;
348 }
349 
OsShellCmdTouch(INT32 argc,const CHAR ** argv)350 INT32 OsShellCmdTouch(INT32 argc, const CHAR **argv)
351 {
352     INT32 ret;
353     INT32 fd = -1;
354     CHAR *fullpath = NULL;
355     const CHAR *filename = NULL;
356     CHAR *shellWorkingDirectory = OsShellGetWorkingDirtectory();
357     if (shellWorkingDirectory == NULL) {
358         return -1;
359     }
360 
361     ERROR_OUT_IF(argc != 1, PRINTK("touch [FILE]\n"), return -1);
362 
363     filename = argv[0];
364     ret = VfsNormalizePath(shellWorkingDirectory, filename, &fullpath);
365     ERROR_OUT_IF(ret < 0, SetErr(-ret, "touch error"), return -1);
366 
367     fd = open(fullpath, O_RDWR | O_CREAT, 0777);
368     free(fullpath);
369     if (fd == -1) {
370         perror("touch error");
371         return -1;
372     }
373 
374     (VOID)close(fd);
375     return 0;
376 }
377 
378 #define CP_BUF_SIZE 4096
379 pthread_mutex_t g_mutexCp = PTHREAD_MUTEX_INITIALIZER;
380 
OsShellCmdDoCp(const CHAR * srcFilePath,const CHAR * dstFileName)381 STATIC INT32 OsShellCmdDoCp(const CHAR *srcFilePath, const CHAR *dstFileName)
382 {
383     INT32  ret;
384     CHAR *srcFullPath = NULL;
385     CHAR *drcFullPath = NULL;
386     const CHAR *srcFileName = NULL;
387     CHAR *dstFilePath = NULL;
388     CHAR *buf = NULL;
389     const CHAR *filename = NULL;
390     ssize_t rdSize, wrSize;
391     INT32 srcFd = -1;
392     INT32 dstFd = -1;
393     struct stat statBuf;
394     mode_t srcMode;
395     CHAR *shellWorkingDirectory = OsShellGetWorkingDirtectory();
396     if (shellWorkingDirectory == NULL) {
397         return -1;
398     }
399 
400     buf = (CHAR *)malloc(CP_BUF_SIZE);
401     if (buf == NULL) {
402         PRINTK("cp error: Out of memory!\n");
403         return -1;
404     }
405 
406     /* Get source fullpath. */
407     ret = VfsNormalizePath(shellWorkingDirectory, srcFilePath, &srcFullPath);
408     if (ret < 0) {
409         SetErrno(-ret);
410         PRINTK("cp error: %s\n", strerror(errno));
411         free(buf);
412         return -1;
413     }
414 
415     /* Is source path exist? */
416     ret = stat(srcFullPath, &statBuf);
417     if (ret == -1) {
418         PRINTK("cp %s error: %s\n", srcFullPath, strerror(errno));
419         goto errout_with_srcpath;
420     }
421     srcMode = statBuf.st_mode;
422     /* Is source path a directory? */
423     if (S_ISDIR(statBuf.st_mode)) {
424         PRINTK("cp %s error: Source file can't be a directory.\n", srcFullPath);
425         goto errout_with_srcpath;
426     }
427 
428     /* Get dest fullpath. */
429     drcFullPath = strdup(dstFileName);
430     if (drcFullPath == NULL) {
431         PRINTK("cp error: Out of memory.\n");
432         goto errout_with_srcpath;
433     }
434     /* Is dest path exist? */
435     ret = stat(drcFullPath, &statBuf);
436     if (ret == 0) {
437         /* Is dest path a directory? */
438         if (S_ISDIR(statBuf.st_mode)) {
439             /* Get source file name without '/'. */
440             srcFileName = srcFilePath;
441             while (1) {
442                 filename = strchr(srcFileName, '/');
443                 if (filename == NULL) {
444                     break;
445                 }
446                 srcFileName = filename + 1;
447             }
448             /* Add the source file after dest path. */
449             ret = VfsNormalizePath(drcFullPath, srcFileName, &dstFilePath);
450             if (ret < 0) {
451                 SetErrno(-ret);
452                 PRINTK("cp error. %s.\n", strerror(errno));
453                 goto errout_with_path;
454             }
455             free(drcFullPath);
456             drcFullPath = dstFilePath;
457         }
458     }
459 
460     /* Is dest file same as source file? */
461     if (strcmp(srcFullPath, drcFullPath) == 0) {
462         PRINTK("cp error: '%s' and '%s' are the same file\n", srcFullPath, drcFullPath);
463         goto errout_with_path;
464     }
465 
466     /* Copy begins. */
467     (VOID)pthread_mutex_lock(&g_mutexCp);
468     srcFd = open(srcFullPath, O_RDONLY);
469     if (srcFd < 0) {
470         PRINTK("cp error: can't open %s. %s.\n", srcFullPath, strerror(errno));
471         goto errout_with_mutex;
472     }
473 
474     dstFd = open(drcFullPath, O_CREAT | O_WRONLY | O_TRUNC, srcMode);
475     if (dstFd < 0) {
476         PRINTK("cp error: can't create %s. %s.\n", drcFullPath, strerror(errno));
477         goto errout_with_srcfd;
478     }
479 
480     do {
481         (VOID)memset_s(buf, CP_BUF_SIZE, 0, CP_BUF_SIZE);
482         rdSize = read(srcFd, buf, CP_BUF_SIZE);
483         if (rdSize < 0) {
484             PRINTK("cp %s %s failed. %s.\n", srcFullPath, drcFullPath, strerror(errno));
485             goto errout_with_fd;
486         }
487         wrSize = write(dstFd, buf, rdSize);
488         if (wrSize != rdSize) {
489             PRINTK("cp %s %s failed. %s.\n", srcFullPath, drcFullPath, strerror(errno));
490             goto errout_with_fd;
491         }
492     } while (rdSize == CP_BUF_SIZE);
493 
494     /* Release resource. */
495     free(buf);
496     free(srcFullPath);
497     free(drcFullPath);
498     (VOID)close(srcFd);
499     (VOID)close(dstFd);
500     (VOID)pthread_mutex_unlock(&g_mutexCp);
501     return LOS_OK;
502 
503 errout_with_fd:
504     (VOID)close(dstFd);
505 errout_with_srcfd:
506     (VOID)close(srcFd);
507 errout_with_mutex:
508     (VOID)pthread_mutex_unlock(&g_mutexCp);
509 errout_with_path:
510     free(drcFullPath);
511 errout_with_srcpath:
512     free(srcFullPath);
513     free(buf);
514     return -1;
515 }
516 
517 /* The separator and EOF for a directory fullpath: '/'and '\0' */
518 #define SEPARATOR_EOF_LEN 2
519 
OsShellCmdDoRmdir(const CHAR * pathname)520 STATIC INT32 OsShellCmdDoRmdir(const CHAR *pathname)
521 {
522     struct dirent *dirent = NULL;
523     struct stat statInfo;
524     DIR *d = NULL;
525     CHAR *fullpath = NULL;
526     INT32 ret;
527 
528     (VOID)memset_s(&statInfo, sizeof(statInfo), 0, sizeof(struct stat));
529     if (stat(pathname, &statInfo) != 0) {
530         return -1;
531     }
532 
533     if (S_ISREG(statInfo.st_mode) || S_ISLNK(statInfo.st_mode)) {
534         return remove(pathname);
535     }
536     d = opendir(pathname);
537     if (d == NULL) {
538         return -1;
539     }
540     while (1) {
541         dirent = readdir(d);
542         if (dirent == NULL) {
543             break;
544         }
545         if (strcmp(dirent->d_name, "..") && strcmp(dirent->d_name, ".")) {
546             size_t fullPathBufSize = strlen(pathname) + strlen(dirent->d_name) + SEPARATOR_EOF_LEN;
547             if (fullPathBufSize <= 0) {
548                 PRINTK("buffer size is invalid!\n");
549                 (VOID)closedir(d);
550                 return -1;
551             }
552             fullpath = (CHAR *)malloc(fullPathBufSize);
553             if (fullpath == NULL) {
554                 PRINTK("malloc failure!\n");
555                 (VOID)closedir(d);
556                 return -1;
557             }
558             ret = snprintf_s(fullpath, fullPathBufSize, fullPathBufSize - 1, "%s/%s", pathname, dirent->d_name);
559             if (ret < 0) {
560                 PRINTK("name is too long!\n");
561                 free(fullpath);
562                 (VOID)closedir(d);
563                 return -1;
564             }
565             (VOID)OsShellCmdDoRmdir(fullpath);
566             free(fullpath);
567         }
568     }
569     (VOID)closedir(d);
570     return rmdir(pathname);
571 }
572 
573 /*  Wildcard matching operations  */
OsWildcardMatch(const CHAR * src,const CHAR * filename)574 STATIC INT32 OsWildcardMatch(const CHAR *src, const CHAR *filename)
575 {
576     INT32 ret;
577 
578     if (*src != '\0') {
579         if (*filename == '*') {
580             while ((*filename == '*') || (*filename == '?')) {
581                 filename++;
582             }
583 
584             if (*filename == '\0') {
585                 return 0;
586             }
587 
588             while (*src != '\0' && !(*src == *filename)) {
589                 src++;
590             }
591 
592             if (*src == '\0') {
593                 return -1;
594             }
595 
596             ret = OsWildcardMatch(src, filename);
597 
598             while ((ret != 0) && (*(++src) != '\0')) {
599                 if (*src == *filename) {
600                     ret = OsWildcardMatch(src, filename);
601                 }
602             }
603             return ret;
604         } else {
605             if ((*src == *filename) || (*filename == '?')) {
606                 return OsWildcardMatch(++src, ++filename);
607             }
608             return -1;
609         }
610     }
611 
612     while (*filename != '\0') {
613         if (*filename != '*') {
614             return -1;
615         }
616         filename++;
617     }
618     return 0;
619 }
620 
621 /*   To determine whether a wildcard character exists in a path   */
OsIsContainersWildcard(const CHAR * filename)622 STATIC INT32 OsIsContainersWildcard(const CHAR *filename)
623 {
624     while (*filename != '\0') {
625         if ((*filename == '*') || (*filename == '?')) {
626             return 1;
627         }
628         filename++;
629     }
630     return 0;
631 }
632 
633 /*  Delete a matching file or directory  */
634 
OsWildcardDeleteFileOrDir(const CHAR * fullpath,wildcard_type mark)635 STATIC INT32 OsWildcardDeleteFileOrDir(const CHAR *fullpath, wildcard_type mark)
636 {
637     INT32 ret;
638 
639     switch (mark) {
640         case RM_RECURSIVER:
641             ret = OsShellCmdDoRmdir(fullpath);
642             break;
643         case RM_FILE:
644             ret = unlink(fullpath);
645             break;
646         case RM_DIR:
647             ret = rmdir(fullpath);
648             break;
649         default:
650             return (INT32)VFS_ERROR;
651     }
652     if (ret == -1) {
653         PRINTK("%s  ", fullpath);
654         perror("rm/rmdir error!");
655         return ret;
656     }
657 
658     PRINTK("%s match successful!delete!\n", fullpath);
659     return 0;
660 }
661 
662 /*  Split the path with wildcard characters  */
663 
OsWildcardSplitPath(CHAR * fullpath,CHAR ** handle,CHAR ** wait)664 STATIC CHAR *OsWildcardSplitPath(CHAR *fullpath, CHAR **handle, CHAR **wait)
665 {
666     INT32 n;
667     INT32 a = 0;
668     INT32 b = 0;
669     INT32 len  = strlen(fullpath);
670 
671     for (n = 0; n < len; n++) {
672         if (fullpath[n] == '/') {
673             if (b != 0) {
674                 fullpath[n] = '\0';
675                 *wait = fullpath + n + 1;
676                 break;
677             }
678             a = n;
679         } else if (fullpath[n] == '*' || fullpath[n] == '?') {
680             b = n;
681             fullpath[a] = '\0';
682             if (a == 0) {
683                 *handle = fullpath + a + 1;
684                 continue;
685             }
686             *handle = fullpath + a + 1;
687         }
688     }
689     return fullpath;
690 }
691 
692 /*  Handling entry of the path with wildcard characters  */
693 
OsWildcardExtractDirectory(CHAR * fullpath,VOID * dst,wildcard_type mark)694 STATIC INT32 OsWildcardExtractDirectory(CHAR *fullpath, VOID *dst, wildcard_type mark)
695 {
696     CHAR separator[] = "/";
697     CHAR src[PATH_MAX] = {0};
698     struct dirent *dirent = NULL;
699     CHAR *f = NULL;
700     CHAR *s = NULL;
701     CHAR *t = NULL;
702     INT32 ret = 0;
703     DIR *d = NULL;
704     struct stat statBuf;
705     INT32 deleteFlag = 0;
706 
707     f = OsWildcardSplitPath(fullpath, &s, &t);
708 
709     if (s == NULL) {
710         if (mark == CP_FILE) {
711             ret = OsShellCmdDoCp(fullpath, dst);
712         } else if (mark == CP_COUNT) {
713             ret = stat(fullpath, &statBuf);
714             if (ret == 0 && (S_ISREG(statBuf.st_mode) || S_ISLNK(statBuf.st_mode))) {
715                 (*(INT32 *)dst)++;
716             }
717         } else {
718             ret = OsWildcardDeleteFileOrDir(fullpath, mark);
719         }
720         return ret;
721     }
722 
723     d = (*f == '\0') ? opendir("/") : opendir(f);
724 
725     if (d == NULL) {
726         perror("opendir error");
727         return VFS_ERROR;
728     }
729 
730     while (1) {
731         dirent = readdir(d);
732         if (dirent == NULL) {
733             break;
734         }
735 
736         ret = strcpy_s(src, PATH_MAX, f);
737         if (ret != EOK) {
738             goto closedir_out;
739         }
740 
741         ret = OsWildcardMatch(dirent->d_name, s);
742         if (ret == 0) {
743             ret = strcat_s(src, sizeof(src), separator);
744             if (ret != EOK) {
745                 goto closedir_out;
746             }
747             ret = strcat_s(src, sizeof(src), dirent->d_name);
748             if (ret != EOK) {
749                 goto closedir_out;
750             }
751             if (t == NULL) {
752                 if (mark == CP_FILE) {
753                     ret = OsShellCmdDoCp(src, dst);
754                 } else if (mark == CP_COUNT) {
755                     ret = stat(src, &statBuf);
756                     if (ret == 0 && (S_ISREG(statBuf.st_mode) || S_ISLNK(statBuf.st_mode))) {
757                         (*(INT32 *)dst)++;
758                         if ((*(INT32 *)dst) > 1) {
759                             break;
760                         }
761                     }
762                 } else {
763                     ret = OsWildcardDeleteFileOrDir(src, mark);
764                     if (ret == 0) {
765                         deleteFlag = 1;
766                     }
767                 }
768             } else {
769                 ret = strcat_s(src, sizeof(src), separator);
770                 if (ret != EOK) {
771                     goto closedir_out;
772                 }
773                 ret = strcat_s(src, sizeof(src), t);
774                 if (ret != EOK) {
775                     goto closedir_out;
776                 }
777                 ret = OsWildcardExtractDirectory(src, dst, mark);
778                 if (mark == CP_COUNT && (*(INT32 *)dst) > 1) {
779                     break;
780                 }
781             }
782         }
783     }
784     (VOID)closedir(d);
785     if (deleteFlag == 1) {
786         ret = 0;
787     }
788     return ret;
789 closedir_out:
790     (VOID)closedir(d);
791     return (INT32)VFS_ERROR;
792 }
793 
OsShellCmdCp(INT32 argc,const CHAR ** argv)794 INT32 OsShellCmdCp(INT32 argc, const CHAR **argv)
795 {
796     INT32  ret;
797     const CHAR *src = NULL;
798     const CHAR *dst = NULL;
799     CHAR *srcFullPath = NULL;
800     CHAR *drcFullPath = NULL;
801     struct stat statBuf;
802     INT32 count = 0;
803     CHAR *shellWorkingDirectory = OsShellGetWorkingDirtectory();
804     if (shellWorkingDirectory == NULL) {
805         return -1;
806     }
807 
808     ERROR_OUT_IF(argc < 2, PRINTK("cp [SOURCEFILE] [DESTFILE]\n"), return -1);
809 
810     src = argv[0];
811     dst = argv[1];
812 
813     /* Get source fullpath. */
814 
815     ret = VfsNormalizePath(shellWorkingDirectory, src, &srcFullPath);
816     if (ret < 0) {
817         SetErrno(-ret);
818         PRINTK("cp error:%s\n", strerror(errno));
819         return -1;
820     }
821 
822     if (src[strlen(src) - 1] == '/') {
823         PRINTK("cp %s error: Source file can't be a directory.\n", src);
824         goto errout_with_srcpath;
825     }
826 
827     /* Get dest fullpath. */
828     ret = VfsNormalizePath(shellWorkingDirectory, dst, &drcFullPath);
829     if (ret < 0) {
830         SetErrno(-ret);
831         PRINTK("cp error: can't open %s. %s\n", dst, strerror(errno));
832         goto errout_with_srcpath;
833     }
834 
835     /* Is dest path exist? */
836 
837     ret = stat(drcFullPath, &statBuf);
838     if (ret < 0) {
839         /* Is dest path a directory? */
840         if (dst[strlen(dst) - 1] == '/') {
841             PRINTK("cp error: %s, %s.\n", drcFullPath, strerror(errno));
842             goto errout_with_path;
843         }
844     } else {
845         if ((S_ISREG(statBuf.st_mode) || S_ISLNK(statBuf.st_mode)) && dst[strlen(dst) - 1] == '/') {
846             PRINTK("cp error: %s is not a directory.\n", drcFullPath);
847             goto errout_with_path;
848         }
849     }
850 
851     if (OsIsContainersWildcard(srcFullPath)) {
852         if (ret < 0 || S_ISREG(statBuf.st_mode) || S_ISLNK(statBuf.st_mode)) {
853             CHAR *srcCopy = strdup(srcFullPath);
854             if (srcCopy == NULL) {
855                 PRINTK("cp error : Out of memory.\n");
856                 goto errout_with_path;
857             }
858             (VOID)OsWildcardExtractDirectory(srcCopy, &count, CP_COUNT);
859             free(srcCopy);
860             if (count > 1) {
861                 PRINTK("cp error : Can not copy two or more files.\n");
862                 goto errout_with_path;
863             }
864         }
865         ret = OsWildcardExtractDirectory(srcFullPath, drcFullPath, CP_FILE);
866     } else {
867         ret = OsShellCmdDoCp(srcFullPath, drcFullPath);
868     }
869     free(drcFullPath);
870     free(srcFullPath);
871     return ret;
872 
873 errout_with_path:
874     free(drcFullPath);
875 errout_with_srcpath:
876     free(srcFullPath);
877     return (INT32)VFS_ERROR;
878 }
879 
PrintRmUsage(VOID)880 STATIC INLINE VOID PrintRmUsage(VOID)
881 {
882     PRINTK("rm [FILE] or rm [-r/-R] [FILE]\n");
883 }
884 
OsShellCmdRm(INT32 argc,const CHAR ** argv)885 INT32 OsShellCmdRm(INT32 argc, const CHAR **argv)
886 {
887     INT32  ret;
888     CHAR *fullpath = NULL;
889     const CHAR *filename = NULL;
890     CHAR *shellWorkingDirectory = OsShellGetWorkingDirtectory();
891 
892     if (shellWorkingDirectory == NULL) {
893         return -1;
894     }
895 
896     ERROR_OUT_IF(argc != 1 && argc != 2, PrintRmUsage(), return -1);
897 
898     if (argc == 2) {
899         ERROR_OUT_IF(strcmp(argv[0], "-r") != 0 && strcmp(argv[0], "-R") != 0, PrintRmUsage(), return -1);
900 
901         filename = argv[1];
902         ret = VfsNormalizePath(shellWorkingDirectory, filename, &fullpath);
903         ERROR_OUT_IF(ret < 0, SetErr(-ret, "rm error"), return -1);
904 
905         if (OsIsContainersWildcard(fullpath)) {
906             ret = OsWildcardExtractDirectory(fullpath, NULL, RM_RECURSIVER);
907         } else {
908             ret = OsShellCmdDoRmdir(fullpath);
909         }
910     } else {
911         filename = argv[0];
912         ret = VfsNormalizePath(shellWorkingDirectory, filename, &fullpath);
913         ERROR_OUT_IF(ret < 0, SetErr(-ret, "rm error"), return -1);
914 
915         if (OsIsContainersWildcard(fullpath)) {
916             ret = OsWildcardExtractDirectory(fullpath, NULL, RM_FILE);
917         } else {
918             ret = unlink(fullpath);
919         }
920     }
921     if (ret == -1) {
922         perror("rm error");
923     }
924     free(fullpath);
925     return 0;
926 }
927 
OsShellCmdRmdir(INT32 argc,const CHAR ** argv)928 INT32 OsShellCmdRmdir(INT32 argc, const CHAR **argv)
929 {
930     INT32  ret;
931     CHAR *fullpath = NULL;
932     const CHAR *filename = NULL;
933     CHAR *shellWorkingDirectory = OsShellGetWorkingDirtectory();
934     if (shellWorkingDirectory == NULL) {
935         return -1;
936     }
937 
938     ERROR_OUT_IF(argc == 0, PRINTK("rmdir [DIRECTORY]\n"), return -1);
939 
940     filename = argv[0];
941     ret = VfsNormalizePath(shellWorkingDirectory, filename, &fullpath);
942     ERROR_OUT_IF(ret < 0, SetErr(-ret, "rmdir error"), return -1);
943 
944     if (OsIsContainersWildcard(fullpath)) {
945         ret = OsWildcardExtractDirectory(fullpath, NULL, RM_DIR);
946     } else {
947         ret = rmdir(fullpath);
948     }
949     if (ret == -1) {
950         PRINTK("rmdir %s failed. Error: %s.\n", fullpath, strerror(errno));
951     }
952     free(fullpath);
953 
954     return 0;
955 }
956 
957