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

📄 incremen.c

📁 gnu tar 源码包。 tar 软件是 Unix 系统下的一个打包软件
💻 C
📖 第 1 页 / 共 3 页
字号:
  /* Prepare space for new dumpdir */  new_dump = xmalloc (len);  new_dump_ptr = new_dump;  /* Fill in the dumpdir template */  for (i = 0; i < dirsize; i++)    {      const char *loc = dumpdir_locate (dump, array[i]);      if (loc)	{	  if (directory->tagfile)	    *new_dump_ptr = strcmp (directory->tagfile, array[i]) == 0 ?		                ' ' : 'I';	  else	    *new_dump_ptr = ' ';	  new_dump_ptr++;	}      else if (directory->tagfile)	*new_dump_ptr++ = strcmp (directory->tagfile, array[i]) == 0 ?		               ' ' : 'I';      else	*new_dump_ptr++ = 'Y'; /* New entry */      /* Copy the file name */      for (p = array[i]; (*new_dump_ptr++ = *p++); )	;    }  *new_dump_ptr = 0;  directory->idump = directory->dump;  directory->dump = dumpdir_create0 (new_dump, NULL);  free (array);}/* Recursively scan the given directory. */static const char *scan_directory (char *dir, dev_t device){  char *dirp = savedir (dir);	/* for scanning directory */  char *name_buffer;		/* directory, `/', and directory member */  size_t name_buffer_size;	/* allocated size of name_buffer, minus 2 */  size_t name_length;		/* used length in name_buffer */  struct stat stat_data;  struct directory *directory;  if (! dirp)    savedir_error (dir);  name_buffer_size = strlen (dir) + NAME_FIELD_SIZE;  name_buffer = xmalloc (name_buffer_size + 2);  strcpy (name_buffer, dir);  if (! ISSLASH (dir[strlen (dir) - 1]))    strcat (name_buffer, "/");  name_length = strlen (name_buffer);  if (deref_stat (dereference_option, name_buffer, &stat_data))    {      stat_diag (name_buffer);      /* FIXME: used to be           children = CHANGED_CHILDREN;	 but changed to: */      free (name_buffer);      free (dirp);      return NULL;    }  directory = procdir (name_buffer, &stat_data, device, NO_CHILDREN, false,		       NULL);  if (dirp && directory->children != NO_CHILDREN)    {      char *entry;	/* directory entry being scanned */      size_t entrylen;	/* length of directory entry */      dumpdir_iter_t itr;      makedumpdir (directory, dirp);      for (entry = dumpdir_first (directory->dump, 1, &itr);	   entry;	   entry = dumpdir_next (itr))	{	  entrylen = strlen (entry);	  if (name_buffer_size <= entrylen - 1 + name_length)	    {	      do		name_buffer_size += NAME_FIELD_SIZE;	      while (name_buffer_size <= entrylen - 1 + name_length);	      name_buffer = xrealloc (name_buffer, name_buffer_size + 2);	    }	  strcpy (name_buffer + name_length, entry + 1);	  if (*entry == 'I') /* Ignored entry */	    *entry = 'N';	  else if (excluded_name (name_buffer))	    *entry = 'N';	  else	    {	      if (deref_stat (dereference_option, name_buffer, &stat_data))		{		  stat_diag (name_buffer);		  *entry = 'N';		  continue;		}	      if (S_ISDIR (stat_data.st_mode))		{		  *entry = 'D';		  procdir (name_buffer, &stat_data, device,			   directory->children,			   verbose_option, entry);		}	      else if (one_file_system_option && device != stat_data.st_dev)		*entry = 'N';	      else if (*entry == 'Y')		/* New entry, skip further checks */;	      /* FIXME: if (S_ISHIDDEN (stat_data.st_mode))?? */	      else if (OLDER_STAT_TIME (stat_data, m)		       && (!after_date_option			   || OLDER_STAT_TIME (stat_data, c)))		*entry = 'N';	      else		*entry = 'Y';	    }	}      free (itr);    }  free (name_buffer);  if (dirp)    free (dirp);  return directory->dump ? directory->dump->contents : NULL;}const char *get_directory_contents (char *dir, dev_t device){  return scan_directory (dir, device);}static voidobstack_code_rename (struct obstack *stk, char *from, char *to){  char *s;  s = from[0] == 0 ? from :                     safer_name_suffix (from, false, absolute_names_option);  obstack_1grow (stk, 'R');  obstack_grow (stk, s, strlen (s) + 1);  s = to[0] == 0 ? to:                   safer_name_suffix (to, false, absolute_names_option);  obstack_1grow (stk, 'T');  obstack_grow (stk, s, strlen (s) + 1);}static boolrename_handler (void *data, void *proc_data){  struct directory *dir = data;  struct obstack *stk = proc_data;  if (DIR_IS_RENAMED (dir))    {      struct directory *prev, *p;      /* Detect eventual cycles and clear DIRF_RENAMED flag, so these entries	 are ignored when hit by this function next time.	 If the chain forms a cycle, prev points to the entry DIR is renamed	 from. In this case it still retains DIRF_RENAMED flag, which will be	 cleared in the `else' branch below */      for (prev = dir; prev && prev->orig != dir; prev = prev->orig)	DIR_CLEAR_FLAG (prev, DIRF_RENAMED);      if (prev == NULL)	{	  for (p = dir; p && p->orig; p = p->orig)	    obstack_code_rename (stk, p->orig->name, p->name);	}      else	{	  char *temp_name;	  DIR_CLEAR_FLAG (prev, DIRF_RENAMED);	  /* Break the cycle by using a temporary name for one of its	     elements.	     First, create a temp name stub entry. */	  temp_name = dir_name (dir->name);	  obstack_1grow (stk, 'X');	  obstack_grow (stk, temp_name, strlen (temp_name) + 1);	  obstack_code_rename (stk, dir->name, "");	  for (p = dir; p != prev; p = p->orig)	    obstack_code_rename (stk, p->orig->name, p->name);	  obstack_code_rename (stk, "", prev->name);	}    }  return true;}const char *append_incremental_renames (const char *dump){  struct obstack stk;  size_t size;  if (directory_table == NULL)    return dump;  obstack_init (&stk);  if (dump)    {      size = dumpdir_size (dump) - 1;      obstack_grow (&stk, dump, size);    }  else    size = 0;  hash_do_for_each (directory_table, rename_handler, &stk);  if (obstack_object_size (&stk) != size)    {      obstack_1grow (&stk, 0);      dump = obstack_finish (&stk);    }  else    obstack_free (&stk, NULL);  return dump;}static FILE *listed_incremental_stream;/* Version of incremental format snapshots (directory files) used by this   tar. Currently it is supposed to be a single decimal number. 0 means   incremental snapshots as per tar version before 1.15.2.   The current tar version supports incremental versions from   0 up to TAR_INCREMENTAL_VERSION, inclusive.   It is able to create only snapshots of TAR_INCREMENTAL_VERSION */#define TAR_INCREMENTAL_VERSION 2/* Read incremental snapshot formats 0 and 1 */static voidread_incr_db_01 (int version, const char *initbuf){  int n;  uintmax_t u;  time_t sec;  long int nsec;  char *buf = 0;  size_t bufsize;  char *ebuf;  long lineno = 1;  if (version == 1)    {      if (getline (&buf, &bufsize, listed_incremental_stream) <= 0)	{	  read_error (listed_incremental_option);	  free (buf);	  return;	}      ++lineno;    }  else    {      buf = strdup (initbuf);      bufsize = strlen (buf) + 1;    }  sec = TYPE_MINIMUM (time_t);  nsec = -1;  errno = 0;  u = strtoumax (buf, &ebuf, 10);  if (!errno && TYPE_MAXIMUM (time_t) < u)    errno = ERANGE;  if (errno || buf == ebuf)    ERROR ((0, errno, "%s:%ld: %s",	    quotearg_colon (listed_incremental_option),	    lineno,	    _("Invalid time stamp")));  else    {      sec = u;      if (version == 1 && *ebuf)	{	  char const *buf_ns = ebuf + 1;	  errno = 0;	  u = strtoumax (buf_ns, &ebuf, 10);	  if (!errno && BILLION <= u)	    errno = ERANGE;	  if (errno || buf_ns == ebuf)	    {	      ERROR ((0, errno, "%s:%ld: %s",		      quotearg_colon (listed_incremental_option),		      lineno,		      _("Invalid time stamp")));	      sec = TYPE_MINIMUM (time_t);	    }	  else	    nsec = u;	}      else	{	  /* pre-1 incremental format does not contain nanoseconds */	  nsec = 0;	}    }  newer_mtime_option.tv_sec = sec;  newer_mtime_option.tv_nsec = nsec;  while (0 < (n = getline (&buf, &bufsize, listed_incremental_stream)))    {      dev_t dev;      ino_t ino;      bool nfs = buf[0] == '+';      char *strp = buf + nfs;      struct timespec mtime;      lineno++;      if (buf[n - 1] == '\n')	buf[n - 1] = '\0';      if (version == 1)	{	  errno = 0;	  u = strtoumax (strp, &ebuf, 10);	  if (!errno && TYPE_MAXIMUM (time_t) < u)	    errno = ERANGE;	  if (errno || strp == ebuf || *ebuf != ' ')	    {	      ERROR ((0, errno, "%s:%ld: %s",		      quotearg_colon (listed_incremental_option), lineno,		      _("Invalid modification time (seconds)")));	      sec = (time_t) -1;	    }	  else	    sec = u;	  strp = ebuf;	  errno = 0;	  u = strtoumax (strp, &ebuf, 10);	  if (!errno && BILLION <= u)	    errno = ERANGE;	  if (errno || strp == ebuf || *ebuf != ' ')	    {	      ERROR ((0, errno, "%s:%ld: %s",		      quotearg_colon (listed_incremental_option), lineno,		      _("Invalid modification time (nanoseconds)")));	      nsec = -1;	    }	  else	    nsec = u;	  mtime.tv_sec = sec;	  mtime.tv_nsec = nsec;	  strp = ebuf;	}      else	memset (&mtime, 0, sizeof mtime);      errno = 0;      u = strtoumax (strp, &ebuf, 10);      if (!errno && TYPE_MAXIMUM (dev_t) < u)	errno = ERANGE;      if (errno || strp == ebuf || *ebuf != ' ')	{	  ERROR ((0, errno, "%s:%ld: %s",		  quotearg_colon (listed_incremental_option), lineno,		  _("Invalid device number")));	  dev = (dev_t) -1;	}      else	dev = u;      strp = ebuf;      errno = 0;      u = strtoumax (strp, &ebuf, 10);      if (!errno && TYPE_MAXIMUM (ino_t) < u)	errno = ERANGE;      if (errno || strp == ebuf || *ebuf != ' ')	{	  ERROR ((0, errno, "%s:%ld: %s",		  quotearg_colon (listed_incremental_option), lineno,		  _("Invalid inode number")));	  ino = (ino_t) -1;	}      else	ino = u;      strp = ebuf;      strp++;      unquote_string (strp);      note_directory (strp, mtime, dev, ino, nfs, false, NULL);    }  free (buf);}/* Read a nul-terminated string from FP and store it in STK.   Store the number of bytes read (including nul terminator) in PCOUNT.   Return the last character read or EOF on end of file. */static intread_obstack (FILE *fp, struct obstack *stk, size_t *pcount){  int c;  size_t i;  for (i = 0, c = getc (fp); c != EOF && c != 0; c = getc (fp), i++)    obstack_1grow (stk, c);  obstack_1grow (stk, 0);  *pcount = i;  return c;}/* Read from file FP a nul-terminated string and convert it to   intmax_t.  Return the resulting value in PVAL.  Assume '-' has   already been read.   Throw a fatal error if the string cannot be converted or if the   converted value is less than MIN_VAL.  */static voidread_negative_num (FILE *fp, intmax_t min_val, intmax_t *pval){  int c;  size_t i;  char buf[INT_BUFSIZE_BOUND (intmax_t)];  char *ep;  buf[0] = '-';  for (i = 1; ISDIGIT (c = getc (fp)); i++)    {      if (i == sizeof buf - 1)	FATAL_ERROR ((0, 0, _("Field too long while reading snapshot file")));      buf[i] = c;    }  if (c < 0)    {      if (ferror (fp))	FATAL_ERROR ((0, errno, _("Read error in snapshot file")));      else	FATAL_ERROR ((0, 0, _("Unexpected EOF in snapshot file")));    }  buf[i] = 0;  errno = 0;  *pval = strtoimax (buf, &ep, 10);  if (c || errno || *pval < min_val)    FATAL_ERROR ((0, errno, _("Unexpected field value in snapshot file")));}/* Read from file FP a nul-terminated string and convert it to   uintmax_t.  Return the resulting value in PVAL.  Assume C has   already been read.   Throw a fatal error if the string cannot be converted or if the   converted value exceeds MAX_VAL.   Return the last character read or EOF on end of file. */static intread_unsigned_num (int c, FILE *fp, uintmax_t max_val, uintmax_t *pval){  size_t i;  char buf[UINTMAX_STRSIZE_BOUND], *ep;  for (i = 0; ISDIGIT (c); i++)    {      if (i == sizeof buf - 1)	FATAL_ERROR ((0, 0, _("Field too long while reading snapshot file")));      buf[i] = c;      c = getc (fp);    }  if (c < 0)    {      if (ferror (fp))	FATAL_ERROR ((0, errno, _("Read error in snapshot file")));      else if (i == 0)	return c;      else	FATAL_ERROR ((0, 0, _("Unexpected EOF in snapshot file")));    }  buf[i] = 0;  errno = 0;  *pval = strtoumax (buf, &ep, 10);  if (c || errno || max_val < *pval)    FATAL_ERROR ((0, errno, _("Unexpected field value in snapshot file")));  return c;}/* Read from file FP a nul-terminated string and convert it to   uintmax_t.  Return the resulting value in PVAL.   Throw a fatal error if the string cannot be converted or if the   converted value exceeds MAX_VAL.   Return the last character read or EOF on end of file. */static intread_num (FILE *fp, uintmax_t max_val, uintmax_t *pval){  return read_unsigned_num (getc (fp), fp, max_val, pval);}/* Read from FP two NUL-terminated strings representing a struct   timespec.  Return the resulting value in PVAL.   Throw a fatal error if the string cannot be converted.  */static voidread_timespec (FILE *fp, struct timespec *pval){  int c = getc (fp);  intmax_t i;  uintmax_t u;  if (c == '-')    {      read_negative_num (fp, TYPE_MINIMUM (time_t), &i);      c = 0;      pval->tv_sec = i;    }  else    {      c = read_unsigned_num (c, fp, TYPE_MAXIMUM (time_t), &u);

⌨️ 快捷键说明

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