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

📄 extract.c

📁 gnu tar 源码包。 tar 软件是 Unix 系统下的一个打包软件
💻 C
📖 第 1 页 / 共 3 页
字号:
	continue;      /* Some other error in the mkdir.  We return to the caller.  */      break;    }  return did_something;		/* tell them to retry if we made one */}static boolfile_newer_p (const char *file_name, struct tar_stat_info *tar_stat){  struct stat st;  if (stat (file_name, &st))    {      stat_warn (file_name);      /* Be on the safe side: if the file does exist assume it is newer */      return errno != ENOENT;    }  if (!S_ISDIR (st.st_mode)      && tar_timespec_cmp (tar_stat->mtime, get_stat_mtime (&st)) <= 0)    {      return true;    }  return false;}/* Attempt repairing what went wrong with the extraction.  Delete an   already existing file or create missing intermediate directories.   Return nonzero if we somewhat increased our chances at a successful   extraction.  errno is properly restored on zero return.  */static intmaybe_recoverable (char *file_name, int *interdir_made){  int e = errno;  if (*interdir_made)    return 0;  switch (errno)    {    case EEXIST:      /* Remove an old file, if the options allow this.  */      switch (old_files_option)	{	case KEEP_OLD_FILES:	  return 0;	case KEEP_NEWER_FILES:	  if (file_newer_p (file_name, &current_stat_info))	    {	      errno = e;	      return 0;	    }	  /* FALL THROUGH */	case DEFAULT_OLD_FILES:	case NO_OVERWRITE_DIR_OLD_FILES:	case OVERWRITE_OLD_FILES:	  {	    int r = remove_any_file (file_name, ORDINARY_REMOVE_OPTION);	    errno = EEXIST;	    return r;	  }	case UNLINK_FIRST_OLD_FILES:	  break;	}    case ENOENT:      /* Attempt creating missing intermediate directories.  */      if (! make_directories (file_name))	{	  errno = ENOENT;	  return 0;	}      *interdir_made = 1;      return 1;    default:      /* Just say we can't do anything about it...  */      return 0;    }}/* Fix the statuses of all directories whose statuses need fixing, and   which are not ancestors of FILE_NAME.  If AFTER_LINKS is   nonzero, do this for all such directories; otherwise, stop at the   first directory that is marked to be fixed up only after delayed   links are applied.  */static voidapply_nonancestor_delayed_set_stat (char const *file_name, bool after_links){  size_t file_name_len = strlen (file_name);  bool check_for_renamed_directories = 0;  while (delayed_set_stat_head)    {      struct delayed_set_stat *data = delayed_set_stat_head;      bool skip_this_one = 0;      struct stat st;      struct stat const *cur_info = 0;      check_for_renamed_directories |= data->after_links;      if (after_links < data->after_links	  || (data->file_name_len < file_name_len	      && file_name[data->file_name_len]	      && (ISSLASH (file_name[data->file_name_len])		  || ISSLASH (file_name[data->file_name_len - 1]))	      && memcmp (file_name, data->file_name, data->file_name_len) == 0))	break;      if (check_for_renamed_directories)	{	  cur_info = &st;	  if (stat (data->file_name, &st) != 0)	    {	      stat_error (data->file_name);	      skip_this_one = 1;	    }	  else if (! (st.st_dev == data->dev && st.st_ino == data->ino))	    {	      ERROR ((0, 0,		      _("%s: Directory renamed before its status could be extracted"),		      quotearg_colon (data->file_name)));	      skip_this_one = 1;	    }	}      if (! skip_this_one)	{	  struct tar_stat_info sb;	  sb.stat.st_mode = data->mode;	  sb.stat.st_uid = data->uid;	  sb.stat.st_gid = data->gid;	  sb.atime = data->atime;	  sb.mtime = data->mtime;	  set_stat (data->file_name, &sb, cur_info,		    data->invert_permissions, data->permstatus, DIRTYPE);	}      delayed_set_stat_head = data->next;      free (data);    }}/* Extractor functions for various member types */static intextract_dir (char *file_name, int typeflag){  int status;  mode_t mode;  int interdir_made = 0;  /* Save 'root device' to avoid purging mount points. */  if (one_file_system_option && root_device == 0)    {      struct stat st;      char *dir = xgetcwd ();      if (deref_stat (true, dir, &st))	stat_diag (dir);      else	root_device = st.st_dev;      free (dir);    }  if (incremental_option)    /* Read the entry and delete files that aren't listed in the archive.  */    purge_directory (file_name);  else if (typeflag == GNUTYPE_DUMPDIR)    skip_member ();  mode = current_stat_info.stat.st_mode | (we_are_root ? 0 : MODE_WXUSR);  if (0 < same_owner_option || current_stat_info.stat.st_mode & ~ MODE_RWX)    mode &= S_IRWXU;  while ((status = mkdir (file_name, mode)))    {      if (errno == EEXIST	  && (interdir_made	      || old_files_option == DEFAULT_OLD_FILES	      || old_files_option == OVERWRITE_OLD_FILES))	{	  struct stat st;	  if (stat (file_name, &st) == 0)	    {	      if (interdir_made)		{		  repair_delayed_set_stat (file_name, &st);		  return 0;		}	      if (S_ISDIR (st.st_mode))		{		  mode = st.st_mode;		  break;		}	    }	  errno = EEXIST;	}      if (maybe_recoverable (file_name, &interdir_made))	continue;      if (errno != EEXIST)	{	  mkdir_error (file_name);	  return 1;	}      break;    }  if (status == 0      || old_files_option == DEFAULT_OLD_FILES      || old_files_option == OVERWRITE_OLD_FILES)    {      if (status == 0)	delay_set_stat (file_name, &current_stat_info,			((mode ^ current_stat_info.stat.st_mode)			 & MODE_RWX & ~ current_umask),			ARCHIVED_PERMSTATUS);      else /* For an already existing directory, invert_perms must be 0 */	delay_set_stat (file_name, &current_stat_info,			0,			UNKNOWN_PERMSTATUS);    }  return status;}static intopen_output_file (char *file_name, int typeflag, mode_t mode){  int fd;  int openflag = (O_WRONLY | O_BINARY | O_CREAT		  | (old_files_option == OVERWRITE_OLD_FILES		     ? O_TRUNC		     : O_EXCL));#if O_CTG  /* Contiguous files (on the Masscomp) have to specify the size in     the open call that creates them.  */  if (typeflag == CONTTYPE)    fd = open (file_name, openflag | O_CTG, mode, current_stat_info.stat.st_size);  else    fd = open (file_name, openflag, mode);#else /* not O_CTG */  if (typeflag == CONTTYPE)    {      static int conttype_diagnosed;      if (!conttype_diagnosed)	{	  conttype_diagnosed = 1;	  WARN ((0, 0, _("Extracting contiguous files as regular files")));	}    }  fd = open (file_name, openflag, mode);#endif /* not O_CTG */  return fd;}static intextract_file (char *file_name, int typeflag){  int fd;  off_t size;  union block *data_block;  int status;  size_t count;  size_t written;  int interdir_made = 0;  mode_t mode = current_stat_info.stat.st_mode & MODE_RWX & ~ current_umask;  mode_t invert_permissions =    0 < same_owner_option ? mode & (S_IRWXG | S_IRWXO) : 0;  /* FIXME: deal with protection issues.  */  if (to_stdout_option)    fd = STDOUT_FILENO;  else if (to_command_option)    {      fd = sys_exec_command (file_name, 'f', &current_stat_info);      if (fd < 0)	{	  skip_member ();	  return 0;	}    }  else    {      do	fd = open_output_file (file_name, typeflag, mode ^ invert_permissions);      while (fd < 0 && maybe_recoverable (file_name, &interdir_made));      if (fd < 0)	{	  skip_member ();	  open_error (file_name);	  return 1;	}    }  mv_begin (&current_stat_info);  if (current_stat_info.is_sparse)    sparse_extract_file (fd, &current_stat_info, &size);  else    for (size = current_stat_info.stat.st_size; size > 0; )      {	mv_size_left (size);	/* Locate data, determine max length writeable, write it,	   block that we have used the data, then check if the write	   worked.  */	data_block = find_next_block ();	if (! data_block)	  {	    ERROR ((0, 0, _("Unexpected EOF in archive")));	    break;		/* FIXME: What happens, then?  */	  }	written = available_space_after (data_block);	if (written > size)	  written = size;	errno = 0;	count = full_write (fd, data_block->buffer, written);	size -= written;	set_next_block_after ((union block *)			      (data_block->buffer + written - 1));	if (count != written)	  {	    if (!to_command_option)	      write_error_details (file_name, count, written);	    /* FIXME: shouldn't we restore from backup? */	    break;	  }      }  skip_file (size);  mv_end ();  /* If writing to stdout, don't try to do anything to the filename;     it doesn't exist, or we don't want to touch it anyway.  */  if (to_stdout_option)    return 0;  status = close (fd);  if (status < 0)    close_error (file_name);  if (to_command_option)    sys_wait_command ();  else    set_stat (file_name, &current_stat_info, NULL, invert_permissions,	      (old_files_option == OVERWRITE_OLD_FILES ?	       UNKNOWN_PERMSTATUS : ARCHIVED_PERMSTATUS),	      typeflag);  return status;}/* Create a placeholder file with name FILE_NAME, which will be   replaced after other extraction is done by a symbolic link if   IS_SYMLINK is true, and by a hard link otherwise.  Set   *INTERDIR_MADE if an intermediate directory is made in the   process.  */static intcreate_placeholder_file (char *file_name, bool is_symlink, int *interdir_made){  int fd;  struct stat st;  while ((fd = open (file_name, O_WRONLY | O_CREAT | O_EXCL, 0)) < 0)    if (! maybe_recoverable (file_name, interdir_made))      break;  if (fd < 0)    open_error (file_name);  else if (fstat (fd, &st) != 0)    {      stat_error (file_name);      close (fd);    }  else if (close (fd) != 0)    close_error (file_name);  else    {      struct delayed_set_stat *h;      struct delayed_link *p =	xmalloc (offsetof (struct delayed_link, target)		 + strlen (current_stat_info.link_name)		 + 1);      p->next = delayed_link_head;      delayed_link_head = p;      p->dev = st.st_dev;      p->ino = st.st_ino;      p->mtime = get_stat_mtime (&st);      p->is_symlink = is_symlink;      if (is_symlink)	{	  p->uid = current_stat_info.stat.st_uid;	  p->gid = current_stat_info.stat.st_gid;	}      p->sources = xmalloc (offsetof (struct string_list, string)			    + strlen (file_name) + 1);      p->sources->next = 0;      strcpy (p->sources->string, file_name);      strcpy (p->target, current_stat_info.link_name);      h = delayed_set_stat_head;      if (h && ! h->after_links	  && strncmp (file_name, h->file_name, h->file_name_len) == 0	  && ISSLASH (file_name[h->file_name_len])	  && (last_component (file_name) == file_name + h->file_name_len + 1))	{	  do	    {	      h->after_links = 1;	      if (stat (h->file_name, &st) != 0)		stat_error (h->file_name);	      else		{		  h->dev = st.st_dev;		  h->ino = st.st_ino;		}	    }	  while ((h = h->next) && ! h->after_links);	}      return 0;    }  return -1;}static intextract_link (char *file_name, int typeflag){  int interdir_made = 0;  char const *link_name;  transform_member_name (&current_stat_info.link_name, xform_link);

⌨️ 快捷键说明

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