diff options
author | zlg <zlg@zlg.space> | 2022-01-18 21:58:37 -0800 |
---|---|---|
committer | zlg <zlg@zlg.space> | 2022-01-18 21:58:37 -0800 |
commit | b1805ae57e314be9d56c099a282206053043fa4b (patch) | |
tree | eb97213f00e0dda50867009a5c76055481f1ef77 | |
parent | Solve Exercise 8-4: fseek() implementation (diff) | |
download | knr-b1805ae57e314be9d56c099a282206053043fa4b.tar.gz knr-b1805ae57e314be9d56c099a282206053043fa4b.tar.bz2 knr-b1805ae57e314be9d56c099a282206053043fa4b.tar.xz knr-b1805ae57e314be9d56c099a282206053043fa4b.zip |
Solve Exercise 8-05: fsize extended
This exercise uses the standard library instead of the homegrown
dirent.h outlined in the book. This is due to misbehavior in outputting
the file or directory names. This pointed to a data mismatch between the
data model supplied by the book and the data model actually used by my
operating system (GNU/Linux).
Diffstat (limited to '')
-rw-r--r-- | ch8/8-05_fsize-extended.c | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/ch8/8-05_fsize-extended.c b/ch8/8-05_fsize-extended.c new file mode 100644 index 0000000..c296104 --- /dev/null +++ b/ch8/8-05_fsize-extended.c @@ -0,0 +1,77 @@ +#include <errno.h> +#include <string.h> +#include <fcntl.h> +#include <stdlib.h> +#include <unistd.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <dirent.h> + +/* The C Programming Language: 2nd Edition + * + * Exercise 8-5: Modify the fsize program to print the other information + * contained in the inode entry. + * + * Notes: The supplied header file examples don't really work well on a + * GNU/Linux system in 2022. :) This makes 8-5 the only exercise in the book + * that's broken enough to nearly require the standard library to complete. + * Despite lacking the homegrown headers, this exercise is still a good example + * of callbacks. + * + * Not all of the information within the stat struct is displayed by this + * program; this is mostly due to the information not being terribly useful + * on all systems. Modification time and permission information is relevant + * to all platforms. + */ + +void fsize(char *); +void dirwalk(char *, void (*fcn)(char *)); + +int main(int argc, char **argv) { + if (argc == 1) { + fsize("."); + } else { + while (--argc > 0) { + fsize(*++argv); + } + } + return 0; +} + +void fsize(char *name) { + struct stat stbuf; + if (stat(name, &stbuf) == -1) { + fprintf(stderr, "fsize: can't access %s\n", name); + return; + } + if ((stbuf.st_mode & S_IFMT) == S_IFDIR) { + dirwalk(name, fsize); + } + /* + * Size, Mode, UID, GID, ModifiedTime, FileName + */ + printf("%8ld %6o %d %d %ld %s\n", stbuf.st_size, stbuf.st_mode, stbuf.st_uid, stbuf.st_gid, stbuf.st_mtime, name); +} + +void dirwalk(char *dir, void (*fcn)(char *)) { + char name[PATH_MAX]; + 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; + } + 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); +} |