1 // $Id: vdu-new.c,v 1.2 2004/08/17 14:44:14 mef-pl_kernel Exp $
3 // Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
4 // based on vdu.cc by Jacques Gelinas
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2, or (at your option)
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #include <sys/types.h>
29 #include <sys/ioctl.h>
38 INOPut(PHashTable tbl, ino_t* key, struct stat **val){
39 return Put(tbl, key, val);
42 __extension__ typedef long long longlong;
43 //__extension__ typedef long longlong;
45 static longlong inodes;
46 static longlong blocks;
49 static short verbose = 0;
51 static inline void warning(char *s) {
52 fprintf(stderr,"%s (%s)\n",s,strerror(errno));
60 static void vdu_onedir (char const *path)
62 char const *foo = path;
63 struct stat dirst, st;
68 longlong dirsize, dirinodes, dirblocks;
70 dirsize = dirinodes = dirblocks = 0;
72 // A handle to speed up chdir
73 if ((dirfd = open (path,O_RDONLY)) == -1) {
74 fprintf (stderr,"Can't open directory %s\n",path);
78 if (fchdir (dirfd) == -1) {
79 fprintf (stderr,"Can't fchdir directory %s\n",path);
80 panic("fchdir failed");
83 if (fstat (dirfd,&dirst) != 0) {
84 fprintf (stderr,"Can't lstat directory %s\n",path);
85 panic("lstat failed");
88 if ((dir = opendir (".")) == NULL) {
89 fprintf (stderr,"Can't open (opendir) directory %s\n",path);
90 panic("opendir failed");
94 /* Walk the directory entries and compute the sum of inodes,
95 * blocks, and disk space used. This code will recursively descend
96 * down the directory structure.
99 while ((ent=readdir(dir))!=NULL){
100 if (lstat(ent->d_name,&st)==-1){
101 fprintf (stderr,"Can't stat %s/%s\n",path,ent->d_name);
102 warning("lstat failed");
108 if (S_ISREG(st.st_mode)){
109 if (st.st_nlink > 1){
113 /* Check hash table if we've seen this inode
114 * before. Note that the hash maintains a
115 * (inode,struct stat) key value pair.
120 (void) INOPut(&tbl,&st.st_ino,&val);
122 /* Note that after the INOPut call "val" refers to the
123 * value entry in the hash table --- not &st. This
124 * means that if the inode has been put into the hash
125 * table before, val will refer to the first st that
126 * was put into the hashtable. Otherwise, if it is
127 * the first time it is put into the hash table, then
128 * val will be equal to this &st.
130 nlink = val->st_nlink;
133 /* val refers to value in hash tbale */
136 /* We saw all hard links to this particular inode
137 * as part of this sweep of vdu. So account for
138 * the size and blocks required by the file.
141 dirsize += val->st_size;
142 dirblocks += val->st_blocks;
144 /* Do not delete the (ino,val) tuple from the tbl,
145 * as we need to handle the case when we are
146 * double counting a file due to a bind mount.
150 } else if (nlink > 0) {
151 val->st_nlink = nlink;
152 } else /* if(nlink < 0) */ {
153 /* We get here when we are double counting nlinks
159 dirsize += st.st_size;
160 dirblocks += st.st_blocks;
163 } else if (S_ISDIR(st.st_mode)) {
164 if ((st.st_dev == dirst.st_dev) &&
165 (strcmp(ent->d_name,".")!=0) &&
166 (strcmp(ent->d_name,"..")!=0)) {
168 dirsize += st.st_size;
169 dirblocks += st.st_blocks;
171 name = strdup(ent->d_name);
173 panic("Out of memory\n");
180 // dirsize += st.st_size;
181 // dirblocks += st.st_blocks;
187 printf("%16lld %16lld %16lld %s\n",dirinodes, dirblocks, dirsize,foo);
194 Count(ino_t* key, struct stat* val) {
196 blocks += val->st_blocks;
197 size += val->st_size;
198 printf("ino=%ld nlink=%d\n",val->st_ino, val->st_nlink);
203 main (int argc, char **argv)
208 fprintf (stderr,"vdu version %s\n",VERSION);
209 fprintf (stderr,"vdu directory ...\n\n");
210 fprintf (stderr,"Compute the size of a directory tree.\n");
212 if ((startdir = open (".",O_RDONLY)) == -1) {
213 fprintf (stderr,"Can't open current working directory\n");
214 panic("open failed");
217 /* hash table support for hard link count */
218 (void) Init(&tbl,0,0);
220 for (i=1; i<argc; i++){
221 inodes = blocks = size = 0;
222 vdu_onedir (argv[i]);
224 printf("%16lld %16lld %16lld %s\n",
229 if (fchdir (startdir) == -1) {
230 panic("fchdir failed");
235 /* show size & blocks for files with nlinks from outside of dir */
236 inodes = blocks = size = 0;
238 printf("%16lld %16lld %16lld NOT COUNTED\n",
244 // Dispose(&tbl); this fails to delete all entries