Last active
November 11, 2022 16:54
-
-
Save ammarfaizi2/83af8801e9b88570d55eea8fd266f457 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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