• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2013-2019 Huawei Technologies Co., Ltd. All rights reserved.
3  * Copyright (c) 2020-2022 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 #include "sys/mount.h"
34 
35 #ifdef LOSCFG_SHELL
36 
37 #include "los_typedef.h"
38 #include "shell.h"
39 #include "sys/stat.h"
40 #include "stdlib.h"
41 #include "unistd.h"
42 #include "fcntl.h"
43 #include "sys/statfs.h"
44 #include "stdio.h"
45 #include "pthread.h"
46 
47 #include "shcmd.h"
48 #include "securec.h"
49 #include "show.h"
50 #include "los_syscall.h"
51 
52 #include "los_process_pri.h"
53 #include <ctype.h>
54 #include "fs/fs_operation.h"
55 
56 typedef enum {
57     RM_RECURSIVER,
58     RM_FILE,
59     RM_DIR,
60     CP_FILE,
61     CP_COUNT
62 } wildcard_type;
63 
64 #define ERROR_OUT_IF(condition, message_function, handler) \
65     do { \
66         if (condition) { \
67             message_function; \
68             handler; \
69         } \
70     } while (0)
71 
set_err(int errcode,const char * err_message)72 static inline void set_err(int errcode, const char *err_message)
73 {
74     set_errno(errcode);
75     perror(err_message);
76 }
77 
osShellCmdDoChdir(const char * path)78 int osShellCmdDoChdir(const char *path)
79 {
80     char *fullpath = NULL;
81     char *fullpath_bak = NULL;
82     int ret;
83     char *shell_working_directory = OsShellGetWorkingDirectory();
84     if (shell_working_directory == NULL) {
85         return -1;
86     }
87 
88     if (path == NULL) {
89         LOS_TaskLock();
90         PRINTK("%s\n", shell_working_directory);
91         LOS_TaskUnlock();
92 
93         return 0;
94     }
95 
96     ERROR_OUT_IF(strlen(path) > PATH_MAX, set_err(ENOTDIR, "cd error"), return -1);
97 
98     ret = vfs_normalize_path(shell_working_directory, path, &fullpath);
99     ERROR_OUT_IF(ret < 0, set_err(-ret, "cd error"), return -1);
100 
101     fullpath_bak = fullpath;
102     ret = chdir(fullpath);
103     if (ret < 0) {
104         free(fullpath_bak);
105         perror("cd");
106         return -1;
107     }
108 
109     /* copy full path to working directory */
110 
111     LOS_TaskLock();
112     ret = strncpy_s(shell_working_directory, PATH_MAX, fullpath, strlen(fullpath));
113     if (ret != EOK) {
114         free(fullpath_bak);
115         LOS_TaskUnlock();
116         return -1;
117     }
118     LOS_TaskUnlock();
119     /* release normalize directory path name */
120 
121     free(fullpath_bak);
122 
123     return 0;
124 }
125 
osShellCmdLs(int argc,const char ** argv)126 int osShellCmdLs(int argc, const char **argv)
127 {
128     char *fullpath = NULL;
129     const char *filename = NULL;
130     int ret;
131     char *shell_working_directory = OsShellGetWorkingDirectory();
132     if (shell_working_directory == NULL) {
133         return -1;
134     }
135 
136     ERROR_OUT_IF(argc > 1, PRINTK("ls or ls [DIRECTORY]\n"), return -1);
137 
138     if (argc == 0) {
139         ls(shell_working_directory);
140         return 0;
141     }
142 
143     filename = argv[0];
144     ret = vfs_normalize_path(shell_working_directory, filename, &fullpath);
145     ERROR_OUT_IF(ret < 0, set_err(-ret, "ls error"), return -1);
146 
147     ls(fullpath);
148     free(fullpath);
149 
150     return 0;
151 }
152 
osShellCmdCd(int argc,const char ** argv)153 int osShellCmdCd(int argc, const char **argv)
154 {
155     if (argc == 0) {
156         (void)osShellCmdDoChdir("/");
157         return 0;
158     }
159 
160     (void)osShellCmdDoChdir(argv[0]);
161 
162     return 0;
163 }
164 
165 #define CAT_BUF_SIZE  512
166 #define CAT_TASK_PRIORITY  10
167 #define CAT_TASK_STACK_SIZE  0x3000
168 pthread_mutex_t g_mutex_cat = PTHREAD_MUTEX_INITIALIZER;
169 
osShellCmdDoCatShow(UINTPTR arg)170 int osShellCmdDoCatShow(UINTPTR arg)
171 {
172     int ret = 0;
173     char buf[CAT_BUF_SIZE];
174     size_t size, written, toWrite;
175     ssize_t cnt;
176     char *fullpath = (char *)arg;
177     FILE *ini = NULL;
178 
179     (void)pthread_mutex_lock(&g_mutex_cat);
180     ini = fopen(fullpath, "r");
181     if (ini == NULL) {
182         ret = -1;
183         perror("cat error");
184         goto out;
185     }
186 
187     do {
188         (void)memset_s(buf, sizeof(buf), 0, CAT_BUF_SIZE);
189         size = fread(buf, 1, CAT_BUF_SIZE, ini);
190         if ((int)size < 0) {
191             ret = -1;
192             perror("cat error");
193             goto out_with_fclose;
194         }
195 
196         for (toWrite = size, written = 0; toWrite > 0;) {
197             cnt = write(1, buf + written, toWrite);
198             if (cnt == 0) {
199                 /* avoid task-starvation */
200                 (void)LOS_TaskDelay(1);
201                 continue;
202             } else if (cnt < 0) {
203                 perror("cat write error");
204                 break;
205             }
206 
207             written += cnt;
208             toWrite -= cnt;
209         }
210     }
211     while (size > 0);
212 
213 out_with_fclose:
214     (void)fclose(ini);
215 out:
216     free(fullpath);
217     (void)pthread_mutex_unlock(&g_mutex_cat);
218     return ret;
219 }
220 
osShellCmdCat(int argc,const char ** argv)221 int osShellCmdCat(int argc, const char **argv)
222 {
223     char *fullpath = NULL;
224     int ret;
225     unsigned int ca_task;
226     struct Vnode *vnode = NULL;
227     TSK_INIT_PARAM_S init_param;
228     char *shell_working_directory = OsShellGetWorkingDirectory();
229     if (shell_working_directory == NULL) {
230         return -1;
231     }
232 
233     ERROR_OUT_IF(argc != 1, PRINTK("cat [FILE]\n"), return -1);
234 
235     ret = vfs_normalize_path(shell_working_directory, argv[0], &fullpath);
236     ERROR_OUT_IF(ret < 0, set_err(-ret, "cat error"), return -1);
237 
238     VnodeHold();
239     ret = VnodeLookup(fullpath, &vnode, O_RDONLY);
240     if (ret != LOS_OK) {
241         set_errno(-ret);
242         perror("cat error");
243         VnodeDrop();
244         free(fullpath);
245         return -1;
246     }
247     if (vnode->type != VNODE_TYPE_REG) {
248         set_errno(EINVAL);
249         perror("cat error");
250         VnodeDrop();
251         free(fullpath);
252         return -1;
253     }
254     VnodeDrop();
255     (void)memset_s(&init_param, sizeof(init_param), 0, sizeof(TSK_INIT_PARAM_S));
256     init_param.pfnTaskEntry = (TSK_ENTRY_FUNC)osShellCmdDoCatShow;
257     init_param.usTaskPrio   = CAT_TASK_PRIORITY;
258     init_param.auwArgs[0]   = (UINTPTR)fullpath;
259     init_param.uwStackSize  = CAT_TASK_STACK_SIZE;
260     init_param.pcName       = "shellcmd_cat";
261     init_param.uwResved     = LOS_TASK_STATUS_DETACHED | OS_TASK_FLAG_SPECIFIES_PROCESS;
262     init_param.processID    = 2; /* 2: kProcess */
263 
264     ret = (int)LOS_TaskCreate(&ca_task, &init_param);
265     if (ret != LOS_OK) {
266         free(fullpath);
267     }
268 
269     return ret;
270 }
271 
272 static int nfs_mount_ref(const char *server_ip_and_path, const char *mount_path,
273                          unsigned int uid, unsigned int gid) __attribute__((weakref("nfs_mount")));
274 
get_mountflags(const char * options)275 static unsigned long get_mountflags(const char *options)
276 {
277     unsigned long mountfalgs = 0;
278     char *p;
279     while ((options != NULL) && (p = strsep((char**)&options, ",")) != NULL) {
280         if (strncmp(p, "ro", strlen("ro")) == 0) {
281             mountfalgs |= MS_RDONLY;
282         } else if (strncmp(p, "rw", strlen("rw")) == 0) {
283             mountfalgs &= ~MS_RDONLY;
284         } else if (strncmp(p, "nosuid", strlen("nosuid")) == 0) {
285             mountfalgs |= MS_NOSUID;
286         } else if (strncmp(p, "suid", strlen("suid")) == 0) {
287             mountfalgs &= ~MS_NOSUID;
288         } else {
289             continue;
290         }
291     }
292 
293     return mountfalgs;
294 }
print_mount_usage(void)295 static inline void print_mount_usage(void)
296 {
297     PRINTK("mount [DEVICE] [PATH] [NAME]\n");
298 }
299 
osShellCmdMount(int argc,const char ** argv)300 int osShellCmdMount(int argc, const char **argv)
301 {
302     int ret;
303     char *fullpath = NULL;
304     const char *filename = NULL;
305     unsigned int gid, uid;
306     char *data = NULL;
307     char *filessystemtype = NULL;
308     unsigned long mountfalgs;
309     char *shell_working_directory = OsShellGetWorkingDirectory();
310     if (shell_working_directory == NULL) {
311         return -1;
312     }
313 
314     ERROR_OUT_IF(argc < 3, print_mount_usage(), return OS_FAIL);
315 
316     if (strncmp(argv[0], "-t", 2) == 0 || strncmp(argv[0], "-o", 2) == 0) // 2: length of "-t"
317     {
318         if (argc < 4) { // 4: required number of parameters
319             PRINTK("mount -t/-o [DEVICE] [PATH] [NAME]\n");
320             return -1;
321         }
322 
323         filename = argv[2]; // 2: index of file path
324         ret = vfs_normalize_path(shell_working_directory, filename, &fullpath);
325         ERROR_OUT_IF(ret < 0, set_err(-ret, "mount error"), return -1);
326 
327         if (strncmp(argv[3], "nfs", 3) == 0) { // 3: index of fs type
328             if (argc <= 6) { // 6: arguments include uid or gid
329                 uid = ((argc >= 5) && (argv[4] != NULL)) ? (unsigned int)strtoul(argv[4], (char **)NULL, 0) : 0;
330                 gid = ((argc == 6) && (argv[5] != NULL)) ? (unsigned int)strtoul(argv[5], (char **)NULL, 0) : 0;
331 
332                 if (nfs_mount_ref != NULL) {
333                     ret = nfs_mount_ref(argv[1], fullpath, uid, gid);
334                     if (ret != LOS_OK) {
335                         PRINTK("mount -t [DEVICE] [PATH] [NAME]\n");
336                     }
337                 } else {
338                     PRINTK("can't find nfs_mount\n");
339                 }
340                 free(fullpath);
341                 return 0;
342             }
343         }
344 
345         filessystemtype = (argc >= 4) ? (char *)argv[3] : NULL; /* 4: specify fs type, 3: fs type */
346         mountfalgs = (argc >= 5) ? get_mountflags((const char *)argv[4]) : 0; /* 4: usr option */
347         data = (argc >= 6) ? (char *)argv[5] : NULL; /* 5: usr option data, 6: six args needed for data */
348 
349         if (strcmp(argv[1], "0") == 0) {
350             ret = mount((const char *)NULL, fullpath, filessystemtype, mountfalgs, data);
351         } else {
352             ret = mount(argv[1], fullpath, filessystemtype, mountfalgs, data); /* 3: fs type */
353         }
354         if (ret != LOS_OK) {
355             perror("mount error");
356         } else {
357             PRINTK("mount ok\n");
358         }
359     } else {
360         filename = argv[1];
361         ret = vfs_normalize_path(shell_working_directory, filename, &fullpath);
362         ERROR_OUT_IF(ret < 0, set_err(-ret, "mount error"), return -1);
363 
364         if (strncmp(argv[2], "nfs", 3) == 0) { // 2: index of fs type, 3: length of "nfs"
365             if (argc <= 5) { // 5: arguments include gid and uid
366                 uid = ((argc >= 4) && (argv[3] != NULL)) ? (unsigned int)strtoul(argv[3], (char **)NULL, 0) : 0;
367                 gid = ((argc == 5) && (argv[4] != NULL)) ? (unsigned int)strtoul(argv[4], (char **)NULL, 0) : 0;
368 
369                 if (nfs_mount_ref != NULL) {
370                     ret = nfs_mount_ref(argv[0], fullpath, uid, gid);
371                     if (ret != LOS_OK) {
372                         PRINTK("mount [DEVICE] [PATH] [NAME]\n");
373                     }
374                 } else {
375                     PRINTK("can't find nfs_mount\n");
376                 }
377                 free(fullpath);
378                 return 0;
379             }
380 
381             print_mount_usage();
382             free(fullpath);
383             return 0;
384         }
385 
386         mountfalgs = (argc >= 4) ? get_mountflags((const char *)argv[3]) : 0;  /* 3: usr option */
387         data = (argc >= 5) ? (char *)argv[4] : NULL; /* 4: usr option data, 5: number of args needed for data */
388 
389         if (strcmp(argv[0], "0") == 0) {
390             ret = mount((const char *)NULL, fullpath, argv[2], mountfalgs, data);
391         } else {
392             ret = mount(argv[0], fullpath, argv[2], mountfalgs, data);  /* 2: fs type */
393         }
394         if (ret != LOS_OK) {
395             perror("mount error");
396         } else {
397             PRINTK("mount ok\n");
398         }
399     }
400 
401     free(fullpath);
402     return 0;
403 }
404 
osShellCmdUmount(int argc,const char ** argv)405 int osShellCmdUmount(int argc, const char **argv)
406 {
407     int ret;
408     const char *filename = NULL;
409     char *fullpath = NULL;
410     char *target_path = NULL;
411     int cmp_num;
412     char *work_path = NULL;
413     char *shell_working_directory = OsShellGetWorkingDirectory();
414     if (shell_working_directory == NULL) {
415         return -1;
416     }
417     work_path = shell_working_directory;
418 
419     ERROR_OUT_IF(argc == 0, PRINTK("umount [PATH]\n"), return 0);
420 
421     filename = argv[0];
422     ret = vfs_normalize_path(shell_working_directory, filename, &fullpath);
423     ERROR_OUT_IF(ret < 0, set_err(-ret, "umount error"), return -1);
424 
425     target_path = fullpath;
426     cmp_num = strlen(fullpath);
427     ret = strncmp(work_path, target_path, cmp_num);
428     if (ret == 0) {
429         work_path += cmp_num;
430         if (*work_path == '/' || *work_path == '\0') {
431             set_errno(EBUSY);
432             perror("umount error");
433             free(fullpath);
434             return -1;
435         }
436     }
437 
438     ret = umount(fullpath);
439     free(fullpath);
440     if (ret != LOS_OK) {
441         perror("umount error");
442         return 0;
443     }
444 
445     PRINTK("umount ok\n");
446     return 0;
447 }
448 
osShellCmdMkdir(int argc,const char ** argv)449 int osShellCmdMkdir(int argc, const char **argv)
450 {
451     int ret;
452     char *fullpath = NULL;
453     const char *filename = NULL;
454     char *shell_working_directory = OsShellGetWorkingDirectory();
455     if (shell_working_directory == NULL) {
456         return -1;
457     }
458 
459     ERROR_OUT_IF(argc != 1, PRINTK("mkdir [DIRECTORY]\n"), return 0);
460 
461     filename = argv[0];
462     ret = vfs_normalize_path(shell_working_directory, filename, &fullpath);
463     ERROR_OUT_IF(ret < 0, set_err(-ret, "mkdir error"), return -1);
464 
465     ret = mkdir(fullpath, S_IRWXU | S_IRWXG | S_IRWXO);
466     if (ret == -1) {
467         perror("mkdir error");
468     }
469     free(fullpath);
470     return 0;
471 }
472 
osShellCmdPwd(int argc,const char ** argv)473 int osShellCmdPwd(int argc, const char **argv)
474 {
475     char buf[SHOW_MAX_LEN] = {0};
476     DIR *dir = NULL;
477     char *shell_working_directory = OsShellGetWorkingDirectory();
478     if (shell_working_directory == NULL) {
479         return -1;
480     }
481 
482     ERROR_OUT_IF(argc > 0, PRINTK("\nUsage: pwd\n"), return -1);
483 
484     dir = opendir(shell_working_directory);
485     if (dir == NULL) {
486         perror("pwd error");
487         return -1;
488     }
489 
490     LOS_TaskLock();
491     if (strncpy_s(buf, SHOW_MAX_LEN, shell_working_directory, SHOW_MAX_LEN - 1) != EOK) {
492         LOS_TaskUnlock();
493         PRINTK("pwd error: strncpy_s error!\n");
494         (void)closedir(dir);
495         return -1;
496     }
497     LOS_TaskUnlock();
498 
499     PRINTK("%s\n", buf);
500     (void)closedir(dir);
501     return 0;
502 }
503 
print_statfs_usage(void)504 static inline void print_statfs_usage(void)
505 {
506     PRINTK("Usage  :\n");
507     PRINTK("    statfs <path>\n");
508     PRINTK("    path  : Mounted file system path that requires query information\n");
509     PRINTK("Example:\n");
510     PRINTK("    statfs /ramfs\n");
511 }
512 
osShellCmdStatfs(int argc,const char ** argv)513 int osShellCmdStatfs(int argc, const char **argv)
514 {
515     struct statfs sfs;
516     int result;
517     unsigned long long total_size, free_size;
518     char *fullpath = NULL;
519     const char *filename = NULL;
520     char *shell_working_directory = OsShellGetWorkingDirectory();
521     if (shell_working_directory == NULL) {
522         return -1;
523     }
524 
525     ERROR_OUT_IF(argc != 1, PRINTK("statfs failed! Invalid argument!\n"), return -1);
526 
527     (void)memset_s(&sfs, sizeof(sfs), 0, sizeof(sfs));
528 
529     filename = argv[0];
530     result = vfs_normalize_path(shell_working_directory, filename, &fullpath);
531     ERROR_OUT_IF(result < 0, set_err(-result, "statfs error"), return -1);
532 
533     result = statfs(fullpath, &sfs);
534     free(fullpath);
535 
536     if (result != 0 || sfs.f_type == 0) {
537         PRINTK("statfs failed! Invalid argument!\n");
538         print_statfs_usage();
539         return -1;
540     }
541 
542     total_size  = (unsigned long long)sfs.f_bsize * sfs.f_blocks;
543     free_size   = (unsigned long long)sfs.f_bsize * sfs.f_bfree;
544 
545     PRINTK("statfs got:\n f_type     = %d\n cluster_size   = %d\n", sfs.f_type, sfs.f_bsize);
546     PRINTK(" total_clusters = %llu\n free_clusters  = %llu\n", sfs.f_blocks, sfs.f_bfree);
547     PRINTK(" avail_clusters = %llu\n f_namelen    = %d\n", sfs.f_bavail, sfs.f_namelen);
548     PRINTK("\n%s\n total size: %4llu Bytes\n free  size: %4llu Bytes\n", argv[0], total_size, free_size);
549 
550     return 0;
551 }
552 
osShellCmdTouch(int argc,const char ** argv)553 int osShellCmdTouch(int argc, const char **argv)
554 {
555     int ret;
556     int fd = -1;
557     char *fullpath = NULL;
558     const char *filename = NULL;
559     char *shell_working_directory = OsShellGetWorkingDirectory();
560     if (shell_working_directory == NULL) {
561         return -1;
562     }
563 
564     ERROR_OUT_IF(argc != 1, PRINTK("touch [FILE]\n"), return -1);
565 
566     filename = argv[0];
567     ret = vfs_normalize_path(shell_working_directory, filename, &fullpath);
568     ERROR_OUT_IF(ret < 0, set_err(-ret, "touch error"), return -1);
569 
570     fd = open(fullpath, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
571     free(fullpath);
572     if (fd == -1) {
573         perror("touch error");
574         return -1;
575     }
576 
577     (void)close(fd);
578     return 0;
579 }
580 
581 #define CP_BUF_SIZE 4096
582 pthread_mutex_t g_mutex_cp = PTHREAD_MUTEX_INITIALIZER;
583 
os_shell_cmd_do_cp(const char * src_filepath,const char * dst_filename)584 static int os_shell_cmd_do_cp(const char *src_filepath, const char *dst_filename)
585 {
586     int  ret;
587     char *src_fullpath = NULL;
588     char *dst_fullpath = NULL;
589     const char *src_filename = NULL;
590     char *dst_filepath = NULL;
591     char *buf = NULL;
592     const char *filename = NULL;
593     ssize_t r_size, w_size;
594     int src_fd = -1;
595     int dst_fd = -1;
596     struct stat stat_buf;
597     mode_t src_mode;
598     char *shell_working_directory = OsShellGetWorkingDirectory();
599     if (shell_working_directory == NULL) {
600         return -1;
601     }
602 
603     buf = (char *)malloc(CP_BUF_SIZE);
604     if (buf == NULL) {
605         PRINTK("cp error: Out of memory!\n");
606         return -1;
607     }
608 
609     /* Get source fullpath. */
610 
611     ret = vfs_normalize_path(shell_working_directory, src_filepath, &src_fullpath);
612     if (ret < 0) {
613         set_errno(-ret);
614         PRINTK("cp error: %s\n", strerror(errno));
615         free(buf);
616         return -1;
617     }
618 
619     /* Is source path exist? */
620 
621     ret = stat(src_fullpath, &stat_buf);
622     if (ret == -1) {
623         PRINTK("cp %s error: %s\n", src_fullpath, strerror(errno));
624         goto errout_with_srcpath;
625     }
626     src_mode = stat_buf.st_mode;
627     /* Is source path a directory? */
628 
629     if (S_ISDIR(stat_buf.st_mode)) {
630         PRINTK("cp %s error: Source file can't be a directory.\n", src_fullpath);
631         goto errout_with_srcpath;
632     }
633 
634     /* Get dest fullpath. */
635 
636     dst_fullpath = strdup(dst_filename);
637     if (dst_fullpath == NULL) {
638         PRINTK("cp error: Out of memory.\n");
639         goto errout_with_srcpath;
640     }
641 
642     /* Is dest path exist? */
643 
644     ret = stat(dst_fullpath, &stat_buf);
645     if (ret == 0) {
646         /* Is dest path a directory? */
647 
648         if (S_ISDIR(stat_buf.st_mode)) {
649             /* Get source file name without '/'. */
650 
651             src_filename = src_filepath;
652             while (1) {
653                 filename = strchr(src_filename, '/');
654                 if (filename == NULL) {
655                     break;
656                 }
657                 src_filename = filename + 1;
658             }
659 
660             /* Add the source file after dest path. */
661 
662             ret = vfs_normalize_path(dst_fullpath, src_filename, &dst_filepath);
663             if (ret < 0) {
664                 set_errno(-ret);
665                 PRINTK("cp error. %s.\n", strerror(errno));
666                 goto errout_with_path;
667             }
668             free(dst_fullpath);
669             dst_fullpath = dst_filepath;
670         }
671     }
672 
673     /* Is dest file same as source file? */
674 
675     if (strcmp(src_fullpath, dst_fullpath) == 0) {
676         PRINTK("cp error: '%s' and '%s' are the same file\n", src_fullpath, dst_fullpath);
677         goto errout_with_path;
678     }
679 
680     /* Copy begins. */
681 
682     (void)pthread_mutex_lock(&g_mutex_cp);
683     src_fd = open(src_fullpath, O_RDONLY);
684     if (src_fd < 0) {
685         PRINTK("cp error: can't open %s. %s.\n", src_fullpath, strerror(errno));
686         goto errout_with_mutex;
687     }
688 
689     dst_fd = open(dst_fullpath, O_CREAT | O_WRONLY | O_TRUNC, src_mode);
690     if (dst_fd < 0) {
691         PRINTK("cp error: can't create %s. %s.\n", dst_fullpath, strerror(errno));
692         goto errout_with_srcfd;
693     }
694 
695     do {
696         (void)memset_s(buf, CP_BUF_SIZE, 0, CP_BUF_SIZE);
697         r_size = read(src_fd, buf, CP_BUF_SIZE);
698         if (r_size < 0) {
699             PRINTK("cp %s %s failed. %s.\n", src_fullpath, dst_fullpath, strerror(errno));
700             goto errout_with_fd;
701         }
702         w_size = write(dst_fd, buf, r_size);
703         if (w_size != r_size) {
704             PRINTK("cp %s %s failed. %s.\n", src_fullpath, dst_fullpath, strerror(errno));
705             goto errout_with_fd;
706         }
707     } while (r_size == CP_BUF_SIZE);
708 
709     /* Release resource. */
710 
711     free(buf);
712     free(src_fullpath);
713     free(dst_fullpath);
714     (void)close(src_fd);
715     (void)close(dst_fd);
716     (void)pthread_mutex_unlock(&g_mutex_cp);
717     return LOS_OK;
718 
719 errout_with_fd:
720     (void)close(dst_fd);
721 errout_with_srcfd:
722     (void)close(src_fd);
723 errout_with_mutex:
724     (void)pthread_mutex_unlock(&g_mutex_cp);
725 errout_with_path:
726     free(dst_fullpath);
727 errout_with_srcpath:
728     free(src_fullpath);
729     free(buf);
730     return -1;
731 }
732 
733 /* The separator and EOF for a directory fullpath: '/'and '\0' */
734 
735 #define SEPARATOR_EOF_LEN 2
736 
os_shell_cmd_do_rmdir(const char * pathname)737 static int os_shell_cmd_do_rmdir(const char *pathname)
738 {
739     struct dirent *dirent = NULL;
740     struct stat stat_info;
741     DIR *d = NULL;
742     char *fullpath = NULL;
743     int ret;
744 
745     (void)memset_s(&stat_info, sizeof(stat_info), 0, sizeof(struct stat));
746     if (stat(pathname, &stat_info) != 0) {
747         return -1;
748     }
749 
750     if (S_ISREG(stat_info.st_mode) || S_ISLNK(stat_info.st_mode)) {
751         return remove(pathname);
752     }
753     d = opendir(pathname);
754     if (d == NULL) {
755         return -1;
756     }
757     while (1) {
758         dirent = readdir(d);
759         if (dirent == NULL) {
760             break;
761         }
762         if (strcmp(dirent->d_name, "..") && strcmp(dirent->d_name, ".")) {
763             size_t fullpath_buf_size = strlen(pathname) + strlen(dirent->d_name) + SEPARATOR_EOF_LEN;
764             fullpath = (char *)malloc(fullpath_buf_size);
765             if (fullpath == NULL) {
766                 PRINTK("malloc failure!\n");
767                 (void)closedir(d);
768                 return -1;
769             }
770             ret = snprintf_s(fullpath, fullpath_buf_size, fullpath_buf_size - 1, "%s/%s", pathname, dirent->d_name);
771             if (ret < 0) {
772                 PRINTK("name is too long!\n");
773                 free(fullpath);
774                 (void)closedir(d);
775                 return -1;
776             }
777             (void)os_shell_cmd_do_rmdir(fullpath);
778             free(fullpath);
779         }
780     }
781     (void)closedir(d);
782     return rmdir(pathname);
783 }
784 
785 /*  Wildcard matching operations  */
786 
os_wildcard_match(const char * src,const char * filename)787 static int os_wildcard_match(const char *src, const char *filename)
788 {
789     int ret;
790 
791     if (*src != '\0') {
792         if (*filename == '*') {
793             while ((*filename == '*') || (*filename == '?')) {
794                 filename++;
795             }
796 
797             if (*filename == '\0') {
798                 return 0;
799             }
800 
801             while (*src != '\0' && !(*src == *filename)) {
802                 src++;
803             }
804 
805             if (*src == '\0') {
806                 return -1;
807             }
808 
809             ret = os_wildcard_match(src, filename);
810 
811             while ((ret != 0) && (*(++src) != '\0')) {
812                 if (*src == *filename) {
813                     ret = os_wildcard_match(src, filename);
814                 }
815             }
816             return ret;
817         } else {
818             if ((*src == *filename) || (*filename == '?')) {
819                 return os_wildcard_match(++src, ++filename);
820             }
821             return -1;
822         }
823     }
824 
825     while (*filename != '\0') {
826         if (*filename != '*') {
827             return -1;
828         }
829         filename++;
830     }
831     return 0;
832 }
833 
834 /*   To determine whether a wildcard character exists in a path   */
835 
os_is_containers_wildcard(const char * filename)836 static int os_is_containers_wildcard(const char *filename)
837 {
838     while (*filename != '\0') {
839         if ((*filename == '*') || (*filename == '?')) {
840             return 1;
841         }
842         filename++;
843     }
844     return 0;
845 }
846 
847 /*  Delete a matching file or directory  */
848 
os_wildcard_delete_file_or_dir(const char * fullpath,wildcard_type mark)849 static int os_wildcard_delete_file_or_dir(const char *fullpath, wildcard_type mark)
850 {
851     int ret;
852 
853     switch (mark) {
854         case RM_RECURSIVER:
855             ret = os_shell_cmd_do_rmdir(fullpath);
856             break;
857         case RM_FILE:
858             ret = unlink(fullpath);
859             break;
860         case RM_DIR:
861             ret = rmdir(fullpath);
862             break;
863         default:
864             return VFS_ERROR;
865     }
866     if (ret == -1) {
867         PRINTK("%s  ", fullpath);
868         perror("rm/rmdir error!");
869         return ret;
870     }
871 
872     PRINTK("%s match successful!delete!\n", fullpath);
873     return 0;
874 }
875 
876 /*  Split the path with wildcard characters  */
877 
os_wildcard_split_path(char * fullpath,char ** handle,char ** wait)878 static char* os_wildcard_split_path(char *fullpath, char **handle, char **wait)
879 {
880     int n = 0;
881     int a = 0;
882     int b = 0;
883     int len  = strlen(fullpath);
884 
885     for (n = 0; n < len; n++) {
886         if (fullpath[n] == '/') {
887             if (b != 0) {
888                 fullpath[n] = '\0';
889                 *wait = fullpath + n + 1;
890                 break;
891             }
892             a = n;
893         } else if (fullpath[n] == '*' || fullpath[n] == '?') {
894             b = n;
895             fullpath[a] = '\0';
896             if (a == 0) {
897                 *handle = fullpath + a + 1;
898                 continue;
899             }
900             *handle = fullpath + a + 1;
901         }
902     }
903     return fullpath;
904 }
905 
906 /*  Handling entry of the path with wildcard characters  */
907 
os_wildcard_extract_directory(char * fullpath,void * dst,wildcard_type mark)908 static int os_wildcard_extract_directory(char *fullpath, void *dst, wildcard_type mark)
909 {
910     char separator[] = "/";
911     char src[PATH_MAX] = {0};
912     struct dirent *dirent = NULL;
913     char *f = NULL;
914     char *s = NULL;
915     char *t = NULL;
916     int ret = 0;
917     DIR *d = NULL;
918     struct stat stat_buf;
919     int deleteFlag = 0;
920 
921     f = os_wildcard_split_path(fullpath, &s, &t);
922 
923     if (s == NULL) {
924         if (mark == CP_FILE) {
925             ret = os_shell_cmd_do_cp(fullpath, dst);
926         } else if (mark == CP_COUNT) {
927             ret = stat(fullpath, &stat_buf);
928             if (ret == 0 && (S_ISREG(stat_buf.st_mode) || S_ISLNK(stat_buf.st_mode))) {
929                 (*(int *)dst)++;
930             }
931         } else {
932             ret = os_wildcard_delete_file_or_dir(fullpath, mark);
933         }
934         return ret;
935     }
936 
937     d = (*f == '\0') ? opendir("/") : opendir(f);
938     if (d == NULL) {
939         perror("opendir error");
940         return VFS_ERROR;
941     }
942 
943     while (1) {
944         dirent = readdir(d);
945         if (dirent == NULL) {
946             break;
947         }
948 
949         ret = strcpy_s(src, PATH_MAX, f);
950         if (ret != EOK) {
951             goto closedir_out;
952         }
953 
954         ret = os_wildcard_match(dirent->d_name, s);
955         if (ret == 0) {
956             ret = strcat_s(src, sizeof(src), separator);
957             if (ret != EOK) {
958                 goto closedir_out;
959             }
960             ret = strcat_s(src, sizeof(src), dirent->d_name);
961             if (ret != EOK) {
962                 goto closedir_out;
963             }
964             if (t == NULL) {
965                 if (mark == CP_FILE) {
966                     ret = os_shell_cmd_do_cp(src, dst);
967                 } else if (mark == CP_COUNT) {
968                     ret = stat(src, &stat_buf);
969                     if (ret == 0 && (S_ISREG(stat_buf.st_mode) || S_ISLNK(stat_buf.st_mode))) {
970                         (*(int *)dst)++;
971                         if ((*(int *)dst) > 1) {
972                             break;
973                         }
974                     }
975                 } else {
976                     ret = os_wildcard_delete_file_or_dir(src, mark);
977                     if (ret == 0) {
978                         deleteFlag = 1;
979                     }
980                 }
981             } else {
982                 ret = strcat_s(src, sizeof(src), separator);
983                 if (ret != EOK) {
984                     goto closedir_out;
985                 }
986                 ret = strcat_s(src, sizeof(src), t);
987                 if (ret != EOK) {
988                     goto closedir_out;
989                 }
990                 ret = os_wildcard_extract_directory(src, dst, mark);
991                 if (mark == CP_COUNT && (*(int *)dst) > 1) {
992                     break;
993                 }
994             }
995         }
996     }
997     (void)closedir(d);
998     if (deleteFlag == 1) {
999         ret = 0;
1000     }
1001     return ret;
1002 closedir_out:
1003     (void)closedir(d);
1004     return VFS_ERROR;
1005 }
1006 
osShellCmdCp(int argc,const char ** argv)1007 int osShellCmdCp(int argc, const char **argv)
1008 {
1009     int  ret;
1010     const char *src = NULL;
1011     const char *dst = NULL;
1012     char *src_fullpath = NULL;
1013     char *dst_fullpath = NULL;
1014     struct stat stat_buf;
1015     int count = 0;
1016     char *shell_working_directory = OsShellGetWorkingDirectory();
1017     if (shell_working_directory == NULL) {
1018         return -1;
1019     }
1020 
1021     ERROR_OUT_IF(argc < 2, PRINTK("cp [SOURCEFILE] [DESTFILE]\n"), return -1);
1022 
1023     src = argv[0];
1024     dst = argv[1];
1025 
1026     /* Get source fullpath. */
1027 
1028     ret = vfs_normalize_path(shell_working_directory, src, &src_fullpath);
1029     if (ret < 0) {
1030         set_errno(-ret);
1031         PRINTK("cp error:%s\n", strerror(errno));
1032         return -1;
1033     }
1034 
1035     if (src[strlen(src) - 1] == '/') {
1036         PRINTK("cp %s error: Source file can't be a directory.\n", src);
1037         goto errout_with_srcpath;
1038     }
1039 
1040     /* Get dest fullpath. */
1041 
1042     ret = vfs_normalize_path(shell_working_directory, dst, &dst_fullpath);
1043     if (ret < 0) {
1044         set_errno(-ret);
1045         PRINTK("cp error: can't open %s. %s\n", dst, strerror(errno));
1046         goto errout_with_srcpath;
1047     }
1048 
1049     /* Is dest path exist? */
1050 
1051     ret = stat(dst_fullpath, &stat_buf);
1052     if (ret < 0) {
1053         /* Is dest path a directory? */
1054 
1055         if (dst[strlen(dst) - 1] == '/') {
1056             PRINTK("cp error: %s, %s.\n", dst_fullpath, strerror(errno));
1057             goto errout_with_path;
1058         }
1059     } else {
1060         if ((S_ISREG(stat_buf.st_mode) || S_ISLNK(stat_buf.st_mode)) && dst[strlen(dst) - 1] == '/') {
1061             PRINTK("cp error: %s is not a directory.\n", dst_fullpath);
1062             goto errout_with_path;
1063         }
1064     }
1065 
1066     if (os_is_containers_wildcard(src_fullpath)) {
1067         if (ret < 0 || S_ISREG(stat_buf.st_mode) || S_ISLNK(stat_buf.st_mode)) {
1068             char *src_copy = strdup(src_fullpath);
1069             if (src_copy == NULL) {
1070                 PRINTK("cp error : Out of memory.\n");
1071                 goto errout_with_path;
1072             }
1073             (void)os_wildcard_extract_directory(src_copy, &count, CP_COUNT);
1074             free(src_copy);
1075             if (count > 1) {
1076                 PRINTK("cp error : %s is not a directory.\n", dst_fullpath);
1077                 goto errout_with_path;
1078             }
1079         }
1080         ret = os_wildcard_extract_directory(src_fullpath, dst_fullpath, CP_FILE);
1081     } else {
1082         ret = os_shell_cmd_do_cp(src_fullpath, dst_fullpath);
1083     }
1084     free(dst_fullpath);
1085     free(src_fullpath);
1086     return ret;
1087 
1088 errout_with_path:
1089     free(dst_fullpath);
1090 errout_with_srcpath:
1091     free(src_fullpath);
1092     return VFS_ERROR;
1093 }
1094 
print_rm_usage(void)1095 static inline void print_rm_usage(void)
1096 {
1097     PRINTK("rm [FILE] or rm [-r/-R] [FILE]\n");
1098 }
1099 
osShellCmdRm(int argc,const char ** argv)1100 int osShellCmdRm(int argc, const char **argv)
1101 {
1102     int  ret = 0;
1103     char *fullpath = NULL;
1104     const char *filename = NULL;
1105     char *shell_working_directory = OsShellGetWorkingDirectory();
1106     if (shell_working_directory == NULL) {
1107         return -1;
1108     }
1109 
1110     ERROR_OUT_IF(argc != 1 && argc != 2, print_rm_usage(), return -1);
1111 
1112     if (argc == 2) { // 2: arguments include "-r" or "-R"
1113         ERROR_OUT_IF(strcmp(argv[0], "-r") != 0 && strcmp(argv[0], "-R") != 0, print_rm_usage(), return -1);
1114 
1115         filename = argv[1];
1116         ret = vfs_normalize_path(shell_working_directory, filename, &fullpath);
1117         ERROR_OUT_IF(ret < 0, set_err(-ret, "rm error"), return -1);
1118 
1119         if (os_is_containers_wildcard(fullpath)) {
1120             ret = os_wildcard_extract_directory(fullpath, NULL, RM_RECURSIVER);
1121         } else {
1122             ret = os_shell_cmd_do_rmdir(fullpath);
1123         }
1124     } else {
1125         filename = argv[0];
1126         ret = vfs_normalize_path(shell_working_directory, filename, &fullpath);
1127         ERROR_OUT_IF(ret < 0, set_err(-ret, "rm error"), return -1);
1128 
1129         if (os_is_containers_wildcard(fullpath)) {
1130             ret = os_wildcard_extract_directory(fullpath, NULL, RM_FILE);
1131         } else {
1132             ret = unlink(fullpath);
1133         }
1134     }
1135     if (ret == -1) {
1136         perror("rm error");
1137     }
1138     free(fullpath);
1139     return 0;
1140 }
1141 
osShellCmdRmdir(int argc,const char ** argv)1142 int osShellCmdRmdir(int argc, const char **argv)
1143 {
1144     int  ret;
1145     char *fullpath = NULL;
1146     const char *filename = NULL;
1147     char *shell_working_directory = OsShellGetWorkingDirectory();
1148     if (shell_working_directory == NULL) {
1149         return -1;
1150     }
1151 
1152     ERROR_OUT_IF(argc == 0, PRINTK("rmdir [DIRECTORY]\n"), return -1);
1153 
1154     filename = argv[0];
1155     ret = vfs_normalize_path(shell_working_directory, filename, &fullpath);
1156     ERROR_OUT_IF(ret < 0, set_err(-ret, "rmdir error"), return -1);
1157 
1158     if (os_is_containers_wildcard(fullpath)) {
1159         ret = os_wildcard_extract_directory(fullpath, NULL, RM_DIR);
1160     } else {
1161         ret = rmdir(fullpath);
1162     }
1163     if (ret == -1) {
1164         PRINTK("rmdir %s failed. Error: %s.\n", fullpath, strerror(errno));
1165     }
1166     free(fullpath);
1167 
1168     return 0;
1169 }
1170 
osShellCmdSync(int argc,const char ** argv)1171 int osShellCmdSync(int argc, const char **argv)
1172 {
1173     ERROR_OUT_IF(argc > 0, PRINTK("\nUsage: sync\n"), return -1);
1174 
1175     sync();
1176     return 0;
1177 }
1178 
osShellCmdLsfd(int argc,const char ** argv)1179 int osShellCmdLsfd(int argc, const char **argv)
1180 {
1181     ERROR_OUT_IF(argc > 0, PRINTK("\nUsage: lsfd\n"), return -1);
1182 
1183     lsfd();
1184 
1185     return 0;
1186 }
1187 
checkNum(const char * arg)1188 int checkNum(const char *arg)
1189 {
1190     int i = 0;
1191     if (arg == NULL) {
1192         return -1;
1193     }
1194     if (arg[0] == '-') {
1195         /* exclude the '-' */
1196 
1197         i = 1;
1198     }
1199     for (; arg[i] != 0; i++) {
1200         if (!isdigit(arg[i])) {
1201             return -1;
1202         }
1203     }
1204     return 0;
1205 }
1206 
1207 #ifdef LOSCFG_KERNEL_SYSCALL
osShellCmdSu(int argc,const char ** argv)1208 int osShellCmdSu(int argc, const char **argv)
1209 {
1210     int su_uid;
1211     int su_gid;
1212 
1213     if (argc == 0) {
1214         /* for su root */
1215 
1216         su_uid = 0;
1217         su_gid = 0;
1218     } else {
1219         ERROR_OUT_IF((argc != 2), PRINTK("su [uid_num] [gid_num]\n"), return -1);
1220         ERROR_OUT_IF((checkNum(argv[0]) != 0) || (checkNum(argv[1]) != 0), /* check argv is digit */
1221         PRINTK("check uid_num and gid_num is digit\n"), return -1);
1222 
1223         su_uid = atoi(argv[0]);
1224         su_gid = atoi(argv[1]);
1225 
1226         ERROR_OUT_IF((su_uid < 0) || (su_uid > 60000) || (su_gid < 0) ||
1227             (su_gid > 60000), PRINTK("uid_num or gid_num out of range!they should be [0~60000]\n"), return -1);
1228     }
1229 
1230     SysSetUserID(su_uid);
1231     SysSetGroupID(su_gid);
1232     return 0;
1233 }
1234 #endif
1235 
osShellCmdChmod(int argc,const char ** argv)1236 int osShellCmdChmod(int argc, const char **argv)
1237 {
1238     int i = 0;
1239     int mode = 0;
1240     int ret;
1241     char *fullpath = NULL;
1242     const char *filename = NULL;
1243     struct IATTR attr = {0};
1244     char *shell_working_directory = NULL;
1245     const char *p = NULL;
1246 #define MODE_BIT 3 /* 3 bits express 1 mode */
1247 
1248     ERROR_OUT_IF((argc != 2), PRINTK("Usage: chmod <MODE> [FILE]\n"), return -1);
1249 
1250     p = argv[0];
1251     while (p[i]) {
1252         if ((p[i] <= '7') && (p[i] >= '0')) {
1253             mode = ((uint)mode << MODE_BIT) | (uint)(p[i] - '0');
1254         } else {
1255             PRINTK("check the input <MODE>\n");
1256             return -1;
1257         }
1258         i++;
1259     }
1260     filename = argv[1];
1261 
1262     shell_working_directory = OsShellGetWorkingDirectory();
1263     if (shell_working_directory == NULL) {
1264         return -1;
1265     }
1266     ret = vfs_normalize_path(shell_working_directory, filename, &fullpath);
1267     ERROR_OUT_IF(ret < 0, set_err(-ret, "chmod error\n"), return -1);
1268 
1269     attr.attr_chg_mode = mode;
1270     attr.attr_chg_valid = CHG_MODE; /* change mode */
1271     ret = chattr(fullpath, &attr);
1272     if (ret < 0) {
1273         free(fullpath);
1274         PRINTK("chmod error! %s\n", strerror(errno));
1275         return ret;
1276     }
1277 
1278     free(fullpath);
1279     return 0;
1280 }
1281 
osShellCmdChown(int argc,const char ** argv)1282 int osShellCmdChown(int argc, const char **argv)
1283 {
1284     int ret;
1285     char *fullpath = NULL;
1286     const char *filename = NULL;
1287     struct IATTR attr;
1288     uid_t owner = -1;
1289     gid_t group = -1;
1290     attr.attr_chg_valid = 0;
1291 
1292     ERROR_OUT_IF(((argc != 2) && (argc != 3)), PRINTK("Usage: chown [OWNER] [GROUP] FILE\n"), return -1);
1293     if (argc == 2) { // 2: chown owner of file
1294         ERROR_OUT_IF((checkNum(argv[0]) != 0), PRINTK("check OWNER is digit\n"), return -1);
1295         owner = atoi(argv[0]);
1296         filename = argv[1];
1297     }
1298     if (argc == 3) { // 3: chown both owner and group
1299         ERROR_OUT_IF((checkNum(argv[0]) != 0), PRINTK("check OWNER is digit\n"), return -1);
1300         ERROR_OUT_IF((checkNum(argv[1]) != 0), PRINTK("check GROUP is digit\n"), return -1);
1301         owner = atoi(argv[0]);
1302         group = atoi(argv[1]);
1303         filename = argv[2];
1304     }
1305 
1306     if (group != -1) {
1307         attr.attr_chg_gid = group;
1308         attr.attr_chg_valid |= CHG_GID;
1309     }
1310     if (owner != -1) {
1311         attr.attr_chg_uid = owner;
1312         attr.attr_chg_valid |= CHG_UID;
1313     }
1314 
1315     char *shell_working_directory = OsShellGetWorkingDirectory();
1316     if (shell_working_directory == NULL) {
1317         return -1;
1318     }
1319     ret = vfs_normalize_path(shell_working_directory, filename, &fullpath);
1320     ERROR_OUT_IF(ret < 0, set_err(-ret, "chown error\n"), return -1);
1321 
1322     ret = chattr(fullpath, &attr);
1323     if (ret < 0) {
1324         free(fullpath);
1325         PRINTK("chown error! %s\n", strerror(errno));
1326         return ret;
1327     }
1328 
1329     free(fullpath);
1330     return 0;
1331 }
1332 
osShellCmdChgrp(int argc,const char ** argv)1333 int osShellCmdChgrp(int argc, const char **argv)
1334 {
1335     int ret;
1336     char *fullpath = NULL;
1337     const char *filename = NULL;
1338     struct IATTR attr;
1339     gid_t group;
1340     attr.attr_chg_valid = 0;
1341     ERROR_OUT_IF((argc != 2), PRINTK("Usage: chgrp GROUP FILE\n"), return -1);
1342     ERROR_OUT_IF((checkNum(argv[0]) != 0), PRINTK("check GROUP is digit\n"), return -1);
1343     group = atoi(argv[0]);
1344     filename = argv[1];
1345 
1346     if (group != -1) {
1347         attr.attr_chg_gid = group;
1348         attr.attr_chg_valid |= CHG_GID;
1349     }
1350 
1351     char *shell_working_directory = OsShellGetWorkingDirectory();
1352     if (shell_working_directory == NULL) {
1353         return -1;
1354     }
1355     ret = vfs_normalize_path(shell_working_directory, filename, &fullpath);
1356     ERROR_OUT_IF(ret < 0, set_err(-ret, "chmod error"), return -1);
1357 
1358     ret = chattr(fullpath, &attr);
1359     if (ret < 0) {
1360         free(fullpath);
1361         PRINTK("chgrp error! %s\n", strerror(errno));
1362         return ret;
1363     }
1364 
1365     free(fullpath);
1366     return 0;
1367 }
1368 
1369 #ifdef LOSCFG_SHELL_CMD_DEBUG
1370 SHELLCMD_ENTRY(lsfd_shellcmd, CMD_TYPE_EX, "lsfd", XARGS, (CmdCallBackFunc)osShellCmdLsfd);
1371 SHELLCMD_ENTRY(statfs_shellcmd, CMD_TYPE_EX, "statfs", XARGS, (CmdCallBackFunc)osShellCmdStatfs);
1372 SHELLCMD_ENTRY(touch_shellcmd, CMD_TYPE_EX, "touch", XARGS, (CmdCallBackFunc)osShellCmdTouch);
1373 #ifdef LOSCFG_KERNEL_SYSCALL
1374 SHELLCMD_ENTRY(su_shellcmd, CMD_TYPE_EX, "su", XARGS, (CmdCallBackFunc)osShellCmdSu);
1375 #endif
1376 #endif
1377 SHELLCMD_ENTRY(sync_shellcmd, CMD_TYPE_EX, "sync", XARGS, (CmdCallBackFunc)osShellCmdSync);
1378 SHELLCMD_ENTRY(ls_shellcmd, CMD_TYPE_EX, "ls", XARGS, (CmdCallBackFunc)osShellCmdLs);
1379 SHELLCMD_ENTRY(pwd_shellcmd, CMD_TYPE_EX, "pwd", XARGS, (CmdCallBackFunc)osShellCmdPwd);
1380 SHELLCMD_ENTRY(cd_shellcmd, CMD_TYPE_EX, "cd", XARGS, (CmdCallBackFunc)osShellCmdCd);
1381 SHELLCMD_ENTRY(cat_shellcmd, CMD_TYPE_EX, "cat", XARGS, (CmdCallBackFunc)osShellCmdCat);
1382 SHELLCMD_ENTRY(rm_shellcmd, CMD_TYPE_EX, "rm", XARGS, (CmdCallBackFunc)osShellCmdRm);
1383 SHELLCMD_ENTRY(rmdir_shellcmd, CMD_TYPE_EX, "rmdir", XARGS, (CmdCallBackFunc)osShellCmdRmdir);
1384 SHELLCMD_ENTRY(mkdir_shellcmd, CMD_TYPE_EX, "mkdir", XARGS, (CmdCallBackFunc)osShellCmdMkdir);
1385 SHELLCMD_ENTRY(chmod_shellcmd, CMD_TYPE_EX, "chmod", XARGS, (CmdCallBackFunc)osShellCmdChmod);
1386 SHELLCMD_ENTRY(chown_shellcmd, CMD_TYPE_EX, "chown", XARGS, (CmdCallBackFunc)osShellCmdChown);
1387 SHELLCMD_ENTRY(chgrp_shellcmd, CMD_TYPE_EX, "chgrp", XARGS, (CmdCallBackFunc)osShellCmdChgrp);
1388 SHELLCMD_ENTRY(mount_shellcmd, CMD_TYPE_EX, "mount", XARGS, (CmdCallBackFunc)osShellCmdMount);
1389 SHELLCMD_ENTRY(umount_shellcmd, CMD_TYPE_EX, "umount", XARGS, (CmdCallBackFunc)osShellCmdUmount);
1390 SHELLCMD_ENTRY(cp_shellcmd, CMD_TYPE_EX, "cp", XARGS, (CmdCallBackFunc)osShellCmdCp);
1391 #endif
1392