Exemple #1
0
struct timespec
dtotimespec (double sec)
{
  if (! (TYPE_MINIMUM (time_t) < sec))
    return make_timespec (TYPE_MINIMUM (time_t), 0);
  else if (! (sec < 1.0 + TYPE_MAXIMUM (time_t)))
    return make_timespec (TYPE_MAXIMUM (time_t), TIMESPEC_RESOLUTION - 1);
  else
    {
      time_t s = sec;
      double frac = TIMESPEC_RESOLUTION * (sec - s);
      long ns = frac;
      ns += ns < frac;
      s += ns / TIMESPEC_RESOLUTION;
      ns %= TIMESPEC_RESOLUTION;

      if (ns < 0)
        {
          s--;
          ns += TIMESPEC_RESOLUTION;
        }

      return make_timespec (s, ns);
    }
}
Exemple #2
0
struct timespec
dtotimespec (double sec)
{
  double min_representable = TYPE_MINIMUM (time_t);
  double max_representable =
    ((TYPE_MAXIMUM (time_t) * (double) TIMESPEC_RESOLUTION
      + (TIMESPEC_RESOLUTION - 1))
     / TIMESPEC_RESOLUTION);

  if (! (min_representable < sec))
    return make_timespec (TYPE_MINIMUM (time_t), 0);
  else if (! (sec < max_representable))
    return make_timespec (TYPE_MAXIMUM (time_t), TIMESPEC_RESOLUTION - 1);
  else
    {
      time_t s = sec;
      double frac = TIMESPEC_RESOLUTION * (sec - s);
      long ns = frac;
      ns += ns < frac;
      s += ns / TIMESPEC_RESOLUTION;
      ns %= TIMESPEC_RESOLUTION;

      if (ns < 0)
        {
          s--;
          ns += TIMESPEC_RESOLUTION;
        }

      return make_timespec (s, ns);
    }
}
Exemple #3
0
/* Read incremental snapshot format 2 */
static void
read_incr_db_2 (void)
{
  struct obstack stk;
  char offbuf[INT_BUFSIZE_BOUND (off_t)];

  obstack_init (&stk);

  read_timespec (listed_incremental_stream, &newer_mtime_option);

  for (;;)
    {
      intmax_t i;
      struct timespec mtime;
      dev_t dev;
      ino_t ino;
      bool nfs;
      char *name;
      char *content;
      size_t s;

      if (! read_num (listed_incremental_stream, "nfs", 0, 1, &i))
	return; /* Normal return */

      nfs = i;

      read_timespec (listed_incremental_stream, &mtime);

      if (! read_num (listed_incremental_stream, "dev",
		      TYPE_MINIMUM (dev_t), TYPE_MAXIMUM (dev_t), &i))
	break;
      dev = i;

      if (! read_num (listed_incremental_stream, "ino",
		      TYPE_MINIMUM (ino_t), TYPE_MAXIMUM (ino_t), &i))
	break;
      ino = i;

      if (read_obstack (listed_incremental_stream, &stk, &s))
	break;

      name = obstack_finish (&stk);

      while (read_obstack (listed_incremental_stream, &stk, &s) == 0 && s > 1)
	;
      if (getc (listed_incremental_stream) != 0)
	FATAL_ERROR ((0, 0, _("%s: byte %s: %s"),
		      quotearg_colon (listed_incremental_option),
		      offtostr (ftello (listed_incremental_stream), offbuf),
		      _("Missing record terminator")));

      content = obstack_finish (&stk);
      note_directory (name, mtime, dev, ino, nfs, false, content);
      obstack_free (&stk, content);
    }
  FATAL_ERROR ((0, 0, "%s: %s",
		quotearg_colon (listed_incremental_option),
		_("Unexpected EOF in snapshot file")));
}
Exemple #4
0
static void
read_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);
      pval->tv_sec = u;
    }

  if (c || read_num (fp, BILLION - 1, &u))
    FATAL_ERROR ((0, 0, "%s: %s",
		  quotearg_colon (listed_incremental_option),
		  _("Unexpected EOF in snapshot file")));
  pval->tv_nsec = u;
}
Exemple #5
0
/* Initialize directory data.  */
static inline void
duinfo_init (struct duinfo *a)
{
  a->size = 0;
  a->tmax.tv_sec = TYPE_MINIMUM (time_t);
  a->tmax.tv_nsec = -1;
}
struct timespec
timespec_sub (struct timespec a, struct timespec b)
{
  struct timespec r;
  time_t rs = a.tv_sec;
  time_t bs = b.tv_sec;
  int ns = a.tv_nsec - b.tv_nsec;
  int rns = ns;

  if (ns < 0)
    {
      rns = ns + 1000000000;
      if (rs == TYPE_MINIMUM (time_t))
        {
          if (bs <= 0)
            goto low_overflow;
          bs--;
        }
      else
        rs--;
    }

  if (INT_SUBTRACT_OVERFLOW (rs, bs))
    {
      if (rs < 0)
        {
        low_overflow:
          rs = TYPE_MINIMUM (time_t);
          rns = 0;
        }
      else
        {
          rs = TYPE_MAXIMUM (time_t);
          rns = 999999999;
        }
    }
  else
    rs -= bs;

  r.tv_sec = rs;
  r.tv_nsec = rns;
  return r;
}
Exemple #7
0
/* Output incremental data for the directory ENTRY to the file DATA.
   Return nonzero if successful, preserving errno on write failure.  */
