Last active
January 15, 2017 11:30
-
-
Save zhanghai/5c71c41914ef153d621b to your computer and use it in GitHub Desktop.
A simple 'ls' program that mimics the behavior of `ls -ali`
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* A simple 'ls' program that mimics the behavior of `ls -ali` | |
* Copyright (C) 2014 Zhang Hai. | |
* | |
* This program is free software: you can redistribute it and/or | |
* modify it under the terms of the GNU General Public License as | |
* published by the Free Software Foundation, either version 3 of the | |
* License, or (at your option) any later version. | |
* | |
* This program is distributed in the hope that it will be useful, but | |
* WITHOUT ANY WARRANTY; without even the implied warranty of | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
* General Public License for more details. | |
* | |
* You should have received a copy of the GNU General Public License | |
* along with this program. If not, see | |
* <http://www.gnu.org/licenses/>. | |
*/ | |
#include <dirent.h> | |
#include <errno.h> | |
#include <pwd.h> | |
#include <grp.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <sys/stat.h> | |
#include <sys/types.h> | |
#include <time.h> | |
#include <unistd.h> | |
int main(int argc, char *argv[]) { | |
time_t recent; | |
char *dirname; | |
DIR *dir; | |
struct dirent *dirent; | |
char *absname; | |
struct stat fstat; | |
char mode[11]; | |
struct passwd *pwd; | |
struct group *grp; | |
char *timefmt, mtime[256]; | |
errno = 0; | |
time(&recent); | |
/* From GNU coreutils ls implementation: | |
Consider a time to be recent if it is within the past six | |
months. A Gregorian year has 365.2425 * 24 * 60 * 60 == | |
31556952 seconds on the average. Write this value as an | |
integer constant to avoid floating point hassles. */ | |
recent -= 31556952 / 2; | |
if (argc == 1) { | |
dirname = "."; | |
} else if (argc == 2) { | |
dirname = argv[1]; | |
} else { | |
printf("Usage: ls [directory]\n"); | |
return -1; | |
} | |
dir = opendir(dirname); | |
if (errno) { | |
perror("opendir"); | |
return errno; | |
} | |
while ((dirent = readdir(dir)) != NULL) { | |
absname = malloc(strlen(dirname) + strlen(dirent->d_name) | |
+ 2); | |
strcpy(absname, dirname); | |
strcat(absname, "/"); | |
strcat(absname, dirent->d_name); | |
stat(absname, &fstat); | |
if (errno) { | |
perror("stat"); | |
free(absname); | |
continue; | |
} | |
free(absname); | |
if (S_ISREG(fstat.st_mode)) { mode[0] = '-'; } | |
else if (S_ISBLK(fstat.st_mode)) { mode[0] = 'b'; } | |
else if (S_ISCHR(fstat.st_mode)) { mode[0] = 'c'; } | |
else if (S_ISDIR(fstat.st_mode)) { mode[0] = 'd'; } | |
else if (S_ISLNK(fstat.st_mode)) { mode[0] = 'l'; } | |
else if (S_ISFIFO(fstat.st_mode)) { mode[0] = 'p'; } | |
else if (S_ISSOCK(fstat.st_mode)) { mode[0] = 's'; } | |
mode[1] = fstat.st_mode & S_IRUSR ? 'r' : '-'; | |
mode[2] = fstat.st_mode & S_IWUSR ? 'w' : '-'; | |
mode[3] = fstat.st_mode & S_IXUSR ? 'x' : '-'; | |
mode[4] = fstat.st_mode & S_IRGRP ? 'r' : '-'; | |
mode[5] = fstat.st_mode & S_IWGRP ? 'w' : '-'; | |
mode[6] = fstat.st_mode & S_IXGRP ? 'x' : '-'; | |
mode[7] = fstat.st_mode & S_IROTH ? 'r' : '-'; | |
mode[8] = fstat.st_mode & S_IWOTH ? 'w' : '-'; | |
mode[9] = fstat.st_mode & S_IXOTH ? 'x' : '-'; | |
mode[10] = 0; | |
pwd = getpwuid(fstat.st_uid); | |
if (errno) { | |
perror("getpwuid"); | |
continue; | |
} | |
grp = getgrgid(fstat.st_gid); | |
if (errno) { | |
perror("getgrgid"); | |
continue; | |
} | |
timefmt = fstat.st_mtim.tv_sec > recent ? "%b %d %H:%M" | |
: "%b %d %Y"; | |
strftime(mtime, sizeof(mtime), timefmt, | |
localtime(&fstat.st_mtim.tv_sec)); | |
printf("%lu %s %lu %s %s %ld %s %s\n", | |
fstat.st_ino, mode, fstat.st_nlink, pwd->pw_name, | |
grp->gr_name, fstat.st_size, mtime, dirent->d_name); | |
} | |
if (errno) { | |
perror("readdir"); | |
} | |
closedir(dir); | |
if (errno) { | |
perror("closedir"); | |
} | |
return errno; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment