A hack to close the existing fd if the caller has already opened a file with the same name. Use with caution.
Compile and LD_PRELOAD this.
PS: http://troydhanson.github.com/uthash/ is awesome.
#include <stdio.h> #include <strings.h> #include <unistd.h> #include <dlfcn.h> #include "uthash.h" /*- * Copyright (c) 2013 Brad Forschinger * All rights reserved. */ /* last entry must be NULL */ static char *target_files[] = { "/var/krb5/rcache/HTTP_8080", NULL }; struct fd_info_s { int fd; char path[FILENAME_MAX]; UT_hash_handle hh; }; struct fd_info_s *fd_to_path = NULL, *path_to_fd = NULL; /* see if we've already got an fd for the path. if so, close it first. */ int open(const char *path, int oflag, mode_t mode) { static int (*real_open) (const char *, int, mode_t); struct fd_info_s *fd_info = NULL; char **target_file; if (real_open == NULL) { fprintf(stderr, "open: init\n"); real_open = dlsym(RTLD_NEXT, "open"); if (real_open == NULL) { return -1; } } /* look for a match */ target_file = &target_files[0]; while (*target_file != NULL) { /* match? */ if (strcmp(*target_file, path) == 0) { int fd; HASH_FIND_STR(path_to_fd, path, fd_info); /* have we opened this already? */ if (fd_info) { fd = fd_info->fd; fd_info = NULL; fprintf(stderr, "open: closing %d before opening %s\n", fd, *target_file); close(fd); /* our hooked close, we'll remove the hash entries there */ } fd = real_open(path, oflag, mode); if (fd != -1) { /* create fd => path */ fd_info = malloc(sizeof(struct fd_info_s)); fd_info->fd = fd; strcpy(fd_info->path, path); HASH_ADD_INT(fd_to_path, fd, fd_info); /* create path => fd */ fd_info = malloc(sizeof(struct fd_info_s)); fd_info->fd = fd; strcpy(fd_info->path, path); HASH_ADD_STR(path_to_fd, path, fd_info); } return fd; } /* next. */ *target_file++; } return real_open(path, oflag, mode); } /* stop tracking the fd */ int close(int filedes) { static int (*real_close) (int); struct fd_info_s *fd_info = NULL; char path[FILENAME_MAX]; if (real_close == NULL) { fprintf(stderr, "close: init\n"); real_close = dlsym(RTLD_NEXT, "close"); if (real_close == NULL) { return -1; } } HASH_FIND_INT(fd_to_path, &filedes, fd_info); if (fd_info) { /* del fd => path */ strcpy(path, fd_info->path); HASH_DEL(fd_to_path, fd_info); free(fd_info); /* del path => fd */ HASH_FIND_STR(path_to_fd, path, fd_info); HASH_DEL(path_to_fd, fd_info); free(fd_info); fprintf(stderr, "close: was tracking %d (%s)\n", filedes, path); } return real_close(filedes); }
No comments:
Post a Comment