#include #include #include #include #include #include #include #include #include #include #include #include unsigned int a_flag; unsigned int l_flag; int get_stat(const char *path, struct stat *stat_path) { if (stat(path, stat_path)) { fprintf(stderr, "rm: unable to stat %s: %s\n", path, strerror(errno)); return 1; } return 0; } char *make_path(const char *src, const char *dst) { size_t len = strlen(src) + strlen(dst) + 2; char *full_path = malloc(len + 1); if (full_path == NULL) { fprintf(stderr, "cp: malloc() returned NULL\n"); return NULL; } snprintf(full_path, len, "%s/%s", src, dst); return full_path; } void PrintPerm(struct stat sb) { printf("%c", (S_ISDIR(sb.st_mode)) ? 'd' : '-'); printf("%c%c%c", (sb.st_mode & S_IRUSR) ? 'r' : '-', (sb.st_mode & S_IWUSR) ? 'w' : '-', (sb.st_mode & S_IXUSR) ? 'x' : '-'); printf("%c%c%c", (sb.st_mode & S_IRGRP) ? 'r' : '-', (sb.st_mode & S_IWGRP) ? 'w' : '-', (sb.st_mode & S_IXGRP) ? 'x' : '-'); printf("%c%c%c", (sb.st_mode & S_IROTH) ? 'r' : '-', (sb.st_mode & S_IWOTH) ? 'w' : '-', (sb.st_mode & S_IXOTH) ? 'x' : '-'); } char *fileflag(const char *path) { struct stat sb; if (get_stat(path, &sb)) return " "; if (S_ISDIR(sb.st_mode)) return "/"; else if ((sb.st_mode & S_IXUSR) || (sb.st_mode & S_IXGRP) || (sb.st_mode & S_IXOTH)) return "*"; else return " "; } void PrintInfo(struct stat sb, const char *filename) { /* Permissions */ PrintPerm(sb); /* Date */ struct tm *tm = localtime(&sb.st_mtime); char date[14]; if (strftime(date, sizeof(date), "%b %d %H:%M", tm) == 0) { fprintf(stderr, "ls: strftime()\n"); return; } /* Group and user name */ struct passwd *pw = getpwuid(sb.st_uid); struct group *gr = getgrgid(sb.st_gid); printf(" %s %s %jd %s %s%s\n", (pw != 0) ? pw->pw_name : "nobody", (gr != 0) ? gr->gr_name : "nobody", (uintmax_t)sb.st_size, date, filename, fileflag(filename)); } int list(const char *path, int label) { struct stat sb; if (lstat(path, &sb)) { fprintf(stderr, "ls: unable to lstat %s: %s\n", path, strerror(errno)); return 1; } /* If its file */ if (!S_ISDIR(sb.st_mode)) { if (l_flag) PrintInfo(sb, path); else puts(path); return 0; } /* Make label */ if (label) printf("\n%s: \n", path); /* Open and print dir */ DIR *dp = opendir(path); if (dp == NULL) { fprintf(stderr, "ls: %s: %s\n", path, strerror(errno)); return 1; } struct dirent *ep; while ((ep = readdir(dp)) != NULL) { if (ep->d_name[0] == '.' && !a_flag) continue; char *full_path = make_path(path, ep->d_name); if (full_path == NULL) return 1; if (l_flag) { if (get_stat(full_path, &sb)) return 1; PrintInfo(sb, full_path); } else printf("%s%s\n", ep->d_name, fileflag(full_path)); free(full_path); } closedir(dp); printf("\n"); return 0; } int main(const int argc, const char **argv) { int i; for (i = 1; i < argc; i++) { if (argv[i][0] != '-') break; else if (!strcmp(argv[i], "-a")) a_flag = 1; else if (!strcmp(argv[i], "-l")) l_flag = 1; else if (!strcmp(argv[i], "--help")) { printf("ls [-a show hidden files] [-l use a long listing format] [Path]\n"); return 0; } } if (i == argc) return list(".", 0); if (i == argc - 1) return list(argv[i], 0); else for (; i < argc; i++) if (list(argv[i], 1)) return 1; return 0; }