1 #include <stdio.h>
2 #include <dirent.h>
3 #include <string.h>
4 #include <errno.h>
5 #include <unistd.h>
6 #include <sys/stat.h>
7 #include <aos/cli.h>
8 #include <stdbool.h>
9 #include <fcntl.h>
10
11 static char g_last_working_directory[512] = "/";
12
up_one_level(char * abspath)13 static int up_one_level(char *abspath)
14 {
15 char *c, *last_slash;
16
17 if (strcmp(abspath, "/") == 0)
18 return -1;
19
20 c = abspath + 1;
21 last_slash = abspath;
22
23 while (*c != '\0') {
24 if ((*c == '/') && (*(c + 1) != '\0'))
25 last_slash = c;
26 c++;
27 }
28
29 *(last_slash + 1) = '\0';
30
31 return 0;
32 }
33
34 #define ROOT_DIR "/"
cd_main(int argc,char ** argv)35 static int cd_main(int argc, char **argv)
36 {
37 char absolute[256] = {0}, *ret, *target, cwd_backup[256] = {0};
38 struct stat s;
39
40 if (argc > 1) {
41 target = argv[1];
42 } else {
43 target = ROOT_DIR;
44 }
45
46 if (!target) {
47 aos_cli_printf("target dir is NULL!\r\n");
48 return -1;
49 }
50
51 ret = getcwd(absolute, sizeof(absolute));
52 if (!ret) {
53 aos_cli_printf("Failed to get current working directory!\r\n");
54 return -1;
55 }
56
57 strncpy(cwd_backup, absolute, sizeof(cwd_backup));
58
59 if (target[0] != '/') {
60 if (target[0] == '-') {
61 memset(absolute, 0, sizeof(absolute));
62 strncpy(absolute, g_last_working_directory, sizeof(absolute));
63 absolute[sizeof(absolute) - 1] = '\0';
64 goto check_and_cd;
65 }
66
67 if (absolute[strlen(absolute) - 1] != '/') {
68 absolute[strlen(absolute)] = '/';
69 }
70
71 // exclude heading "./"
72 while (strncmp(target, "./", strlen("./")) == 0) {
73 target += strlen("./");
74 while (target[0] == '/')
75 target++;
76 }
77
78 // parse heading ".."
79 while (target && strncmp(target, "..", strlen("..")) == 0) {
80 if (up_one_level(absolute) != 0) {
81 aos_cli_printf("up to parent dir failed. %s may " \
82 "not be a valid path!", target);
83 return -1;
84 }
85
86 target += strlen("..");
87 while (target[0] == '/')
88 target++;
89 }
90
91 if (target)
92 strncpy(absolute + strlen(absolute), target, \
93 sizeof(absolute) - strlen(absolute));
94 } else {
95 strncpy(absolute, target, sizeof(absolute));
96 }
97
98 check_and_cd:
99 if (stat(absolute, &s)) {
100 aos_cli_printf("cd: %s not existed\r\n", target);
101 return -1;
102 }
103
104 if (access(absolute, F_OK) != 0) {
105 aos_cli_printf("%s is not a valid path.\r\n", target);
106 return -1;
107 }
108
109 if (!S_ISDIR(s.st_mode)) {
110 aos_cli_printf("cd: %s not a directory\r\n", target);
111 return -1;
112 }
113
114 int err = chdir(absolute);
115 if (err != 0) {
116 aos_cli_printf("Failed to change to %s, errno: %d\r\n",
117 absolute, errno);
118 return -1;
119 }
120
121 memset(g_last_working_directory,
122 0,
123 sizeof(g_last_working_directory));
124
125 strncpy(g_last_working_directory,
126 cwd_backup,
127 sizeof(g_last_working_directory));
128
129 return 0;
130 }
131 ALIOS_CLI_CMD_REGISTER(cd_main, cd, change current working directory);
132