[BACK]Return to du.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / du

Diff for /src/usr.bin/du/du.c between version 1.16 and 1.17

version 1.16, 2004/06/14 18:21:31 version 1.17, 2004/06/21 09:44:31
Line 57 
Line 57 
 #include <stdio.h>  #include <stdio.h>
 #include <stdlib.h>  #include <stdlib.h>
 #include <string.h>  #include <string.h>
   #include <sys/tree.h>
 #include <unistd.h>  #include <unistd.h>
 #include <util.h>  #include <util.h>
   
Line 217 
Line 218 
         exit(rval);          exit(rval);
 }  }
   
   
   struct links_entry {
           RB_ENTRY(links_entry) entry;
           struct links_entry *fnext;
           int      links;
           dev_t    dev;
           ino_t    ino;
   };
   
 int  int
   links_cmp(struct links_entry *e1, struct links_entry *e2)
   {
           if (e1->dev == e2->dev) {
                   if (e1->ino == e2->ino)
                           return (0);
                   else
                           return (e1->ino < e2->ino ? -1 : 1);
           }
           else
                   return (e1->dev < e2->dev ? -1 : 1);
   }
   
   RB_HEAD(ltree, links_entry) links = RB_INITIALIZER(&links);
   
   RB_GENERATE(ltree, links_entry, entry, links_cmp);
   
   
   int
 linkchk(FTSENT *p)  linkchk(FTSENT *p)
 {  {
         struct links_entry {          static struct links_entry *free_list = NULL;
                 struct links_entry *next;          static int stop_allocating = 0;
                 struct links_entry *previous;          struct links_entry ltmp, *le;
                 int      links;  
                 dev_t    dev;  
                 ino_t    ino;  
         };  
         static const size_t links_hash_initial_size = 8192;  
         static struct links_entry **buckets;  
         static struct links_entry *free_list;  
         static size_t number_buckets;  
         static unsigned long number_entries;  
         static char stop_allocating;  
         struct links_entry *le, **new_buckets;  
         struct stat *st;          struct stat *st;
         size_t i, new_size;  
         int count, hash;  
   
         st = p->fts_statp;          st = p->fts_statp;
   
         /* If necessary, initialize the hash table. */          ltmp.ino = st->st_ino;
         if (buckets == NULL) {          ltmp.dev = st->st_dev;
                 number_buckets = links_hash_initial_size;  
                 buckets = malloc(number_buckets * sizeof(buckets[0]));  
                 if (buckets == NULL)  
                         errx(1, "No memory for hardlink detection");  
                 for (i = 0; i < number_buckets; i++)  
                         buckets[i] = NULL;  
         }  
   
         /* If the hash table is getting too full, enlarge it. */          le = RB_FIND(ltree, &links, &ltmp);
         if (number_entries > number_buckets * 10 && !stop_allocating) {          if (le != NULL) {
                 new_size = number_buckets * 2;                  /*
                 new_buckets = malloc(new_size * sizeof(struct links_entry *));                   * Save memory by releasing an entry when we've seen
                 count = 0;                   * all of it's links.
                    */
                 /* Try releasing the free list to see if that helps. */                  if (--le->links <= 0) {
                 if (new_buckets == NULL && free_list != NULL) {                          RB_REMOVE(ltree, &links, le);
                         while (free_list != NULL) {                          /* Recycle this node through the free list */
                                 le = free_list;                          if (stop_allocating) {
                                 free_list = le->next;  
                                 free(le);                                  free(le);
                           } else {
                                   le->fnext = free_list;
                                   free_list = le;
                         }                          }
                         new_buckets = malloc(new_size * sizeof(new_buckets[0]));  
                 }                  }
                   return (1);
                 if (new_buckets == NULL) {  
                         stop_allocating = 1;  
                         warnx("No more memory for tracking hard links");  
                 } else {  
                         memset(new_buckets, 0,  
                             new_size * sizeof(struct links_entry *));  
                         for (i = 0; i < number_buckets; i++) {  
                                 while (buckets[i] != NULL) {  
                                         /* Remove entry from old bucket. */  
                                         le = buckets[i];  
                                         buckets[i] = le->next;  
   
                                         /* Add entry to new bucket. */  
                                         hash = (le->dev ^ le->ino) % new_size;  
   
                                         if (new_buckets[hash] != NULL)  
                                                 new_buckets[hash]->previous =  
                                                     le;  
                                         le->next = new_buckets[hash];  
                                         le->previous = NULL;  
                                         new_buckets[hash] = le;  
                                 }  
                         }  
                         free(buckets);  
                         buckets = new_buckets;  
                         number_buckets = new_size;  
                 }  
         }          }
   
         /* Try to locate this entry in the hash table. */  
         hash = ( st->st_dev ^ st->st_ino ) % number_buckets;  
         for (le = buckets[hash]; le != NULL; le = le->next) {  
                 if (le->dev == st->st_dev && le->ino == st->st_ino) {  
                         /*  
                          * Save memory by releasing an entry when we've seen  
                          * all of it's links.  
                          */  
                         if (--le->links <= 0) {  
                                 if (le->previous != NULL)  
                                         le->previous->next = le->next;  
                                 if (le->next != NULL)  
                                         le->next->previous = le->previous;  
                                 if (buckets[hash] == le)  
                                         buckets[hash] = le->next;  
                                 number_entries--;  
                                 /* Recycle this node through the free list */  
                                 if (stop_allocating) {  
                                         free(le);  
                                 } else {  
                                         le->next = free_list;  
                                         free_list = le;  
                                 }  
                         }  
                         return (1);  
                 }  
         }  
   
         if (stop_allocating)          if (stop_allocating)
                 return (0);                  return (0);
   
Line 330 
Line 284 
         if (free_list != NULL) {          if (free_list != NULL) {
                 /* Pull a node from the free list if we can. */                  /* Pull a node from the free list if we can. */
                 le = free_list;                  le = free_list;
                 free_list = le->next;                  free_list = le->fnext;
         } else          } else
                 /* Malloc one if we have to. */                  /* Malloc one if we have to. */
                 le = malloc(sizeof(struct links_entry));                  le = malloc(sizeof(struct links_entry));
   
         if (le == NULL) {          if (le == NULL) {
                 stop_allocating = 1;                  stop_allocating = 1;
                 warnx("No more memory for tracking hard links");                  warnx("No more memory for tracking hard links");
                 return (0);                  return (0);
         }          }
   
         le->dev = st->st_dev;          le->dev = st->st_dev;
         le->ino = st->st_ino;          le->ino = st->st_ino;
         le->links = st->st_nlink - 1;          le->links = st->st_nlink - 1;
         number_entries++;          le->fnext = NULL;
         le->next = buckets[hash];  
         le->previous = NULL;          RB_INSERT(ltree, &links, le);
         if (buckets[hash] != NULL)  
                 buckets[hash]->previous = le;  
         buckets[hash] = le;  
         return (0);          return (0);
 }  }
   

Legend:
Removed from v.1.16  
changed lines
  Added in v.1.17