Switch to side-by-side view

--- a/src/utils/fstreewalk.cpp
+++ b/src/utils/fstreewalk.cpp
@@ -36,6 +36,7 @@
 #include "log.h"
 #include "pathut.h"
 #include "fstreewalk.h"
+#include "transcode.h"
 
 using namespace std;
 
@@ -310,6 +311,20 @@
     return FtwOk;
 }
 
+#ifdef _WIN32
+#define DIRENT _wdirent
+#define DIRHDL _WDIR
+#define OPENDIR _wopendir
+#define CLOSEDIR _wclosedir
+#define READDIR _wreaddir
+#else
+#define DIRENT dirent
+#define DIRHDL DIR
+#define OPENDIR opendir
+#define CLOSEDIR closedir
+#define READDIR readdir
+#endif
+
 // Note that the 'norecurse' flag is handled as part of the directory read. 
 // This means that we always go into the top 'walk()' parameter if it is a 
 // directory, even if norecurse is set. Bug or Feature ?
@@ -341,24 +356,25 @@
 
     // This is a directory, read it and process entries:
 
+#ifndef _WIN32
     // Detect if directory already seen. This could just be several
     // symlinks pointing to the same place (if FtwFollow is set), it
     // could also be some other kind of cycle. In any case, there is
     // no point in entering again.
     // For now, we'll ignore the "other kind of cycle" part and only monitor
     // this is FtwFollow is set
-#ifndef _WIN32
     if (data->options & FtwFollow) {
 	DirId dirid(stp->st_dev, stp->st_ino);
 	if (data->donedirs.find(dirid) != data->donedirs.end()) {
-	    LOGINFO("Not processing ["  << (top) << "] (already seen as other path)\n" );
+	    LOGINFO("Not processing [" << top <<
+                    "] (already seen as other path)\n");
 	    return status;
 	}
 	data->donedirs.insert(dirid);
     }
 #endif
-    
-    DIR *d = opendir(top.c_str());
+    SYSPATH(top, systop);
+    DIRHDL *d = OPENDIR(systop);
     if (d == 0) {
 	data->logsyserr("opendir", top);
 	switch (errno) {
@@ -376,42 +392,38 @@
 	}
     }
 
-    struct dirent *ent;
-    while ((ent = readdir(d)) != 0) {
+    struct DIRENT *ent;
+    while ((ent = READDIR(d)) != 0) {
         string fn;
         struct stat st;
+#ifdef _WIN32
+        string sdname;
+        if (!wchartoutf8(ent->d_name, sdname)) {
+            LOGERR("wchartoutf8 failed in " << top << endl);
+            continue;
+        }
+        const char *dname = sdname.c_str();
+#else
+        const char *dname = ent->d_name;
+#endif
 	// Maybe skip dotfiles
-	if ((data->options & FtwSkipDotFiles) && ent->d_name[0] == '.')
+	if ((data->options & FtwSkipDotFiles) && dname[0] == '.')
 	    continue;
 	// Skip . and ..
-	if (!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) 
+	if (!strcmp(dname, ".") || !strcmp(dname, "..")) 
 	    continue;
 
 	// Skipped file names match ?
 	if (!data->skippedNames.empty()) {
-	    if (inSkippedNames(ent->d_name))
+	    if (inSkippedNames(dname))
 		continue;
 	}
-
-        fn = path_cat(top, ent->d_name);
-#ifdef _WIN32
-        // readdir gets the useful attrs, no inode indirection on windows,
-        // spare the path_fileprops() call, but make sure we mimick it.
-        memset(&st, 0, sizeof(st));
-        st.st_mtime = ent->d_mtime;
-        st.st_size = ent->d_size;
-        st.st_mode = ent->d_mode;
-        // ctime is really creation time on Windows. Just use mtime
-        // for all. We only use ctime on Unix to catch xattr changes
-        // anyway.
-        st.st_ctime = st.st_mtime;
-#else
+        fn = path_cat(top, dname);
         int statret =  path_fileprops(fn.c_str(), &st, data->options&FtwFollow);
         if (statret == -1) {
             data->logsyserr("stat", fn);
             continue;
         }
-#endif
 
         if (!data->skippedPaths.empty()) {
             // We do not check the ancestors. This means that you can have
@@ -461,7 +473,7 @@
 
  out:
     if (d)
-	closedir(d);
+	CLOSEDIR(d);
     return status;
 }