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