Bug 1409692 - Use _wfopen instead of fopen on windows executed code in TraceLoggingGraph. r?jandem draft
authorAndi-Bogdan Postelnicu <bpostelnicu@mozilla.com>
Thu, 19 Oct 2017 12:24:18 +0300
changeset 683221 3f11e9f0ba542bbf0f9838389bb138a74e59898d
parent 682167 4efa95ae9141a1973b2cdc026f315691f4e3d7ea
child 736564 c8a28339a8f306f4ca4649eca0fbf3ffcb2f607d
push id85289
push userbmo:bpostelnicu@mozilla.com
push dateThu, 19 Oct 2017 10:31:20 +0000
reviewersjandem
bugs1409692
milestone58.0a1
Bug 1409692 - Use _wfopen instead of fopen on windows executed code in TraceLoggingGraph. r?jandem MozReview-Commit-ID: BE90ptsAaFf
js/src/vm/TraceLoggingGraph.cpp
mfbt/FileAccessWrappers.h
mfbt/moz.build
--- a/js/src/vm/TraceLoggingGraph.cpp
+++ b/js/src/vm/TraceLoggingGraph.cpp
@@ -11,16 +11,17 @@
 #define getpid _getpid
 #else
 #include <unistd.h>
 #endif
 
 #include "mozilla/EndianUtils.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/ScopeExit.h"
+#include "mozilla/FileAccessWrappers.h"
 
 #include "jsstr.h"
 
 #include "js/UniquePtr.h"
 #include "threading/LockGuard.h"
 #include "threading/Thread.h"
 #include "vm/TraceLogging.h"
 
@@ -94,28 +95,28 @@ AllocTraceLogFilename(const char* patter
 }
 
 bool
 TraceLoggerGraphState::init()
 {
     pid_ = (uint32_t) getpid();
 
     js::UniqueChars filename = AllocTraceLogFilename("tl-data.%u.json", pid_);
-    out = fopen(filename.get(), "w");
+    out = mozilla::FileOpen(filename.get(), "w");
     if (!out) {
         fprintf(stderr, "warning: failed to create TraceLogger output file %s\n", filename.get());
         return false;
     }
 
     fprintf(out, "[");
 
     // Write the latest tl-data.*.json file to tl-data.json.
     // In most cases that is the wanted file.
     js::UniqueChars masterFilename = AllocTraceLogFilename("tl-data.json");
-    if (FILE* last = fopen(masterFilename.get(), "w")) {
+    if (FILE* last = mozilla::FileOpen(masterFilename.get(), "w")) {
         char *basename = strrchr(filename.get(), '/');
         basename = basename ? basename + 1 : filename.get();
         fprintf(last, "\"%s\"", basename);
         fclose(last);
     }
 
 #ifdef DEBUG
     initialized = true;
@@ -233,29 +234,29 @@ TraceLoggerGraph::init(uint64_t startTim
 
     uint32_t loggerId = traceLoggerGraphState->nextLoggerId();
     if (loggerId == uint32_t(-1))
         return false;
 
     uint32_t pid = traceLoggerGraphState->pid();
 
     js::UniqueChars dictFilename = AllocTraceLogFilename("tl-dict.%u.%d.json", pid, loggerId);
-    dictFile = fopen(dictFilename.get(), "w");
+    dictFile = mozilla::FileOpen(dictFilename.get(), "w");
     if (!dictFile)
         return false;
     auto cleanupDict = MakeScopeExit([&] { fclose(dictFile); dictFile = nullptr; });
 
     js::UniqueChars treeFilename = AllocTraceLogFilename("tl-tree.%u.%d.tl", pid, loggerId);
-    treeFile = fopen(treeFilename.get(), "w+b");
+    treeFile = mozilla::FileOpen(treeFilename.get(), "w+b");
     if (!treeFile)
         return false;
     auto cleanupTree = MakeScopeExit([&] { fclose(treeFile); treeFile = nullptr; });
 
     js::UniqueChars eventFilename = AllocTraceLogFilename("tl-event.%u.%d.tl", pid, loggerId);
-    eventFile = fopen(eventFilename.get(), "wb");
+    eventFile = mozilla::FileOpen(eventFilename.get(), "wb");
     if (!eventFile)
         return false;
     auto cleanupEvent = MakeScopeExit([&] { fclose(eventFile); eventFile = nullptr; });
 
     // Create the top tree node and corresponding first stack item.
     TreeEntry& treeEntry = tree.pushUninitialized();
     treeEntry.setStart(startTimestamp);
     treeEntry.setStop(0);
new file mode 100644
--- /dev/null
+++ b/mfbt/FileAccessWrappers.h
@@ -0,0 +1,41 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* Provides a safer way to use fopen on systems that don't support UTF file
+ * system, like Microsoft Windows. */
+
+#ifndef mozilla_FileAccessWrappers_h
+#define mozilla_FileAccessWrappers_h
+
+#include <stdio.h>
+#include <string.h>
+#ifdef XP_WIN
+#include <windows.h>
+#endif
+
+namespace mozilla {
+
+FILE*
+FileOpen(const char* path, const char* mode)
+{
+#ifdef XP_WIN
+  /* Prevent lossy conversion by using wchar_t* for path names on Windows. This
+   * is not the case on MacOS since the filesystem is always UTF-8 and nor on
+   * Linux where the 8-bit string is the canonical POSIX filename. */
+  const size_t wPathSize = strlen(path) + 1;
+  const size_t wModeSize = strlen(mode) + 1;
+  wchar_t wPath[wPathSize];
+  wchar_t wMode[wModeSize];
+  MultiByteToWideChar(CP_UTF8, 0, path, -1, wPath, wPathSize);
+  MultiByteToWideChar(CP_UTF8, 0, mode, -1, wMode, wModeSize);
+  return _wfopen(wPath, wMode);
+#else
+  return fopen(path, mode);
+#endif
+}
+}
+
+#endif  /* mozilla_FileAccessWrappers_h_ */
\ No newline at end of file
--- a/mfbt/moz.build
+++ b/mfbt/moz.build
@@ -37,16 +37,17 @@ EXPORTS.mozilla = [
     'double-conversion.h',
     'DoublyLinkedList.h',
     'EndianUtils.h',
     'EnumeratedArray.h',
     'EnumeratedRange.h',
     'EnumSet.h',
     'EnumTypeTraits.h',
     'FastBernoulliTrial.h',
+    'FileAccessWrappers.h',
     'FloatingPoint.h',
     'GuardObjects.h',
     'HashFunctions.h',
     'IndexSequence.h',
     'IntegerPrintfMacros.h',
     'IntegerRange.h',
     'IntegerTypeTraits.h',
     'JSONWriter.h',