/* 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