- struct stat statbuf;
- long sum;
-
- if ((lstat(filename, &statbuf)) != 0) {
- fprintf(stdout, "du: %s: %s\n", filename, strerror(errno));
- return 0;
- }
-
- du_depth++;
- 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[PATH_MAX + 1];
- char *name = entry->d_name;
-
- if ( (strcmp(name, "..") == 0)
- || (strcmp(name, ".") == 0))
- { continue; }
-
- if (strlen(filename) + strlen(name) + 1 > PATH_MAX) {
- fprintf(stderr, name_too_long, "du");
- return 0;
- }
- sprintf(newfile, "%s/%s", filename, name);
-
- sum += du(newfile);
+ struct stat statbuf;
+ unsigned long long sum;
+
+ if (lstat(filename, &statbuf) != 0) {
+ bb_simple_perror_msg(filename);
+ G.status = EXIT_FAILURE;
+ return 0;
+ }
+
+ if (option_mask32 & OPT_x_one_FS) {
+ if (G.du_depth == 0) {
+ G.dir_dev = statbuf.st_dev;
+ } else if (G.dir_dev != statbuf.st_dev) {
+ return 0;
+ }
+ }
+
+ sum = statbuf.st_blocks;
+
+ if (S_ISLNK(statbuf.st_mode)) {
+ if (G.slink_depth > G.du_depth) { /* -H or -L */
+ if (stat(filename, &statbuf) != 0) {
+ bb_simple_perror_msg(filename);
+ G.status = EXIT_FAILURE;
+ return 0;
+ }
+ sum = statbuf.st_blocks;
+ if (G.slink_depth == 1) {
+ /* Convert -H to -L */
+ G.slink_depth = INT_MAX;
+ }
+ }
+ }
+
+ if (!(option_mask32 & OPT_l_hardlinks)
+ && statbuf.st_nlink > 1
+ ) {
+ /* Add files/directories with links only once */
+ if (is_in_ino_dev_hashtable(&statbuf)) {
+ return 0;
+ }
+ add_to_ino_dev_hashtable(&statbuf, NULL);
+ }
+
+ if (S_ISDIR(statbuf.st_mode)) {
+ DIR *dir;
+ struct dirent *entry;
+ char *newfile;
+
+ dir = warn_opendir(filename);
+ if (!dir) {
+ G.status = EXIT_FAILURE;
+ return sum;
+ }
+
+ while ((entry = readdir(dir))) {
+ newfile = concat_subpath_file(filename, entry->d_name);
+ if (newfile == NULL)
+ continue;
+ ++G.du_depth;
+ sum += du(newfile);
+ --G.du_depth;
+ free(newfile);
+ }
+ closedir(dir);
+ } else {
+ if (!(option_mask32 & OPT_a_files_too) && G.du_depth != 0)
+ return sum;
+ }
+ if (G.du_depth <= G.max_print_depth) {
+ print(sum, filename);