mirror of the now-defunct rocklinux.org
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

223 lines
4.5 KiB

/*
TODO:
get rid of the compiler warnings:
fl_wrapper.c: In function '_Exit':
fl_wrapper.c:1100: warning: 'noreturn' function does return
fl_wrapper.c: In function '_exit':
fl_wrapper.c:1075: warning: 'noreturn' function does return
fl_wrapper.c: In function 'exit':
fl_wrapper.c:1050: warning: 'noreturn' function does return
maybe TODO:
wrape clone(); catch termination of child process created with clone()
*/
# if FD_TRACKER == 1
/*
Whenever a new file descriptor is opened, it will/should be added to the
fl_wrapper-internal register, together with its current file status.
Accordingly, when a file descriptor is closed, it will be removed from this
register, and handle_file_access_after() will be called with the stored
filename and status.
*/
struct pid_reg
{
pid_t id;
int executed;
struct fd_reg *fd_head;
struct pid_reg *next;
};
struct pid_reg *pid_head = 0;
struct fd_reg
{
int fd;
int closed;
struct status_t status;
char *filename;
struct fd_reg *next;
};
void add_pid(pid_t pid)
{
struct pid_reg *newpid = malloc(sizeof(struct pid_reg));
newpid->id = pid;
newpid->fd_head = 0;
newpid->executed = 0;
newpid->next = pid_head;
pid_head = newpid;
# if DEBUG == 1
if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: PID %d added.\n",
getpid(), pid);
# endif
}
void add_fd(struct pid_reg *pid, int fd, const char *filename, struct status_t *status)
{
struct fd_reg *newfd = malloc(sizeof(struct fd_reg));
newfd->fd = fd;
newfd->closed = 0;
newfd->status = *status;
newfd->filename = strdup(filename);
newfd->next = pid->fd_head;
pid->fd_head = newfd;
# if DEBUG == 1
if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: fd %d (%s) added.\n",
getpid(), fd, filename);
# endif
}
void remove_fd(struct fd_reg **fd);
void remove_pid(struct pid_reg **pid)
{
struct pid_reg *tmp = *pid;
struct fd_reg **fd_iter = &(*pid)->fd_head;
# if DEBUG == 1
if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: PID %d removed.\n",
getpid(), (*pid)->id);
# endif
while (*fd_iter) remove_fd(fd_iter);
*pid = (*pid)->next;
free(tmp);
}
void remove_fd(struct fd_reg **fd)
{
struct fd_reg *tmp = *fd;
# if DEBUG == 1
if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: fd %d (%s) removed.\n",
getpid(), (*fd)->fd, (*fd)->filename);
# endif
free((*fd)->filename);
*fd = (*fd)->next;
free(tmp);
}
void deregister_fd(int fd);
struct pid_reg **find_pid(pid_t pid)
{
struct pid_reg **pid_iter = &pid_head;
while (*pid_iter)
{
if ((*pid_iter)->executed)
{
struct fd_reg **fd_iter = &(*pid_iter)->fd_head;
while (*fd_iter)
{
if ((*fd_iter)->closed)
{
handle_file_access_after("exec*", (*fd_iter)->filename, &(*fd_iter)->status);
deregister_fd((*fd_iter)->fd);
}
else fd_iter = &(*fd_iter)->next;
}
}
if ((*pid_iter)->fd_head == 0) remove_pid(pid_iter);
else pid_iter = &(*pid_iter)->next;
}
pid_iter = &pid_head;
while (*pid_iter)
{
if ((*pid_iter)->id == pid) break;
pid_iter = &(*pid_iter)->next;
}
return pid_iter;
}
struct fd_reg **find_fd(struct pid_reg *pid, int fd)
{
struct fd_reg **fd_iter = &pid->fd_head;
while (*fd_iter)
{
if ((*fd_iter)->fd == fd) break;
fd_iter = &(*fd_iter)->next;
}
return fd_iter;
}
void register_fd(int fd, const char *filename, struct status_t *status)
{
struct pid_reg *pid_iter = *find_pid(getpid());
if (pid_iter == 0)
{
add_pid(getpid());
pid_iter = pid_head;
}
struct fd_reg *fd_iter = *find_fd(pid_iter, fd);
if (fd_iter == 0)
{
add_fd(pid_iter, fd, filename, status);
} else {
# if DEBUG == 1
if (debug) fprintf(stderr, "fl_wrapper.so debug [%d]: fd %d already registered (is %s, was %s).\n",
getpid(), fd, filename, fd_iter->filename);
# endif
free(fd_iter->filename);
fd_iter->filename = strdup(filename);
fd_iter->status = *status;
}
}
/* removes fd from register, returning its filename and status via filename
and status arguments.
*/
void deregister_fd(int fd)
{
struct pid_reg **pid_iter = find_pid(getpid());
if (*pid_iter)
{
struct fd_reg **fd_iter = find_fd(*pid_iter, fd);
if (*fd_iter)
{
remove_fd(fd_iter);
if ((*pid_iter)->fd_head == 0) remove_pid(pid_iter);
}
}
}
void copy_fds(pid_t parent, pid_t child)
{
struct pid_reg *pid_iter = *find_pid(parent);
if (pid_iter)
{
struct fd_reg *fd_iter = pid_iter->fd_head;
add_pid(child);
struct fd_reg **nextfd = &pid_head->fd_head;
while (fd_iter)
{
*nextfd = malloc(sizeof(struct fd_reg));
**nextfd = *fd_iter;
nextfd = &(*nextfd)->next;
fd_iter = fd_iter->next;
}
}
}
# endif