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.
20 #define _LARGEFILE64_SOURCE
29 #include <sys/types.h>
35 #include <sys/ioctl.h>
44 INOPut(PHashTable tbl, ino64_t* key, struct stat64 **val){
45 return Put(tbl, key, val);
48 __extension__ typedef long long longlong;
49 //__extension__ typedef long longlong;
51 static longlong inodes;
52 static longlong blocks;
55 static short verbose = 0;
57 static inline void warning(char *s) {
58 fprintf(stderr,"%s (%s)\n",s,strerror(errno));
66 static void vdu_onedir (char const *path)
68 char const *foo = path;
69 struct stat64 dirst, st;
74 longlong dirsize, dirinodes, dirblocks;
76 dirsize = dirinodes = dirblocks = 0;
78 // A handle to speed up chdir
79 if ((dirfd = open (path,O_RDONLY)) == -1) {
80 fprintf (stderr,"Can't open directory %s\n",path);
84 if (fchdir (dirfd) == -1) {
85 fprintf (stderr,"Can't fchdir directory %s\n",path);
86 panic("fchdir failed");
89 if (fstat64 (dirfd,&dirst) != 0) {
90 fprintf (stderr,"Can't lstat directory %s\n",path);
91 panic("lstat failed");
94 if ((dir = opendir (".")) == NULL) {
95 fprintf (stderr,"Can't open (opendir) directory %s\n",path);
96 panic("opendir failed");
100 /* Walk the directory entries and compute the sum of inodes,
101 * blocks, and disk space used. This code will recursively descend
102 * down the directory structure.
105 while ((ent=readdir(dir))!=NULL){
106 if (lstat64(ent->d_name,&st)==-1){
107 fprintf (stderr,"Can't stat %s/%s\n",path,ent->d_name);
108 warning("lstat failed");
114 if (S_ISREG(st.st_mode)){
115 if (st.st_nlink > 1){
119 /* Check hash table if we've seen this inode
120 * before. Note that the hash maintains a
121 * (inode,struct stat) key value pair.
126 (void) INOPut(&tbl,&st.st_ino,&val);
128 /* Note that after the INOPut call "val" refers to the
129 * value entry in the hash table --- not &st. This
130 * means that if the inode has been put into the hash
131 * table before, val will refer to the first st that
132 * was put into the hashtable. Otherwise, if it is
133 * the first time it is put into the hash table, then
134 * val will be equal to this &st.
136 nlink = val->st_nlink;
139 /* val refers to value in hash tbale */
142 /* We saw all hard links to this particular inode
143 * as part of this sweep of vdu. So account for
144 * the size and blocks required by the file.
147 dirsize += val->st_size;
148 dirblocks += val->st_blocks;
150 /* Do not delete the (ino,val) tuple from the tbl,
151 * as we need to handle the case when we are
152 * double counting a file due to a bind mount.
156 } else if (nlink > 0) {
157 val->st_nlink = nlink;
158 } else /* if(nlink < 0) */ {
159 /* We get here when we are double counting nlinks
165 dirsize += st.st_size;
166 dirblocks += st.st_blocks;
169 } else if (S_ISDIR(st.st_mode)) {
170 if ((st.st_dev == dirst.st_dev) &&
171 (strcmp(ent->d_name,".")!=0) &&
172 (strcmp(ent->d_name,"..")!=0)) {
174 dirsize += st.st_size;
175 dirblocks += st.st_blocks;
177 name = strdup(ent->d_name);
179 panic("Out of memory\n");
186 // dirsize += st.st_size;
187 // dirblocks += st.st_blocks;
193 printf("%16lld %16lld %16lld %s\n",dirinodes, dirblocks, dirsize,foo);
200 Count(ino64_t* key, struct stat64* val) {
202 blocks += val->st_blocks;
203 size += val->st_size;
204 printf("ino=%16lld nlink=%d\n",val->st_ino, val->st_nlink);
209 main (int argc, char **argv)
214 fprintf (stderr,"vdu version %s\n",VERSION);
215 fprintf (stderr,"vdu directory ...\n\n");
216 fprintf (stderr,"Compute the size of a directory tree.\n");
218 if ((startdir = open (".",O_RDONLY)) == -1) {
219 fprintf (stderr,"Can't open current working directory\n");
220 panic("open failed");
223 /* hash table support for hard link count */
224 (void) Init(&tbl,0,0);
226 for (i=1; i<argc; i++){
227 inodes = blocks = size = 0;
228 vdu_onedir (argv[i]);
230 printf("%16lld %16lld %16lld %s\n",
235 if (fchdir (startdir) == -1) {
236 panic("fchdir failed");
241 /* show size & blocks for files with nlinks from outside of dir */
242 inodes = blocks = size = 0;
244 printf("%16lld %16lld %16lld NOT COUNTED\n",
250 // Dispose(&tbl); this fails to delete all entries