|
| 1 | +#include <dirent.h> |
| 2 | +#include <fcntl.h> |
1 | 3 | #include <stdio.h>
|
2 | 4 | #include <stdlib.h>
|
3 | 5 | #include <string.h>
|
4 | 6 | #include <sys/stat.h>
|
| 7 | +#include <sys/time.h> |
5 | 8 | #include <sys/types.h>
|
| 9 | +#include <time.h> |
6 | 10 | #include <unistd.h>
|
| 11 | +#include <utime.h> |
7 | 12 | #define N 1024
|
8 | 13 |
|
| 14 | +const char *help_string[] = { |
| 15 | + "cat {file}: Display content of {file}.", |
| 16 | + "cd {dir}: Switch current working directory to {dir}.", |
| 17 | + "chmod {mode} {file/dir}: Change the mode (permission) of a file or " |
| 18 | + "directory.", |
| 19 | + " {mode} is an octal number.", |
| 20 | + " Please do not follow symbolc links.", |
| 21 | + "echo {str} [filename]: Display {str}. If [filename] is given,", |
| 22 | + " open [filename] and append {str} to the file.", |
| 23 | + "exit: Leave the shell.", |
| 24 | + "find [dir]: List files/dirs in the current working " |
| 25 | + "directory", |
| 26 | + " or [dir] if it is given.", |
| 27 | + " Minimum outputs contatin file type, size, and " |
| 28 | + "name.", |
| 29 | + "help: Display help message.", |
| 30 | + "id: Show current euid and egid.", |
| 31 | + "mkdir {dir}: Create a new directory {dir}.", |
| 32 | + "pwd: Print the current working directory.", |
| 33 | + "rm {file}: Remove a file.", |
| 34 | + "rmdir {dir}: Remove an empty directory.", |
| 35 | + "stat {file/dir}: Display detailed information of the given " |
| 36 | + "file/dir.", |
| 37 | + "touch {file}: Create {file} if it does not exist,", |
| 38 | + " or update its access and modification " |
| 39 | + "timestamp.", |
| 40 | + "umask {mode}: Change the umask of the current session."}; |
| 41 | + |
| 42 | +const char *get_file_type(int mode) { |
| 43 | + const char *file_type[] = {"named pipe (fifo)", |
| 44 | + "character special file", |
| 45 | + "directory", |
| 46 | + "block special file", |
| 47 | + "regular file", |
| 48 | + "symbolic link", |
| 49 | + "socket", |
| 50 | + "unknown"}; |
| 51 | + const int file_mask[] = {S_IFIFO, S_IFCHR, S_IFDIR, S_IFBLK, |
| 52 | + S_IFREG, S_IFLNK, S_IFSOCK}; |
| 53 | + |
| 54 | + for (size_t i = 0; i < 7; ++i) { |
| 55 | + if (mode == file_mask[i]) { |
| 56 | + return file_type[i]; |
| 57 | + } |
| 58 | + } |
| 59 | + return file_type[7]; |
| 60 | +} |
| 61 | + |
9 | 62 | int builtin_cat(char *line) {
|
10 | 63 | char arg[N], extra[N];
|
11 | 64 | if (sscanf(line, "%*s %s %s", arg, extra) != 1) return -1;
|
@@ -64,40 +117,31 @@ int builtin_exit(char *line) {
|
64 | 117 | return 1;
|
65 | 118 | }
|
66 | 119 |
|
67 |
| -int builtin_find(char *cmd) { return 0; } |
| 120 | +int builtin_find(char *line) { |
| 121 | + char arg[N], extra[N]; |
| 122 | + int argc; |
| 123 | + if ((argc = sscanf(line, "%*s %s %s", arg, extra)) > 1) return -1; |
| 124 | + |
| 125 | + DIR *dir = opendir(argc == 1 ? arg : "."); |
| 126 | + struct dirent *dp; |
| 127 | + struct stat info; |
| 128 | + int ret; |
| 129 | + while ((dp = readdir(dir)) != NULL) { |
| 130 | + printf("%-20s", dp->d_name); |
| 131 | + ret = stat(dp->d_name, &info); |
| 132 | + // if (ret == -1) { ; continue; } |
| 133 | + printf("\t%-20s\t%-5ld\n", get_file_type(info.st_mode & S_IFMT), |
| 134 | + info.st_size); |
| 135 | + } |
| 136 | + closedir(dir); |
| 137 | + return 0; |
| 138 | +} |
68 | 139 |
|
69 | 140 | int builtin_help(char *line) {
|
70 | 141 | char extra[N];
|
71 | 142 | if (sscanf(line, "%*s %s", extra) > 0) return -1;
|
72 | 143 |
|
73 |
| - const char *help_string[] = { |
74 |
| - "cat {file}: Display content of {file}.", |
75 |
| - "cd {dir}: Switch current working directory to {dir}.", |
76 |
| - "chmod {mode} {file/dir}: Change the mode (permission) of a file or " |
77 |
| - "directory.", |
78 |
| - " {mode} is an octal number.", |
79 |
| - " Please do not follow symbolc links.", |
80 |
| - "echo {str} [filename]: Display {str}. If [filename] is given,", |
81 |
| - " open [filename] and append {str} to the file.", |
82 |
| - "exit: Leave the shell.", |
83 |
| - "find [dir]: List files/dirs in the current working " |
84 |
| - "directory", |
85 |
| - " or [dir] if it is given.", |
86 |
| - " Minimum outputs contatin file type, size, and " |
87 |
| - "name.", |
88 |
| - "help: Display help message.", |
89 |
| - "id: Show current euid and egid.", |
90 |
| - "mkdir {dir}: Create a new directory {dir}.", |
91 |
| - "pwd: Print the current working directory.", |
92 |
| - "rm {file}: Remove a file.", |
93 |
| - "rmdir {dir}: Remove an empty directory.", |
94 |
| - "stat {file/dir}: Display detailed information of the given " |
95 |
| - "file/dir.", |
96 |
| - "touch {file}: Create {file} if it does not exist,", |
97 |
| - " or update its access and modification " |
98 |
| - "timestamp.", |
99 |
| - "umask {mode}: Change the umask of the current session."}; |
100 |
| - size_t len = sizeof(help_string) / sizeof(char *); |
| 144 | + const size_t len = sizeof(help_string) / sizeof(char *); |
101 | 145 | for (size_t i = 0; i < len; ++i) printf("%s\n", help_string[i]);
|
102 | 146 | return 0;
|
103 | 147 | }
|
@@ -148,16 +192,38 @@ int builtin_rmdir(char *line) {
|
148 | 192 | return 0;
|
149 | 193 | }
|
150 | 194 |
|
151 |
| -int builtin_stat(char *cmd) { return 0; } |
| 195 | +int builtin_stat(char *line) { |
| 196 | + char arg[N], extra[N]; |
| 197 | + if (sscanf(line, "%*s %s %s", arg, extra) != 1) return -1; |
| 198 | + |
| 199 | + struct stat info; |
| 200 | + int ret = stat(arg, &info); |
| 201 | + // if (ret == -1) |
| 202 | + printf( |
| 203 | + "\ |
| 204 | + File: %s\n\ |
| 205 | + Size: %lld Blocks: %lld IO Block: %ld %s\n\ |
| 206 | +Device: %s Inode: %ld Links: %d\n\ |
| 207 | +Access: (%lo) Uid: (%ld) Gid: (%ld)\n\ |
| 208 | +Access: %s\ |
| 209 | +Modify: %s\ |
| 210 | +Change: %s", |
| 211 | + arg, info.st_size, info.st_blocks, info.st_blksize, |
| 212 | + get_file_type(info.st_mode & S_IFMT), |
| 213 | + "", // info.st_dev, |
| 214 | + info.st_ino, info.st_nlink, info.st_mode & 0777, info.st_uid, info.st_gid, |
| 215 | + ctime(&info.st_atime), ctime(&info.st_mtime), ctime(&info.st_ctime)); |
| 216 | + return 0; |
| 217 | +} |
152 | 218 |
|
153 | 219 | int builtin_touch(char *line) {
|
154 | 220 | char arg[N], extra[N];
|
155 | 221 | if (sscanf(line, "%*s %s %s", arg, extra) != 1) return -1;
|
156 | 222 |
|
157 |
| - FILE *file; |
158 |
| - // if (access(arg, F_OK) != -1) |
159 |
| - file = fopen(arg, "a+"); |
160 |
| - fclose(file); |
| 223 | + int fd = open(arg, O_WRONLY | O_CREAT | O_NOCTTY | O_NONBLOCK, 0666); |
| 224 | + // if (fd < 0) |
| 225 | + int rc = utimensat(AT_FDCWD, arg, NULL, 0); |
| 226 | + // if (rc) |
161 | 227 | return 0;
|
162 | 228 | }
|
163 | 229 |
|
|
0 commit comments