• 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         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