#include <limits.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <dirent.h>
#include <ctype.h>
#include <string.h>
#include <stddef.h>
#include <sys/mkdev.h>
#include "libproc.h"
#include "Pcontrol.h"
#include "proc_fd.h"
void
Pinitfd(struct ps_prochandle *P)
{
list_create(&P->fd_head, sizeof (fd_info_t),
offsetof(fd_info_t, fd_list));
}
fd_info_t *
Pfd2info(struct ps_prochandle *P, int fd)
{
fd_info_t *fip, *next = NULL;
for (fip = list_head(&P->fd_head); fip != NULL;
fip = list_next(&P->fd_head, fip)) {
if (fip->fd_info == NULL)
continue;
if (fip->fd_info->pr_fd == fd) {
return (fip);
}
if (fip->fd_info->pr_fd < fd) {
break;
}
}
next = fip;
if ((fip = calloc(1, sizeof (*fip))) == NULL)
return (NULL);
list_insert_before(&P->fd_head, next, fip);
return (fip);
}
static int
fdwalk_cb(const prfdinfo_t *info, void *arg)
{
struct ps_prochandle *P = arg;
fd_info_t *fip;
fip = Pfd2info(P, info->pr_fd);
if (fip == NULL) {
errno = ENOMEM;
return (-1);
}
if (fip->fd_info == NULL)
fip->fd_info = proc_fdinfo_dup(info);
if (fip->fd_info == NULL) {
errno = ENOMEM;
return (-1);
}
return (0);
}
static void
load_fdinfo(struct ps_prochandle *P)
{
if (!list_is_empty(&P->fd_head))
return;
if (P->state == PS_DEAD || P->state == PS_IDLE)
return;
proc_fdwalk(P->pid, fdwalk_cb, P);
}
int
Pfdinfo_iter(struct ps_prochandle *P, proc_fdinfo_f *func, void *cd)
{
fd_info_t *fip;
int rv;
load_fdinfo(P);
for (fip = list_tail(&P->fd_head); fip != NULL;
fip = list_prev(&P->fd_head, fip)) {
if ((rv = func(cd, fip->fd_info)) != 0)
return (rv);
}
return (0);
}