static bool
write_directory_file_entry (void *entry, void *data)
{
  struct directory const *directory = entry;
  FILE *fp = data;

  if (DIR_IS_FOUND (directory))
    {
      char buf[SYSINT_BUFSIZE];
      char const *s;

      s = DIR_IS_NFS (directory) ? "1" : "0";
      fwrite (s, 2, 1, fp);
      s = sysinttostr (directory->mtime.tv_sec, TYPE_MINIMUM (time_t),
		       TYPE_MAXIMUM (time_t), buf);
      fwrite (s, strlen (s) + 1, 1, fp);
      s = imaxtostr (directory->mtime.tv_nsec, buf);
      fwrite (s, strlen (s) + 1, 1, fp);
      s = sysinttostr (directory->device_number,
		       TYPE_MINIMUM (dev_t), TYPE_MAXIMUM (dev_t), buf);
      fwrite (s, strlen (s) + 1, 1, fp);
      s = sysinttostr (directory->inode_number,
		       TYPE_MINIMUM (ino_t), TYPE_MAXIMUM (ino_t), buf);
      fwrite (s, strlen (s) + 1, 1, fp);

      fwrite (directory->name, strlen (directory->name) + 1, 1, fp);
      if (directory->dump)
	{
	  const char *p;
	  struct dumpdir_iter *itr;

	  for (p = dumpdir_first (directory->dump, 0, &itr);
	       p;
	       p = dumpdir_next (itr))
	    fwrite (p, strlen (p) + 1, 1, fp);
	  free (itr);
	}
      fwrite ("\0\0", 2, 1, fp);
    }

  return ! ferror (fp);
}
Exemple #8
0
struct timespec
timespec_sub (struct timespec a, struct timespec b)
{
  time_t rs = a.tv_sec;
  time_t bs = b.tv_sec;
  int ns = a.tv_nsec - b.tv_nsec;
  int rns = ns;

  if (ns < 0)
    {
      rns = ns + TIMESPEC_RESOLUTION;
      if (rs == TYPE_MINIMUM (time_t))
        {
          if (bs <= 0)
            goto low_overflow;
          bs--;
        }
      else
        rs--;
    }

  if (INT_SUBTRACT_OVERFLOW (rs, bs))
    {
      if (rs < 0)
        {
        low_overflow:
          rs = TYPE_MINIMUM (time_t);
          rns = 0;
        }
      else
        {
          rs = TYPE_MAXIMUM (time_t);
          rns = TIMESPEC_RESOLUTION - 1;
        }
    }
  else
    rs -= bs;

  return make_timespec (rs, rns);
}
Exemple #9
0
static bool
decode_time (struct timespec *ts, char const *arg, char const *keyword)
{
  switch (_decode_time (ts, arg, keyword))
    {
    case decode_time_success:
      return true;
    case decode_time_bad_header:
      ERROR ((0, 0, _("Malformed extended header: invalid %s=%s"),
	      keyword, arg));
      return false;
    case decode_time_range:
      out_of_range_header (keyword, arg, - (uintmax_t) TYPE_MINIMUM (time_t),
			   TYPE_MAXIMUM (time_t));
      return false;
    }
  return true;
}
Exemple #10
0
static void
read_timespec (FILE *fp, struct timespec *pval)
{
  intmax_t s, ns;

  if (read_num (fp, "sec", TYPE_MINIMUM (time_t), TYPE_MAXIMUM (time_t), &s)
      && read_num (fp, "nsec", 0, BILLION - 1, &ns))
    {
      pval->tv_sec = s;
      pval->tv_nsec = ns;
    }
  else
    {
      FATAL_ERROR ((0, 0, "%s: %s",
		    quotearg_colon (listed_incremental_option),
		    _("Unexpected EOF in snapshot file")));
    }
}
Exemple #11
0
struct timespec
timespec_add (struct timespec a, struct timespec b)
{
  time_t rs = a.tv_sec;
  time_t bs = b.tv_sec;
  int ns = a.tv_nsec + b.tv_nsec;
  int nsd = ns - TIMESPEC_RESOLUTION;
  int rns = ns;
  time_t tmin = TYPE_MINIMUM (time_t);
  time_t tmax = TYPE_MAXIMUM (time_t);

  if (0 <= nsd)
    {
      rns = nsd;
      if (bs < tmax)
        bs++;
      else if (rs < 0)
        rs++;
      else
        goto high_overflow;
    }

  /* INT_ADD_WRAPV is not appropriate since time_t might be unsigned.
     In theory time_t might be narrower than int, so plain
     INT_ADD_OVERFLOW does not suffice.  */
  if (! INT_ADD_OVERFLOW (rs, bs) && tmin <= rs + bs && rs + bs <= tmax)
    rs += bs;
  else
    {
      if (rs < 0)
        {
          rs = tmin;
          rns = 0;
        }
      else
        {
        high_overflow:
          rs = tmax;
          rns = TIMESPEC_RESOLUTION - 1;
        }
    }

  return make_timespec (rs, rns);
}
Exemple #12
0
static bool
decode_time (struct timespec *ts, char const *arg, char const *keyword)
{
  char *arg_lim;
  struct timespec t = decode_timespec (arg, &arg_lim, true);

  if (! valid_timespec (t))
    {
      if (arg < arg_lim && !*arg_lim)
	out_of_range_header (keyword, arg, TYPE_MINIMUM (time_t),
			     TYPE_MAXIMUM (time_t));
      else
	ERROR ((0, 0, _("Malformed extended header: invalid %s=%s"),
		keyword, arg));
      return false;
    }

  *ts = t;
  return true;
}
Exemple #13
0
struct timespec
timespec_add (struct timespec a, struct timespec b)
{
    time_t rs = a.tv_sec;
    time_t bs = b.tv_sec;
    int ns = a.tv_nsec + b.tv_nsec;
    int nsd = ns - TIMESPEC_RESOLUTION;
    int rns = ns;

    if (0 <= nsd)
    {
        rns = nsd;
        if (rs == TYPE_MAXIMUM (time_t))
        {
            if (0 <= bs)
                goto high_overflow;
            bs++;
        }
        else
            rs++;
    }

    if (INT_ADD_OVERFLOW (rs, bs))
    {
        if (rs < 0)
        {
            rs = TYPE_MINIMUM (time_t);
            rns = 0;
        }
        else
        {
high_overflow:
            rs = TYPE_MAXIMUM (time_t);
            rns = TIMESPEC_RESOLUTION - 1;
        }
    }
    else
        rs += bs;

    return make_timespec (rs, rns);
}
Exemple #14
0
static void
print_context_label (char const *mark,
		     struct file_data *inf,
		     char const *name,
		     char const *label)
{
  if (label)
    fprintf (outfile, "%s %s\n", mark, label);
  else
    {
      char buf[MAX (INT_STRLEN_BOUND (int) + 32,
		    INT_STRLEN_BOUND (time_t) + 11)];
      struct tm const *tm = localtime (&inf->stat.st_mtime);
      int nsec = get_stat_mtime_ns (&inf->stat);
      if (! (tm && nstrftime (buf, sizeof buf, time_format, tm, 0, nsec)))
	{
	  verify (TYPE_IS_INTEGER (time_t));
	  if (LONG_MIN <= TYPE_MINIMUM (time_t)
	      && TYPE_MAXIMUM (time_t) <= LONG_MAX)
	    {
	      long int sec = inf->stat.st_mtime;
	      sprintf (buf, "%ld.%.9d", sec, nsec);
	    }
	  else if (TYPE_MAXIMUM (time_t) <= INTMAX_MAX)
	    {
	      intmax_t sec = inf->stat.st_mtime;
	      sprintf (buf, "%"PRIdMAX".%.9d", sec, nsec);
	    }
	  else
	    {
	      uintmax_t sec = inf->stat.st_mtime;
	      sprintf (buf, "%"PRIuMAX".%.9d", sec, nsec);
	    }
	}
      fprintf (outfile, "%s %s\t%s\n", mark, name, buf);
    }
}
Exemple #15
0
   with any changes made to the read_num() calls in the parsing
   loop inside read_incr_db_2().

   (This function is invoked via the --show-snapshot-field-ranges
   command line option.) */

