X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;ds=sidebyside;f=lib%2Ffchdir.c;fp=lib%2Ffchdir.c;h=0000000000000000000000000000000000000000;hb=22f1eb8bc17e5be72dd23d42d6aaa60196ac22e6;hp=969e984c9555b11a95f3e411f15a0ff6bdc581bd;hpb=00fa13ff3f2d5b6e2a94c5e948c38616ff7ad37a;p=tar diff --git a/lib/fchdir.c b/lib/fchdir.c deleted file mode 100644 index 969e984..0000000 --- a/lib/fchdir.c +++ /dev/null @@ -1,238 +0,0 @@ -/* fchdir replacement. - Copyright (C) 2006-2008 Free Software Foundation, Inc. - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - -#include - -/* Specification. */ -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "canonicalize.h" - -/* This replacement assumes that a directory is not renamed while opened - through a file descriptor. */ - -/* Array of file descriptors opened. If it points to a directory, it stores - info about this directory; otherwise it stores an errno value of ENOTDIR. */ -typedef struct -{ - char *name; /* Absolute name of the directory, or NULL. */ - int saved_errno; /* If name == NULL: The error code describing the failure - reason. */ -} dir_info_t; -static dir_info_t *dirs; -static size_t dirs_allocated; - -/* Try to ensure dirs has enough room for a slot at index fd. */ -static void -ensure_dirs_slot (size_t fd) -{ - if (fd >= dirs_allocated) - { - size_t new_allocated; - dir_info_t *new_dirs; - size_t i; - - new_allocated = 2 * dirs_allocated + 1; - if (new_allocated <= fd) - new_allocated = fd + 1; - new_dirs = - (dirs != NULL - ? (dir_info_t *) realloc (dirs, new_allocated * sizeof (dir_info_t)) - : (dir_info_t *) malloc (new_allocated * sizeof (dir_info_t))); - if (new_dirs != NULL) - { - for (i = dirs_allocated; i < new_allocated; i++) - { - new_dirs[i].name = NULL; - new_dirs[i].saved_errno = ENOTDIR; - } - dirs = new_dirs; - dirs_allocated = new_allocated; - } - } -} - -/* Hook into the gnulib replacements for open() and close() to keep track - of the open file descriptors. */ - -void -_gl_unregister_fd (int fd) -{ - if (fd >= 0 && fd < dirs_allocated) - { - if (dirs[fd].name != NULL) - free (dirs[fd].name); - dirs[fd].name = NULL; - dirs[fd].saved_errno = ENOTDIR; - } -} - -void -_gl_register_fd (int fd, const char *filename) -{ - struct stat statbuf; - - ensure_dirs_slot (fd); - if (fd < dirs_allocated - && fstat (fd, &statbuf) >= 0 && S_ISDIR (statbuf.st_mode)) - { - dirs[fd].name = canonicalize_file_name (filename); - if (dirs[fd].name == NULL) - dirs[fd].saved_errno = errno; - } -} - -/* Override opendir() and closedir(), to keep track of the open file - descriptors. Needed because there is a function dirfd(). */ - -int -rpl_closedir (DIR *dp) -#undef closedir -{ - int fd = dirfd (dp); - int retval = closedir (dp); - - if (retval >= 0) - _gl_unregister_fd (fd); - return retval; -} - -DIR * -rpl_opendir (const char *filename) -#undef opendir -{ - DIR *dp; - - dp = opendir (filename); - if (dp != NULL) - { - int fd = dirfd (dp); - if (fd >= 0) - _gl_register_fd (fd, filename); - } - return dp; -} - -/* Override dup() and dup2(), to keep track of open file descriptors. */ - -int -rpl_dup (int oldfd) -#undef dup -{ - int newfd = dup (oldfd); - - if (oldfd >= 0 && newfd >= 0) - { - ensure_dirs_slot (newfd); - if (newfd < dirs_allocated) - { - if (oldfd < dirs_allocated) - { - if (dirs[oldfd].name != NULL) - { - dirs[newfd].name = strdup (dirs[oldfd].name); - if (dirs[newfd].name == NULL) - dirs[newfd].saved_errno = ENOMEM; - } - else - { - dirs[newfd].name = NULL; - dirs[newfd].saved_errno = dirs[oldfd].saved_errno; - } - } - else - { - dirs[newfd].name = NULL; - dirs[newfd].saved_errno = ENOMEM; - } - } - } - return newfd; -} - -int -rpl_dup2 (int oldfd, int newfd) -#undef dup2 -{ - int retval = dup2 (oldfd, newfd); - - if (retval >= 0 && oldfd >= 0 && newfd >= 0 && newfd != oldfd) - { - ensure_dirs_slot (newfd); - if (newfd < dirs_allocated) - { - if (oldfd < dirs_allocated) - { - if (dirs[oldfd].name != NULL) - { - dirs[newfd].name = strdup (dirs[oldfd].name); - if (dirs[newfd].name == NULL) - dirs[newfd].saved_errno = ENOMEM; - } - else - { - dirs[newfd].name = NULL; - dirs[newfd].saved_errno = dirs[oldfd].saved_errno; - } - } - else - { - dirs[newfd].name = NULL; - dirs[newfd].saved_errno = ENOMEM; - } - } - } - return retval; -} - -/* Implement fchdir() in terms of chdir(). */ - -int -fchdir (int fd) -{ - if (fd >= 0) - { - if (fd < dirs_allocated) - { - if (dirs[fd].name != NULL) - return chdir (dirs[fd].name); - else - { - errno = dirs[fd].saved_errno; - return -1; - } - } - else - { - errno = ENOMEM; - return -1; - } - } - else - { - errno = EBADF; - return -1; - } -}