diff options
author | Aaron Ball <nullspoon@oper.io> | 2023-06-09 17:49:04 -0600 |
---|---|---|
committer | Aaron Ball <nullspoon@oper.io> | 2023-06-09 17:49:04 -0600 |
commit | 102f10b0c2bb16cdbc654506cd2fa4000c66de78 (patch) | |
tree | 8910cd95061820dda6dd790fb090ef2fbcf479a5 | |
parent | 2fcb8ea3ffa50b4866e1d97f3625129c8257605b (diff) | |
download | fd-enum-102f10b0c2bb16cdbc654506cd2fa4000c66de78.tar.gz fd-enum-102f10b0c2bb16cdbc654506cd2fa4000c66de78.tar.xz |
Reorganize code
This moves file descriptor stating code into the new fdstats files, and
the config code into the new config files. Relevant updates made to
reference structs by pointer.
-rw-r--r-- | Makefile | 5 | ||||
-rw-r--r-- | config.c | 61 | ||||
-rw-r--r-- | config.h | 24 | ||||
-rw-r--r-- | fdstats.c | 94 | ||||
-rw-r--r-- | fdstats.h | 22 | ||||
-rw-r--r-- | main.c | 206 |
6 files changed, 230 insertions, 182 deletions
@@ -1,4 +1,7 @@ CCOPTS := --std=gnu99 -Wall -Werror -O3 all: - cc $(CCOPTS) main.c -o fd-enum + if [ ! -d obj ]; then mkdir obj; fi + cc $(CCOPTS) -o obj/config.o -c config.c + cc $(CCOPTS) -o obj/fdstats.o -c fdstats.c + cc $(CCOPTS) -o fd-enum main.c obj/*.o diff --git a/config.c b/config.c new file mode 100644 index 0000000..1f209c6 --- /dev/null +++ b/config.c @@ -0,0 +1,61 @@ +#include "config.h" + +void get_help() { + puts("Usage: \n\ + -d, --dead Print list of dead file descriptors (deleted but still open)\n\ + -i, --inodes Print list of inode file descriptors\n\ + -l, --live Print list of live file descriptors (open and existing)\n\ + -p, --pipes Print list of pipe file descriptors\n\ + -s, --sockets Print list of socket file descriptors\n\ +\n\ + -n, --no-stats Hide file descriptor statistics\n\ + -sf, --sizefd Show total size of dead and live file descriptors\n\ + -sd, --sizedead Show total size of dead file descriptors\n\ + -sl, --sizelive Show total size of live file descriptors\n\ + --truncate-dead Truncate dead file descriptors\n\ + -h, --help Print this help text\n\ +"); +} + +int config_from_argv(struct config* c, int argc, char* argv[]) { + int i = 1; + while(i < argc) { + if(strcmp(argv[i], "-d") == 0 || strcmp(argv[i], "--dead") == 0) { + c->dead = 1; + } else if(strcmp(argv[i], "--truncate-dead") == 0) { + c->truncate_dead = 1; + } else if(strcmp(argv[i], "-l") == 0 || strcmp(argv[i], "--live") == 0) { + c->live = 1; + } else if(strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "--sockets") == 0) { + c->sockets = 1; + } else if(strcmp(argv[i], "-i") == 0 || strcmp(argv[i], "--inodes") == 0) { + c->inodes = 1; + } else if(strcmp(argv[i], "-p") == 0 || strcmp(argv[i], "--pipes") == 0) { + c->pipes = 1; + } else if(strcmp(argv[i], "-n") == 0 || strcmp(argv[i], "--no-stats") == 0) { + c->showstats = 0; + } else if(strcmp(argv[i], "-sfd") == 0 || strcmp(argv[i], "--sizefd") == 0) { + c->showsizefd = 1; + } else if(strcmp(argv[i], "-sd") == 0 || strcmp(argv[i], "--sizedead") == 0) { + c->showsizedead = 1; + } else if(strcmp(argv[i], "-sl") == 0 || strcmp(argv[i], "--sizelive") == 0) { + c->showsizelive = 1; + } else if(strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) { + get_help(); + return 1; + } else if(argv[i][0] == '-') { + fprintf(stderr, "Unknown argument \"%s\"\n", argv[i]); + return 1; + } else { + c->pid = strtol(argv[i], NULL, 10); + } + + i++; + } + + if(c->pid == -1) { + fprintf(stderr, "Must specify valid pid\n"); + return 2; + } + return 0; +} diff --git a/config.h b/config.h new file mode 100644 index 0000000..98d0d86 --- /dev/null +++ b/config.h @@ -0,0 +1,24 @@ +#include <sys/types.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#ifndef _config_h +#define _config_h + +struct config { + pid_t pid; + char dead; + char live; + char sockets; + char inodes; + char pipes; + char showstats; + char showsizefd; + char showsizelive; + char showsizedead; + char truncate_dead; +}; + +int config_from_argv(struct config*, int, char**); +#endif diff --git a/fdstats.c b/fdstats.c new file mode 100644 index 0000000..d2652af --- /dev/null +++ b/fdstats.c @@ -0,0 +1,94 @@ +/** + * Fd-enum is a simple tool to list open file descriptors of a pid by type + * Copyright (C) 2023 Aaron Ball <nullspoon@oper.io> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#include "fdstats.h" + +long _fgetsize(char* path) { + FILE* fd = NULL; + long size = 0; + fd = fopen(path, "r"); + + fseek(fd, 0, SEEK_END); + size = ftell(fd); + + fclose(fd); + return size; +} + +int fdstats_read(struct fdstats* fds, char* fdpath, struct config* c) { + int retval = 0; + int len = 0; + char lnpath[512] = {'\0'}; + struct stat sb; + + retval = stat(fdpath, &sb); + len = readlink(fdpath, lnpath, 512); + + if(len <= 0) + return -1; + lnpath[len] = '\0'; + + // Sockets + if(S_ISSOCK(sb.st_mode)) { + fds->sockets++; + if(c->sockets) + printf("%s -> %s\n", fdpath, lnpath); + + // Pipes + } else if(S_ISFIFO(sb.st_mode)) { + fds->pipes++; + if(c->pipes) + printf("%s -> %s\n", fdpath, lnpath); + + // Char device links + } else if(S_ISCHR(sb.st_mode)) { + fds->live++; + if(c->live) + printf("%s -> %s\n", fdpath, lnpath); + + // File desccriptors + } else if(S_ISREG(sb.st_mode) || S_ISDIR(sb.st_mode)) { + // Exists + if(retval == 0 && access(lnpath, F_OK) == 0) { + fds->live++; + if(c->live) + printf("%s -> %s\n", fdpath, lnpath); + if(c->showsizefd || c->showsizelive) + fds->livesize += _fgetsize(fdpath); + + // Does not exist + } else { + fds->dead++; + if(c->dead) + printf("%s -> %s\n", fdpath, lnpath); + if(c->showsizefd || c->showsizedead) + fds->deadsize += _fgetsize(fdpath); + if(c->truncate_dead) + truncate(fdpath, 0); + } + + // Inodes + } else if(sb.st_mode == 384) { + fds->inodes++; + if(c->inodes) + printf("%s -> %s\n", fdpath, lnpath); + + } else { + fds->unknown++; + } + return 0; +} diff --git a/fdstats.h b/fdstats.h new file mode 100644 index 0000000..f01f2ca --- /dev/null +++ b/fdstats.h @@ -0,0 +1,22 @@ +#include <sys/stat.h> +#include <unistd.h> +#include <stdio.h> +#include "config.h" + +#ifndef _fdstats_h +#define _fdstats_h + +struct fdstats { + unsigned long livesize; + unsigned long deadsize; + unsigned long unknown; + unsigned long dead; + unsigned long live; + unsigned long sockets; + unsigned long inodes; + unsigned long pipes; +}; + +int fdstats_read(struct fdstats*, char*, struct config*); + +#endif @@ -22,209 +22,53 @@ #include <string.h> #include <sys/stat.h> -struct config { - pid_t pid; - char dead; - char live; - char sockets; - char inodes; - char pipes; - char showstats; - char showsizefd; - char showsizelive; - char showsizedead; - char truncate_dead; -}; - -int fexists(char* path) { - FILE *fd = fopen(path, "r"); - if(!fd) - return 0; - fclose(fd); - return 1; -} - -void get_help() { - puts("Usage: \n\ - -d, --dead Print list of dead file descriptors (deleted but still open)\n\ - -i, --inodes Print list of inode file descriptors\n\ - -l, --live Print list of live file descriptors (open and existing)\n\ - -p, --pipes Print list of pipe file descriptors\n\ - -s, --sockets Print list of socket file descriptors\n\ -\n\ - -n, --no-stats Hide file descriptor statistics\n\ - -sf, --sizefd Show total size of dead and live file descriptors\n\ - -sd, --sizedead Show total size of dead file descriptors\n\ - -sl, --sizelive Show total size of live file descriptors\n\ - --truncate-dead Truncate dead file descriptors\n\ - -h, --help Print this help text\n\ -"); -} - -long fgetsize(char* path) { - FILE* fd = NULL; - long size = 0; - fd = fopen(path, "r"); - - fseek(fd, 0, SEEK_END); - size = ftell(fd); - - fclose(fd); - return size; -} - -int parse_args(int argc, char* argv[], struct config* c) { - int i = 1; - // Initialize config struct to all 0 - memset(c, 0, sizeof(struct config)); - c->pid = -1; // Default to an impossible pid - c->showstats = 1; // Default to showing stats - - while(i < argc) { - if(strcmp(argv[i], "-d") == 0 || strcmp(argv[i], "--dead") == 0) { - c->dead = 1; - } else if(strcmp(argv[i], "--truncate-dead") == 0) { - c->truncate_dead = 1; - } else if(strcmp(argv[i], "-l") == 0 || strcmp(argv[i], "--live") == 0) { - c->live = 1; - } else if(strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "--sockets") == 0) { - c->sockets = 1; - } else if(strcmp(argv[i], "-i") == 0 || strcmp(argv[i], "--inodes") == 0) { - c->inodes = 1; - } else if(strcmp(argv[i], "-p") == 0 || strcmp(argv[i], "--pipes") == 0) { - c->pipes = 1; - } else if(strcmp(argv[i], "-n") == 0 || strcmp(argv[i], "--no-stats") == 0) { - c->showstats = 0; - } else if(strcmp(argv[i], "-sfd") == 0 || strcmp(argv[i], "--sizefd") == 0) { - c->showsizefd = 1; - } else if(strcmp(argv[i], "-sd") == 0 || strcmp(argv[i], "--sizedead") == 0) { - c->showsizedead = 1; - } else if(strcmp(argv[i], "-sl") == 0 || strcmp(argv[i], "--sizelive") == 0) { - c->showsizelive = 1; - } else if(strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) { - get_help(); - exit(1); - } else if(argv[i][0] == '-') { - fprintf(stderr, "Unknown argument \"%s\"\n", argv[i]); - exit(1); - } else { - c->pid = strtol(argv[i], NULL, 10); - } - - i++; - } - - if(c->pid == -1) { - fprintf(stderr, "Must specify valid pid\n"); - return 2; - } - return 0; -} +#include "fdstats.h" +#include "config.h" int main(int argc, char* argv[]) { - struct config c; - char pidpath_fd[32] = {'\0'}; char fdpath[289] = {'\0'}; - char lnpath[512] = {'\0'}; - int retval = 0; - int len = 0; - unsigned long livesize = 0; - unsigned long deadsize = 0; - unsigned long unknown = 0; - unsigned long dead = 0; - unsigned long live = 0; - unsigned long sockets = 0; - unsigned long inodes = 0; - unsigned long pipes = 0; - - struct stat sb; + DIR *dp = NULL; + struct dirent *de = NULL; + struct config c; + struct fdstats fds; - DIR *dp = NULL; - struct dirent *de = NULL; + //if(parse_args(argc, argv, &c) != 0) + memset(&c, 0, sizeof(struct config)); + c.pid = -1; // Default to an impossible pid + c.showstats = 1; // Default to showing stats - if(parse_args(argc, argv, &c) != 0) + if(config_from_argv(&c, argc, argv) != 0) return 1; // Construct the pid path sprintf(pidpath_fd, "/proc/%d/fd", c.pid); dp = opendir(pidpath_fd); - while((de = readdir(dp)) != NULL) { - sprintf(fdpath, "%s/%s%c", pidpath_fd, de->d_name, '\0'); - - retval = stat(fdpath, &sb); - len = readlink(fdpath, lnpath, 512); - - if(len <= 0) - continue; - lnpath[len] = '\0'; - // Sockets - if(S_ISSOCK(sb.st_mode)) { - sockets++; - if(c.sockets) - printf("%s -> %s\n", fdpath, lnpath); + // Initialize all fdstats to 0 + memset(&fds, 0, sizeof(struct fdstats)); - // Pipes - } else if(S_ISFIFO(sb.st_mode)) { - pipes++; - if(c.pipes) - printf("%s -> %s\n", fdpath, lnpath); - - // Char device links - } else if(S_ISCHR(sb.st_mode)) { - live++; - if(c.live) - printf("%s -> %s\n", fdpath, lnpath); - - // File desccriptors - } else if(S_ISREG(sb.st_mode) || S_ISDIR(sb.st_mode)) { - // Exists - if(retval == 0 && fexists(lnpath)) { - live++; - if(c.live) - printf("%s -> %s\n", fdpath, lnpath); - if(c.showsizefd || c.showsizelive) - livesize += fgetsize(fdpath); - - // Does not exist - } else { - dead++; - if(c.dead) - printf("%s -> %s\n", fdpath, lnpath); - if(c.showsizefd || c.showsizedead) - deadsize += fgetsize(fdpath); - if(c.truncate_dead) - truncate(fdpath, 0); - } - - // Inodes - } else if(sb.st_mode == 384) { - inodes++; - if(c.inodes) - printf("%s -> %s\n", fdpath, lnpath); - - } else { - unknown++; - } + while((de = readdir(dp)) != NULL) { + sprintf(fdpath, "%s/%s%c", pidpath_fd, de->d_name, '\0'); + fdstats_read(&fds, fdpath, &c); } closedir(dp); if(c.showstats) { - printf("dead: %ld\n", dead); - printf("live: %ld\n", live); - printf("sockets: %ld\n", sockets); - printf("anon_inodes: %ld\n", inodes); - printf("pipes: %ld\n", pipes); - printf("unknown: %ld\n", unknown); + printf("dead: %ld\n", fds.dead); + printf("live: %ld\n", fds.live); + printf("sockets: %ld\n", fds.sockets); + printf("anon_inodes: %ld\n", fds.inodes); + printf("pipes: %ld\n", fds.pipes); + printf("unknown: %ld\n", fds.unknown); } if(c.showsizelive) - printf("livesize: %ld KB\n", livesize / 1024); + printf("livesize: %ld KB\n", fds.livesize / 1024); if(c.showsizedead) - printf("deadsize: %ld KB\n", deadsize / 1024); + printf("deadsize: %ld KB\n", fds.deadsize / 1024); if(c.showsizefd) - printf("fdsize: %ld KB\n", (livesize + deadsize) / 1024); + printf("fdsize: %ld KB\n", (fds.livesize + fds.deadsize) / 1024); return 0; } |