Skip to content

Instantly share code, notes, and snippets.

@l1fe
Created May 12, 2013 17:34
Show Gist options
  • Select an option

  • Save l1fe/5564332 to your computer and use it in GitHub Desktop.

Select an option

Save l1fe/5564332 to your computer and use it in GitHub Desktop.
a simple recursive LS for *nix (memory leaks due shitty getpwuid && getgrgid)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <assert.h>
#include <errno.h>
#include <time.h>
#include <string.h>
#include <pwd.h>
#include <grp.h>
#include <stdbool.h>
typedef struct file_info file_info;
typedef struct queue queue;
void queue_init(const queue* q);
void print_dir(const char* dirname);
const char* joinpath(const char* dirname, const char* filename);
void print_file(const char* dirname, struct dirent* entry, bool rec);
char* get_username(uid_t uid);
char* get_grpname(gid_t gid);
void set_perms(struct stat* const buf, char perms[10]);
void print_file_info(const file_info* curfile_info);
typedef struct file_info {
char* usr_name;
char* grp_name;
char perms[10];
int links_n;
struct tm* time;
size_t size;
} file_info;
const char* joinpath(const char* dirname, const char* filename) {
assert(dirname != NULL && NULL != filename);
char* result = malloc(strlen(dirname) + strlen(filename) + 2);
if (NULL == result)
return NULL;
strcpy(result, dirname);
strcat(result, "/");
strcat(result, filename);
return result;
}
char* get_username(uid_t uid) {
struct passwd* pwd = getpwuid(uid);
if (NULL == pwd)
return NULL;
char* retVal = pwd->pw_name;
return retVal;
}
char* get_groupname(gid_t gid) {
struct group* grp = getgrgid(gid);
if (NULL == grp)
return NULL;
char* retVal = grp->gr_name;
return retVal;
}
void set_perms(struct stat* const buf, char perms[10]) {
const char mode[3] = {'r', 'w', 'x'};
const int flags[9] = {S_IRUSR, S_IWUSR, S_IXUSR, S_IRGRP, S_IWGRP, S_IXGRP, S_IROTH, S_IWOTH, S_IXOTH};
memset(perms, '-', 10);
if ((buf->st_mode & S_IFMT) == S_IFDIR)
perms[0] = 'd';
int i;
for (i = 0; i < 9; ++i) {
if ((buf->st_mode & flags[i]))
perms[i + 1] = mode [ i % 3 ];
}
}
void print_file_info(const file_info* curfile_info) {
int i;
for (i = 0; i < 10; ++i)
printf("%c", curfile_info->perms[i]);
printf(" %d", curfile_info->links_n);
printf(" %s %s", curfile_info->usr_name, curfile_info->grp_name);
printf(" %6d", curfile_info->size);
printf(" %02d-%02d-%02d %02d:%02d ", curfile_info->time->tm_year + 1900,
curfile_info->time->tm_mon,
curfile_info->time->tm_mday,
curfile_info->time->tm_hour,
curfile_info->time->tm_min);
}
void print_file(const char* dirname, struct dirent* entry, bool rec) {
const char* filepath = joinpath(dirname, entry->d_name);
if (NULL == filepath) {
fprintf(stderr, "not enough memory");
return;
}
file_info curfile_info;
struct stat buf;
if (-1 == lstat(filepath, &buf)) {
fprintf(stderr, "can't open file");
free((void*)filepath);
return;
}
if (!rec) {
set_perms(&buf, curfile_info.perms);
curfile_info.links_n = buf.st_nlink;
if (NULL == (curfile_info.usr_name = get_username(buf.st_uid)))
fprintf(stderr, "error: can't obtain username of file");
if (NULL == (curfile_info.grp_name = get_groupname(buf.st_gid)))
fprintf(stderr, "error: can't obtain groupname of file");
curfile_info.size = buf.st_size;
curfile_info.time = localtime((time_t*)&buf.st_mtime);
print_file_info(&curfile_info);
printf("%40s", entry->d_name);
if (S_ISDIR(buf.st_mode)) printf(" [directory]\n");
else if (S_ISREG(buf.st_mode)) printf(" [regular file]\n");
else if (S_ISCHR(buf.st_mode)) printf(" [char. device]\n");
else if (S_ISBLK(buf.st_mode)) printf(" [block device]\n");
else if (S_ISFIFO(buf.st_mode)) printf(" [FIFO]\n");
else if (S_ISLNK(buf.st_mode)) printf(" [symb. link]\n");
else if (S_ISSOCK(buf.st_mode)) printf(" [socket]\n");
} else {
if (S_ISDIR(buf.st_mode)) {
const char* nextdir = joinpath(dirname, entry->d_name);
print_dir(nextdir);
free((void*)nextdir);
}
}
free((void*)filepath);
}
void print_dir(const char* dirname) {
DIR* curDir = opendir(dirname);
if (NULL == curDir) {
fprintf(stderr, "can't open directory %s\n", dirname);
return;
}
printf("%s:\n", dirname);
struct dirent* curFile;
int files_count = 0;
while ((NULL != (curFile = readdir(curDir))))
if (0 != strcmp("..", curFile->d_name) && 0 != strcmp(".", curFile->d_name))
++files_count;
printf("total files: %d\n", files_count);
rewinddir(curDir);
while ((NULL != (curFile = readdir(curDir)))) {
if (0 != strcmp("..", curFile->d_name) && 0 != strcmp(".", curFile->d_name))
print_file(dirname, curFile, 0);
}
rewinddir(curDir);
while ((NULL != (curFile = readdir(curDir)))) {
if (0 != strcmp("..", curFile->d_name) && 0 != strcmp(".", curFile->d_name))
print_file(dirname, curFile, 1);
}
closedir(curDir);
}
int main(int argc, char* argv[]) {
char* dirName;
if (argc < 2)
dirName = ".";
else
dirName = argv[1];
print_dir(dirName);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment