/********************************************************************************* * Copyright: (C) 2025 LingYun IoT System Studio * All rights reserved. * * Filename: myls.c * Description: This file is a simple ls command implement. * * Version: 1.0.0(10/15/2025) * Author: Guo Wenxue * ChangeLog: 1, Release initial version on "10/15/2025 11:08:39 AM" * ********************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include // 格式化输出文件权限 void print_permissions(mode_t mode) { printf("%c", S_ISDIR(mode) ? 'd' : S_ISLNK(mode) ? 'l' : S_ISCHR(mode) ? 'c' : S_ISBLK(mode) ? 'b' : S_ISFIFO(mode) ? 'p' : S_ISSOCK(mode) ? 's' : '-'); printf("%c", mode & S_IRUSR ? 'r' : '-'); printf("%c", mode & S_IWUSR ? 'w' : '-'); printf("%c", mode & S_IXUSR ? 'x' : '-'); printf("%c", mode & S_IRGRP ? 'r' : '-'); printf("%c", mode & S_IWGRP ? 'w' : '-'); printf("%c", mode & S_IXGRP ? 'x' : '-'); printf("%c", mode & S_IROTH ? 'r' : '-'); printf("%c", mode & S_IWOTH ? 'w' : '-'); printf("%c", mode & S_IXOTH ? 'x' : '-'); } // 格式化输出时间(省略年份) void print_time(time_t t) { char time_str[20]; strftime(time_str, sizeof(time_str), "%b %d %H:%M", localtime(&t)); printf("%s", time_str); } // 输出单个文件的详细信息 void print_file_info(const char *path) { struct stat sb; if (lstat(path, &sb) == -1) { perror("lstat"); return; } // 文件权限 print_permissions(sb.st_mode); printf(" "); // 硬链接数 printf("%ld ", (long)sb.st_nlink); // 所有者用户名 struct passwd *pw = getpwuid(sb.st_uid); printf("%s ", pw ? pw->pw_name : "?"); // 组名 struct group *gr = getgrgid(sb.st_gid); printf("%s ", gr ? gr->gr_name : "?"); // 文件大小 if (S_ISCHR(sb.st_mode) || S_ISBLK(sb.st_mode)) { printf("%4d,%4d ", major(sb.st_rdev), minor(sb.st_rdev)); // 设备文件 } else { printf("%8ld ", (long)sb.st_size); // 普通文件 } // 修改时间 print_time(sb.st_mtime); printf(" "); // 文件名 printf("%s", path); // 如果是符号链接,打印链接目标 if (S_ISLNK(sb.st_mode)) { char target[1024]; ssize_t len = readlink(path, target, sizeof(target) - 1); if (len != -1) { target[len] = '\0'; printf(" -> %s", target); } } printf("\n"); } // 处理目录或文件 void process_path(const char *path) { struct stat sb; if (stat(path, &sb) == -1) { perror("stat"); return; } if (S_ISDIR(sb.st_mode)) { // 如果是目录,遍历其内容 DIR *dir = opendir(path); if (!dir) { perror("opendir"); return; } struct dirent *entry; while ((entry = readdir(dir)) != NULL) { if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { continue; // 跳过 . 和 .. } char full_path[1024]; snprintf(full_path, sizeof(full_path), "%s/%s", path, entry->d_name); print_file_info(full_path); } closedir(dir); } else { // 如果是文件,直接输出信息 print_file_info(path); } } int main(int argc, char *argv[]) { if (argc < 2) { process_path("."); // 默认输出当前目录 } else { for (int i = 1; i < argc; i++) // 处理每个参数 { process_path(argv[i]); } } return 0; }