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