struct field_range
{
  char const *fieldname;
  intmax_t min_val;
  uintmax_t max_val;
};

static struct field_range const field_ranges[] = {
  { "nfs", 0, 1 },
  { "timestamp_sec", TYPE_MINIMUM (time_t), TYPE_MAXIMUM (time_t) },
  { "timestamp_nsec", 0, BILLION - 1 },
  { "dev", TYPE_MINIMUM (dev_t), TYPE_MAXIMUM (dev_t) },
  { "ino", TYPE_MINIMUM (ino_t), TYPE_MAXIMUM (ino_t) },
  { NULL, 0, 0 }
};

void
show_snapshot_field_ranges (void)
{
  struct field_range const *p;
  char minbuf[SYSINT_BUFSIZE];
  char maxbuf[SYSINT_BUFSIZE];

  printf("This tar's snapshot file field ranges are\n");
  printf ("   (%-15s => [ %s, %s ]):\n\n", "field name", "min", "max");
Exemple #16
0
#if __GNUC__ >= 2 && DO_PEDANTIC
# define verify_same_types(expr1,expr2)  \
    extern void _verify_func(__LINE__) (__typeof__ (expr1) *); \
    extern void _verify_func(__LINE__) (__typeof__ (expr2) *);
# define _verify_func(line) _verify_func2(line)
# define _verify_func2(line) verify_func_ ## line
#else
# define verify_same_types(expr1,expr2) extern void verify_func (int)
#endif

/* 7.18.1.1. Exact-width integer types */
/* 7.18.2.1. Limits of exact-width integer types */

int8_t a1[3] = { INT8_C (17), INT8_MIN, INT8_MAX };
verify (TYPE_MINIMUM (int8_t) == INT8_MIN);
verify (TYPE_MAXIMUM (int8_t) == INT8_MAX);
verify_same_types (INT8_MIN, (int8_t) 0 + 0);
verify_same_types (INT8_MAX, (int8_t) 0 + 0);

int16_t a2[3] = { INT16_C (17), INT16_MIN, INT16_MAX };
verify (TYPE_MINIMUM (int16_t) == INT16_MIN);
verify (TYPE_MAXIMUM (int16_t) == INT16_MAX);
verify_same_types (INT16_MIN, (int16_t) 0 + 0);
verify_same_types (INT16_MAX, (int16_t) 0 + 0);

int32_t a3[3] = { INT32_C (17), INT32_MIN, INT32_MAX };
verify (TYPE_MINIMUM (int32_t) == INT32_MIN);
verify (TYPE_MAXIMUM (int32_t) == INT32_MAX);
verify_same_types (INT32_MIN, (int32_t) 0 + 0);
verify_same_types (INT32_MAX, (int32_t) 0 + 0);
Exemple #17
0
/* Read incremental snapshot formats 0 and 1 */
static void
read_incr_db_01 (int version, const char *initbuf)
{
  int n;
  uintmax_t u;
  char *buf = NULL;
  size_t bufsize = 0;
  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;
    }

  newer_mtime_option = decode_timespec (buf, &ebuf, false);

  if (! valid_timespec (newer_mtime_option))
    ERROR ((0, errno, "%s:%ld: %s",
	    quotearg_colon (listed_incremental_option),
	    lineno,
	    _("Invalid time stamp")));
  else
    {
      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")));
	      newer_mtime_option.tv_sec = TYPE_MINIMUM (time_t);
	      newer_mtime_option.tv_nsec = -1;
	    }
	  else
	    newer_mtime_option.tv_nsec = u;
	}
    }

  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)
	{
	  mtime = decode_timespec (strp, &ebuf, false);
	  strp = ebuf;
	  if (!valid_timespec (mtime) || *strp != ' ')
	    ERROR ((0, errno, "%s:%ld: %s",
		    quotearg_colon (listed_incremental_option), lineno,
		    _("Invalid modification time")));

	  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)")));
	      mtime.tv_nsec = -1;
	    }
	  else
	    mtime.tv_nsec = u;
	  strp = ebuf;
	}
      else
	mtime.tv_sec = mtime.tv_nsec = 0;

      dev = strtosysint (strp, &ebuf,
			 TYPE_MINIMUM (dev_t), TYPE_MAXIMUM (dev_t));
      strp = ebuf;
      if (errno || *strp != ' ')
	ERROR ((0, errno, "%s:%ld: %s",
		quotearg_colon (listed_incremental_option), lineno,
		_("Invalid device number")));

      ino = strtosysint (strp, &ebuf,
			 TYPE_MINIMUM (ino_t), TYPE_MAXIMUM (ino_t));
      strp = ebuf;
      if (errno || *strp != ' ')
	ERROR ((0, errno, "%s:%ld: %s",
		quotearg_colon (listed_incremental_option), lineno,
		_("Invalid inode number")));

      strp++;
      unquote_string (strp);
      note_directory (strp, mtime, dev, ino, nfs, false, NULL);
    }
  free (buf);
}
Exemple #18
0
struct timespec
decode_timespec (char const *arg, char **arg_lim, bool parse_fraction)
{
  time_t s = TYPE_MINIMUM (time_t);
  int ns = -1;
  char const *p = arg;
  bool negative = *arg == '-';
  struct timespec r;

  if (! ISDIGIT (arg[negative]))
    errno = EINVAL;
  else
    {
      errno = 0;

      if (negative)
	{
	  intmax_t i = strtoimax (arg, arg_lim, 10);
	  if (TYPE_SIGNED (time_t) ? TYPE_MINIMUM (time_t) <= i : 0 <= i)
	    s = i;
	  else
	    errno = ERANGE;
	}
      else
	{
	  uintmax_t i = strtoumax (arg, arg_lim, 10);
	  if (i <= TYPE_MAXIMUM (time_t))
	    s = i;
	  else
	    errno = ERANGE;
	}

      p = *arg_lim;
      ns = 0;

      if (parse_fraction && *p == '.')
	{
	  int digits = 0;
	  bool trailing_nonzero = false;

	  while (ISDIGIT (*++p))
	    if (digits < LOG10_BILLION)
	      digits++, ns = 10 * ns + (*p - '0');
	    else
	      trailing_nonzero |= *p != '0';

	  while (digits < LOG10_BILLION)
	    digits++, ns *= 10;

	  if (negative)
	    {
	      /* Convert "-1.10000000000001" to s == -2, ns == 89999999.
		 I.e., truncate time stamps towards minus infinity while
		 converting them to internal form.  */
	      ns += trailing_nonzero;
	      if (ns != 0)
		{
		  if (s == TYPE_MINIMUM (time_t))
		    ns = -1;
		  else
		    {
		      s--;
		      ns = BILLION - ns;
		    }
		}
	    }
	}

      if (errno == ERANGE)
	ns = -1;
    }

  *arg_lim = (char *) p;
  r.tv_sec = s;
  r.tv_nsec = ns;
  return r;
}
Exemple #19
0
/* Read incremental snapshot formats 0 and 1 */
static void
read_incr_db_01 (int version, const char *initbuf)
{
  int n;
  uintmax_t u;
  time_t sec;
  long int nsec;
  char *buf = NULL;
  size_t bufsize = 0;
  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);
}
Exemple #20
0
static enum decode_time_status
_decode_time (struct timespec *ts, char const *arg, char const *keyword)
{
  time_t s;
  unsigned long int ns = 0;
  char *p;
  char *arg_lim;
  bool negative = *arg == '-';

  errno = 0;

  if (ISDIGIT (arg[negative]))
    {
      if (negative)
	{
	  intmax_t i = strtoimax (arg, &arg_lim, 10);
	  if (TYPE_SIGNED (time_t) ? i < TYPE_MINIMUM (time_t) : i < 0)
	    return decode_time_range;
	  s = i;
	}
      else
	{
	  uintmax_t i = strtoumax (arg, &arg_lim, 10);
	  if (TYPE_MAXIMUM (time_t) < i)
	    return decode_time_range;
	  s = i;
	}

      p = arg_lim;

      if (errno == ERANGE)
	return decode_time_range;

      if (*p == '.')
	{
	  int digits = 0;
	  bool trailing_nonzero = false;

	  while (ISDIGIT (*++p))
	    if (digits < LOG10_BILLION)
	      {
		ns = 10 * ns + (*p - '0');
		digits++;
	      }
	    else
	      trailing_nonzero |= *p != '0';

	  while (digits++ < LOG10_BILLION)
	    ns *= 10;

	  if (negative)
	    {
	      /* Convert "-1.10000000000001" to s == -2, ns == 89999999.
		 I.e., truncate time stamps towards minus infinity while
		 converting them to internal form.  */
	      ns += trailing_nonzero;
	      if (ns != 0)
		{
		  if (s == TYPE_MINIMUM (time_t))
		    return decode_time_range;
		  s--;
		  ns = BILLION - ns;
		}
	    }
	}

      if (! *p)
	{
	  ts->tv_sec = s;
	  ts->tv_nsec = ns;
	  return decode_time_success;
	}
    }

  return decode_time_bad_header;
}