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 54typedef 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 70INT32 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 120STATIC 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; 153exit_with_nomem: 154 return (CHAR *)NULL; 155} 156 157VOID 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 218INT32 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 245INT32 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 259pthread_mutex_t g_mutex_cat = PTHREAD_MUTEX_INITIALIZER; 260 261INT32 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 305INT32 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 329INT32 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 351INT32 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 380pthread_mutex_t g_mutexCp = PTHREAD_MUTEX_INITIALIZER; 381 382STATIC 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 504errout_with_fd: 505 (VOID)close(dstFd); 506errout_with_srcfd: 507 (VOID)close(srcFd); 508errout_with_mutex: 509 (VOID)pthread_mutex_unlock(&g_mutexCp); 510errout_with_path: 511 free(drcFullPath); 512errout_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 521STATIC 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 */ 570STATIC 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 */ 618STATIC 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 */ 630STATIC 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 649STATIC 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 676STATIC 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 706STATIC 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; 805closedir_out: 806 (VOID)closedir(d); 807 return (INT32)VFS_ERROR; 808} 809 810INT32 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 889errout_with_path: 890 free(drcFullPath); 891errout_with_srcpath: 892 free(srcFullPath); 893 return (INT32)VFS_ERROR; 894} 895 896STATIC INLINE VOID PrintRmUsage(VOID) 897{ 898 PRINTK("rm [FILE] or rm [-r/-R] [FILE]\n"); 899} 900 901INT32 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 944INT32 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