From 692eae711d5061160896335cd59feab223ed5909 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 22 Dec 2016 20:54:36 +0000 Subject: [PATCH] Fix emulated readdir() d_type to return DT_FILE or DT_DIR like Unix does We used to abuse dirent.d_type to store Windows attributes, but we can now just add a new attribute to store these (win_attrs), so I have. --- lib/bbackupd/BackupClientDirectoryRecord.cpp | 14 +++++--------- lib/win32/emu.cpp | 10 +++++++++- lib/win32/emu.h | 14 +++++++++++++- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/lib/bbackupd/BackupClientDirectoryRecord.cpp b/lib/bbackupd/BackupClientDirectoryRecord.cpp index 94cb7965b..f39c2b707 100644 --- a/lib/bbackupd/BackupClientDirectoryRecord.cpp +++ b/lib/bbackupd/BackupClientDirectoryRecord.cpp @@ -435,13 +435,9 @@ bool BackupClientDirectoryRecord::SyncDirectoryEntry( #ifdef WIN32 // Don't stat the file just yet, to ensure that users can exclude // unreadable files to suppress warnings that they are not accessible. - // - // Our emulated readdir() abuses en->d_type, which would normally - // contain DT_REG, DT_DIR, etc, but we only use it here and prefer to - // have the full file attributes. int type; - if (en->d_type & FILE_ATTRIBUTE_DIRECTORY) + if (en->d_type == DT_DIR) { type = S_IFDIR; } @@ -514,24 +510,24 @@ bool BackupClientDirectoryRecord::SyncDirectoryEntry( return false; } - #ifdef WIN32 +#ifdef WIN32 // exclude reparse points, as Application Data points to the // parent directory under Vista and later, and causes an // infinite loop: // http://social.msdn.microsoft.com/forums/en-US/windowscompatibility/thread/05d14368-25dd-41c8-bdba-5590bf762a68/ - if (en->d_type & FILE_ATTRIBUTE_REPARSE_POINT) + if (en->win_attrs & FILE_ATTRIBUTE_REPARSE_POINT) { rNotifier.NotifyMountPointSkipped(this, realFileName); return false; } - #endif +#endif // WIN32 } else // not a file or directory, what is it? { if (type == S_IFSOCK #ifndef WIN32 || type == S_IFIFO -#endif +#endif // !WIN32 ) { // removed notification for these types diff --git a/lib/win32/emu.cpp b/lib/win32/emu.cpp index 1f6392d5e..87992f1ab 100644 --- a/lib/win32/emu.cpp +++ b/lib/win32/emu.cpp @@ -1141,7 +1141,15 @@ struct dirent *readdir(DIR *dp) NULL, NULL); //den->d_name = (char *)dp->info.name; den->d_name = &tempbuff[0]; - den->d_type = dp->info.dwFileAttributes; + den->win_attrs = dp->info.dwFileAttributes; + if(dp->info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + { + den->d_type = DT_DIR; + } + else + { + den->d_type = DT_REG; + } } else // FindNextFileW failed { diff --git a/lib/win32/emu.h b/lib/win32/emu.h index 91793004a..d6b3badd9 100644 --- a/lib/win32/emu.h +++ b/lib/win32/emu.h @@ -213,10 +213,22 @@ inline int strncasecmp(const char *s1, const char *s2, size_t count) #error You must not include the MinGW dirent.h! #endif +// File types for struct dirent.d_type. Not all are supported by our emulated readdir(): +#define DT_UNKNOWN 0 +#define DT_FIFO 1 +#define DT_CHR 2 +#define DT_DIR 4 +#define DT_BLK 6 +#define DT_REG 8 +#define DT_LNK 10 +#define DT_SOCK 12 +#define DT_WHT 14 + struct dirent { char *d_name; - DWORD d_type; // file attributes + int d_type; // emulated UNIX file attributes + DWORD win_attrs; // WIN32_FIND_DATA.dwFileAttributes }; struct DIR