#include #include #include #include #include #include #include bool all { false }; bool list { false }; const char* mode_string(mode_t mode) { static char buffer[11]; buffer[0] = (mode & 0770000) == S_IFLNK ? 'l' : (mode & 0770000) == S_IFDIR ? 'd' : (mode & 0770000) == S_IFBLK ? 'b' : (mode & 0770000) == S_IFCHR ? 'c' : '-'; buffer[1] = mode & S_IRUSR ? 'r' : '-'; buffer[2] = mode & S_IWUSR ? 'w' : '-'; buffer[3] = mode & S_IXUSR ? 'x' : '-'; buffer[4] = mode & S_IRGRP ? 'r' : '-'; buffer[5] = mode & S_IWGRP ? 'w' : '-'; buffer[6] = mode & S_IXGRP ? 'x' : '-'; buffer[7] = mode & S_IROTH ? 'r' : '-'; buffer[8] = mode & S_IWOTH ? 'w' : '-'; buffer[9] = mode & S_IXOTH ? 'x' : '-'; buffer[10] = '\0'; return buffer; } const char* color_string(mode_t mode) { if ((mode & 0770000) == S_IFLNK) return "\e[36m"; if ((mode & 0770000) == S_IFDIR) return "\e[34m"; if ((mode & 0770000) == S_IFCHR) return "\e[33m"; if ((mode & 0770000) == S_IFBLK) return "\e[33m"; if ((mode & (S_IXUSR | S_IXGRP | S_IXOTH))) return "\e[32m"; return ""; } void list_directory(const char* path) { DIR* dirp = opendir(path); if (dirp == nullptr) return perror("opendir"); errno = 0; bool first = true; while (auto* dirent = readdir(dirp)) { if (!all && dirent->d_name[0] == '.') continue; if (!first) printf(list ? "\n" : " "); struct stat st; if (fstatat(dirfd(dirp), dirent->d_name, &st, AT_SYMLINK_NOFOLLOW) == -1) { perror("stat"); if (list) printf("?????????? ???? ???? ?????? %s", dirent->d_name); else printf("%s", dirent->d_name); } if (list) { printf("%s %4d %4d %6d %s%s\e[m", mode_string(st.st_mode), st.st_uid, st.st_gid, st.st_size, color_string(st.st_mode), dirent->d_name); if (S_ISLNK(st.st_mode)) { char link_buffer[128]; ssize_t ret = readlinkat(dirfd(dirp), dirent->d_name, link_buffer, sizeof(link_buffer)); if (ret >= 0) printf(" -> %.*s", ret, link_buffer); else perror("readlink"); } } else printf("%s%s\e[m", color_string(st.st_mode), dirent->d_name); first = false; } if (errno != 0) perror("readdir"); printf("\n"); closedir(dirp); } void print_usage() { printf("Usage: ls [OPTION]... [FILE]...\n"); printf(" -a, --all show all files\n"); printf(" -l, --list print files on separate lines\n"); } int main(int argc, char** argv) { int arg = 1; while (arg < argc && argv[arg][0] == '-') { if (strcmp(argv[arg], "--all") == 0) all = true; else if (strcmp(argv[arg], "--list") == 0) list = true; else if (strcmp(argv[arg], "--help") == 0) { print_usage(); return 0; } else { for (int i = 1; argv[arg][i]; i++) { char c = argv[arg][i]; if (c == 'a') all = true; else if (c == 'l') list = true; else { print_usage(); return 1; } } } arg++; } if (arg == argc) { list_directory("."); } else if (arg + 1 == argc) { list_directory(argv[arg]); } else { for (int i = arg; i < argc; i++) { if (i > arg) printf("\n"); printf("%s:\n", argv[i]); list_directory(argv[i]); } } return 0; }