- int ret = -1;
- int dirfd = open (path,O_RDONLY); // A handle to speed up
- // chdir
- if (dirfd == -1){
- fprintf (stderr,"Can't open directory %s (%s)\n",path
- ,strerror(errno));
- }else{
- DIR *dir;
-
- fchdir (dirfd);
- dir = opendir (".");
- if (dir == NULL){
- fprintf (stderr,"Can't open (opendir) directory %s (%s)\n",path
- ,strerror(errno));
- }else{
- struct stat dirst;
- struct dirent *ent;
- longlong dirsize = 0;
-
- ret = 0;
- lstat (".",&dirst);
- while ((ent=readdir(dir))!=NULL){
- struct stat st;
- if (lstat(ent->d_name,&st)==-1){
- fprintf (stderr,"Can't stat %s/%s (%s)\n",path
- ,ent->d_name,strerror(errno));
- ret = -1;
- break;
- }else if (S_ISREG(st.st_mode)){
- if (st.st_nlink == 1){
- dirsize += st.st_size;
- }
- }else if (S_ISDIR(st.st_mode) && st.st_dev == dirst.st_dev){
- if (strcmp(ent->d_name,".")!=0
- && strcmp(ent->d_name,"..")!=0){
- char *tmp = malloc(strlen(path) + strlen(ent->d_name) + 2);
- if (tmp==0) ret=-1;
- else {
- strcpy(tmp, path);
- strcat(tmp, "/");
- strcat(tmp, ent->d_name);
- ret = vdu_onedir(tmp,&dirsize);
- free(tmp);
- fchdir (dirfd);
- }
- }
- }
- }
- closedir (dir);
- *size += dirsize;
+ char const *foo = path;
+ struct stat64 dirst, st;
+ struct dirent *ent;
+ char *name;
+ DIR *dir;
+ int dirfd;
+ longlong dirsize, dirinodes, dirblocks;
+
+ dirsize = dirinodes = dirblocks = 0;
+
+ // A handle to speed up chdir
+ if ((dirfd = open (path,O_RDONLY)) == -1) {
+ fprintf (stderr,"Can't open directory %s\n",path);
+ panic("open failed");
+ }
+
+ if (fchdir (dirfd) == -1) {
+ fprintf (stderr,"Can't fchdir directory %s\n",path);
+ panic("fchdir failed");
+ }
+
+ if (fstat64 (dirfd,&dirst) != 0) {
+ fprintf (stderr,"Can't lstat directory %s\n",path);
+ panic("lstat failed");
+ }
+
+ if ((dir = opendir (".")) == NULL) {
+ fprintf (stderr,"Can't open (opendir) directory %s\n",path);
+ panic("opendir failed");
+ }
+
+
+ /* Walk the directory entries and compute the sum of inodes,
+ * blocks, and disk space used. This code will recursively descend
+ * down the directory structure.
+ */
+
+ while ((ent=readdir(dir))!=NULL){
+ if (lstat64(ent->d_name,&st)==-1){
+ fprintf (stderr,"Can't stat %s/%s\n",path,ent->d_name);
+ warning("lstat failed");
+ continue;
+ }
+
+ dirinodes ++;
+
+ if (S_ISREG(st.st_mode)){
+ if (st.st_nlink > 1){
+ struct stat64 *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;
+ }
+
+ } else if (S_ISDIR(st.st_mode)) {
+ if ((st.st_dev == dirst.st_dev) &&
+ (strcmp(ent->d_name,".")!=0) &&
+ (strcmp(ent->d_name,"..")!=0)) {
+
+ dirsize += st.st_size;
+ dirblocks += st.st_blocks;
+
+ name = strdup(ent->d_name);
+ if (name==0) {
+ panic("Out of memory\n");