I've created a rough program that prints out a similar prompt to that of ls -al using C. While it works nearly perfectly besides not being able to dynamically print out the directory that wasnt able to be opened as no arguments are given its just run in the currently directory so i figured .
would suffice but if theres a better way to dynamically do such let me know. I was wondering how can you print out the symbolic links to a file if there are any like is displayed below.
CODE
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <grp.h>
#include <time.h>
#include <pwd.h>
#include <errno.h>
#include <string.h>
int main(void)
{
DIR *mydir;
DIR *thedir;
struct dirent *myfile;
struct stat myStat;
struct passwd *pwd;
int size = 0;
struct tm lt;
char buf[1024];
char length[100];
long width;
struct group *gf;
int len = 0;
mydir = opendir("./");
thedir = opendir("./");
if(mydir!= NULL){
while((myfile = readdir(thedir)) != NULL){
lstat(myfile->d_name, &myStat);
size += myStat.st_blocks;
width = (long)myStat.st_size;
sprintf(length, "%ld", width);
if(len < strlen(length)){
len = strlen(length);
}
}
printf("total %d\n", size/2);
closedir(thedir);
while((myfile = readdir(mydir)) != NULL)
{
lstat(myfile->d_name, &myStat);
if((lstat(myfile->d_name, &myStat) ) == 0){
pwd = getpwuid(myStat.st_uid);
}
gf = getgrgid(myStat.st_gid);
time_t t = myStat.st_mtime;
localtime_r(&t, <);
char timebuf[80];
char timebuf2[80];
strftime(timebuf, sizeof(timebuf), "%F", <);
strftime(timebuf2, sizeof(timebuf2), "%R", <);
printf( (S_ISDIR(myStat.st_mode)) ? "d" : "-");
printf( (myStat.st_mode & S_IRUSR) ? "r" : "-");
printf( (myStat.st_mode & S_IWUSR) ? "w" : "-");
printf( (myStat.st_mode & S_IXUSR) ? "x" : "-");
printf( (myStat.st_mode & S_IRGRP) ? "r" : "-");
printf( (myStat.st_mode & S_IWGRP) ? "w" : "-");
printf( (myStat.st_mode & S_IXGRP) ? "x" : "-");
printf( (myStat.st_mode & S_IROTH) ? "r" : "-");
printf( (myStat.st_mode & S_IWOTH) ? "w" : "-");
printf( (myStat.st_mode & S_IXOTH) ? "x" : "-");
printf(" ");
printf("%ld ", myStat.st_nlink);
if(pwd != 0){
printf("%s %s %*ld %s %s %s\n", pwd->pw_name, gf->gr_name, len, (long)myStat.st_size, timebuf, timebuf2, myfile->d_name);
}else {
printf("%d %s %*ld %s %s %s\n", myStat.st_uid, gf->gr_name, len, (long)myStat.st_size, timebuf, timebuf2, myfile->d_name);
printf("\n");
}
}
closedir(mydir);
}else{
printf("ls: cannot open directory .: Permission denied");
}
}
Current Output
total 8
-rw-rw-r-- 1 travis travis 0 2019-04-04 17:11 file2.txt
-rw-rw-r-- 1 travis travis 0 2019-04-04 17:11 file1.txt
drwxrwxr-x 4 travis travis 4096 2019-04-04 17:11 ..
drwxrwxr-x 2 travis travis 4096 2019-04-04 17:11 .
-rwxrwxrwx 1 travis travis 9 2019-04-04 17:11 link1
-rwxrwxrwx 1 travis travis 9 2019-04-04 17:11 link2
Desired output
total 8
-rw-rw-r-- 1 travis travis 0 2019-04-04 17:11 file2.txt
-rw-rw-r-- 1 travis travis 0 2019-04-04 17:11 file1.txt
drwxrwxr-x 4 travis travis 4096 2019-04-04 17:11 ..
drwxrwxr-x 2 travis travis 4096 2019-04-04 17:11 .
lrwxrwxrwx 1 travis travis 9 2019-04-04 17:11 link1 -> file1.txt
lrwxrwxrwx 1 travis travis 9 2019-04-04 17:11 link2 -> file2.txt
In your program you look at st_nlink
but it concerns the hard link (ln ...
), not the symbolic links (ln -s ...
)
Look at readlink for the path you want to write
SYNOPSIS
#include <unistd.h> ssize_t readlink(const char *pathname, char *buf, size_t bufsiz);
DESCRIPTION
readlink() places the contents of the symbolic link pathname in the buffer buf, which has size bufsiz. readlink() does not append a null byte to buf. It will (silently) truncate the contents (to a length of bufsiz characters), in case the buffer is too small to hold all of the contents.
For instance replace
if(pwd != 0){ printf("%s %s %*ld %s %s %s\n", pwd->pw_name, gf->gr_name, len, (long)myStat.st_size, timebuf, timebuf2, myfile->d_name); }else { printf("%d %s %*ld %s %s %s\n", myStat.st_uid, gf->gr_name, len, (long)myStat.st_size, timebuf, timebuf2, myfile->d_name); printf("\n"); }
by
if(pwd != 0){
printf("%s %s %*ld %s %s %s", pwd->pw_name, gf->gr_name, len, (long)myStat.st_size, timebuf, timebuf2, myfile->d_name);
}else {
printf("%d %s %*ld %s %s %s", myStat.st_uid, gf->gr_name, len, (long)myStat.st_size, timebuf, timebuf2, myfile->d_name);
}
char linkname[PATH_MAX];
ssize_t r = readlink(myfile->d_name, linkname, PATH_MAX);
if (r != -1) {
linkname[r] = '\0';
printf(" -> %s\n", linkname);
}
else
putchar('\n');