/* * check_open_files -- verify open files match recorded open files */ static void check_open_files() { int dirfd; DIR *dirp = NULL; struct dirent *dp; if ((dirfd = open("/proc/self/fd", O_RDONLY)) < 0 || (dirp = fdopendir(dirfd)) == NULL) FATAL("!/proc/self/fd"); while ((dp = readdir(dirp)) != NULL) { int fdnum; char fdfile[PATH_MAX]; ssize_t cc; if (*dp->d_name == '.') continue; if ((cc = readlinkat(dirfd, dp->d_name, fdfile, PATH_MAX)) < 0) FATAL("!readlinkat: /proc/self/fd/%s", dp->d_name); fdfile[cc] = '\0'; fdnum = atoi(dp->d_name); if (dirfd == fdnum) continue; open_file_remove(Fd_lut, fdnum, fdfile); } closedir(dirp); open_file_walk(Fd_lut); if (Fd_errcount) FATAL("open file list changed between START() and DONE()"); open_file_free(Fd_lut); }
static void file_close(struct fd_info *fdi) { struct file_info *file; struct fd_info *fdp; struct fd_info **prev; /* Close file */ CHECK(close(fdi->fd) != -1); /* Remove struct fd_info */ open_file_remove(fdi); file = fdi->file; prev = &file->fds; for (fdp = file->fds; fdp; fdp = fdp->next) { if (fdp == fdi) { *prev = fdi->next; free(fdi); if (file->deleted && !file->fds) { /* Closing deleted file */ struct write_info *w, *next; w = file->writes; while (w) { next = w->next; free(w); w = next; } free(file->name); free(file); } return; } prev = &fdp->next; } CHECK(0); /* Didn't find struct fd_info */ }
/* * open_file_remove -- find exact match & remove it from lut * * prints error if exact match not found, increments Fd_errcount */ static void open_file_remove(struct fd_lut *root, int fdnum, const char *fdfile) { if (root == NULL) { ERR("unexpected open file: fd %d => \"%s\"", fdnum, fdfile); Fd_errcount++; } else if (root->fdnum == fdnum) { if (root->fdfile == NULL) { ERR("open file dup: fd %d => \"%s\"", fdnum, fdfile); Fd_errcount++; } else if (strcmp(root->fdfile, fdfile) == 0) { /* found exact match */ FREE(root->fdfile); root->fdfile = NULL; } else { ERR("open file changed: fd %d was \"%s\" now \"%s\"", fdnum, root->fdfile, fdfile); Fd_errcount++; } } else if (root->fdnum < fdnum) open_file_remove(root->left, fdnum, fdfile); else open_file_remove(root->right, fdnum, fdfile); }