Thumbnail

rani/cscroll.git

Clone URL: https://git.buni.party/rani/cscroll.git

commit 190a0fe188f5f1cf7b0cc26088c7948f03af5468 Author: rani <clagv.randomgames@gmail.com> Date: Tue Dec 30 17:41:45 2025 +0000 Add all requisite fields to directory entries 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);