Exemple #1
0
char *
get_directory_contents (char *path, dev_t device)
{
  struct accumulator *accumulator;

  /* Recursively scan the given PATH.  */

  {
    DIR *dirp = opendir (path);	/* for scanning directory */
    struct dirent *entry;	/* directory entry being scanned */
    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 directory *directory; /* for checking if already already seen */
    bool all_children;

    if (dirp == NULL)
      {
	ERROR ((0, errno, _("Cannot open directory %s"), path));
	return NULL;
      }
    errno = 0;			/* FIXME: errno should be read-only */

    name_buffer_size = strlen (path) + NAME_FIELD_SIZE;
    name_buffer = xmalloc (name_buffer_size + 2);
    strcpy (name_buffer, path);
    if (path[strlen (path) - 1] != '/')
      strcat (name_buffer, "/");
    name_length = strlen (name_buffer);

    directory = find_directory (path);
    all_children = directory ? directory->all_new : false;

    accumulator = new_accumulator ();

    while (entry = readdir (dirp), entry)
      {
	struct stat stat_info;

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

	if (is_dot_or_dotdot (entry->d_name))
	  continue;

	if (NAMLEN (entry) + name_length >= name_buffer_size)
	  {
	    while (NAMLEN (entry) + name_length >= name_buffer_size)
	      name_buffer_size += NAME_FIELD_SIZE;
	    name_buffer = (char *)
	      xrealloc (name_buffer, name_buffer_size + 2);
	  }
	strcpy (name_buffer + name_length, entry->d_name);

	if (dereference_option
#ifdef AIX
	    ? statx (name_buffer, &stat_info, STATSIZE, STX_HIDDEN)
	    : statx (name_buffer, &stat_info, STATSIZE, STX_HIDDEN | STX_LINK)
#else
	    ? stat (name_buffer, &stat_info)
	    : lstat (name_buffer, &stat_info)
#endif
	    )
	  {
	    ERROR ((0, errno, _("Cannot stat %s"), name_buffer));
	    continue;
	  }

	if ((one_file_system_option && device != stat_info.st_dev)
	    || (exclude_option && check_exclude (name_buffer)))
	  add_to_accumulator (accumulator, "N", (size_t) 1);

#ifdef AIX
	else if (S_ISHIDDEN (stat_info.st_mode))
	  {
	    add_to_accumulator (accumulator, "D", (size_t) 1);
	    strcat (entry->d_name, "A");
	    entry->d_namlen++;
	  }
#endif

	else if (S_ISDIR (stat_info.st_mode))
	  {
	    if (directory = find_directory (name_buffer), directory)
	      {
		/* The same file can have two different devices if an NFS
		   directory is mounted in multiple locations, which is
		   relatively common when automounting.  For avoiding
		   spurious incremental redumping of directories, we have to
		   plainly consider all NFS devices as equal, relying on the
		   i-node only to establish differences.

		   Devices having the high bit set usually are NFS devices.  */

		/* FIXME: Göran Uddeborg <*****@*****.**> says, on
		   1996-09-20, that SunOS 5/Solaris 2 uses unsigned long for
		   the device number type.  */

		if ((((short) directory->device_number >= 0
		      || (short) stat_info.st_dev >= 0)
		     && directory->device_number != stat_info.st_dev)
		    || directory->inode_number != stat_info.st_ino)
		  {
		    if (verbose_option)
		      WARN ((0, 0, _("Directory %s has been renamed"),
			     name_buffer));
		    directory->all_new = true;
		    directory->device_number = stat_info.st_dev;
		    directory->inode_number = stat_info.st_ino;
		  }
		directory->dir_text = "";
	      }
	    else
	      {
		if (verbose_option)
		  WARN ((0, 0, _("Directory %s is new"), name_buffer));
		note_directory (name_buffer,
				stat_info.st_dev, stat_info.st_ino, "");
		directory = find_directory (name_buffer);
		directory->all_new = true;
	      }
	    if (all_children && directory)
	      directory->all_new = true;

	    add_to_accumulator (accumulator, "D", (size_t) 1);
	  }

	else
	  if (all_children || FILE_IS_NEW_ENOUGH (&stat_info))
	    add_to_accumulator (accumulator, "Y", (size_t) 1);
	  else
	    add_to_accumulator (accumulator, "N", (size_t) 1);

	add_to_accumulator (accumulator, entry->d_name, NAMLEN (entry) + 1);
      }
    add_to_accumulator (accumulator, "\000\000", (size_t) 2);

    free (name_buffer);
    closedir (dirp);
  }

  /* Sort the contents of the directory, now that we have it all.  */

  {
    char *pointer = get_accumulator (accumulator);
    size_t counter;
    char *cursor;
    char *buffer;
    char **array;
    char **array_cursor;

    counter = 0;
    for (cursor = pointer; *cursor; cursor += strlen (cursor) + 1)
      counter++;

    if (counter == 0)
      {
	delete_accumulator (accumulator);
	return NULL;
      }

    array = (char **) xmalloc (sizeof (char *) * (counter + 1));

    array_cursor = array;
    for (cursor = pointer; *cursor; cursor += strlen (cursor) + 1)
      *array_cursor++ = cursor;
    *array_cursor = NULL;

    qsort ((voidstar) array, counter, sizeof (char *), compare_dirents);

    buffer = (char *) xmalloc ((size_t) (cursor - pointer + 2));

    cursor = buffer;
    for (array_cursor = array; *array_cursor; array_cursor++)
      {
	char *string = *array_cursor;

	while ((*cursor++ = *string++))
	  continue;
      }
    *cursor = '\0';

    delete_accumulator (accumulator);
    free (array);
    return buffer;
  }
}
Exemple #2
0
Fichier : gnu.c Projet : 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;
}