Skip to content

Commit

Permalink
Exerc 8_5.
Browse files Browse the repository at this point in the history
  • Loading branch information
rsm-lisper committed Aug 28, 2024
1 parent 2e432c4 commit 7127159
Show file tree
Hide file tree
Showing 19 changed files with 267 additions and 0 deletions.
3 changes: 3 additions & 0 deletions chapter_8.unix_interface/8_5.finfo/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
BINARY=finfo

include ../../Exercise.mk
92 changes: 92 additions & 0 deletions chapter_8.unix_interface/8_5.finfo/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# define _DEFAULT_SOURCE

# include <stdio.h>
# include <string.h>
# include <sys/types.h> /* typedefs */
# include <sys/stat.h> /* structure returned by stat */
# include <dirent.h>
# include <time.h>

/*
you can't read a directory like a file in modern system. so no manual "dirent.h"
*/

# define MAX_PATH 1024

/* dirwalk: apply fcn to all files in dir */
void dirwalk (char *dir, void (*fcn)(char *))
{
char name[MAX_PATH];
struct dirent *dp;
DIR *dfd;

if ((dfd = opendir(dir)) == NULL) {
fprintf(stderr, "dirwalk: can't open %s\n", dir);
return;
}
while ((dp = readdir(dfd)) != NULL) {
if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)
continue; /* skip self and parent */
if (strlen(dir)+strlen(dp->d_name)+2 > sizeof(name))
fprintf(stderr, "dirwalk: name %s %s too long\n", dir, dp->d_name);
else {
sprintf(name, "%s/%s", dir, dp->d_name);
(*fcn)(name);
}
}
closedir(dfd);
}

/* finfo: print the name of file "name" */
void finfo (char *name)
{
struct stat stbuf;
char *ftype, fbits[4] = "---", fmode[10] = "---------", mtime[64];

if (stat(name, &stbuf) == -1) {
fprintf(stderr, "finfo: can't access %s\n", name);
return;
}
if ((stbuf.st_mode & S_IFMT) == S_IFDIR)
dirwalk(name, finfo);

if (S_ISREG (stbuf.st_mode)) ftype = "FILE";
else if (S_ISDIR (stbuf.st_mode)) ftype = " DIR";
else if (S_ISCHR (stbuf.st_mode)) ftype = "CDEV";
else if (S_ISBLK (stbuf.st_mode)) ftype = "BDEV";
else if (S_ISFIFO(stbuf.st_mode)) ftype = "PIPE";
else if (S_ISLNK (stbuf.st_mode)) ftype = "LINK";
else if (S_ISSOCK(stbuf.st_mode)) ftype = "SOCK";
else ftype = "(\?\?)";

if (stbuf.st_mode & S_ISUID) fbits[0] = 'u';
if (stbuf.st_mode & S_ISGID) fbits[1] = 'g';
if (stbuf.st_mode & S_ISVTX) fbits[2] = 's';

if (stbuf.st_mode & S_IRUSR) fmode[0] = 'r';
if (stbuf.st_mode & S_IWUSR) fmode[1] = 'w';
if (stbuf.st_mode & S_IXUSR) fmode[2] = 'x';
if (stbuf.st_mode & S_IRGRP) fmode[3] = 'r';
if (stbuf.st_mode & S_IWGRP) fmode[4] = 'w';
if (stbuf.st_mode & S_IXGRP) fmode[5] = 'x';
if (stbuf.st_mode & S_IROTH) fmode[6] = 'r';
if (stbuf.st_mode & S_IWOTH) fmode[7] = 'w';
if (stbuf.st_mode & S_IXOTH) fmode[8] = 'x';

strftime(mtime, sizeof(mtime), "%Y/%m/%d %H:%M:%S", localtime(&stbuf.st_mtim.tv_sec));

printf("%4s %4d:%4d %3s %9s %s %8ld %2lu %s\n",
ftype, stbuf.st_uid, stbuf.st_gid, fbits, fmode, mtime,
stbuf.st_size, stbuf.st_nlink, name);
}

