Merge pull request #183 from hughbe/stat-fixes

Fix Windows build with posix specific stat APIs
diff --git a/include/llbuild/Basic/PlatformUtility.h b/include/llbuild/Basic/PlatformUtility.h
index 2415007..c2453d1 100644
--- a/include/llbuild/Basic/PlatformUtility.h
+++ b/include/llbuild/Basic/PlatformUtility.h
@@ -19,27 +19,19 @@
 #define LLBUILD_BASIC_PLATFORMUTILITY_H
 
 #include <cstdio>
-#include <sys/stat.h>
 
 namespace llbuild {
 namespace basic {
 namespace sys {
-#if defined(_WIN32)
-using StatStruct = struct ::_stat;
-#else
-using StatStruct = struct ::stat;
-#endif
 
 bool chdir(const char *fileName);
 int close(int fileHandle);
-int lstat(const char *fileName, StatStruct *buf);
 bool mkdir(const char *fileName);
 int pclose(FILE *stream);
 int pipe(int ptHandles[2]);
 FILE *popen(const char *command, const char *mode);
 int read(int fileHandle, void *destinationBuffer, unsigned int maxCharCount);
 int rmdir(const char *path);
-int stat(const char *fileName, StatStruct *buf);
 int symlink(const char *source, const char *target);
 int unlink(const char *fileName);
 int write(int fileHandle, void *destinationBuffer, unsigned int maxCharCount);
diff --git a/include/llbuild/Basic/Stat.h b/include/llbuild/Basic/Stat.h
new file mode 100644
index 0000000..7d79e38
--- /dev/null
+++ b/include/llbuild/Basic/Stat.h
@@ -0,0 +1,77 @@
+//===- Stat.h -------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See http://swift.org/LICENSE.txt for license information
+// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLBUILD_BASIC_STAT_H
+#define LLBUILD_BASIC_STAT_H
+
+#include <sys/stat.h>
+
+#include "llvm/Support/FileSystem.h"
+
+namespace llbuild {
+namespace basic {
+namespace sys {
+
+#if !defined(S_IFBLK)
+#define S_IFBLK 0060000
+#endif
+#if !defined(S_IFIFO)
+#define S_IFIFO 0010000
+#endif
+#if !defined(S_IFSOCK)
+#define S_IFSOCK 00140000
+#endif
+#if !defined(S_IFLNK)
+#define S_IFLNK 0120000
+#endif
+
+#if !defined(S_ISREG)
+#define S_ISREG(mode) ((mode) & _S_IFMT) == S_IFREG
+#endif
+
+#if !defined(S_ISDIR)
+#define S_ISDIR(mode) ((mode) & _S_IFMT) == S_IFDIR
+#endif
+
+#if !defined(S_ISBLK)
+#define S_ISBLK(mode) ((mode) & _S_IFMT) == S_IFBLK
+#endif
+
+#if !defined(S_ISCHR)
+#define S_ISCHR(mode) ((mode) & _S_IFMT) == S_IFCHR
+#endif
+
+#if !defined(S_ISFIFO)
+#define S_ISFIFO(mode) ((mode) & _S_IFMT) == S_IFIFO
+#endif
+
+#if !defined(S_ISSOCK)
+#define S_ISSOCK(mode) ((mode) & _S_IFMT) == S_IFSOCK
+#endif
+
+#if !defined(S_ISLNK)
+#define S_ISLNK(mode) ((mode) & _S_IFMT) == S_IFLNK
+#endif
+
+#if defined(_WIN32)
+using StatStruct = struct ::_stat;
+#else
+using StatStruct = struct ::stat;
+#endif
+
+int lstat(const char *fileName, StatStruct *buf);
+int stat(const char *fileName, StatStruct *buf);
+}
+}
+}
+
+#endif // LLBUILD_BASIC_STAT_H
diff --git a/lib/Basic/FileInfo.cpp b/lib/Basic/FileInfo.cpp
index 7e7d7dd..ec76640 100644
--- a/lib/Basic/FileInfo.cpp
+++ b/lib/Basic/FileInfo.cpp
@@ -12,7 +12,7 @@
 
 #include "llbuild/Basic/FileInfo.h"
 
-#include "llbuild/Basic/PlatformUtility.h"
+#include "llbuild/Basic/Stat.h"
 
 #include <cassert>
 #include <cstring>
diff --git a/lib/Basic/FileSystem.cpp b/lib/Basic/FileSystem.cpp
index 42db497..010348f 100644
--- a/lib/Basic/FileSystem.cpp
+++ b/lib/Basic/FileSystem.cpp
@@ -12,6 +12,7 @@
 
 #include "llbuild/Basic/FileSystem.h"
 #include "llbuild/Basic/PlatformUtility.h"
+#include "llbuild/Basic/Stat.h"
 
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/Support/FileSystem.h"
@@ -27,7 +28,7 @@
   using namespace llvm;
   using namespace llvm::sys::fs;
 
-  static std::error_code fillStatus(int StatRet, const struct stat &Status,
+  static std::error_code fillStatus(int StatRet, const llbuild::basic::sys::StatStruct &Status,
                                     file_status &Result) {
     if (StatRet != 0) {
       std::error_code ec(errno, std::generic_category());
@@ -55,10 +56,14 @@
     else if (S_ISLNK(Status.st_mode))
       Type = file_type::symlink_file;
 
+#if defined(_WIN32)
+    Result = file_status(Type);
+#else
     perms Perms = static_cast<perms>(Status.st_mode);
     Result =
     file_status(Type, Perms, Status.st_dev, Status.st_ino, Status.st_mtime,
                 Status.st_uid, Status.st_gid, Status.st_size);
+#endif
 
     return std::error_code();
   }
@@ -67,8 +72,8 @@
     SmallString<128> PathStorage;
     StringRef P = Path.toNullTerminatedStringRef(PathStorage);
 
-    struct stat Status;
-    int StatRet = ::lstat(P.begin(), &Status);
+    llbuild::basic::sys::StatStruct Status;
+    int StatRet = llbuild::basic::sys::lstat(P.begin(), &Status);
     return fillStatus(StatRet, Status, Result);
   }
 
@@ -167,7 +172,7 @@
     }
 
     // Check if `path` is a directory.
-    struct stat statbuf;
+    llbuild::basic::sys::StatStruct statbuf;
     if (llbuild::basic::sys::lstat(path.c_str(), &statbuf) != 0) {
       return false;
     }
diff --git a/lib/Basic/PlatformUtility.cpp b/lib/Basic/PlatformUtility.cpp
index 2498e96..0ef78b9 100644
--- a/lib/Basic/PlatformUtility.cpp
+++ b/lib/Basic/PlatformUtility.cpp
@@ -8,6 +8,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llbuild/Basic/PlatformUtility.h"
+#include "llbuild/Basic/Stat.h"
 
 #if defined(_WIN32)
 #include "LeanWindows.h"
diff --git a/unittests/Basic/FileSystemTest.cpp b/unittests/Basic/FileSystemTest.cpp
index 65182b6..31c94aa 100644
--- a/unittests/Basic/FileSystemTest.cpp
+++ b/unittests/Basic/FileSystemTest.cpp
@@ -15,6 +15,7 @@
 #include "llbuild/Basic/FileSystem.h"
 #include "llbuild/Basic/LLVM.h"
 #include "llbuild/Basic/PlatformUtility.h"
+#include "llbuild/Basic/Stat.h"
 
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/MemoryBuffer.h"
@@ -94,7 +95,7 @@
   bool result = fs->remove(tempDir.c_str());
   EXPECT_TRUE(result);
 
-  struct stat statbuf;
+  sys::StatStruct statbuf;
   EXPECT_EQ(-1, sys::stat(tempDir.c_str(), &statbuf));
   EXPECT_EQ(ENOENT, errno);
 }
@@ -144,7 +145,7 @@
   bool result = fs->remove(tempDir.c_str());
   EXPECT_TRUE(result);
 
-  struct stat statbuf;
+  sys::StatStruct  statbuf;
   EXPECT_EQ(-1, sys::stat(tempDir.c_str(), &statbuf));
   EXPECT_EQ(ENOENT, errno);
   // Verify that the symlink target still exists.