Add another thought to the docs for --mtime.
[sgt/agedu] / du.c
diff --git a/du.c b/du.c
index 1a375bf..6d26c34 100644 (file)
--- a/du.c
+++ b/du.c
@@ -2,26 +2,24 @@
  * du.c: implementation of du.h.
  */
 
-#include "agedu.h" /* for config.h */
-
-#ifdef HAVE_FEATURES_H
-#define _GNU_SOURCE
-#include <features.h>
-#endif
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
+#include "agedu.h"
 #include "du.h"
 #include "alloc.h"
 
-#if !defined __linux__ || defined HAVE_FDOPENDIR
+#if !defined __linux__ || !defined O_NOATIME || defined HAVE_FDOPENDIR
+
+#ifdef HAVE_DIRENT_H
+#  include <dirent.h>
+#endif
+#ifdef HAVE_NDIR_H
+#  include <ndir.h>
+#endif
+#ifdef HAVE_SYS_DIR_H
+#  include <sys/dir.h>
+#endif
+#ifdef HAVE_SYS_NDIR_H
+#  include <sys/ndir.h>
+#endif
 
 /*
  * Wrappers around POSIX opendir, readdir and closedir, which
@@ -29,7 +27,6 @@
  * circumstances.
  */
 
-#include <dirent.h>
 typedef DIR *dirhandle;
 
 int open_dir(const char *path, dirhandle *dh)
@@ -106,8 +103,6 @@ void close_dir(dirhandle *dh)
  */
 
 #define __KERNEL__
-#include <unistd.h>
-#include <fcntl.h>
 #include <linux/types.h>
 #include <linux/dirent.h>
 #include <linux/unistd.h>
@@ -175,16 +170,26 @@ static int str_cmp(const void *av, const void *bv)
 }
 
 static void du_recurse(char **path, size_t pathlen, size_t *pathsize,
-                      gotdata_fn_t gotdata, void *gotdata_ctx)
+                      gotdata_fn_t gotdata, err_fn_t err, void *gotdata_ctx,
+                      int toplevel)
 {
     const char *name;
     dirhandle d;
     STRUCT_STAT st;
     char **names;
     size_t i, nnames, namesize;
+    int statret;
 
-    if (LSTAT(*path, &st) < 0) {
-       fprintf(stderr, "%s: lstat: %s\n", *path, strerror(errno));
+    /*
+     * Special case: at the very top of the scan, we follow a
+     * symlink.
+     */
+    if (toplevel)
+       statret = STAT(*path, &st);
+    else
+       statret = LSTAT(*path, &st);
+    if (statret < 0) {
+       err(gotdata_ctx, "%s: lstat: %s\n", *path, strerror(errno));
        return;
     }
 
@@ -198,7 +203,7 @@ static void du_recurse(char **path, size_t pathlen, size_t *pathsize,
     nnames = namesize = 0;
 
     if (open_dir(*path, &d) < 0) {
-       fprintf(stderr, "%s: opendir: %s\n", *path, strerror(errno));
+       err(gotdata_ctx, "%s: opendir: %s\n", *path, strerror(errno));
        return;
     }
     while ((name = read_dir(&d)) != NULL) {
@@ -236,14 +241,15 @@ static void du_recurse(char **path, size_t pathlen, size_t *pathsize,
            sprintf(*path + pathlen, "/%s", names[i]);
        }
 
-       du_recurse(path, newpathlen, pathsize, gotdata, gotdata_ctx);
+       du_recurse(path, newpathlen, pathsize, gotdata, err, gotdata_ctx, 0);
 
        sfree(names[i]);
     }
     sfree(names);
 }
 
-void du(const char *inpath, gotdata_fn_t gotdata, void *gotdata_ctx)
+void du(const char *inpath, gotdata_fn_t gotdata, err_fn_t err,
+       void *gotdata_ctx)
 {
     char *path;
     size_t pathlen, pathsize;
@@ -253,5 +259,5 @@ void du(const char *inpath, gotdata_fn_t gotdata, void *gotdata_ctx)
     path = snewn(pathsize, char);
     strcpy(path, inpath);
 
-    du_recurse(&path, pathlen, &pathsize, gotdata, gotdata_ctx);
+    du_recurse(&path, pathlen, &pathsize, gotdata, err, gotdata_ctx, 1);
 }