- struct stat statbuf;
- size_t sum;
-
- if ((lstat(filename, &statbuf)) != 0) {
- fprintf(stdout, "du: %s: %s\n", filename, strerror(errno));
- return 0;
- }
- sum = statbuf.st_blocks;
-
- if (S_ISDIR(statbuf.st_mode)) {
- DIR *dir;
- struct dirent *entry;
-
- dir = opendir(filename);
- if (!dir) { return 0; }
- while ((entry = readdir(dir))) {
- char newfile[512];
- char *name = entry->d_name;
-
- if ( (strcmp(name, "..") == 0)
- || (strcmp(name, ".") == 0))
- { continue; }
-
- sprintf(newfile, "%s/%s", filename, name);
- sum += du(newfile);
+ struct stat statbuf;
+ long sum;
+ int len;
+
+ if ((lstat(filename, &statbuf)) != 0) {
+ printf("du: %s: %s\n", filename, strerror(errno));
+ return 0;
+ }
+
+ du_depth++;
+ sum = (statbuf.st_blocks >> 1);
+
+ /* Don't add in stuff pointed to by symbolic links */
+ if (S_ISLNK(statbuf.st_mode)) {
+ sum = 0L;
+ if (du_depth == 1)
+ print(sum, filename);
+ }
+ if (S_ISDIR(statbuf.st_mode)) {
+ DIR *dir;
+ struct dirent *entry;
+
+ dir = opendir(filename);
+ if (!dir) {
+ du_depth--;
+ return 0;
+ }
+
+ len = strlen(filename);
+ if (filename[len - 1] == '/')
+ filename[--len] = '\0';
+
+ while ((entry = readdir(dir))) {
+ char newfile[PATH_MAX + 1];
+ char *name = entry->d_name;
+
+ if ((strcmp(name, "..") == 0)
+ || (strcmp(name, ".") == 0)) {
+ continue;
+ }
+
+ if (len + strlen(name) + 1 > PATH_MAX) {
+ fprintf(stderr, name_too_long, "du");
+ du_depth--;
+ return 0;
+ }
+ sprintf(newfile, "%s/%s", filename, name);
+
+ sum += du(newfile);
+ }
+ closedir(dir);
+ print(sum, filename);
+ }
+ else if (statbuf.st_nlink > 1 && !count_hardlinks) {
+ /* Add files with hard links only once */
+ if (is_in_ino_dev_hashtable(&statbuf, NULL)) {
+ sum = 0L;
+ if (du_depth == 1)
+ print(sum, filename);
+ }
+ else {
+ add_to_ino_dev_hashtable(&statbuf, NULL);
+ }