summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile5
-rw-r--r--config.c61
-rw-r--r--config.h24
-rw-r--r--fdstats.c94
-rw-r--r--fdstats.h22
-rw-r--r--main.c206
6 files changed, 230 insertions, 182 deletions
diff --git a/Makefile b/Makefile
index d2485be..e97e1f8 100644
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/main.c b/main.c
index c384896..fd6254e 100644
--- a/main.c
+++ b/main.c
@@ -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;
}

Generated by cgit