Example #1
0
char *
xgetcwd ()
{
  char *cwd;
  char *ret;
  unsigned path_max;

  errno = 0;
  path_max = (unsigned) PATH_MAX;
  path_max += 2;		/* The getcwd docs say to do this. */

  cwd = tar_xmalloc (path_max);

  errno = 0;
  while ((ret = getcwd (cwd, path_max)) == NULL && errno == ERANGE)
    {
      path_max += PATH_INCR;
      cwd = tar_realloc (cwd, path_max);
      errno = 0;
    }

  if (ret == NULL)
    {
      int save_errno = errno;
      free (cwd);
      errno = save_errno;
      return NULL;
    }
  return cwd;
}
Example #2
0
File: gnu.c Project: VanL/zrt
static void
__tar_add_dir (char *name, dev_t dev, ino_t ino, const char *text)
{
  struct dirname *dp;

  dp = (struct dirname *) tar_xmalloc (sizeof (struct dirname));
  dp->next = dir_list;
  dir_list = dp;

  dp->dev = dev;
  dp->ino = ino;
  dp->name = __tar_xstrdup (name);
  dp->dir_text = text;
  dp->allnew = 0;
}
Example #3
0
void
diff_archive (void)
{
  register char *data;
  int check, namelen;
  int err;
  off_t offset;
  struct stat filestat;

#ifndef __MSDOS__
  dev_t dev;
  ino_t ino;
#endif

  errno = EPIPE;		/* FIXME, remove perrors */

  saverec (&head);		/* make sure it sticks around */
  userec (head);		/* and go past it in the archive */
  decode_header (head, &hstat, &head_standard, 1);	/* snarf fields */

  /* Print the record from `head' and `hstat'.  */

  if (flag_verbose)
    {
      if (now_verifying)
	fprintf (stdlis, _("Verify "));
      print_header ();
    }

  switch (head->header.linkflag)
    {

    default:
      WARN ((0, 0, _("Unknown file type '%c' for %s, diffed as normal file"),
		 head->header.linkflag, current_file_name));
      /* Fall through.  */

    case LF_OLDNORMAL:
    case LF_NORMAL:
    case LF_SPARSE:
    case LF_CONTIG:

      /* Appears to be a file.  See if it's really a directory.  */

      namelen = strlen (current_file_name) - 1;
      if (current_file_name[namelen] == '/')
	goto really_dir;

      if (do_stat (&filestat))
	{
	  if (head->header.isextended)
	    skip_extended_headers ();
	  skip_file ((long) hstat.st_size);
	  different++;
	  goto quit;
	}

      if (!S_ISREG (filestat.st_mode))
	{
	  fprintf (stdlis, _("%s: Not a regular file\n"), current_file_name);
	  skip_file ((long) hstat.st_size);
	  different++;
	  goto quit;
	}

      filestat.st_mode &= 07777;
      if (filestat.st_mode != hstat.st_mode)
	sigh (_("Mode"));
      if (filestat.st_uid != hstat.st_uid)
	sigh (_("Uid"));
      if (filestat.st_gid != hstat.st_gid)
	sigh (_("Gid"));
      if (filestat.st_mtime != hstat.st_mtime)
	sigh (_("Mod time"));
      if (head->header.linkflag != LF_SPARSE &&
	  filestat.st_size != hstat.st_size)
	{
	  sigh (_("Size"));
	  skip_file ((long) hstat.st_size);
	  goto quit;
	}

      diff_fd = open (current_file_name, O_NDELAY | O_RDONLY | O_BINARY);

      if (diff_fd < 0 && !flag_absolute_names)
	{
	  char *tmpbuf = tar_xmalloc (strlen (current_file_name) + 2);

	  *tmpbuf = '/';
	  strcpy (tmpbuf + 1, current_file_name);
	  diff_fd = open (tmpbuf, O_NDELAY | O_RDONLY);
	  free (tmpbuf);
	}
      if (diff_fd < 0)
	{
	  ERROR ((0, errno, _("Cannot open %s"), current_file_name));
	  if (head->header.isextended)
	    skip_extended_headers ();
	  skip_file ((long) hstat.st_size);
	  different++;
	  goto quit;
	}

      /* Need to treat sparse files completely differently here.  */

      if (head->header.linkflag == LF_SPARSE)
	diff_sparse_files (hstat.st_size);
      else
	{
	  if (flag_multivol)
	    {
	      assign_string (&save_name, current_file_name);
	      save_totsize = hstat.st_size;
	      /* save_size is set in wantbytes ().  */
	    }
	  wantbytes ((long) (hstat.st_size), compare_chunk);
	  if (flag_multivol)
	    assign_string (&save_name, NULL);
	}

      check = close (diff_fd);
      if (check < 0)
	ERROR ((0, errno, _("Error while closing %s"), current_file_name));

    quit:
      break;

#ifndef __MSDOS__
    case LF_LINK:
      if (do_stat (&filestat))
	break;
      dev = filestat.st_dev;
      ino = filestat.st_ino;
      err = stat (current_link_name, &filestat);
      if (err < 0)
	{
	  if (errno == ENOENT)
	    fprintf (stdlis, _("%s: Does not exist\n"), current_file_name);
	  else
	    WARN ((0, errno, _("Cannot stat file %s"), current_file_name));
	  different++;
	  break;
	}
      if (filestat.st_dev != dev || filestat.st_ino != ino)
	{
	  fprintf (stdlis, _("%s: Not linked to %s\n"),
		   current_file_name, current_link_name);
	  break;
	}
      break;
#endif

#ifdef S_ISLNK
    case LF_SYMLINK:
      {
	char linkbuf[NAMSIZ + 3]; /* FIXME: may be too short.  */

	check = readlink (current_file_name, linkbuf, (sizeof linkbuf) - 1);

	if (check < 0)
	  {
	    if (errno == ENOENT)
	      fprintf (stdlis, _("%s: No such file or directory\n"),
		       current_file_name);
	    else
	      WARN ((0, errno, _("Cannot read link %s"), current_file_name));
	    different++;
	    break;
	  }

	linkbuf[check] = '\0';	/* null-terminate it */
	if (strncmp (current_link_name, linkbuf, (size_t) check) != 0)
	  {
	    fprintf (stdlis, _("%s: Symlink differs\n"), current_link_name);
	    different++;
	  }
      }
      break;
#endif

#ifdef S_IFCHR
    case LF_CHR:
      hstat.st_mode |= S_IFCHR;
      goto check_node;
#endif

#ifdef S_IFBLK
      /* If local system doesn't support block devices, use default case.  */

    case LF_BLK:
      hstat.st_mode |= S_IFBLK;
      goto check_node;
#endif

#ifdef S_ISFIFO
      /* If local system doesn't support FIFOs, use default case.  */

    case LF_FIFO:
#ifdef S_IFIFO
      hstat.st_mode |= S_IFIFO;
#endif
      hstat.st_rdev = 0;	/* FIXME, do we need this? */
      goto check_node;
#endif

    check_node:
      /* FIXME, deal with umask.  */

      if (do_stat (&filestat))
	break;
      if (hstat.st_rdev != filestat.st_rdev)
	{
	  fprintf (stdlis, _("%s: Device numbers changed\n"),
		   current_file_name);
	  different++;
	  break;
	}
      if (
#ifdef S_IFMT
	  hstat.st_mode != filestat.st_mode
#else
	  /* POSIX lossage */
	  (hstat.st_mode & 07777) != (filestat.st_mode & 07777)
#endif
	  )
	{
	  fprintf (stdlis, _("%s: Mode or device-type changed\n"),
		   current_file_name);
	  different++;
	  break;
	}
      break;

    case LF_DUMPDIR:
      data = diff_dir = get_dir_contents (current_file_name, 0);
      if (flag_multivol)
	{
	  assign_string (&save_name, current_file_name);
	  save_totsize = hstat.st_size;
	  /* save_size is set in wantbytes ().  */
	}
      if (data)
	{
	  wantbytes ((long) (hstat.st_size), compare_dir);
	  free (data);
	}
      else
	wantbytes ((long) (hstat.st_size), no_op);
      if (flag_multivol)
	assign_string (&save_name, NULL);
      /* Fall through.  */

    case LF_DIR:
      /* Check for trailing /.  */

      namelen = strlen (current_file_name) - 1;

    really_dir:
      while (namelen && current_file_name[namelen] == '/')
	current_file_name[namelen--] = '\0';	/* zap / */

      if (do_stat (&filestat))
	break;
      if (!S_ISDIR (filestat.st_mode))
	{
	  fprintf (stdlis, _("%s: No longer a directory\n"),
		   current_file_name);
	  different++;
	  break;
	}
      if ((filestat.st_mode & 07777) != (hstat.st_mode & 07777))
	sigh (_("Mode"));
      break;

    case LF_VOLHDR:
      break;

    case LF_MULTIVOL:
      namelen = strlen (current_file_name) - 1;
      if (current_file_name[namelen] == '/')
	goto really_dir;

      if (do_stat (&filestat))
	break;

      if (!S_ISREG (filestat.st_mode))
	{
	  fprintf (stdlis, _("%s: Not a regular file\n"), current_file_name);
	  skip_file ((long) hstat.st_size);
	  different++;
	  break;
	}

      filestat.st_mode &= 07777;
      offset = from_oct (1 + 12, head->header.offset);
      if (filestat.st_size != hstat.st_size + offset)
	{
	  sigh (_("Size"));
	  skip_file ((long) hstat.st_size);
	  different++;
	  break;
	}

      diff_fd = open (current_file_name, O_NDELAY | O_RDONLY | O_BINARY);

      if (diff_fd < 0)
	{
	  WARN ((0, errno, _("Cannot open file %s"), current_file_name));
	  skip_file ((long) hstat.st_size);
	  different++;
	  break;
	}
      err = lseek (diff_fd, offset, 0);
      if (err != offset)
	{
	  WARN ((0, errno, _("Cannot seek to %ld in file %s"),
		     offset, current_file_name));
	  different++;
	  break;
	}

      if (flag_multivol)
	{
	  assign_string (&save_name, current_file_name);
	  save_totsize = filestat.st_size;
	  /* save_size is set in wantbytes ().  */
	}
      wantbytes ((long) (hstat.st_size), compare_chunk);
      if (flag_multivol)
	assign_string (&save_name, NULL);

      check = close (diff_fd);
      if (check < 0)
	ERROR ((0, errno, _("Error while closing %s"), current_file_name));
      break;

    }

  /* We don't need to save it any longer. */

  saverec ((union record **) 0);	/* unsave it */
}
Example #4
0
static void
fill_in_sparse_array (void)
{
  int ind;

  /* Allocate space for our scratch space; it's initially 10 elements
     long, but can change in this routine if necessary.  */

  sp_array_size = 10;
  sparsearray = (struct sp_array *) tar_xmalloc (sp_array_size * sizeof (struct sp_array));

  /* There are at most five of these structures in the header itself;
     read these in first.  */

  for (ind = 0; ind < SPARSE_IN_HDR; ind++)
    {
      /* Compare to 0, or use !(int)..., for Pyramid's dumb compiler.  */
      if (head->header.sp[ind].numbytes == 0)
	break;
      sparsearray[ind].offset =
	from_oct (1 + 12, head->header.sp[ind].offset);
      sparsearray[ind].numbytes =
	from_oct (1 + 12, head->header.sp[ind].numbytes);
    }

  /* If the header's extended, we gotta read in exhdr's till we're done.  */

  if (head->header.isextended)
    {

      /* How far into the sparsearray we are `so far'.  */
      static int so_far_ind = SPARSE_IN_HDR;
      union record *exhdr;

      while (1)
	{
	  exhdr = findrec ();
	  for (ind = 0; ind < SPARSE_EXT_HDR; ind++)
	    {
	      if (ind + so_far_ind > sp_array_size - 1)
		{

		  /* We just ran out of room in our scratch area -
		     realloc it.  */

		  sp_array_size *= 2;
		  sparsearray = (struct sp_array *)
		    tar_realloc (sparsearray,
			      sp_array_size * sizeof (struct sp_array));
		}

	      /* Convert the character strings into longs.  */

	      sparsearray[ind + so_far_ind].offset =
		from_oct (1 + 12, exhdr->ext_hdr.sp[ind].offset);
	      sparsearray[ind + so_far_ind].numbytes =
		from_oct (1 + 12, exhdr->ext_hdr.sp[ind].numbytes);
	    }

	  /* If this is the last extended header for this file, we can
	     stop.  */

	  if (!exhdr->ext_hdr.isextended)
	    break;
	  else
	    {
	      so_far_ind += SPARSE_EXT_HDR;
	      userec (exhdr);
	    }
	}

      /* Be sure to skip past the last one.  */

      userec (exhdr);
    }
}
Example #5
0
static void
diff_sparse_files (int filesize)
{
  int sparse_ind = 0;
  char *buf;
  int buf_size = RECORDSIZE;
  union record *datarec;
  int err;
  long numbytes;
#if 0
  int amt_read = 0;
#endif
  int size = filesize;

  /* FIXME: `datarec' might be used uninitialized in this function.
     Reported by Bruno Haible.  */

  buf = (char *) tar_xmalloc (buf_size * sizeof (char));

  fill_in_sparse_array ();


  while (size > 0)
    {
      datarec = findrec ();
      if (!sparsearray[sparse_ind].numbytes)
	break;

      /* `numbytes' is nicer to write than
	 `sparsearray[sparse_ind].numbytes' all the time...  */

      numbytes = sparsearray[sparse_ind].numbytes;

      lseek (diff_fd, sparsearray[sparse_ind].offset, 0);

      /* Take care to not run out of room in our buffer.  */

      while (buf_size < numbytes)
	{
	  buf_size *= 2;
	  buf = (char *) tar_realloc (buf, buf_size * sizeof (char));
	}
      while (numbytes > RECORDSIZE)
	{
	  if (err = read (diff_fd, buf, RECORDSIZE), err != RECORDSIZE)
	    {
	      if (err < 0)
		WARN ((0, errno, _("Cannot read %s"), current_file_name));
	      else
		fprintf (stdlis, _("%s: Could only read %d of %ld bytes\n"),
			 current_file_name, err, numbytes);
	      break;
	    }
	  if (memcmp (buf, datarec->charptr, RECORDSIZE))
	    {
	      different++;
	      break;
	    }
	  numbytes -= err;
	  size -= err;
	  userec (datarec);
	  datarec = findrec ();
	}
      if (err = read (diff_fd, buf, (size_t) numbytes), err != numbytes)
	{
	  if (err < 0)
	    WARN ((0, errno, _("Cannot read %s"), current_file_name));
	  else
	    fprintf (stdlis, _("%s: Could only read %d of %ld bytes\n"),
		     current_file_name, err, numbytes);
	  break;
	}

      if (memcmp (buf, datarec->charptr, (size_t) numbytes))
	{
	  different++;
	  break;
	}
#if 0
      amt_read += numbytes;
      if (amt_read >= RECORDSIZE)
	{
	  amt_read = 0;
	  userec (datarec);
	  datarec = findrec ();
	}
#endif
      userec (datarec);
      sparse_ind++;
      size -= numbytes;
    }

  /* If the number of bytes read isn't the number of bytes supposedly in
     the file, they're different.  */

#if 0
  if (amt_read != filesize)
    different++;
#endif

  userec (datarec);
  free (sparsearray);
  if (different)
    {
      fprintf (stdlis, _("%s: Data differs\n"), current_file_name);
      if (exit_status == TAREXIT_SUCCESS)
	exit_status = TAREXIT_DIFFERS;
    }
}
Example #6
0
File: gnu.c Project: VanL/zrt
static void
__tar_read_dir_file (void)
{
  dev_t dev;
  ino_t ino;
  char *strp;
  FILE *fp;
  char buf[512];
  static char *path = 0;

  if (path == 0)
    path = tar_xmalloc (PATH_MAX);
  time (&this_time);
  if (gnu_dumpfile[0] != '/')
    {
#ifdef HAVE_GETCWD
      if (!getcwd (path, PATH_MAX))
	ERROR ((TAREXIT_FAILURE, 0, _("Could not get current directory")));
#else
      char *getwd ();

      if (!getwd (path))
	ERROR ((TAREXIT_FAILURE, 0, _("Could not get current directory: %s"),
		path));
#endif

      /* If this doesn't fit, we're in serious trouble.  */

      strcat (path, "/");
      strcat (path, gnu_dumpfile);
      gnu_dumpfile = path;
    }
  fp = fopen (gnu_dumpfile, "r");
  if (fp == 0 && errno != ENOENT)
    {
      ERROR ((0, errno, _("Cannot open %s"), gnu_dumpfile));
      return;
    }
  if (!fp)
    return;
  fgets (buf, sizeof (buf), fp);
  if (!flag_new_files)
    {
      flag_new_files++;
      new_time = atol (buf);
    }
  while (fgets (buf, sizeof (buf), fp))
    {
      strp = &buf[strlen (buf)];
      if (strp[-1] == '\n')
	strp[-1] = '\0';
      strp = buf;
      dev = atol (strp);
      while (ISDIGIT (*strp))
	strp++;
      ino = atol (strp);
      while (ISSPACE (*strp))
	strp++;
      while (ISDIGIT (*strp))
	strp++;
      strp++;
      __tar_add_dir (__tar_un_quote_string (strp), dev, ino, (char *) 0);
    }
  fclose (fp);
}
Example #7
0
File: gnu.c Project: VanL/zrt
static void
__tar_add_dir_name (char *p, int device)
{
  char *new_buf;
  char *p_buf;

  char *namebuf;
  int buflen;
  register int len;
  int sublen;

#if 0
  voidstar the_buffer;

  char *buf;
  char **vec,**p_vec;
  int n_strs,n_size;
#endif

  struct name *n;

  new_buf = __tar_get_dir_contents (p, device);

  for (n = namelist; n; n = n->next)
    {
      if (!strcmp (n->name, p))
	{
	  n->dir_contents = new_buf ? new_buf : "\0\0\0\0";
	  break;
	}
    }

  if (new_buf)
    {
      len = strlen (p);
      buflen = NAMSIZ <= len ? len + NAMSIZ : NAMSIZ;
      namebuf = tar_xmalloc ((size_t) (buflen + 1));

      strcpy (namebuf, p);
      if (namebuf[len - 1] != '/')
	{
	  namebuf[len++] = '/';
	  namebuf[len] = '\0';
	}
      for (p_buf = new_buf; p_buf && *p_buf; p_buf += sublen + 1)
	{
	  sublen = strlen (p_buf);
	  if (*p_buf == 'D')
	    {
	      if (len + sublen >= buflen)
		{
		  buflen += NAMSIZ;
		  namebuf = (char *) tar_realloc (namebuf, (size_t) (buflen + 1));
		}
	      strcpy (namebuf + len, p_buf + 1);
	      __tar_addname (namebuf);
	      __tar_add_dir_name (namebuf, device);
	    }
	}
      free (namebuf);
    }
}
Example #8
0
File: gnu.c Project: VanL/zrt
char *
__tar_get_dir_contents (char *p, int device)
{
  DIR *dirp;
  register struct dirent *d;
  char *new_buf;
  char *namebuf;
  int bufsiz;
  int len;
  voidstar the_buffer;
  char *buf;
  size_t n_strs;
#if 0
  int n_size;
#endif
  char *p_buf;
  char **vec, **p_vec;

  errno = 0;
  dirp = opendir (p);
  bufsiz = strlen (p) + NAMSIZ;
  namebuf = tar_xmalloc ((size_t) (bufsiz + 2));
  if (!dirp)
    {
      ERROR ((0, errno, _("Cannot open directory %s"), p));
      new_buf = NULL;
    }
  else
    {
      struct dirname *dp;
      int all_children;

      dp = __tar_get_dir (p);
      all_children = dp ? dp->allnew : 0;
      strcpy (namebuf, p);
      if (p[strlen (p) - 1] != '/')
	strcat (namebuf, "/");
      len = strlen (namebuf);

      the_buffer = __tar_init_buffer ();
      while (d = readdir (dirp), d)
	{
	  struct stat hs;

	  /* Skip `.' and `..'.  */

	  if (__tar_is_dot_or_dotdot (d->d_name))
	    continue;
	  if ((int) NAMLEN (d) + len >= bufsiz)
	    {
	      bufsiz += NAMSIZ;
	      namebuf = (char *) tar_realloc (namebuf, (size_t) (bufsiz + 2));
	    }
	  strcpy (namebuf + len, d->d_name);
#ifdef AIX
	  if (flag_follow_links ? statx (namebuf, &hs, STATSIZE, STX_HIDDEN)
	      : statx (namebuf, &hs, STATSIZE, STX_HIDDEN | STX_LINK))
#else
	  if (flag_follow_links ? stat (namebuf, &hs) : lstat (namebuf, &hs))
#endif
	    {
	      ERROR ((0, errno, _("Cannot stat %s"), namebuf));
	      continue;
	    }
	  if ((flag_local_filesys && device != hs.st_dev)
	      || (flag_exclude && __tar_check_exclude (namebuf)))
	    __tar_add_buffer (the_buffer, "N", 1);
#ifdef AIX
	  else if (S_ISHIDDEN (hs.st_mode))
	    {
	      __tar_add_buffer (the_buffer, "D", 1);
	      strcat (d->d_name, "A");
	      d->d_namlen++;
	    }
#endif /* AIX */
	  else if (S_ISDIR (hs.st_mode))
	    {
	      if (dp = __tar_get_dir (namebuf), dp)
		{
		  if (dp->dev != hs.st_dev
		      || dp->ino != hs.st_ino)
		    {
		      if (flag_verbose)
			WARN ((0, 0, _("Directory %s has been renamed"),
			       namebuf));
		      dp->allnew = 1;
		      dp->dev = hs.st_dev;
		      dp->ino = hs.st_ino;
		    }
		  dp->dir_text = "";
		}
	      else
		{
		  if (flag_verbose)
		    WARN ((0, 0, _("Directory %s is new"), namebuf));
		  __tar_add_dir (namebuf, hs.st_dev, hs.st_ino, "");
		  dp = __tar_get_dir (namebuf);
		  dp->allnew = 1;
		}
	      if (all_children && dp)
		dp->allnew = 1;

	      __tar_add_buffer (the_buffer, "D", 1);
	    }
	  else if (!all_children
		   && flag_new_files
		   && new_time > hs.st_mtime
		   && (flag_new_files > 1
		       || new_time > hs.st_ctime))
	    __tar_add_buffer (the_buffer, "N", 1);
	  else
	    __tar_add_buffer (the_buffer, "Y", 1);
	  __tar_add_buffer (the_buffer, d->d_name, (int) (NAMLEN (d) + 1));
	}
      __tar_add_buffer (the_buffer, "\000\000", 2);
      closedir (dirp);

      /* Well, we've read in the contents of the dir, now sort them.  */

      buf = __tar_get_buffer (the_buffer);
      if (buf[0] == '\0')
	{
	  __tar_flush_buffer (the_buffer);
	  new_buf = NULL;
	}
      else
	{
	  n_strs = 0;
	  for (p_buf = buf; *p_buf;)
	    {
	      int tmp;

	      tmp = strlen (p_buf) + 1;
	      n_strs++;
	      p_buf += tmp;
	    }
	  vec = (char **) tar_xmalloc (sizeof (char *) * (n_strs + 1));
	  for (p_vec = vec, p_buf = buf; *p_buf; p_buf += strlen (p_buf) + 1)
	    *p_vec++ = p_buf;
	  *p_vec = 0;
	  qsort ((voidstar) vec, n_strs, sizeof (char *), __tar_dirent_cmp);
	  new_buf = (char *) tar_xmalloc ((size_t) (p_buf - buf + 2));
	  for (p_vec = vec, p_buf = new_buf; *p_vec; p_vec++)
	    {
	      char *p_tmp;

	      for (p_tmp = *p_vec; (*p_buf++ = *p_tmp++); )
		;
	    }
	  *p_buf++ = '\0';
	  free (vec);
	  __tar_flush_buffer (the_buffer);
	}
    }
  free (namebuf);
  return new_buf;
}