/* print file name */
int main (int argc, char **argv)
{
if (argc == 1) /* default: current directory */
finfo(".");
else
while (--argc > 0)
finfo(*++argv);
return 0;
}
1 change: 1 addition & 0 deletions chapter_8.unix_interface/8_5.finfo/tests/0_no_file.targs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
no_file.txt
1 change: 1 addition & 0 deletions chapter_8.unix_interface/8_5.finfo/tests/0_no_file.terr
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
finfo: can't access no_file.txt
Empty file.
Empty file.
1 change: 1 addition & 0 deletions chapter_8.unix_interface/8_5.finfo/tests/1_file.targs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
tests/testdir/Makefile
Empty file.
Empty file.
1 change: 1 addition & 0 deletions chapter_8.unix_interface/8_5.finfo/tests/1_file.tout
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
FILE 1000:1000 --- rw-r--r-- 2024/08/28 15:39:07 40 1 tests/testdir/Makefile
1 change: 1 addition & 0 deletions chapter_8.unix_interface/8_5.finfo/tests/2_directory.targs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
tests/testdir/
Empty file.
Empty file.
7 changes: 7 additions & 0 deletions chapter_8.unix_interface/8_5.finfo/tests/2_directory.tout
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
FILE 1000:1000 --- rw-r--r-- 2024/08/28 15:39:07 1506 1 tests/testdir//dirent.c
FILE 1000:1000 --- rw-r--r-- 2024/08/28 15:48:28 2741 1 tests/testdir//main.c
FILE 1000:1000 --- rw-r--r-- 2024/08/28 15:39:07 40 1 tests/testdir//Makefile
FILE 1000:1000 --- rw-r--r-- 2024/08/28 15:48:28 2741 1 tests/testdir//mainlink.c
FILE 1000:1000 --- rw-r--r-- 2024/08/28 15:45:37 0 1 tests/testdir//maindir/another_file
DIR 1000:1000 --- rwxr-xr-x 2024/08/28 15:45:37 24 1 tests/testdir//maindir
DIR 1000:1000 --- rwxr-xr-x 2024/08/28 15:40:17 78 1 tests/testdir/
3 changes: 3 additions & 0 deletions chapter_8.unix_interface/8_5.finfo/tests/testdir/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
BINARY=finfo

include ../../Exercise.mk
64 changes: 64 additions & 0 deletions chapter_8.unix_interface/8_5.finfo/tests/testdir/dirent.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# define _XOPEN_SOURCE

# include <error.h>
# include <errno.h>

# include <stdlib.h>
# include <unistd.h>
# include <string.h>
# include <fcntl.h> /* flags for read and write */
# include <sys/types.h> /* typedefs */
# include <sys/stat.h> /* structure returned by stat */
# include <sys/dir.h> /* local directory structure */
# include "dirent.h"


# ifndef DIRSIZ
# define DIRSIZ 14
# endif

/* opendir: open a directory for readdir calls */
KNR_DIR *knr_opendir (char *dirname)
{
int fd;
struct stat stbuf;
KNR_DIR *dp;
if ((fd = open(dirname, O_RDONLY, 0)) == -1
|| fstat(fd, &stbuf) == -1
|| (stbuf.st_mode & S_IFMT) != S_IFDIR
|| (dp = (KNR_DIR *) malloc(sizeof(KNR_DIR))) == NULL)
return NULL;
dp->fd = fd;
return dp;
}

/* closedir: close directory opened by opendir */
void knr_closedir (KNR_DIR *dp)
{
if (dp) {
close(dp->fd);
free(dp);
}
}

/* readdir: read directory entries in sequence */
KNR_Dirent *knr_readdir (KNR_DIR *dp)
{
struct direct dirbuf; /* local directory structure */
static KNR_Dirent d; /* return: portable structure */

ssize_t r;

while ((r = read(dp->fd, (char *) &dirbuf, sizeof(dirbuf))) == sizeof(dirbuf)) {
if (dirbuf.d_ino == 0) /* slot not in use */
continue;
d.ino = dirbuf.d_ino;
strncpy(d.name, dirbuf.d_name, DIRSIZ);
d.name[DIRSIZ] = '\0'; /* ensure termination */
return &d;
}
if (r == -1)
error(-1, errno, "reading dir \"%s\"", dp->d.name);
return NULL;
}

