X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=src%2Fvdu.c;h=19b5dec7add928ed7ea9723af4267984cef2ca7a;hb=02ca3cb72401c1bfb9361c8ea340d065a6d9a377;hp=04c060c5905dbfcac9da9efe381e3390c28945c1;hpb=60c730b51008d84616ac87e162e78b17d8c65d12;p=util-vserver.git diff --git a/src/vdu.c b/src/vdu.c index 04c060c..19b5dec 100644 --- a/src/vdu.c +++ b/src/vdu.c @@ -1,4 +1,4 @@ -// $Id: vdu.c,v 1.1 2003/09/29 22:01:57 ensc Exp $ +// $Id: vdu-new.c,v 1.2 2004/08/17 14:44:14 mef-pl_kernel Exp $ // Copyright (C) 2003 Enrico Scholz // based on vdu.cc by Jacques Gelinas @@ -17,11 +17,6 @@ // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -#ifdef HAVE_CONFIG_H -# include -#endif -#include "compat.h" - #include #include #include @@ -31,19 +26,21 @@ #include #include #include - #include -#include "ext2fs.h" -// Patch to help compile this utility on unpatched kernel source -#ifndef EXT2_IMMUTABLE_FILE_FL - #define EXT2_IMMUTABLE_FILE_FL 0x00000010 - #define EXT2_IMMUTABLE_LINK_FL 0x00008000 -#endif +#include + +#include "vdu.h" +HashTable tbl; + +static int // boolean +INOPut(PHashTable tbl, ino_t* key, struct stat **val){ + return Put(tbl, key, val); +} -//__extension__ typedef long long longlong; -__extension__ typedef long longlong; +__extension__ typedef long long longlong; +//__extension__ typedef long longlong; static longlong inodes; static longlong blocks; @@ -62,6 +59,7 @@ void panic(char *s) { static void vdu_onedir (char const *path) { + char const *foo = path; struct stat dirst, st; struct dirent *ent; char *name; @@ -94,8 +92,9 @@ static void vdu_onedir (char const *path) /* Walk the directory entries and compute the sum of inodes, - blocks, and disk space used. This code will recursively descend - down the directory structure. */ + * blocks, and disk space used. This code will recursively descend + * down the directory structure. + */ while ((ent=readdir(dir))!=NULL){ if (lstat(ent->d_name,&st)==-1){ @@ -108,27 +107,58 @@ static void vdu_onedir (char const *path) if (S_ISREG(st.st_mode)){ if (st.st_nlink > 1){ - long flags; - int fd, res; - - if ((fd = open(ent->d_name,O_RDONLY))==-1) { - fprintf (stderr,"Can't open file %s/%s\n",path,ent->d_name); - warning ("open failed"); - continue; - } - - flags = 0; - res = ioctl(fd, EXT2_IOC_GETFLAGS, &flags); - close(fd); - - if ((res == 0) && (flags & EXT2_IMMUTABLE_LINK_FL)){ - if (verbose) - printf ("Skipping %s\n",ent->d_name); - continue; + struct stat *val; + int nlink; + + /* Check hash table if we've seen this inode + * before. Note that the hash maintains a + * (inode,struct stat) key value pair. + */ + + val = &st; + + (void) INOPut(&tbl,&st.st_ino,&val); + + /* Note that after the INOPut call "val" refers to the + * value entry in the hash table --- not &st. This + * means that if the inode has been put into the hash + * table before, val will refer to the first st that + * was put into the hashtable. Otherwise, if it is + * the first time it is put into the hash table, then + * val will be equal to this &st. + */ + nlink = val->st_nlink; + nlink --; + + /* val refers to value in hash tbale */ + if (nlink == 0) { + + /* We saw all hard links to this particular inode + * as part of this sweep of vdu. So account for + * the size and blocks required by the file. + */ + + dirsize += val->st_size; + dirblocks += val->st_blocks; + + /* Do not delete the (ino,val) tuple from the tbl, + * as we need to handle the case when we are + * double counting a file due to a bind mount. + */ + val->st_nlink = 0; + + } else if (nlink > 0) { + val->st_nlink = nlink; + } else /* if(nlink < 0) */ { + /* We get here when we are double counting nlinks + due a bind mount. */ + + /* DO NOTHING */ } + } else { + dirsize += st.st_size; + dirblocks += st.st_blocks; } - dirsize += st.st_size; - dirblocks += st.st_blocks; } else if (S_ISDIR(st.st_mode)) { if ((st.st_dev == dirst.st_dev) && @@ -147,43 +177,71 @@ static void vdu_onedir (char const *path) fchdir(dirfd); } } else { - dirsize += st.st_size; - dirblocks += st.st_blocks; + // dirsize += st.st_size; + // dirblocks += st.st_blocks; } } closedir (dir); close (dirfd); if (verbose) - printf("%8ld %8ld %8ld %s\n",dirinodes, dirblocks, dirsize>>10,path); + printf("%16lld %16lld %16lld %s\n",dirinodes, dirblocks, dirsize,foo); inodes += dirinodes; blocks += dirblocks; size += dirsize; } +static void +Count(ino_t* key, struct stat* val) { + if(val->st_nlink) { + blocks += val->st_blocks; + size += val->st_size; + printf("ino=%ld nlink=%d\n",val->st_ino, val->st_nlink); + } +} - -int main (int argc, char *argv[]) +int +main (int argc, char **argv) { int startdir, i; if (argc < 2){ fprintf (stderr,"vdu version %s\n",VERSION); fprintf (stderr,"vdu directory ...\n\n"); - fprintf (stderr,"Compute the size of a directory tree."); + fprintf (stderr,"Compute the size of a directory tree.\n"); }else{ if ((startdir = open (".",O_RDONLY)) == -1) { fprintf (stderr,"Can't open current working directory\n"); panic("open failed"); } + /* hash table support for hard link count */ + (void) Init(&tbl,0,0); + for (i=1; i>10,argv[i]); + + printf("%16lld %16lld %16lld %s\n", + inodes, + blocks>>1, + size, + argv[i]); if (fchdir (startdir) == -1) { panic("fchdir failed"); } } + + if(0) { + /* show size & blocks for files with nlinks from outside of dir */ + inodes = blocks = size = 0; + Iterate(&tbl,Count); + printf("%16lld %16lld %16lld NOT COUNTED\n", + inodes, + blocks, + size); + } + + // Dispose(&tbl); this fails to delete all entries close(startdir); } return 0;