Ejemplo n.º 1
0
static void
copy_to_fd (const char *from, int tofd)
{
  int fromfd;
  ssize_t i;

  if ((fromfd = open (from, O_RDONLY | O_BINARY)) < 0)
    pfatal ("Can't reopen file %s", quotearg (from));
  while ((i = read (fromfd, buf, bufsize)) != 0)
    {
      if (i == (ssize_t) -1)
	read_fatal ();
      if (full_write (tofd, buf, i) != i)
	write_fatal ();
    }
  if (close (fromfd) != 0)
    read_fatal ();
}
Ejemplo n.º 2
0
void
copy_file (char const *from, char const *to, int to_flags, mode_t mode)
{
  int tofd;
  int fromfd;
  size_t i;

  if ((fromfd = open (from, O_RDONLY | O_BINARY, 0)) < 0)
    pfatal ("Can't reopen file %s", quotearg (from));
  tofd = create_file (to, O_WRONLY | O_BINARY | to_flags, mode);
  while ((i = read (fromfd, buf, bufsize)) != 0)
    {
      if (i == (size_t) -1)
	read_fatal ();
      if (write (tofd, buf, i) != i)
	write_fatal ();
    }
  if (close (fromfd) != 0)
    read_fatal ();
  if (close (tofd) != 0)
    write_fatal ();
}
Ejemplo n.º 3
0
char const *
	ifetch (LINENUM line, bool whichbuf, size_t *psize)
{
	register char const *q;
	register char const *p;

	if (line < 1 || line > input_lines) 
	{
		*psize = 0;
		return "";
	}
	if (using_plan_a) {
		p = i_ptr[line];
		*psize = i_ptr[line + 1] - p;
		return p;
	} else {
		LINENUM offline = line % lines_per_buf;
		LINENUM baseline = line - offline;

		if (tiline[0] == baseline)
			whichbuf = false;
		else if (tiline[1] == baseline)
			whichbuf = true;
		else {
			tiline[whichbuf] = baseline;
			if (lseek (tifd, (off_t) (baseline/lines_per_buf * tibufsize),
				SEEK_SET) == -1
				|| read (tifd, tibuf[whichbuf], tibufsize) < 0)
				read_fatal ();
		}
		p = tibuf[whichbuf] + (tireclen*offline);
		if (line == input_lines)
			*psize = last_line_size;
		else {
			for (q = p;  *q++ != '\n';  )
				continue;
			*psize = q - p;
		}
		return p;
	}
}
Ejemplo n.º 4
0
void
move_file (char const *from, bool *from_needs_removal,
	   struct stat const *fromst,
	   char const *to, mode_t mode, bool backup)
{
  struct stat to_st;
  int to_errno;

  to_errno = stat_file (to, &to_st);
  if (backup)
    create_backup (to, to_errno ? NULL : &to_st, false);
  if (! to_errno)
    insert_file_id (&to_st, OVERWRITTEN);

  if (from)
    {
      if (S_ISLNK (mode))
	{
	  bool to_dir_known_to_exist = false;

	  /* FROM contains the contents of the symlink we have patched; need
	     to convert that back into a symlink. */
	  char *buffer = xmalloc (PATH_MAX);
	  int fd, size = 0, i;

	  if ((fd = open (from, O_RDONLY | O_BINARY)) < 0)
	    pfatal ("Can't reopen file %s", quotearg (from));
	  while ((i = read (fd, buffer + size, PATH_MAX - size)) > 0)
	    size += i;
	  if (i != 0 || close (fd) != 0)
	    read_fatal ();
	  buffer[size] = 0;

	  if (! backup)
	    {
	      if (unlink (to) == 0)
		to_dir_known_to_exist = true;
	    }
	  if (symlink (buffer, to) != 0)
	    {
	      if (errno == ENOENT && ! to_dir_known_to_exist)
		makedirs (to);
	      if (symlink (buffer, to) != 0)
		pfatal ("Can't create %s %s", "symbolic link", to);
	    }
	  free (buffer);
	  if (lstat (to, &to_st) != 0)
	    pfatal ("Can't get file attributes of %s %s", "symbolic link", to);
	  insert_file_id (&to_st, CREATED);
	}
      else
	{
	  if (debug & 4)
	    say ("Renaming file %s to %s\n",
		 quotearg_n (0, from), quotearg_n (1, to));

	  if (rename (from, to) != 0)
	    {
	      bool to_dir_known_to_exist = false;

	      if (errno == ENOENT
		  && (to_errno == -1 || to_errno == ENOENT))
		{
		  makedirs (to);
		  to_dir_known_to_exist = true;
		  if (rename (from, to) == 0)
		    goto rename_succeeded;
		}

	      if (errno == EXDEV)
		{
		  struct stat tost;
		  if (! backup)
		    {
		      if (unlink (to) == 0)
			to_dir_known_to_exist = true;
		      else if (errno != ENOENT)
			pfatal ("Can't remove file %s", quotearg (to));
		    }
		  copy_file (from, to, &tost, 0, mode, to_dir_known_to_exist);
		  insert_file_id (&tost, CREATED);
		  return;
		}

	      pfatal ("Can't rename file %s to %s",
		      quotearg_n (0, from), quotearg_n (1, to));
	    }

	rename_succeeded:
	  insert_file_id (fromst, CREATED);
	  /* Do not clear *FROM_NEEDS_REMOVAL if it's possible that the
	     rename returned zero because FROM and TO are hard links to
	     the same file.  */
	  if ((0 < to_errno
	       || (to_errno == 0 && to_st.st_nlink <= 1))
	      && from_needs_removal)
	    *from_needs_removal = false;
	}
    }
  else if (! backup)
    {
      if (debug & 4)
	say ("Removing file %s\n", quotearg (to));
      if (unlink (to) != 0 && errno != ENOENT)
	pfatal ("Can't remove file %s", quotearg (to));
    }
}
Ejemplo n.º 5
0
/* Set ARCHIVE for writing, then compressing an archive.  */
pid_t
sys_child_open_for_compress (void)
{
  int parent_pipe[2];
  int child_pipe[2];
  pid_t grandchild_pid;
  pid_t child_pid;

  xpipe (parent_pipe);
  child_pid = xfork ();

  if (child_pid > 0)
    {
      /* The parent tar is still here!  Just clean up.  */

      archive = parent_pipe[PWRITE];
      xclose (parent_pipe[PREAD]);
      return child_pid;
    }

  /* The new born child tar is here!  */

  set_program_name (_("tar (child)"));
  signal (SIGPIPE, SIG_DFL);
  
  xdup2 (parent_pipe[PREAD], STDIN_FILENO);
  xclose (parent_pipe[PWRITE]);

  /* Check if we need a grandchild tar.  This happens only if either:
     a) the file is to be accessed by rmt: compressor doesn't know how;
     b) the file is not a plain file.  */

  if (!_remdev (archive_name_array[0])
      && is_regular_file (archive_name_array[0]))
    {
      if (backup_option)
	maybe_backup_file (archive_name_array[0], 1);

      /* We don't need a grandchild tar.  Open the archive and launch the
	 compressor.  */
      if (strcmp (archive_name_array[0], "-"))
	{
	  archive = creat (archive_name_array[0], MODE_RW);
	  if (archive < 0)
	    {
	      int saved_errno = errno;

	      if (backup_option)
		undo_last_backup ();
	      errno = saved_errno;
	      open_fatal (archive_name_array[0]);
	    }
	  xdup2 (archive, STDOUT_FILENO);
	}
      execlp (use_compress_program_option, use_compress_program_option, NULL);
      exec_fatal (use_compress_program_option);
    }

  /* We do need a grandchild tar.  */

  xpipe (child_pipe);
  grandchild_pid = xfork ();

  if (grandchild_pid == 0)
    {
      /* The newborn grandchild tar is here!  Launch the compressor.  */

      set_program_name (_("tar (grandchild)"));

      xdup2 (child_pipe[PWRITE], STDOUT_FILENO);
      xclose (child_pipe[PREAD]);
      execlp (use_compress_program_option, use_compress_program_option,
	      (char *) 0);
      exec_fatal (use_compress_program_option);
    }

  /* The child tar is still here!  */

  /* Prepare for reblocking the data from the compressor into the archive.  */

  xdup2 (child_pipe[PREAD], STDIN_FILENO);
  xclose (child_pipe[PWRITE]);

  if (strcmp (archive_name_array[0], "-") == 0)
    archive = STDOUT_FILENO;
  else
    {
      archive = rmtcreat (archive_name_array[0], MODE_RW, rsh_command_option);
      if (archive < 0)
	open_fatal (archive_name_array[0]);
    }

  /* Let's read out of the stdin pipe and write an archive.  */

  while (1)
    {
      size_t status = 0;
      char *cursor;
      size_t length;

      /* Assemble a record.  */

      for (length = 0, cursor = record_start->buffer;
	   length < record_size;
	   length += status, cursor += status)
	{
	  size_t size = record_size - length;

	  status = safe_read (STDIN_FILENO, cursor, size);
	  if (status == SAFE_READ_ERROR)
	    read_fatal (use_compress_program_option);
	  if (status == 0)
	    break;
	}

      /* Copy the record.  */

      if (status == 0)
	{
	  /* We hit the end of the file.  Write last record at
	     full length, as the only role of the grandchild is
	     doing proper reblocking.  */

	  if (length > 0)
	    {
	      memset (record_start->buffer + length, 0, record_size - length);
	      status = sys_write_archive_buffer ();
	      if (status != record_size)
		archive_write_error (status);
	    }

	  /* There is nothing else to read, break out.  */
	  break;
	}

      status = sys_write_archive_buffer ();
      if (status != record_size)
	archive_write_error (status);
    }

  wait_for_grandchild (grandchild_pid);
}
Ejemplo n.º 6
0
static void
	plan_b (char const *filename)
{
	register FILE *ifp;
	register int c;
	register size_t len;
	register size_t maxlen;
	register bool found_revision;
	register size_t i;
	register char const *rev;
	register size_t revlen;
	register LINENUM line = 1;
	int exclusive;

	if (instat.st_size == 0)
		filename = NULL_DEVICE;
	if (! (ifp = fopen (filename, binary_transput ? "rb" : "rt")))
		pfatal ("Can't open file %s", quotearg (filename));
	exclusive = TMPINNAME_needs_removal ? 0 : O_EXCL;
	TMPINNAME_needs_removal = 1;
	tifd = create_file (TMPINNAME, O_RDWR | O_BINARY | exclusive, (mode_t) 0);
	i = 0;
	len = 0;
	maxlen = 1;
	rev = revision;
	found_revision = !rev;
	revlen = rev ? strlen (rev) : 0;

	while ((c = getc (ifp)) != EOF)
	{
		len++;

		if (c == '\n')
		{
			if (++line < 0)
				too_many_lines (filename);
			if (maxlen < len)
				maxlen = len;
			len = 0;
		}

		if (!found_revision)
		{
			if (i == revlen)
			{
				found_revision = ISSPACE ((unsigned char) c);
				i = (size_t) -1;
			}
			else if (i != (size_t) -1)
				i = rev[i]==c ? i + 1 : (size_t) -1;

			if (i == (size_t) -1  &&  ISSPACE ((unsigned char) c))
				i = 0;
		}
	}

	if (revision)
		report_revision (found_revision);
	Fseek (ifp, (off_t) 0, SEEK_SET);		/* rewind file */
	for (tibufsize = TIBUFSIZE_MINIMUM;  tibufsize < maxlen;  tibufsize <<= 1)
		continue;
	lines_per_buf = tibufsize / maxlen;
	tireclen = maxlen;
	tibuf[0] = (char *)malloc (2 * tibufsize);
	tibuf[1] = tibuf[0] + tibufsize;

	for (line = 1; ; line++)
	{
		char *p = tibuf[0] + maxlen * (line % lines_per_buf);
		char const *p0 = p;
		if (! (line % lines_per_buf))	/* new block */
			if (write (tifd, tibuf[0], tibufsize) != tibufsize)
				write_fatal ();
		if ((c = getc (ifp)) == EOF)
			break;

		for (;;)
		{
			*p++ = c;
			if (c == '\n')
			{
				last_line_size = p - p0;
				break;
			}

			if ((c = getc (ifp)) == EOF)
			{
				last_line_size = p - p0;
				line++;
				goto EOF_reached;
			}
		}
	}
EOF_reached:
	if (ferror (ifp)  ||  fclose (ifp) != 0)
		read_fatal ();

	if (line % lines_per_buf  !=  0)
		if (write (tifd, tibuf[0], tibufsize) != tibufsize)
			write_fatal ();
	input_lines = line - 1;
}
Ejemplo n.º 7
0
static bool
	plan_a (char const *filename)
{
	register char const *s;
	register char const *lim;
	register char const **ptr;
	register char *buffer;
	register LINENUM iline;
	size_t size = (size_t)instat.st_size;

	/* Fail if the file size doesn't fit in a size_t,
	or if storage isn't available.  */
	if (! (size == instat.st_size
		&& (buffer = (char *)malloc (size ? size : (size_t) 1))))
		return false;

	/* Read the input file, but don't bother reading it if it's empty.
	When creating files, the files do not actually exist.  */
	if (size)
	{
		int ifd = open (filename, O_RDONLY|binary_transput);
		size_t buffered = 0, n;
		if (ifd < 0)
			pfatal ("can't open file %s", quotearg (filename));

		while (size - buffered != 0)
		{
			n = read (ifd, buffer + buffered, size - buffered);
			if (n == 0)
			{
				/* Some non-POSIX hosts exaggerate st_size in text mode;
				or the file may have shrunk!  */
				size = buffered;
				break;
			}
			if (n == (size_t) -1)
			{
				/* Perhaps size is too large for this host.  */
				close (ifd);
				free (buffer);
				return false;
			}
			buffered += n;
		}

		if (close (ifd) != 0)
			read_fatal ();
	}

	/* Scan the buffer and build array of pointers to lines.  */
	lim = buffer + size;
	iline = 3; /* 1 unused, 1 for SOF, 1 for EOF if last line is incomplete */
	for (s = buffer;  (s = (char *) memchr (s, '\n', lim - s));  s++)
		if (++iline < 0)
			too_many_lines (filename);
	if (! (iline == (size_t) iline
		&& (size_t) iline * sizeof *ptr / sizeof *ptr == (size_t) iline
		&& (ptr = (char const **) malloc ((size_t) iline * sizeof *ptr))))
	{
		free (buffer);
		return false;
	}
	iline = 0;
	for (s = buffer;  ;  s++)
	{
		ptr[++iline] = s;
		if (! (s = (char *) memchr (s, '\n', lim - s)))
			break;
	}
	if (size && lim[-1] != '\n')
		ptr[++iline] = lim;
	input_lines = iline - 1;

	if (revision)
	{
		char const *rev = revision;
		int rev0 = rev[0];
		bool found_revision = false;
		size_t revlen = strlen (rev);

		if (revlen <= size)
		{
			char const *limrev = lim - revlen;

			for (s = buffer;  (s = (char *) memchr (s, rev0, limrev - s));  s++)
				if (memcmp (s, rev, revlen) == 0
					&& (s == buffer || ISSPACE ((unsigned char) s[-1]))
					&& (s + 1 == limrev || ISSPACE ((unsigned char) s[revlen])))
				{
					found_revision = true;
					break;
				}
		}

		report_revision (found_revision);
	}

	/* Plan A will work.  */
	i_buffer = buffer;
	i_ptr = ptr;
	return true;
}
Ejemplo n.º 8
0
static bool
read_num (FILE *fp, char const *fieldname,
	  intmax_t min_val, uintmax_t max_val, intmax_t *pval)
{
  int i;
  char buf[INT_BUFSIZE_BOUND (intmax_t)];
  char offbuf[INT_BUFSIZE_BOUND (off_t)];
  char minbuf[INT_BUFSIZE_BOUND (intmax_t)];
  char maxbuf[INT_BUFSIZE_BOUND (intmax_t)];
  int conversion_errno;
  int c = getc (fp);
  bool negative = c == '-';

  for (i = 0; (i == 0 && negative) || ISDIGIT (c); i++)
    {
      buf[i] = c;
      if (i == sizeof buf - 1)
	FATAL_ERROR ((0, 0,
		      _("%s: byte %s: %s %.*s... too long"),
		      quotearg_colon (listed_incremental_option),
		      offtostr (ftello (fp), offbuf),
		      fieldname, i + 1, buf));
      c = getc (fp);
    }

  buf[i] = 0;

  if (c < 0)
    {
      if (ferror (fp))
	read_fatal (listed_incremental_option);
      if (i != 0)
	FATAL_ERROR ((0, 0, "%s: %s",
		      quotearg_colon (listed_incremental_option),
		      _("Unexpected EOF in snapshot file")));
      return false;
    }

  if (c)
    {
      unsigned uc = c;
      FATAL_ERROR ((0, 0,
		    _("%s: byte %s: %s %s followed by invalid byte 0x%02x"),
		    quotearg_colon (listed_incremental_option),
		    offtostr (ftello (fp), offbuf),
		    fieldname, buf, uc));
    }

  *pval = strtosysint (buf, NULL, min_val, max_val);
  conversion_errno = errno;

  switch (conversion_errno)
    {
    case ERANGE:
      FATAL_ERROR ((0, conversion_errno,
		    _("%s: byte %s: (valid range %s..%s)\n\t%s %s"),
		    quotearg_colon (listed_incremental_option),
		    offtostr (ftello (fp), offbuf),
		    imaxtostr (min_val, minbuf),
		    umaxtostr (max_val, maxbuf), fieldname, buf));
    default:
      FATAL_ERROR ((0, conversion_errno,
		    _("%s: byte %s: %s %s"),
		    quotearg_colon (listed_incremental_option),
		    offtostr (ftello (fp), offbuf), fieldname, buf));
    case 0:
      break;
    }

  return true;
}