• 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 non directory file  */
OsRmFileOnly(const CHAR * fullpath)630 STATIC INT32 OsRmFileOnly(const CHAR *fullpath)
631 {
632     struct stat statInfo = {0};
633     INT32 ret = stat(fullpath, &statInfo);
634     if (ret == 0) {
635         if (!S_ISDIR(statInfo.st_mode)) {
636             ret = unlink(fullpath);
637         } else {
638             ret = 0;
639             PRINTK("rm: cannot remove '%s': Is a directory\n", fullpath);
640         }
641     } else {
642         PRINTK("stat: get '%s' statInfo fail!\n", fullpath);
643     }
644     return ret;
645 }
646 
647 /*  Delete a matching file or directory  */
648 
OsWildcardDeleteFileOrDir(const CHAR * fullpath,wildcard_type mark)649 STATIC INT32 OsWildcardDeleteFileOrDir(const CHAR *fullpath, wildcard_type mark)
650 {
651     INT32 ret;
652 
653     switch (mark) {
654         case RM_RECURSIVER:
655             ret = OsShellCmdDoRmdir(fullpath);
656             break;
657         case RM_FILE:
658             ret = OsRmFileOnly(fullpath);
659             break;
660         case RM_DIR:
661             ret = rmdir(fullpath);
662             break;
663         default:
664             return (INT32)VFS_ERROR;
665     }
666     if (ret == -1) {
667         PRINTK("%s  ", fullpath);
668         perror("rm/rmdir error!");
669         return ret;
670     }
671     return 0;
672 }
673 
674 /*  Split the path with wildcard characters  */
675 
OsWildcardSplitPath(CHAR * fullpath,CHAR ** handle,CHAR ** wait)676 STATIC CHAR *OsWildcardSplitPath(CHAR *fullpath, CHAR **handle, CHAR **wait)
677 {
678     INT32 n;
679     INT32 a = 0;
680     INT32 b = 0;
681     INT32 len  = strlen(fullpath);
682 
683     for (n = 0; n < len; n++) {
684         if (fullpath[n] == '/') {
685             if (b != 0) {
686                 fullpath[n] = '\0';
687                 *wait = fullpath + n + 1;
688                 break;
689             }
690             a = n;
691         } else if (fullpath[n] == '*' || fullpath[n] == '?') {
692             b = n;
693             fullpath[a] = '\0';
694             if (a == 0) {
695                 *handle = fullpath + a + 1;
696                 continue;
697             }
698             *handle = fullpath + a + 1;
699         }
700     }
701     return fullpath;
702 }
703 
704 /*  Handling entry of the path with wildcard characters  */
705 
OsWildcardExtractDirectory(CHAR * fullpath,VOID * dst,wildcard_type mark)706 STATIC INT32 OsWildcardExtractDirectory(CHAR *fullpath, VOID *dst, wildcard_type mark)
707 {
708     CHAR separator[] = "/";
709     CHAR src[PATH_MAX] = {0};
710     struct dirent *dirent = NULL;
711     CHAR *f = NULL;
712     CHAR *s = NULL;
713     CHAR *t = NULL;
714     INT32 ret = 0;
715     DIR *d = NULL;
716     struct stat statBuf;
717     INT32 deleteFlag = 0;
718 
719     f = OsWildcardSplitPath(fullpath, &s, &t);
720 
721     if (s == NULL) {
722         if (mark == CP_FILE) {
723             ret = OsShellCmdDoCp(fullpath, dst);
724         } else if (mark == CP_COUNT) {
725             ret = stat(fullpath, &statBuf);
726             if (ret == 0 && (S_ISREG(statBuf.st_mode) || S_ISLNK(statBuf.st_mode))) {
727                 (*(INT32 *)dst)++;
728             }
729         } else {
730             ret = OsWildcardDeleteFileOrDir(fullpath, mark);
731         }
732         return ret;
733     }
734 
735     d = (*f == '\0') ? opendir("/") : opendir(f);
736 
737     if (d == NULL) {
738         perror("opendir error");
739         return (INT32)VFS_ERROR;
740     }
741 
742     while (1) {
743         dirent = readdir(d);
744         if (dirent == NULL) {
745             break;
746         }
747 
748         if (!strcmp(dirent->d_name, ".") || !strcmp(dirent->d_name, "..")) {
749             continue;
750         }
751 
752         ret = strcpy_s(src, PATH_MAX, f);
753         if (ret != EOK) {
754             goto closedir_out;
755         }
756 
757         ret = OsWildcardMatch(dirent->d_name, s);
758         if (ret == 0) {
759             ret = strcat_s(src, sizeof(src), separator);
760             if (ret != EOK) {
761                 goto closedir_out;
762             }
763             ret = strcat_s(src, sizeof(src), dirent->d_name);
764             if (ret != EOK) {
765                 goto closedir_out;
766             }
767             if (t == NULL) {
768                 if (mark == CP_FILE) {
769                     ret = OsShellCmdDoCp(src, dst);
770                 } else if (mark == CP_COUNT) {
771                     ret = stat(src, &statBuf);
772                     if (ret == 0 && (S_ISREG(statBuf.st_mode) || S_ISLNK(statBuf.st_mode))) {
773                         (*(INT32 *)dst)++;
774                         if ((*(INT32 *)dst) > 1) {
775                             break;
776                         }
777                     }
778                 } else {
779                     ret = OsWildcardDeleteFileOrDir(src, mark);
780                     if (ret == 0) {
781                         deleteFlag = 1;
782                     }
783                 }
784             } else {
785                 ret = strcat_s(src, sizeof(src), separator);
786                 if (ret != EOK) {
787                     goto closedir_out;
788                 }
789                 ret = strcat_s(src, sizeof(src), t);
790                 if (ret != EOK) {
791                     goto closedir_out;
792                 }
793                 ret = OsWildcardExtractDirectory(src, dst, mark);
794                 if (mark == CP_COUNT && (*(INT32 *)dst) > 1) {
795                     break;
796                 }
797             }
798         }
799     }
800     (VOID)closedir(d);
801     if (deleteFlag == 1) {
802         ret = 0;
803     }
804     return ret;
805 closedir_out:
806     (VOID)closedir(d);
807     return (INT32)VFS_ERROR;
808 }
809 
OsShellCmdCp(INT32 argc,const CHAR ** argv)810 INT32 OsShellCmdCp(INT32 argc, const CHAR **argv)
811 {
812     INT32  ret;
813     const CHAR *src = NULL;
814     const CHAR *dst = NULL;
815     CHAR *srcFullPath = NULL;
816     CHAR *drcFullPath = NULL;
817     struct stat statBuf;
818     INT32 count = 0;
819     CHAR *shellWorkingDirectory = OsShellGetWorkingDirtectory();
820     if (shellWorkingDirectory == NULL) {
821         return -1;
822     }
823 
824     ERROR_OUT_IF(argc < 2, PRINTK("cp [SOURCEFILE] [DESTFILE]\n"), return -1);
825 
826     src = argv[0];
827     dst = argv[1];
828 
829     /* Get source fullpath. */
830 
831     ret = VfsNormalizePath(shellWorkingDirectory, src, &srcFullPath);
832     if (ret < 0) {
833         SetErrno(-ret);
834         PRINTK("cp error:%s\n", strerror(errno));
835         return -1;
836     }
837 
838     if (src[strlen(src) - 1] == '/') {
839         PRINTK("cp %s error: Source file can't be a directory.\n", src);
840         goto errout_with_srcpath;
841     }
842 
843     /* Get dest fullpath. */
844     ret = VfsNormalizePath(shellWorkingDirectory, dst, &drcFullPath);
845     if (ret < 0) {
846         SetErrno(-ret);
847         PRINTK("cp error: can't open %s. %s\n", dst, strerror(errno));
848         goto errout_with_srcpath;
849     }
850 
851     /* Is dest path exist? */
852 
853     ret = stat(drcFullPath, &statBuf);
854     if (ret < 0) {
855         /* Is dest path a directory? */
856         if (dst[strlen(dst) - 1] == '/') {
857             PRINTK("cp error: %s, %s.\n", drcFullPath, strerror(errno));
858             goto errout_with_path;
859         }
860     } else {
861         if ((S_ISREG(statBuf.st_mode) || S_ISLNK(statBuf.st_mode)) && dst[strlen(dst) - 1] == '/') {
862             PRINTK("cp error: %s is not a directory.\n", drcFullPath);
863             goto errout_with_path;
864         }
865     }
866 
867     if (OsIsContainersWildcard(srcFullPath)) {
868         if (ret < 0 || S_ISREG(statBuf.st_mode) || S_ISLNK(statBuf.st_mode)) {
869             CHAR *srcCopy = strdup(srcFullPath);
870             if (srcCopy == NULL) {
871                 PRINTK("cp error : Out of memory.\n");
872                 goto errout_with_path;
873             }
874             (VOID)OsWildcardExtractDirectory(srcCopy, &count, CP_COUNT);
875             free(srcCopy);
876             if (count > 1) {
877                 PRINTK("cp error : Can not copy two or more files.\n");
878                 goto errout_with_path;
879             }
880         }
881         ret = OsWildcardExtractDirectory(srcFullPath, drcFullPath, CP_FILE);
882     } else {
883         ret = OsShellCmdDoCp(srcFullPath, drcFullPath);
884     }
885     free(drcFullPath);
886     free(srcFullPath);
887     return ret;
888 
889 errout_with_path:
890     free(drcFullPath);
891 errout_with_srcpath:
892     free(srcFullPath);
893     return (INT32)VFS_ERROR;
894 }
895 
PrintRmUsage(VOID)896 STATIC INLINE VOID PrintRmUsage(VOID)
897 {
898     PRINTK("rm [FILE] or rm [-r/-R] [FILE]\n");
899 }
900 
OsShellCmdRm(INT32 argc,const CHAR ** argv)901 INT32 OsShellCmdRm(INT32 argc, const CHAR **argv)
902 {
903     INT32  ret;
904     CHAR *fullpath = NULL;
905     const CHAR *filename = NULL;
906     CHAR *shellWorkingDirectory = OsShellGetWorkingDirtectory();
907 
908     if (shellWorkingDirectory == NULL) {
909         return -1;
910     }
911 
912     ERROR_OUT_IF(argc != 1 && argc != 2, PrintRmUsage(), return -1);
913 
914     if (argc == 2) {
915         ERROR_OUT_IF(strcmp(argv[0], "-r") != 0 && strcmp(argv[0], "-R") != 0, PrintRmUsage(), return -1);
916 
917         filename = argv[1];
918         ret = VfsNormalizePath(shellWorkingDirectory, filename, &fullpath);
919         ERROR_OUT_IF(ret < 0, SetErr(-ret, "rm error"), return -1);
920 
921         if (OsIsContainersWildcard(fullpath)) {
922             ret = OsWildcardExtractDirectory(fullpath, NULL, RM_RECURSIVER);
923         } else {
924             ret = OsShellCmdDoRmdir(fullpath);
925         }
926     } else {
927         filename = argv[0];
928         ret = VfsNormalizePath(shellWorkingDirectory, filename, &fullpath);
929         ERROR_OUT_IF(ret < 0, SetErr(-ret, "rm error"), return -1);
930 
931         if (OsIsContainersWildcard(fullpath)) {
932             ret = OsWildcardExtractDirectory(fullpath, NULL, RM_FILE);
933         } else {
934             ret = OsRmFileOnly(fullpath);
935         }
936     }
937     if (ret == -1) {
938         perror("rm error");
939     }
940     free(fullpath);
941     return 0;
942 }
943 
OsShellCmdRmdir(INT32 argc,const CHAR ** argv)944 INT32 OsShellCmdRmdir(INT32 argc, const CHAR **argv)
945 {
946     INT32  ret;
947     CHAR *fullpath = NULL;
948     const CHAR *filename = NULL;
949     CHAR *shellWorkingDirectory = OsShellGetWorkingDirtectory();
950     if (shellWorkingDirectory == NULL) {
951         return -1;
952     }
953 
954     ERROR_OUT_IF(argc == 0, PRINTK("rmdir [DIRECTORY]\n"), return -1);
955 
956     filename = argv[0];
957     ret = VfsNormalizePath(shellWorkingDirectory, filename, &fullpath);
958     ERROR_OUT_IF(ret < 0, SetErr(-ret, "rmdir error"), return -1);
959 
960     if (OsIsContainersWildcard(fullpath)) {
961         ret = OsWildcardExtractDirectory(fullpath, NULL, RM_DIR);
962     } else {
963         ret = rmdir(fullpath);
964     }
965     if (ret == -1) {
966         PRINTK("rmdir %s failed. Error: %s.\n", fullpath, strerror(errno));
967     }
968     free(fullpath);
969 
970     return 0;
971 }
972 
973