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
25 #include <sys/types.h>
31 #include <sys/ioctl.h>
40 INOPut(PHashTable tbl, ino64_t* key, struct stat64 **val){
41 return Put(tbl, key, val);
44 __extension__ typedef long long longlong;
45 //__extension__ typedef long longlong;
47 static longlong inodes;
48 static longlong blocks;
51 static short verbose = 0;
53 static inline void warning(char *s) {
54 fprintf(stderr,"%s (%s)\n",s,strerror(errno));
62 static void vdu_onedir (char const *path)
64 char const *foo = path;
65 struct stat64 dirst, st;
70 longlong dirsize, dirinodes, dirblocks;
72 dirsize = dirinodes = dirblocks = 0;
74 // A handle to speed up chdir
75 if ((dirfd = open (path,O_RDONLY)) == -1) {
76 fprintf (stderr,"Can't open directory %s\n",path);
80 if (fchdir (dirfd) == -1) {
81 fprintf (stderr,"Can't fchdir directory %s\n",path);
82 panic("fchdir failed");
85 if (fstat64 (dirfd,&dirst) != 0) {
86 fprintf (stderr,"Can't lstat directory %s\n",path);
87 panic("lstat failed");
90 if ((dir = opendir (".")) == NULL) {
91 fprintf (stderr,"Can't open (opendir) directory %s\n",path);
92 panic("opendir failed");
96 /* Walk the directory entries and compute the sum of inodes,
97 * blocks, and disk space used. This code will recursively descend
98 * down the directory structure.
101 while ((ent=readdir(dir))!=NULL){
102 if (lstat64(ent->d_name,&st)==-1){
103 fprintf (stderr,"Can't stat %s/%s\n",path,ent->d_name);
104 warning("lstat failed");
110 if (S_ISREG(st.st_mode)){
111 if (st.st_nlink > 1){
115 /* Check hash table if we've seen this inode
116 * before. Note that the hash maintains a
117 * (inode,struct stat) key value pair.
122 (void) INOPut(&tbl,&st.st_ino,&val);
124 /* Note that after the INOPut call "val" refers to the
125 * value entry in the hash table --- not &st. This
126 * means that if the inode has been put into the hash
127 * table before, val will refer to the first st that
128 * was put into the hashtable. Otherwise, if it is
129 * the first time it is put into the hash table, then
130 * val will be equal to this &st.
132 nlink = val->st_nlink;
135 /* val refers to value in hash tbale */
138 /* We saw all hard links to this particular inode
139 * as part of this sweep of vdu. So account for
140 * the size and blocks required by the file.
143 dirsize += val->st_size;
144 dirblocks += val->st_blocks;
146 /* Do not delete the (ino,val) tuple from the tbl,
147 * as we need to handle the case when we are
148 * double counting a file due to a bind mount.
152 } else if (nlink > 0) {
153 val->st_nlink = nlink;
154 } else /* if(nlink < 0) */ {
155 /* We get here when we are double counting nlinks
161 dirsize += st.st_size;
162 dirblocks += st.st_blocks;
165 } else if (S_ISDIR(st.st_mode)) {
166 if ((st.st_dev == dirst.st_dev) &&
167 (strcmp(ent->d_name,".")!=0) &&
168 (strcmp(ent->d_name,"..")!=0)) {
170 dirsize += st.st_size;
171 dirblocks += st.st_blocks;
173 name = strdup(ent->d_name);
175 panic("Out of memory\n");
182 // dirsize += st.st_size;
183 // dirblocks += st.st_blocks;
189 printf("%16lld %16lld %16lld %s\n",dirinodes, dirblocks, dirsize,foo);
196 Count(ino64_t* key, struct stat64* val) {
198 blocks += val->st_blocks;
199 size += val->st_size;
200 printf("ino=%16lld nlink=%d\n",val->st_ino, val->st_nlink);
205 main (int argc, char **argv)
210 fprintf (stderr,"vdu version %s\n",VERSION);
211 fprintf (stderr,"vdu directory ...\n\n");
212 fprintf (stderr,"Compute the size of a directory tree.\n");
214 if ((startdir = open (".",O_RDONLY)) == -1) {
215 fprintf (stderr,"Can't open current working directory\n");
216 panic("open failed");
219 /* hash table support for hard link count */
220 (void) Init(&tbl,0,0);
222 for (i=1; i<argc; i++){
223 inodes = blocks = size = 0;
224 vdu_onedir (argv[i]);
226 printf("%16lld %16lld %16lld %s\n",
231 if (fchdir (startdir) == -1) {
232 panic("fchdir failed");
237 /* show size & blocks for files with nlinks from outside of dir */
238 inodes = blocks = size = 0;
240 printf("%16lld %16lld %16lld NOT COUNTED\n",
246 // Dispose(&tbl); this fails to delete all entries