Переглянути джерело

Removed accumulator stuff in favor of obstack.
get_directory_contents): Split into two functions

Sergey Poznyakoff 21 роки тому
батько
коміт
df7792b5d8
1 змінених файлів з 177 додано та 226 видалено
  1. 177 226
      src/incremen.c

+ 177 - 226
src/incremen.c

@@ -22,62 +22,10 @@
 #include <hash.h>
 #include <quotearg.h>
 #include "common.h"
-
-/* Variable sized generic character buffers.  */
-
-struct accumulator
-{
-  size_t allocated;
-  size_t length;
-  char *pointer;
-};
-
-/* Amount of space guaranteed just after a reallocation.  */
-#define ACCUMULATOR_SLACK 50
-
-/* Return the accumulated data from an ACCUMULATOR buffer.  */
-static char *
-get_accumulator (struct accumulator *accumulator)
-{
-  return accumulator->pointer;
-}
-
-/* Allocate and return a new accumulator buffer.  */
-static struct accumulator *
-new_accumulator (void)
-{
-  struct accumulator *accumulator
-    = xmalloc (sizeof (struct accumulator));
+#define obstack_chunk_alloc xmalloc
+#define obstack_chunk_free free
+#include <obstack.h>
 
-  accumulator->allocated = ACCUMULATOR_SLACK;
-  accumulator->pointer = xmalloc (ACCUMULATOR_SLACK);
-  accumulator->length = 0;
-  return accumulator;
-}
-
-/* Deallocate an ACCUMULATOR buffer.  */
-static void
-delete_accumulator (struct accumulator *accumulator)
-{
-  free (accumulator->pointer);
-  free (accumulator);
-}
-
-/* At the end of an ACCUMULATOR buffer, add a DATA block of SIZE bytes.  */
-static void
-add_to_accumulator (struct accumulator *accumulator,
-		    const char *data, size_t size)
-{
-  if (accumulator->length + size > accumulator->allocated)
-    {
-      accumulator->allocated = accumulator->length + size + ACCUMULATOR_SLACK;
-      accumulator->pointer =
-	xrealloc (accumulator->pointer, accumulator->allocated);
-    }
-  memcpy (accumulator->pointer + accumulator->length, data, size);
-  accumulator->length += size;
-}
-
 /* Incremental dump specialities.  */
 
 /* Which child files to save under a directory.  */
@@ -169,83 +117,77 @@ compare_dirents (const void *first, const void *second)
 		 (*(char *const *) second) + 1);
 }
 
-char *
-get_directory_contents (char *path, dev_t device)
+/* Recursively scan the given PATH.  */
+static void
+scan_path (struct obstack *stk, char *path, dev_t device)
 {
-  struct accumulator *accumulator;
-
-  /* Recursively scan the given PATH.  */
-
-  {
-    char *dirp = savedir (path);	/* for scanning directory */
-    char const *entry;	/* directory entry being scanned */
-    size_t entrylen;	/* length of directory entry */
-    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 */
-    enum children children;
-
-    if (! dirp)
+  char *dirp = savedir (path);	/* for scanning directory */
+  char const *entry;	/* directory entry being scanned */
+  size_t entrylen;	/* length of directory entry */
+  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 */
+  enum children children;
+
+  if (! dirp)
+    {
+      savedir_error (path);
+    }
+  errno = 0;
+
+  name_buffer_size = strlen (path) + NAME_FIELD_SIZE;
+  name_buffer = xmalloc (name_buffer_size + 2);
+  strcpy (name_buffer, path);
+  if (! ISSLASH (path[strlen (path) - 1]))
+    strcat (name_buffer, "/");
+  name_length = strlen (name_buffer);
+
+  directory = find_directory (path);
+  children = directory ? directory->children : CHANGED_CHILDREN;
+  
+  if (dirp && children != NO_CHILDREN)
+    for (entry = dirp;
+	 (entrylen = strlen (entry)) != 0;
+	 entry += entrylen + 1)
       {
-        savedir_error (path);
-      }
-    errno = 0;
-
-    name_buffer_size = strlen (path) + NAME_FIELD_SIZE;
-    name_buffer = xmalloc (name_buffer_size + 2);
-    strcpy (name_buffer, path);
-    if (! ISSLASH (path[strlen (path) - 1]))
-      strcat (name_buffer, "/");
-    name_length = strlen (name_buffer);
-
-    directory = find_directory (path);
-    children = directory ? directory->children : CHANGED_CHILDREN;
-
-    accumulator = new_accumulator ();
-
-    if (dirp && children != NO_CHILDREN)
-      for (entry = dirp;
-	   (entrylen = strlen (entry)) != 0;
-	   entry += entrylen + 1)
-	{
-	  if (name_buffer_size <= entrylen + name_length)
-	    {
-	      do
-		name_buffer_size += NAME_FIELD_SIZE;
-	      while (name_buffer_size <= entrylen + name_length);
-	      name_buffer = xrealloc (name_buffer, name_buffer_size + 2);
-	    }
-	  strcpy (name_buffer + name_length, entry);
-
-	  if (excluded_name (name_buffer))
-	    add_to_accumulator (accumulator, "N", 1);
-	  else
-	    {
-	      struct stat stat_data;
-
-	      if (deref_stat (dereference_option, name_buffer, &stat_data))
-		{
-		  stat_diag (name_buffer);
-		  continue;
-		}
-
-	      if (S_ISDIR (stat_data.st_mode))
-		{
-		  bool nfs = NFS_FILE_STAT (stat_data);
-
-		  if (directory = find_directory (name_buffer), directory)
-		    {
-		      /* With NFS, the same file can have two different devices
-			 if an NFS directory is mounted in multiple locations,
-			 which is relatively common when automounting.
-			 To avoid spurious incremental redumping of
-			 directories, consider all NFS devices as equal,
-			 relying on the i-node to establish differences.  */
-
-		      if (! (((directory->nfs & nfs)
-			      || directory->device_number == stat_data.st_dev)
-			     && directory->inode_number == stat_data.st_ino))
+	if (name_buffer_size <= entrylen + name_length)
+	  {
+	    do
+	      name_buffer_size += NAME_FIELD_SIZE;
+	    while (name_buffer_size <= entrylen + name_length);
+	    name_buffer = xrealloc (name_buffer, name_buffer_size + 2);
+	  }
+	strcpy (name_buffer + name_length, entry);
+	
+	if (excluded_name (name_buffer))
+	  obstack_1grow (stk, 'N');
+	else
+	  {
+	    struct stat stat_data;
+	    
+	    if (deref_stat (dereference_option, name_buffer, &stat_data))
+	      {
+		stat_diag (name_buffer);
+		continue;
+	      }
+	    
+	    if (S_ISDIR (stat_data.st_mode))
+	      {
+		bool nfs = NFS_FILE_STAT (stat_data);
+		
+		if (directory = find_directory (name_buffer), directory)
+		  {
+		    /* With NFS, the same file can have two different devices
+		       if an NFS directory is mounted in multiple locations,
+		       which is relatively common when automounting.
+		       To avoid spurious incremental redumping of
+		       directories, consider all NFS devices as equal,
+		       relying on the i-node to establish differences.  */
+		    
+		    if (! (((directory->nfs & nfs)
+			    || directory->device_number == stat_data.st_dev)
+			   && directory->inode_number == stat_data.st_ino))
 			{
 			  if (verbose_option)
 			    WARN ((0, 0, _("%s: Directory has been renamed"),
@@ -255,113 +197,122 @@ get_directory_contents (char *path, dev_t device)
 			  directory->device_number = stat_data.st_dev;
 			  directory->inode_number = stat_data.st_ino;
 			}
-		      directory->found = 1;
-		    }
-		  else
-		    {
-		      if (verbose_option)
-			WARN ((0, 0, _("%s: Directory is new"),
-			       quotearg_colon (name_buffer)));
-		      directory = note_directory (name_buffer,
-						  stat_data.st_dev,
-						  stat_data.st_ino, nfs, 1);
-		      directory->children =
-			((listed_incremental_option
-			  || newer_mtime_option <= stat_data.st_mtime
-			  || (after_date_option &&
-			      newer_ctime_option <= stat_data.st_ctime))
-			 ? ALL_CHILDREN
-			 : CHANGED_CHILDREN);
-		    }
-
-		  if (one_file_system_option && device != stat_data.st_dev)
-		    directory->children = NO_CHILDREN;
-		  else if (children == ALL_CHILDREN)
-		    directory->children = ALL_CHILDREN;
-
-		  add_to_accumulator (accumulator, "D", 1);
-		}
-
-	      else if (one_file_system_option && device != stat_data.st_dev)
-		add_to_accumulator (accumulator, "N", 1);
+		    directory->found = 1;
+		  }
+		else
+		  {
+		    if (verbose_option)
+		      WARN ((0, 0, _("%s: Directory is new"),
+			     quotearg_colon (name_buffer)));
+		    directory = note_directory (name_buffer,
+						stat_data.st_dev,
+						stat_data.st_ino, nfs, 1);
+		    directory->children =
+		      ((listed_incremental_option
+			|| newer_mtime_option <= stat_data.st_mtime
+			|| (after_date_option &&
+			    newer_ctime_option <= stat_data.st_ctime))
+		       ? ALL_CHILDREN
+		       : CHANGED_CHILDREN);
+		  }
+		
+		if (one_file_system_option && device != stat_data.st_dev)
+		  directory->children = NO_CHILDREN;
+		else if (children == ALL_CHILDREN)
+		  directory->children = ALL_CHILDREN;
+
+		obstack_1grow (stk, 'D');
+	      }
+
+	    else if (one_file_system_option && device != stat_data.st_dev)
+	      obstack_1grow (stk, 'N');
 
 #ifdef S_ISHIDDEN
-	      else if (S_ISHIDDEN (stat_data.st_mode))
-		{
-		  add_to_accumulator (accumulator, "D", 1);
-		  add_to_accumulator (accumulator, entry, entrylen);
-		  add_to_accumulator (accumulator, "A", 2);
-		  continue;
-		}
+	    else if (S_ISHIDDEN (stat_data.st_mode))
+	      {
+		obstack_1grow (stk, 'D');
+		obstack_grow (stk, entry, entrylen);
+		obstack_grow (stk, "A", 2);
+		continue;
+	      }
 #endif
 
+	    else
+	      if (children == CHANGED_CHILDREN
+		  && stat_data.st_mtime < newer_mtime_option
+		  && (!after_date_option
+		      || stat_data.st_ctime < newer_ctime_option))
+		obstack_1grow (stk, 'N');
 	      else
-		if (children == CHANGED_CHILDREN
-		    && stat_data.st_mtime < newer_mtime_option
-		    && (!after_date_option
-			|| stat_data.st_ctime < newer_ctime_option))
-		  add_to_accumulator (accumulator, "N", 1);
-		else
-		  add_to_accumulator (accumulator, "Y", 1);
-	    }
-
-	  add_to_accumulator (accumulator, entry, entrylen + 1);
-	}
-
-    add_to_accumulator (accumulator, "\000\000", 2);
-
-    free (name_buffer);
-    if (dirp)
-      free (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)
-      {
-	delete_accumulator (accumulator);
-	return 0;
+		obstack_1grow (stk, 'Y');
+	  }
+	
+	obstack_grow (stk, entry, entrylen + 1);
       }
 
-    array = xmalloc (sizeof (char *) * (counter + 1));
-
-    array_cursor = array;
-    for (cursor = pointer; *cursor; cursor += strlen (cursor) + 1)
-      *array_cursor++ = cursor;
-    *array_cursor = 0;
-
-    qsort (array, counter, sizeof (char *), compare_dirents);
-
-    buffer = xmalloc (cursor - pointer + 2);
-
-    cursor = buffer;
-    for (array_cursor = array; *array_cursor; array_cursor++)
-      {
-	char *string = *array_cursor;
+  obstack_grow (stk, "\000\000", 2);
+  
+  free (name_buffer);
+  if (dirp)
+    free (dirp);
+}
 
-	while ((*cursor++ = *string++))
-	  continue;
-      }
-    *cursor = '\0';
+/* Sort the contents of the obstack, anr convert it to the char * */
+static char *
+sort_obstack (struct obstack *stk)
+{
+  char *pointer = obstack_finish (stk);
+  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)
+    return NULL;
+
+  array = obstack_alloc (stk, sizeof (char *) * (counter + 1));
+  
+  array_cursor = array;
+  for (cursor = pointer; *cursor; cursor += strlen (cursor) + 1)
+    *array_cursor++ = cursor;
+  *array_cursor = 0;
+
+  qsort (array, counter, sizeof (char *), compare_dirents);
+
+  buffer = xmalloc (cursor - pointer + 2);
+
+  cursor = buffer;
+  for (array_cursor = array; *array_cursor; array_cursor++)
+    {
+      char *string = *array_cursor;
+      
+      while ((*cursor++ = *string++))
+	continue;
+    }
+  *cursor = '\0';
+  return buffer;
+}
 
-    delete_accumulator (accumulator);
-    free (array);
-    return buffer;
-  }
+char *
+get_directory_contents (char *path, dev_t device)
+{
+  struct obstack stk;
+  char *buffer;
+
+  obstack_init (&stk);
+  scan_path (&stk, path, device);
+  buffer = sort_obstack (&stk);
+  obstack_free (&stk, NULL);
+  return buffer;;
 }
+
 
+
 static FILE *listed_incremental_stream;
 
 void