92 changes: 92 additions & 0 deletions chapter_8.unix_interface/8_5.finfo/tests/testdir/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# define _DEFAULT_SOURCE

# include <stdio.h>
# include <string.h>
# include <sys/types.h> /* typedefs */
# include <sys/stat.h> /* structure returned by stat */
# include <dirent.h>
# include <time.h>

/*
you can't read a directory like a file in modern system. so no manual "dirent.h"
*/

# define MAX_PATH 1024

/* dirwalk: apply fcn to all files in dir */
void dirwalk (char *dir, void (*fcn)(char *))
{
char name[MAX_PATH];
struct dirent *dp;
DIR *dfd;

if ((dfd = opendir(dir)) == NULL) {
fprintf(stderr, "dirwalk: can't open %s\n", dir);
return;
}
while ((dp = readdir(dfd)) != NULL) {
if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)
continue; /* skip self and parent */
if (strlen(dir)+strlen(dp->d_name)+2 > sizeof(name))
fprintf(stderr, "dirwalk: name %s %s too long\n", dir, dp->d_name);
else {
sprintf(name, "%s/%s", dir, dp->d_name);
(*fcn)(name);
}
}
closedir(dfd);
}

/* finfo: print the name of file "name" */
void finfo (char *name)
{
struct stat stbuf;
char *ftype, fbits[4] = "---", fmode[10] = "---------", mtime[64];

if (stat(name, &stbuf) == -1) {
fprintf(stderr, "finfo: can't access %s\n", name);
return;
}
if ((stbuf.st_mode & S_IFMT) == S_IFDIR)
dirwalk(name, finfo);

if (S_ISREG (stbuf.st_mode)) ftype = "FILE";
else if (S_ISDIR (stbuf.st_mode)) ftype = " DIR";
else if (S_ISCHR (stbuf.st_mode)) ftype = "CDEV";
else if (S_ISBLK (stbuf.st_mode)) ftype = "BDEV";
else if (S_ISFIFO(stbuf.st_mode)) ftype = "PIPE";
else if (S_ISLNK (stbuf.st_mode)) ftype = "LINK";
else if (S_ISSOCK(stbuf.st_mode)) ftype = "SOCK";
else ftype = "(\?\?)";

if (stbuf.st_mode & S_ISUID) fbits[0] = 'u';
if (stbuf.st_mode & S_ISGID) fbits[1] = 'g';
if (stbuf.st_mode & S_ISVTX) fbits[2] = 's';

if (stbuf.st_mode & S_IRUSR) fmode[0] = 'r';
if (stbuf.st_mode & S_IWUSR) fmode[1] = 'w';
if (stbuf.st_mode & S_IXUSR) fmode[2] = 'x';
if (stbuf.st_mode & S_IRGRP) fmode[3] = 'r';
if (stbuf.st_mode & S_IWGRP) fmode[4] = 'w';
if (stbuf.st_mode & S_IXGRP) fmode[5] = 'x';
if (stbuf.st_mode & S_IROTH) fmode[6] = 'r';
if (stbuf.st_mode & S_IWOTH) fmode[7] = 'w';
if (stbuf.st_mode & S_IXOTH) fmode[8] = 'x';

strftime(mtime, sizeof(mtime), "%Y/%m/%d %H:%M:%S", localtime(&stbuf.st_mtim.tv_sec));

printf("%4s %4d:%4d %3s %9s %s %8ld %2lu %s\n",
ftype, stbuf.st_uid, stbuf.st_gid, fbits, fmode, mtime,
stbuf.st_size, stbuf.st_nlink, name);
}

/* print file name */
int main (int argc, char **argv)
{
if (argc == 1) /* default: current directory */
finfo(".");
else
while (--argc > 0)
finfo(*++argv);
return 0;
}
Empty file.

0 comments on commit 7127159

Please sign in to comment.