Ijar: extract file stating logic to platform_utils

This change takes us closer to compiling ijar,
thus Bazel, with MSVC.

See https://github.com/bazelbuild/bazel/issues/2107 and https://github.com/bazelbuild/bazel/issues/2157

--
MOS_MIGRATED_REVID=140717828
diff --git a/third_party/ijar/BUILD b/third_party/ijar/BUILD
index 63d1182..4137620 100644
--- a/third_party/ijar/BUILD
+++ b/third_party/ijar/BUILD
@@ -27,7 +27,10 @@
         "mapped_file.h",
         "zip.h",
     ],
-    deps = [":zlib_client"],
+    deps = [
+        ":platform_utils",
+        ":zlib_client",
+    ],
 )
 
 cc_library(
@@ -40,6 +43,16 @@
     deps = ["//third_party/zlib"],
 )
 
+cc_library(
+    name = "platform_utils",
+    srcs = ["platform_utils.cc"],
+    hdrs = [
+        "common.h",
+        "platform_utils.h",
+    ],
+    visibility = ["//visibility:private"],
+)
+
 cc_binary(
     name = "zipper",
     srcs = ["zip_main.cc"],
diff --git a/third_party/ijar/platform_utils.cc b/third_party/ijar/platform_utils.cc
new file mode 100644
index 0000000..19e10c0
--- /dev/null
+++ b/third_party/ijar/platform_utils.cc
@@ -0,0 +1,50 @@
+// Copyright 2016 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "third_party/ijar/platform_utils.h"
+
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+
+#ifdef COMPILER_MSVC
+#else  // not COMPILER_MSVC
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#endif  // COMPILER_MSVC
+
+#include <string>
+
+namespace devtools_ijar {
+
+bool stat_file(const char* path, Stat* result) {
+#ifdef COMPILER_MSVC
+  // TODO(laszlocsomor) 2016-12-01: implement this and other methods, in order
+  // to close https://github.com/bazelbuild/bazel/issues/2157.
+  fprintf(stderr, "Not yet implemented on Windows\n");
+  return false;
+#else   // not COMPILER_MSVC
+  struct stat statst;
+  if (stat(path, &statst) < 0) {
+    return false;
+  }
+  result->total_size = statst.st_size;
+  result->file_mode = statst.st_mode;
+  result->is_directory = (statst.st_mode & S_IFDIR) != 0;
+  return true;
+#endif  // COMPILER_MSVC
+}
+
+}  // namespace devtools_ijar
diff --git a/third_party/ijar/platform_utils.h b/third_party/ijar/platform_utils.h
new file mode 100644
index 0000000..cb48819
--- /dev/null
+++ b/third_party/ijar/platform_utils.h
@@ -0,0 +1,42 @@
+// Copyright 2016 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef THIRD_PARTY_IJAR_PLATFORM_UTILS_H_
+#define THIRD_PARTY_IJAR_PLATFORM_UTILS_H_
+
+#include <stdlib.h>
+
+#include <string>
+
+#include "third_party/ijar/common.h"
+
+namespace devtools_ijar {
+
+// Platform-independent stat data.
+struct Stat {
+  // Total size of the file in bytes.
+  int total_size;
+  // The Unix file mode from the stat.st_mode field.
+  mode_t file_mode;
+  // True if this is a directory.
+  bool is_directory;
+};
+
+// Writes stat data into `result` about the file under `path`.
+// Returns true upon success: file is found and can be stat'ed.
+bool stat_file(const char* path, Stat* result);
+
+}  // namespace devtools_ijar
+
+#endif  // THIRD_PARTY_IJAR_PLATFORM_UTILS_H_
diff --git a/third_party/ijar/zip.cc b/third_party/ijar/zip.cc
index 7b34151..6fd9590 100644
--- a/third_party/ijar/zip.cc
+++ b/third_party/ijar/zip.cc
@@ -35,6 +35,7 @@
 #include <vector>
 
 #include "third_party/ijar/mapped_file.h"
+#include "third_party/ijar/platform_utils.h"
 #include "third_party/ijar/zip.h"
 #include "third_party/ijar/zlib_client.h"
 
@@ -1119,18 +1120,18 @@
 u8 ZipBuilder::EstimateSize(char const* const* files,
                             char const* const* zip_paths,
                             int nb_entries) {
-  struct stat statst;
+  Stat file_stat;
   // Digital signature field size = 6, End of central directory = 22, Total = 28
   u8 size = 28;
   // Count the size of all the files in the input to estimate the size of the
   // output.
   for (int i = 0; i < nb_entries; i++) {
-    statst.st_size = 0;
-    if (files[i] != NULL && stat(files[i], &statst) != 0) {
+    file_stat.total_size = 0;
+    if (files[i] != NULL && !stat_file(files[i], &file_stat)) {
       fprintf(stderr, "File %s does not seem to exist.", files[i]);
       return 0;
     }
-    size += statst.st_size;
+    size += file_stat.total_size;
     // Add sizes of Zip meta data
     // local file header = 30 bytes
     // data descriptor = 12 bytes
diff --git a/third_party/ijar/zip_main.cc b/third_party/ijar/zip_main.cc
index 388bca7..351faba 100644
--- a/third_party/ijar/zip_main.cc
+++ b/third_party/ijar/zip_main.cc
@@ -32,6 +32,7 @@
 #include <set>
 #include <string>
 
+#include "third_party/ijar/platform_utils.h"
 #include "third_party/ijar/zip.h"
 
 namespace devtools_ijar {
@@ -106,14 +107,14 @@
 // All folders are created using "mode" for creation mode.
 void mkdirs(const char *path, mode_t mode) {
   char path_[PATH_MAX];
-  struct stat statst;
+  Stat file_stat;
   strncpy(path_, path, PATH_MAX);
   path_[PATH_MAX-1] = 0;
   char *pointer = path_;
   while ((pointer = strchr(pointer, '/')) != NULL) {
     if (path_ != pointer) {  // skip leading slash
       *pointer = 0;
-      if (stat(path_, &statst) != 0) {
+      if (!stat_file(path_, &file_stat)) {
         if (mkdir(path_, mode) < 0) {
           fprintf(stderr, "Cannot create folder %s: %s\n",
                   path_, strerror(errno));
@@ -224,18 +225,18 @@
 // add a file to the zip
 int add_file(std::unique_ptr<ZipBuilder> const &builder, char *file,
              char *zip_path, bool flatten, bool verbose, bool compress) {
-  struct stat statst;
-  statst.st_size = 0;
-  statst.st_mode = 0666;
+  Stat file_stat;
+  file_stat.total_size = 0;
+  file_stat.file_mode = 0666;
   if (file != NULL) {
-    if (stat(file, &statst) < 0) {
+    if (!stat_file(file, &file_stat)) {
       fprintf(stderr, "Cannot stat file %s: %s.\n", file, strerror(errno));
       return -1;
     }
   }
   char *final_path = zip_path != NULL ? zip_path : file;
 
-  bool isdir = (statst.st_mode & S_IFDIR) != 0;
+  bool isdir = file_stat.is_directory;
 
   if (flatten && isdir) {
     return 0;
@@ -261,12 +262,12 @@
   }
 
   if (verbose) {
-    mode_t perm = statst.st_mode & 0777;
+    mode_t perm = file_stat.file_mode & 0777;
     printf("%c %o %s\n", isdir ? 'd' : 'f', perm, path);
   }
 
-  u1 *buffer = builder->NewFile(path, mode_to_zipattr(statst.st_mode));
-  if (isdir || statst.st_size == 0) {
+  u1 *buffer = builder->NewFile(path, mode_to_zipattr(file_stat.file_mode));
+  if (isdir || file_stat.total_size == 0) {
     builder->FinishFile(0);
   } else {
     // read the input file
@@ -276,13 +277,13 @@
               strerror(errno));
       return -1;
     }
-    if (copy_file_to_buffer(fd, statst.st_size, buffer) < 0) {
+    if (copy_file_to_buffer(fd, file_stat.total_size, buffer) < 0) {
       fprintf(stderr, "Can't read file %s: %s.\n", file, strerror(errno));
       close(fd);
       return -1;
     }
     close(fd);
-    builder->FinishFile(statst.st_size, compress, true);
+    builder->FinishFile(file_stat.total_size, compress, true);
   }
   return 0;
 }
@@ -290,20 +291,21 @@
 // Read a list of files separated by newlines. The resulting array can be
 // freed using the free method.
 char **read_filelist(char *filename) {
-  struct stat statst;
+  Stat file_stat;
+  if (!stat_file(filename, &file_stat)) {
+    fprintf(stderr, "Cannot stat file %s: %s.\n", filename, strerror(errno));
+    return NULL;
+  }
+
   int fd = open(filename, O_RDONLY);
   if (fd < 0) {
     fprintf(stderr, "Can't open file %s for reading: %s.\n", filename,
             strerror(errno));
     return NULL;
   }
-  if (fstat(fd, &statst) < 0) {
-    fprintf(stderr, "Cannot stat file %s: %s.\n", filename, strerror(errno));
-    return NULL;
-  }
 
-  char *data = static_cast<char *>(malloc(statst.st_size));
-  if (copy_file_to_buffer(fd, statst.st_size, data) < 0) {
+  char *data = static_cast<char *>(malloc(file_stat.total_size));
+  if (copy_file_to_buffer(fd, file_stat.total_size, data) < 0) {
     fprintf(stderr, "Can't read file %s: %s.\n", filename, strerror(errno));
     close(fd);
     return NULL;
@@ -311,26 +313,26 @@
   close(fd);
 
   int nb_entries = 1;
-  for (int i = 0; i < statst.st_size; i++) {
+  for (int i = 0; i < file_stat.total_size; i++) {
     if (data[i] == '\n') {
       nb_entries++;
     }
   }
 
   size_t sizeof_array = sizeof(char *) * (nb_entries + 1);
-  void *result = malloc(sizeof_array + statst.st_size);
+  void *result = malloc(sizeof_array + file_stat.total_size);
   // copy the content
   char **filelist = static_cast<char **>(result);
   char *content = static_cast<char *>(result) + sizeof_array;
-  memcpy(content, data, statst.st_size);
+  memcpy(content, data, file_stat.total_size);
   free(data);
   // Create the corresponding array
   int j = 1;
   filelist[0] = content;
-  for (int i = 0; i < statst.st_size; i++) {
+  for (int i = 0; i < file_stat.total_size; i++) {
     if (content[i] == '\n') {
       content[i] = 0;
-      if (i + 1 < statst.st_size) {
+      if (i + 1 < file_stat.total_size) {
         filelist[j] = content + i + 1;
         j++;
       }