Created
July 2, 2020 06:49
-
-
Save iggyvolz/c664e04f1849b7a020dd0226d09c781b to your computer and use it in GitHub Desktop.
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
#define _XOPEN_SOURCE 700 | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include <ftw.h> | |
#include <stdio.h> | |
#include <string.h> | |
#include <sys/sysmacros.h> | |
char typechar(int typeflag) | |
{ | |
switch(typeflag & S_IFMT) { | |
case S_IFLNK: | |
return 's'; | |
case S_IFREG: | |
return 'f'; | |
case S_IFDIR: | |
return 'd'; | |
case S_IFCHR: | |
return 'c'; | |
default: | |
return '?'; | |
} | |
} | |
int nlinks = 0; | |
ino_t* links = NULL; | |
char** files = NULL; | |
int print_entry(const char *filepath, const struct stat *info, | |
const int typeflag, struct FTW *pathinfo) | |
{ | |
const char *const filename = filepath + pathinfo->base; | |
char type = typechar(info->st_mode); | |
char* link = NULL; | |
// Check for duplicate hardlinks | |
if(type == 'f' && info->st_nlink > 1) { | |
// Search for links to see if we find a matching one | |
for(int i=0;i<nlinks;i++) { | |
if(info->st_ino == links[i]) { | |
// Found a matching hardlink | |
type = 'h'; | |
// Overwrite link with the filename that we are pointing to | |
link=files[i]; | |
break; | |
} | |
} | |
if(type != 'h') { | |
// This is the first instance of this inode, we must add it | |
links = realloc(links, sizeof(ino_t) * (nlinks+1)); | |
files = realloc(files, sizeof(char*) * (nlinks+1)); | |
links[nlinks] = info->st_ino; | |
files[nlinks] = malloc(strlen(filepath) + 1); | |
strcpy(files[nlinks], filepath); | |
nlinks++; | |
} | |
} | |
if(type == 's') { | |
// Resolve symlink | |
link = malloc(1024); | |
ssize_t length = readlink(filepath, link, 1023); | |
link[length] = 0; // Manually null-terminate string | |
} | |
printf("%s\t%06o\t%d\t%d\t%c\t", filepath, info->st_mode, info->st_uid, info->st_gid, type); | |
if(type == 'c') { | |
printf("%d,%d\n",major(info->st_rdev),minor(info->st_rdev)); | |
} else if(link == NULL) { | |
printf("\n"); | |
} else { | |
printf("%s\n", link); | |
} | |
if(type == 's') { | |
free(link); | |
} | |
return 0; | |
} | |
int main(int argc, char *argv[]) | |
{ | |
printf("#<file>\t<permissions>\t<owner>\t<group>\t<type>\t<extra>\n"); | |
// https://stackoverflow.com/a/29402705 saved my life from programming this manually | |
return nftw(".", print_entry, 15, FTW_PHYS); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment