Skip to content

Instantly share code, notes, and snippets.

@ammarfaizi2
Last active November 11, 2022 16:54
Show Gist options
  • Save ammarfaizi2/83af8801e9b88570d55eea8fd266f457 to your computer and use it in GitHub Desktop.
Save ammarfaizi2/83af8801e9b88570d55eea8fd266f457 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>
#include <string.h>
#include <stdbool.h>
#include <limits.h>
#include <stdlib.h>
#include <errno.h>
#define TASK_COMM_LEN 16
static bool is_numeric(const char *str)
{
while (1) {
char c = *str++;
if (!c)
return true;
if (!('0' <= c && c <= '9'))
return false;
}
}
static bool pid_has_open_file(const char *pid, const char *file)
{
bool has_the_file = false;
char link[PATH_MAX];
char buf[PATH_MAX];
ssize_t ret;
DIR *dir;
snprintf(buf, sizeof(buf), "/proc/%s/fd", pid);
dir = opendir(buf);
if (!dir)
return false;
while (1) {
struct dirent *d;
const char *name;
d = readdir(dir);
if (!d)
break;
name = d->d_name;
snprintf(buf, sizeof(buf), "/proc/%s/fd/%s", pid, name);
ret = readlink(buf, link, sizeof(link));
if (ret < 0)
continue;
link[ret] = '\0';
if (!strcmp(file, link)) {
has_the_file = true;
break;
}
}
closedir(dir);
return has_the_file;
}
static int get_task_comm(const char *pid, char *comm)
{
char buf[PATH_MAX];
int ret;
int fd;
comm[0] = '\0';
snprintf(buf, sizeof(buf), "/proc/%s/comm", pid);
fd = open(buf, O_RDONLY);
if (fd < 0)
return -1;
ret = read(fd, comm, TASK_COMM_LEN);
if (ret < 0) {
close(fd);
return -1;
}
close(fd);
comm[ret - 1] = '\0';
return 0;
}
static int find_pid_open_file(const char *file)
{
char comm[TASK_COMM_LEN + 1];
char real_path[PATH_MAX];
DIR *dir;
if (access(file, F_OK)) {
printf("File %s does not exist: %s\n", file, strerror(errno));
return 1;
}
if (!realpath(file, real_path)) {
printf("Cannot resolve the realpath %s: %s\n", file, strerror(errno));
return 1;
}
dir = opendir("/proc");
if (!dir) {
printf("Cannot open /proc directory: %s\n", strerror(errno));
return 1;
}
while (1) {
struct dirent *d;
const char *name;
d = readdir(dir);
if (!d)
break;
name = d->d_name;
if (!is_numeric(name))
continue;
if (!pid_has_open_file(name, file))
continue;
get_task_comm(name, comm);
printf("PID: %s; Comm: %s\n", name, comm);
}
closedir(dir);
return 0;
}
static int do_fuser(int argc, char * const argv[])
{
int i;
for (i = 0; i < argc; i++)
find_pid_open_file(argv[i]);
return 0;
}
int main(int argc, char *argv[])
{
if (argc < 2) {
printf("Usage: %s [file1] [file2] ... [fileN]\n", argv[0]);
return 1;
}
return do_fuser(argc - 1, argv + 1);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment