⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fchdir.c

📁 gnu tar 源码包。 tar 软件是 Unix 系统下的一个打包软件
💻 C
字号:
/* fchdir replacement.   Copyright (C) 2006, 2007 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 <http://www.gnu.org/licenses/>.  */#include <config.h>/* Specification.  */#include <unistd.h>#include <errno.h>#include <fcntl.h>#include <stdarg.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <dirent.h>#include "canonicalize.h"#include "dirfd.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 voidensure_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;	}    }}/* Override open() and close(), to keep track of the open file descriptors.  */intrpl_close (int fd)#undef close{  int retval = close (fd);  if (retval >= 0 && fd >= 0 && fd < dirs_allocated)    {      if (dirs[fd].name != NULL)	free (dirs[fd].name);      dirs[fd].name = NULL;      dirs[fd].saved_errno = ENOTDIR;    }  return retval;}intrpl_open (const char *filename, int flags, ...)#undef open{  mode_t mode;  int fd;  struct stat statbuf;  mode = 0;  if (flags & O_CREAT)    {      va_list arg;      va_start (arg, flags);      /* If mode_t is narrower than int, use the promoted type (int),	 not mode_t.  Use sizeof to guess whether mode_t is narrower;	 we don't know of any practical counterexamples.  */      mode = (sizeof (mode_t) < sizeof (int)	      ? va_arg (arg, int)	      : va_arg (arg, mode_t));      va_end (arg);    }#if defined GNULIB_OPEN && ((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__)  if (strcmp (filename, "/dev/null") == 0)    filename = "NUL";#endif  fd = open (filename, flags, mode);  if (fd >= 0)    {      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;	}    }  return fd;}/* Override opendir() and closedir(), to keep track of the open file   descriptors.  Needed because there is a function dirfd().  */intrpl_closedir (DIR *dp)#undef closedir{  int fd = dirfd (dp);  int retval = closedir (dp);  if (retval >= 0 && fd >= 0 && fd < dirs_allocated)    {      if (dirs[fd].name != NULL)	free (dirs[fd].name);      dirs[fd].name = NULL;      dirs[fd].saved_errno = ENOTDIR;    }  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)	{	  ensure_dirs_slot (fd);	  if (fd < dirs_allocated)	    {	      dirs[fd].name = canonicalize_file_name (filename);	      if (dirs[fd].name == NULL)	        dirs[fd].saved_errno = errno;	    }	}    }  return dp;}/* Override dup() and dup2(), to keep track of open file descriptors.  */intrpl_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;}intrpl_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().  */intfchdir (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;    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -