Login | Register
My pages Projects Community openCollabNet

Discussions > commits > svn commit: r23 - in trunk: . fsvs/src

fsvs
Discussion topic

Hide all messages in topic

All messages in topic

svn commit: r23 - in trunk: . fsvs/src

Author pmarek
Full name P.Marek
Date 2005-10-07 01:24:17 PDT
Message Author: pmarek
Date: Fri Oct 7 01:24:17 2005
New Revision: 23

Modified:
   trunk/ (props changed)
   trunk/fsvs/src/waa.c
Log:
bugfix: if a directory is removed, the children have no by_inode to register them in.
some clarifications in comments.



Modified: trunk/fsvs/src/waa.c
Url: http://fsvs.tigris.o​rg/source/browse/fsv​s/trunk/fsvs/src/waa​.c?view=diff&rev​=23&p1=trunk/fsv​s/src/waa.c&r1=2​2&p2=trunk/fsvs/​src/waa.c&r2=23
====================​====================​====================​==================
--- trunk/fsvs/src/waa.c (original)
+++ trunk/fsvs/src/waa.c Fri Oct 7 01:24:17 2005
@@ -1019,6 +1019,7 @@
         if (first) first=0;
         else cur++;
 
+ /* First - set all fields of this entry */
         strcpy(strings, filename);
         sts->name=strings;
         strings += strlen(filename)+1;
@@ -1034,81 +1035,97 @@
                 sts->parent=stat_mem+i;
             }
 
- /* If a directory has been deleted, all of it's children don't
- * exist anymore, too.
- * We avoid allocating memory, just tell that they're missing.
- * The goto is a bit ugly here; but it's the same thing to be done,
- * and it's not better to reach it via several if's or somesuch.
- * We have to do that for REMOVED and REPLACED. */
+
+ /* If the parent's status is removed (or replaced), that tells us
+ * - the parent was a directory
+ * - the parent is no longer a directory
+ * So there can be no children now.
+ *
+ * Furthermore we break the tree here. Makes no sense to
+ * build non-existing branches.
+ *
+ * Note: we have to read the entries nonetheless, else the
+ * stored index numbers to parents would no longer match! */
             if (sts->parent->​entry_status & FS_REMOVED)
                 goto removed;
 
             sts->parent->by_inode[ sts->parent->s​ubdir_count++ ] = sts;
             BUG_ON(sts->paren​t->subdir_count > sts->parent->entry_count,
- "too many children for parent");
+ "too many children for parent");
+
 
- if (sts->parent->​subdir_count == sts->parent->entry_count)
+ /* If this was the last entry (of its parent), and the parent
+ * may have changed, check for new files. */
+ if (sts->parent->​subdir_count == sts->parent->entry_count &&
+ sts->parent->e​ntry_status)
             {
- /* This was the last entry (of it's parent). */
- if (sts->parent->​entry_status)
- {
- /* Check the parent for added elements.
- * This can be done only now, as we're finished reading
- * children.
- * Deleted entries will be found while running through. */
- /* now get the path, and stat() */
- STOPIF( ops__build_path(&fullpath, sts->parent), NULL);
- STOPIF( waa__update_dir(sts->parent, fullpath), NULL);
- } /* if parent changed */
- } /* if parent-EOF */
+ /* Check the parent for added elements.
+ * This can be done only now, as we're finished reading
+ * children.
+ * Deleted entries will be found while running through. */
+ /* now get the path, and stat() */
+ STOPIF( ops__build_path(&fullpath, sts->parent), NULL);
+ STOPIF( waa__update_dir(sts->parent, fullpath), NULL);
+ } /* if parent-EOF and changed */
         } /* if parent */
 
 
         /* now get the path, and stat() */
         STOPIF( ops__build_path(&fullpath, sts), NULL);
+ status=lstat64(fullpath, &st);
 
- if (lstat64(fullpath, &st))
+ if (status == -1)
         {
             DEBUGP("lstat whines %d",errno);
- /* entry removed ??? */
+
+ /* only valid error is ENOENT - then this entry has been removed */
+ if (errno == ENOENT)
+ {
+ /* If a directory is removed, we don't allocate the by_inode
+ * and by_name arrays. */
 removed:
- sts->entry_status​=FS_REMOVED;
- STOPIF( ac__dispatch(sts, fullpath), NULL);
+ sts->entry_status​=FS_REMOVED;
+ STOPIF( ac__dispatch(sts, fullpath), NULL);
+ continue;
+ }
+
+ STOPIF_CODE_ERR(1, errno, "cannot lstat(%s)", fullpath);
         }
- else
- {
- /* entry exists */
- sts->entry_status​=waa___stat_to_actio​n(sts, &st);
 
- /* maybe give old values ? */
- sts->st=st;
 
- STOPIF( ac__dispatch(sts, fullpath), NULL);
- DEBUGP("existing %s: action=%X, status=%d",
- fullpath, sts->entry_status, status);
- }
+ /* entry exists */
+ sts->entry_status​=waa___stat_to_actio​n(sts, &st);
+
+ /* Now we've compared we take the new values.
+ * Better for display, needed for commit (current values) */
+ sts->st=st;
 
- /* if a directory and not removed */
- if (S_ISDIR(sts->st.st_mode) &&
- (sts->entry_status & FS_REPLACED) != FS_REMOVED)
+ STOPIF( ac__dispatch(sts, fullpath), NULL);
+ DEBUGP("existing %s: action=%X, status=%d",
+ fullpath, sts->entry_status, status);
+
+
+ /* if it's a directory, we need the child-pointers. */
+ if (S_ISDIR(sts->st.st_mode))
         {
+ /* if it had children, we need to read them first - so make an array. */
             if (sts->entry_count)
             {
- /* make list(s?) for child nodes */
                 sts->by_inode=mal​loc(sizeof(*sts->​by_inode) * (sts->entry_count+1));
                 sts->by_inode[sts​->entry_count]=NU​LL;
- /* use subdir_count as child counter */
+ /* subdir_count is used as child counter */
                 sts->subdir_count=0;
             }
             else if (sts->entry_status)
             {
- /* The waa-area is always returned as empty, so it will
- * always be done here.
- * waa__update_dir() checks specifically. */
+ /* If this entry was replaced, it must not have been a directory
+ * before, so ->entry_count is defined as 0 (see ops__load_1entry()).
+ * For replaced entries which are _now_ directories we'll always
+ * get here, and waa__update_dir() will give us the children. */
                 STOPIF( waa__update_dir(sts, fullpath), NULL);
             }
         }
- }
+ } /* while (!eof) read entries */
 
     status=0;
Messages per page: