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