[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.15 and 1.16

version 1.15, 2004/06/02 14:58:46 version 1.16, 2004/06/14 18:21:31
Line 54 
Line 54 
 #include <err.h>  #include <err.h>
 #include <errno.h>  #include <errno.h>
 #include <fts.h>  #include <fts.h>
 #include <math.h>  
 #include <stdio.h>  #include <stdio.h>
 #include <stdlib.h>  #include <stdlib.h>
 #include <string.h>  #include <string.h>
 #include <unistd.h>  #include <unistd.h>
   #include <util.h>
   
 typedef enum { NONE = 0, KILO, MEGA, GIGA, TERA, PETA /* , EXA */ } unit_t;  
   
 int      linkchk(FTSENT *);  int      linkchk(FTSENT *);
 void     prtout(quad_t, char *, int);  void     prtout(quad_t, char *, int);
 void     usage(void);  void     usage(void);
 unit_t   unit_adjust(double *);  
   
 int  int
 main(int argc, char *argv[])  main(int argc, char *argv[])
Line 219 
Line 217 
         exit(rval);          exit(rval);
 }  }
   
 typedef struct _ID {  
         dev_t   dev;  
         ino_t   inode;  
 } ID;  
   
 int  int
 linkchk(FTSENT *p)  linkchk(FTSENT *p)
 {  {
         static ID *files;          struct links_entry {
         static int maxfiles, nfiles;                  struct links_entry *next;
         ID *fp, *start;                  struct links_entry *previous;
         ino_t ino;                  int      links;
         dev_t dev;                  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;
           size_t i, new_size;
           int count, hash;
   
         ino = p->fts_statp->st_ino;          st = p->fts_statp;
         dev = p->fts_statp->st_dev;  
         if ((start = files) != NULL)  
                 for (fp = start + nfiles - 1; fp >= start; --fp)  
                         if (ino == fp->inode && dev == fp->dev)  
                                 return (1);  
   
         if (nfiles == maxfiles && (files = realloc((char *)files,          /* If necessary, initialize the hash table. */
             (u_int)(sizeof(ID) * (maxfiles += 128)))) == NULL)          if (buckets == NULL) {
                 err(1, NULL);                  number_buckets = links_hash_initial_size;
         files[nfiles].inode = ino;                  buckets = malloc(number_buckets * sizeof(buckets[0]));
         files[nfiles].dev = dev;                  if (buckets == NULL)
         ++nfiles;                          errx(1, "No memory for hardlink detection");
         return (0);                  for (i = 0; i < number_buckets; i++)
 }                          buckets[i] = NULL;
           }
   
 /*          /* If the hash table is getting too full, enlarge it. */
  * "human-readable" output: use 3 digits max.--put unit suffixes at          if (number_entries > number_buckets * 10 && !stop_allocating) {
  * the end.  Makes output compact and easy-to-read.                  new_size = number_buckets * 2;
  */                  new_buckets = malloc(new_size * sizeof(struct links_entry *));
                   count = 0;
   
 unit_t                  /* Try releasing the free list to see if that helps. */
 unit_adjust(double *val)                  if (new_buckets == NULL && free_list != NULL) {
 {                          while (free_list != NULL) {
         double abval;                                  le = free_list;
         unit_t unit;                                  free_list = le->next;
                                   free(le);
                           }
                           new_buckets = malloc(new_size * sizeof(new_buckets[0]));
                   }
   
         abval = fabs(*val);                  if (new_buckets == NULL) {
         if (abval < 1024)                          stop_allocating = 1;
                 unit = NONE;                          warnx("No more memory for tracking hard links");
         else if (abval < 1048576ULL) {                  } else {
                 unit = KILO;                          memset(new_buckets, 0,
                 *val /= 1024;                              new_size * sizeof(struct links_entry *));
         } else if (abval < 1073741824ULL) {                          for (i = 0; i < number_buckets; i++) {
                 unit = MEGA;                                  while (buckets[i] != NULL) {
                 *val /= 1048576;                                          /* Remove entry from old bucket. */
         } else if (abval < 1099511627776ULL) {                                          le = buckets[i];
                 unit = GIGA;                                          buckets[i] = le->next;
                 *val /= 1073741824ULL;  
         } else if (abval < 1125899906842624ULL) {                                          /* Add entry to new bucket. */
                 unit = TERA;                                          hash = (le->dev ^ le->ino) % new_size;
                 *val /= 1099511627776ULL;  
         } else /* if (abval < 1152921504606846976ULL) */ {                                          if (new_buckets[hash] != NULL)
                 unit = PETA;                                                  new_buckets[hash]->previous =
                 *val /= 1125899906842624ULL;                                                      le;
                                           le->next = new_buckets[hash];
                                           le->previous = NULL;
                                           new_buckets[hash] = le;
                                   }
                           }
                           free(buckets);
                           buckets = new_buckets;
                           number_buckets = new_size;
                   }
         }          }
         return (unit);  
           /* 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)
                   return (0);
   
           /* Add this entry to the links cache. */
           if (free_list != NULL) {
                   /* Pull a node from the free list if we can. */
                   le = free_list;
                   free_list = le->next;
           } else
                   /* Malloc one if we have to. */
                   le = malloc(sizeof(struct links_entry));
           if (le == NULL) {
                   stop_allocating = 1;
                   warnx("No more memory for tracking hard links");
                   return (0);
           }
           le->dev = st->st_dev;
           le->ino = st->st_ino;
           le->links = st->st_nlink - 1;
           number_entries++;
           le->next = buckets[hash];
           le->previous = NULL;
           if (buckets[hash] != NULL)
                   buckets[hash]->previous = le;
           buckets[hash] = le;
           return (0);
 }  }
   
 void  void
 prtout(quad_t size, char *path, int hflag)  prtout(quad_t size, char *path, int hflag)
 {  {
         unit_t unit;  
         double bytes;  
   
         if (!hflag)          if (!hflag)
                 (void)printf("%lld\t%s\n", (long long)size, path);                  (void)printf("%lld\t%s\n", (long long)size, path);
         else {          else {
                 bytes = (double)size * 512.0;                  char buf[FMT_SCALED_STRSIZE];
                 unit = unit_adjust(&bytes);  
   
                 if (bytes == 0)                  if (fmt_scaled(size * 512, buf) == 0)
                         (void)printf("0B\t%s\n", path);                          (void)printf("%s\t%s\n", buf, path);
                 else if (bytes > 10)  
                         (void)printf("%.0f%c\t%s\n", bytes, "BKMGTPE"[unit], path);  
                 else                  else
                         (void)printf("%.1f%c\t%s\n", bytes, "BKMGTPE"[unit], path);                          (void)printf("%lld\t%s\n", (long long)size, path);
         }          }
 }  }
   

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