1 /* 2 1.尝试实现ls命令的功能 加选项-l -a -i -h 3 */ 4 #include <stdio.h> 5 #include <sys/types.h> 6 #include <sys/stat.h> 7 #include <unistd.h> 8 #include <errno.h> 9 #include <time.h> 10 #include <string.h> 11 #include <stdlib.h> 12 #include <dirent.h> 13 #include <pwd.h> 14 #include <grp.h> 15 16 #define MAX 1024 17 18 static int myls_l(char *optarg); 19 static void ls_all(char *path); 20 static int myls_a(char *path); 21 static int is_dir(char *path); 22 static void myls_i(char *path); 23 static void myls_i_notdir(char *path); 24 static int myls_h(char *path); 25 26 int main(int argc, char *argv[]) 27 { 28 int c; 29 char *str = "-l:a:i:h:"; 30 if (argc < 2) 31 return -1; 32 33 while (1) { 34 if ((c = getopt(argc, argv, str)) == -1) 35 break; 36 switch (c) { 37 case 'l': 38 is_dir(optarg) ? ls_all(optarg) : myls_l(optarg); 39 break; 40 case 'a': 41 is_dir(optarg) ? myls_a(optarg) : puts(optarg); 42 break; 43 case 'i': 44 is_dir(optarg) ? myls_i(optarg) : myls_i_notdir(optarg); 45 break; 46 case 'h': 47 is_dir(optarg) ? myls_h(optarg) : puts(optarg); 48 break; 49 case '?': 50 printf("输入选项错误\n"); 51 break; 52 case 1: 53 printf("错误参数选项%s\n", argv[optind-1]); 54 break; 55 default: 56 break; 57 } 58 } 59 60 return 0; 61 } 62 63 // 单文件显示详细信息 相当于ls -l +文件名 64 static int myls_l(char *optarg) 65 { 66 struct stat buf; 67 68 if (stat(optarg, &buf) == -1) { 69 perror("STAT()"); 70 return -1; 71 } 72 // 文件类型 73 if (S_ISREG(buf.st_mode)) 74 putchar('-'); 75 if (S_ISDIR(buf.st_mode)) 76 putchar('d'); 77 if (S_ISCHR(buf.st_mode)) 78 putchar('c'); 79 if (S_ISBLK(buf.st_mode)) 80 putchar('b'); 81 if (S_ISFIFO(buf.st_mode)) 82 putchar('p'); 83 if ((buf.st_mode & S_IFMT) == S_IFSOCK) 84 putchar('s'); 85 if ((buf.st_mode & S_IFMT) == S_IFLNK) 86 putchar('l'); 87 // 权限 88 if (buf.st_mode & S_IRUSR) 89 putchar('r'); 90 else 91 putchar('-'); 92 if (buf.st_mode & S_IWUSR) 93 putchar('w'); 94 else 95 putchar('-'); 96 if (buf.st_mode & S_IXUSR) { 97 if (buf.st_mode & S_ISUID) { 98 putchar('s'); 99 } else { 100 putchar('x'); 101 } 102 } 103 else 104 putchar('-'); 105 if (buf.st_mode & S_IRGRP) 106 putchar('r'); 107 else 108 putchar('-'); 109 if (buf.st_mode & S_IWGRP) 110 putchar('w'); 111 else 112 putchar('-'); 113 if (buf.st_mode & S_IXGRP) { 114 if (buf.st_mode & S_ISGID) { 115 putchar('s'); 116 } else { 117 putchar('x'); 118 } 119 } 120 else 121 putchar('-'); 122 if (buf.st_mode & S_IROTH) 123 putchar('r'); 124 else 125 putchar('-'); 126 if (buf.st_mode & S_IWOTH) 127 putchar('w'); 128 else 129 putchar('-'); 130 if (buf.st_mode & S_IXOTH) { 131 if (buf.st_mode & S_ISVTX) { 132 putchar('t'); 133 } else { 134 putchar('x'); 135 } 136 } 137 else 138 putchar('-'); 139 // 硬链接 140 printf(" %zu ", buf.st_nlink); 141 // 拥有者 142 struct passwd *pwd = NULL; 143 pwd = getpwuid(buf.st_uid); 144 printf("%s ", pwd->pw_name); 145 // 所属组 146 struct group *grp = NULL; 147 grp = getgrgid(buf.st_gid); 148 printf("%s ", grp->gr_name); 149 // 文件字节大小 150 printf("%zu ", buf.st_size); 151 // 最后更改文件时间 152 struct tm *tmp = NULL; 153 char s[MAX] = {}; 154 tmp = localtime(&(buf.st_mtim.tv_sec)); 155 strftime(s, MAX, "%m月 %d %H:%M ", tmp); 156 printf("%s ", s); 157 // 文件名 158 char *ptr = NULL; 159 if ((ptr = strrchr(optarg, '/')) != NULL) { 160 printf("%s", ptr+1); 161 } else { 162 printf("%s", optarg); 163 } 164 165 putchar('\n'); 166 167 return 0; 168 } 169 170 // 判断该文件名第一个字符是否为隐藏文件和 . .. .asd 171 static int is_hidden(char *str) 172 { 173 if (str[0] == '.') { 174 return 1; // 是隐藏文件返回1 175 } 176 return 0; 177 } 178 179 // 相当于 ls -l +目录的路径 180 static void ls_all(char *path) 181 { 182 DIR *dp = NULL; 183 char str[MAX] = {}; 184 struct dirent *ret_dir = NULL; 185 dp = opendir(path); 186 187 while (1) { 188 memset(str, '\0', MAX); 189 strcpy(str, path); 190 strcat(str, "/"); 191 if ((ret_dir = readdir(dp)) != NULL) { 192 if (is_hidden(ret_dir->d_name)) //排除隐藏文件 193 continue; 194 strcat(str, ret_dir->d_name); //完整路径 195 myls_l(str); //调用函数 196 } else { // 目录读取完毕 197 break; 198 } 199 } 200 closedir(dp); 201 } 202 203 // 判断是文件还是目录 是目录返回1 不是返回0 204 static int is_dir(char *path) 205 { 206 struct stat buf; 207 lstat(path, &buf); 208 if (!S_ISDIR(buf.st_mode)) { 209 return 0; 210 } else 211 return 1; 212 } 213 214 // 相当于 ls -a +目录的路径 (当前目录下所以文件包含隐藏文件) 215 static int myls_a(char *path) 216 { 217 DIR *dp = NULL; 218 struct dirent *ptr = NULL; 219 220 dp = opendir(path); 221 if (dp == NULL) { 222 perror("OPENDIR()"); 223 return -1; 224 } 225 while (1) { 226 ptr = readdir(dp); //返回值为结构体类型指针 227 if (ptr == NULL) { 228 if (errno) { 229 perror("READDIR()"); 230 closedir(dp); 231 return -1; 232 } 233 break; 234 } 235 printf("%s\n", ptr->d_name); 236 } 237 238 closedir(dp); 239 return 0; 240 } 241 242 // 相当于 ls -i +目录 显示当前目录下所有文件的inode号 (不包含隐藏) 243 static void myls_i(char *path) 244 { 245 DIR *dp = NULL; 246 struct dirent *entry = NULL; 247 dp = opendir(path); 248 while (1) { 249 if ((entry = readdir(dp)) == NULL) 250 break; 251 if (is_hidden(entry->d_name)) { //隐藏文件 252 continue; 253 } 254 printf("%zu %s\n", entry->d_ino, entry->d_name); 255 } 256 } 257 258 // 相当于 ls -i +文件 259 static void myls_i_notdir(char *path) 260 { 261 struct stat buf; 262 stat(path, &buf); 263 printf("%zu %s\n", buf.st_ino, path); 264 } 265 266 // 相当于 ls -h +目录 本目录下所有文件(不包含隐藏) 267 static int myls_h(char *path) 268 { 269 DIR *dp = NULL; 270 struct dirent *ptr = NULL; 271 272 dp = opendir(path); 273 if (dp == NULL) { 274 perror("OPENDIR()"); 275 return -1; 276 } 277 while (1) { 278 ptr = readdir(dp); //返回值为结构体类型指针 279 if (ptr == NULL) { 280 if (errno) { 281 perror("READDIR()"); 282 closedir(dp); 283 return -1; 284 } 285 break; 286 } 287 if (is_hidden(ptr->d_name)) { 288 continue; 289 } 290 printf("%s\n", ptr->d_name); 291 } 292 293 closedir(dp); 294 return 0; 295 }