commit 190a0fe188f5f1cf7b0cc26088c7948f03af5468
Author: rani <clagv.randomgames@gmail.com>
Date: Tue Dec 30 17:41:45 2025 +0000
diff --git a/include/dir.h b/include/dir.h
index 05a360d..d806578 100644
--- a/include/dir.h
+++ b/include/dir.h
@@ -17 +19 @@
#ifndef DIR_H
#define DIR_H
+#include <time.h>
#include <stddef.h>
+#include <stdint.h>
#include "cvector.h"
enum de_type {
@@ -169 +1817 @@ enum de_type {
};
typedef struct {
+ char * name;
enum de_type type;
+
size_t size;
- char * name;
+ uint16_t mode;
+ time_t mtime;
+ char * uname;
+ char * gname;
+
+ char * linkname;
+ enum de_type linktype;
} dirent_t;
typedef struct {
diff --git a/src/dir.c b/src/dir.c
index 11c12e0..211d783 100644
--- a/src/dir.c
+++ b/src/dir.c
@@ -215 +223 @@
#include <dirent.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include <fcntl.h>
+#include <pwd.h>
+#include <grp.h>
#include "dir.h"
#include "cvector.h"
+#define LINKNAMESZ PATH_MAX
static void dir_entry(int dirfd, const char * name, dirent_t * dirent);
static void free_dirent(void * p) {
- free(((dirent_t*)p)->name);
+ dirent_t * de = (dirent_t*)p;
+ free(de->name);
+ free(de->uname);
+ free(de->gname);
+ free(de->linkname);
}
int dir_list(const char * path, dir_t * dir) {
@@ -4213 +5015 @@ int dir_list(const char * path, dir_t * dir) {
void dir_entry(int dirfd, const char * name, dirent_t * dirent) {
dirent->type = DE_UNKNOWN;
- dirent->size = 0;
- dirent->name = NULL;
-
dirent->name = strdup(name);
+ dirent->uname = NULL;
+ dirent->gname = NULL;
+ dirent->linkname = NULL;
struct stat statbuf;
if (fstatat(dirfd, name, &statbuf, AT_SYMLINK_NOFOLLOW) < 0) {
+ // in the case where stat fails, the file is marked unknown
+ // every field other than type and name are left uninitialized
return;
}
@@ -647 +7444 @@ void dir_entry(int dirfd, const char * name, dirent_t * dirent) {
default: dirent->type = DE_UNKNOWN; break;
}
+ if (S_ISLNK(statbuf.st_mode)) {
+ size_t linknamesz;
+ if (statbuf.st_size == 0) linknamesz = LINKNAMESZ;
+ else linknamesz = statbuf.st_size;
+ char * linkname = malloc(linknamesz + 1);
+ ssize_t len = readlinkat(dirfd, name, linkname, linknamesz);
+ if (len < 0) {
+ free(linkname);
+ dirent->linkname = NULL;
+ } else {
+ linkname[len] = 0;
+ dirent->linkname = linkname;
+ }
+
+ struct stat lstatbuf;
+ if (fstatat(dirfd, name, &lstatbuf, 0) < 0) {
+ dirent->linktype = DE_UNKNOWN;
+ } else switch (lstatbuf.st_mode & S_IFMT) {
+ case S_IFSOCK: dirent->linktype = DE_SOCKET; break;
+ case S_IFLNK: dirent->linktype = DE_LINK; break;
+ case S_IFREG: dirent->linktype = DE_FILE; break;
+ case S_IFBLK: dirent->linktype = DE_BLOCK; break;
+ case S_IFDIR: dirent->linktype = DE_DIR; break;
+ case S_IFCHR: dirent->linktype = DE_CHAR; break;
+ case S_IFIFO: dirent->linktype = DE_FIFO; break;
+ default: dirent->linktype = DE_UNKNOWN; break;
+ }
+ }
+
dirent->size = statbuf.st_size;
+ dirent->mode = statbuf.st_mode & 07777;
+ dirent->mtime = statbuf.st_mtime;
+
+ struct passwd * pw = getpwuid(statbuf.st_uid);
+ if (pw) dirent->uname = strdup(pw->pw_name);
+
+ struct group * gr = getgrgid(statbuf.st_gid);
+ if (gr) dirent->gname = strdup(gr->gr_name);
}
void dir_free(dir_t * dir) {
diff --git a/src/main.c b/src/main.c
index 90ac8bd..7f748ab 100644
--- a/src/main.c
+++ b/src/main.c
@@ -87 +811 @@ int main(int argc, char ** argv) {
dir_list(argv[1], &dir);
for (size_t i = 0; i < dir.len; i++) {
- printf("%lu %s\n", dir.entries[i].size, dir.entries[i].name);
+ dirent_t * de = &dir.entries[i];
+ printf("%s %s %lu %ld %s", de->uname, de->gname, de->size, de->mtime, de->name);
+ if (de->linkname) {
+ printf(" -> %s\n", de->linkname);
+ } else putchar('\n');
}
dir_free(&dir);