Commit e05e777d authored by Laszlo Csomor's avatar Laszlo Csomor

Windows: support long paths

Add implementations of open(2), mkdir(2), stat(2),
etc. that support long paths under Windows (paths
longer than MAX_PATH in <windows.h>, which is 260
characters).

The implementations are in a separate namespace
(google::protobuf::internal::win32), so they won't
collide with the standard implementations in
<io.h>, but after importing them with `using` they
can be drop-in replacements.

Fixes https://github.com/bazelbuild/bazel/issues/2634
Fixes https://github.com/google/protobuf/issues/2891
parent 9ab7c73f
......@@ -108,6 +108,7 @@ cc_library(
"src/google/protobuf/stubs/bytestream.cc",
"src/google/protobuf/stubs/common.cc",
"src/google/protobuf/stubs/int128.cc",
"src/google/protobuf/stubs/io_win32.cc",
"src/google/protobuf/stubs/once.cc",
"src/google/protobuf/stubs/status.cc",
"src/google/protobuf/stubs/statusor.cc",
......@@ -159,6 +160,7 @@ cc_library(
"src/google/protobuf/service.cc",
"src/google/protobuf/source_context.pb.cc",
"src/google/protobuf/struct.pb.cc",
"src/google/protobuf/stubs/io_win32.cc",
"src/google/protobuf/stubs/mathlimits.cc",
"src/google/protobuf/stubs/substitute.cc",
"src/google/protobuf/text_format.cc",
......@@ -470,6 +472,7 @@ COMMON_TEST_SRCS = [
# AUTOGEN(common_test_srcs)
"src/google/protobuf/arena_test_util.cc",
"src/google/protobuf/map_test_util.cc",
"src/google/protobuf/stubs/io_win32.cc",
"src/google/protobuf/test_util.cc",
"src/google/protobuf/testing/file.cc",
"src/google/protobuf/testing/googletest.cc",
......@@ -490,6 +493,16 @@ cc_binary(
],
)
cc_test(
name = "win32_test",
srcs = ["src/google/protobuf/stubs/io_win32_unittest.cc"],
deps = [
":protobuf_lite",
"//external:gtest_main",
],
tags = ["manual", "windows"],
)
cc_test(
name = "protobuf_test",
srcs = COMMON_TEST_SRCS + [
......@@ -536,6 +549,7 @@ cc_test(
"src/google/protobuf/stubs/bytestream_unittest.cc",
"src/google/protobuf/stubs/common_unittest.cc",
"src/google/protobuf/stubs/int128_unittest.cc",
"src/google/protobuf/stubs/io_win32_unittest.cc",
"src/google/protobuf/stubs/once_unittest.cc",
"src/google/protobuf/stubs/status_test.cc",
"src/google/protobuf/stubs/statusor_test.cc",
......
......@@ -99,6 +99,7 @@ copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\casts.h" includ
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\common.h" include\google\protobuf\stubs\common.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\fastmem.h" include\google\protobuf\stubs\fastmem.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\hash.h" include\google\protobuf\stubs\hash.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\io_win32.h" include\google\protobuf\stubs\io_win32.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\logging.h" include\google\protobuf\stubs\logging.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\macros.h" include\google\protobuf\stubs\macros.h
copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\mutex.h" include\google\protobuf\stubs\mutex.h
......
......@@ -13,6 +13,7 @@ set(libprotobuf_lite_files
${protobuf_source_dir}/src/google/protobuf/stubs/bytestream.cc
${protobuf_source_dir}/src/google/protobuf/stubs/common.cc
${protobuf_source_dir}/src/google/protobuf/stubs/int128.cc
${protobuf_source_dir}/src/google/protobuf/stubs/io_win32.cc
${protobuf_source_dir}/src/google/protobuf/stubs/once.cc
${protobuf_source_dir}/src/google/protobuf/stubs/status.cc
${protobuf_source_dir}/src/google/protobuf/stubs/statusor.cc
......
......@@ -93,6 +93,7 @@ set(libprotoc_files
${protobuf_source_dir}/src/google/protobuf/compiler/ruby/ruby_generator.cc
${protobuf_source_dir}/src/google/protobuf/compiler/subprocess.cc
${protobuf_source_dir}/src/google/protobuf/compiler/zip_writer.cc
${protobuf_source_dir}/src/google/protobuf/stubs/io_win32.cc
)
set(libprotoc_headers
......
......@@ -160,6 +160,8 @@ set(tests_files
${protobuf_source_dir}/src/google/protobuf/stubs/bytestream_unittest.cc
${protobuf_source_dir}/src/google/protobuf/stubs/common_unittest.cc
${protobuf_source_dir}/src/google/protobuf/stubs/int128_unittest.cc
${protobuf_source_dir}/src/google/protobuf/stubs/io_win32.cc
${protobuf_source_dir}/src/google/protobuf/stubs/io_win32_unittest.cc
${protobuf_source_dir}/src/google/protobuf/stubs/once_unittest.cc
${protobuf_source_dir}/src/google/protobuf/stubs/status_test.cc
${protobuf_source_dir}/src/google/protobuf/stubs/statusor_test.cc
......@@ -198,6 +200,7 @@ target_link_libraries(tests libprotoc libprotobuf gmock_main)
set(test_plugin_files
${protobuf_source_dir}/src/google/protobuf/compiler/mock_code_generator.cc
${protobuf_source_dir}/src/google/protobuf/stubs/io_win32.cc
${protobuf_source_dir}/src/google/protobuf/testing/file.cc
${protobuf_source_dir}/src/google/protobuf/testing/file.h
${protobuf_source_dir}/src/google/protobuf/compiler/test_plugin.cc
......
......@@ -198,6 +198,8 @@ libprotobuf_lite_la_SOURCES = \
google/protobuf/stubs/hash.h \
google/protobuf/stubs/int128.cc \
google/protobuf/stubs/int128.h \
google/protobuf/stubs/io_win32.cc \
google/protobuf/stubs/io_win32.h \
google/protobuf/stubs/map_util.h \
google/protobuf/stubs/mathutil.h \
google/protobuf/stubs/once.cc \
......@@ -761,6 +763,7 @@ protobuf_test_SOURCES = \
google/protobuf/stubs/bytestream_unittest.cc \
google/protobuf/stubs/common_unittest.cc \
google/protobuf/stubs/int128_unittest.cc \
google/protobuf/stubs/io_win32_unittest.cc \
google/protobuf/stubs/once_unittest.cc \
google/protobuf/stubs/statusor_test.cc \
google/protobuf/stubs/status_test.cc \
......
......@@ -45,10 +45,7 @@
#endif
#include <sys/stat.h>
#include <fcntl.h>
#ifdef _MSC_VER
#include <io.h>
#include <direct.h>
#else
#ifndef _MSC_VER
#include <unistd.h>
#endif
#include <errno.h>
......@@ -80,6 +77,7 @@
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/stubs/io_win32.h>
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/substitute.h>
......@@ -91,22 +89,6 @@ namespace google {
namespace protobuf {
namespace compiler {
#if defined(_WIN32)
#define mkdir(name, mode) mkdir(name)
#ifndef W_OK
#define W_OK 02 // not defined by MSVC for whatever reason
#endif
#ifndef F_OK
#define F_OK 00 // not defined by MSVC for whatever reason
#endif
#ifndef STDIN_FILENO
#define STDIN_FILENO 0
#endif
#ifndef STDOUT_FILENO
#define STDOUT_FILENO 1
#endif
#endif
#ifndef O_BINARY
#ifdef _O_BINARY
#define O_BINARY _O_BINARY
......@@ -118,6 +100,14 @@ namespace compiler {
namespace {
#if defined(_WIN32) && !defined(__CYGWIN__)
static const char* kPathSeparator = ";";
// DO NOT include <io.h>, instead create functions in io_win32.{h,cc} and import
// them like we do below.
using google::protobuf::internal::win32::access;
using google::protobuf::internal::win32::close;
using google::protobuf::internal::win32::mkdir;
using google::protobuf::internal::win32::open;
using google::protobuf::internal::win32::setmode;
using google::protobuf::internal::win32::write;
#else
static const char* kPathSeparator = ":";
#endif
......@@ -141,9 +131,9 @@ static bool IsWindowsAbsolutePath(const string& text) {
void SetFdToTextMode(int fd) {
#ifdef _WIN32
if (_setmode(fd, _O_TEXT) == -1) {
if (setmode(fd, _O_TEXT) == -1) {
// This should never happen, I think.
GOOGLE_LOG(WARNING) << "_setmode(" << fd << ", _O_TEXT): " << strerror(errno);
GOOGLE_LOG(WARNING) << "setmode(" << fd << ", _O_TEXT): " << strerror(errno);
}
#endif
// (Text and binary are the same on non-Windows platforms.)
......@@ -151,9 +141,9 @@ void SetFdToTextMode(int fd) {
void SetFdToBinaryMode(int fd) {
#ifdef _WIN32
if (_setmode(fd, _O_BINARY) == -1) {
if (setmode(fd, _O_BINARY) == -1) {
// This should never happen, I think.
GOOGLE_LOG(WARNING) << "_setmode(" << fd << ", _O_BINARY): " << strerror(errno);
GOOGLE_LOG(WARNING) << "setmode(" << fd << ", _O_BINARY): " << strerror(errno);
}
#endif
// (Text and binary are the same on non-Windows platforms.)
......
......@@ -35,9 +35,7 @@
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#ifdef _MSC_VER
#include <io.h>
#else
#ifndef _MSC_VER
#include <unistd.h>
#endif
#include <memory>
......@@ -65,27 +63,27 @@
#include <gtest/gtest.h>
#include <google/protobuf/stubs/strutil.h>
#include <google/protobuf/stubs/io_win32.h>
namespace google {
namespace protobuf {
namespace compiler {
#if defined(_WIN32)
// DO NOT include <io.h>, instead create functions in io_win32.{h,cc} and import
// them like we do below.
using google::protobuf::internal::win32::access;
using google::protobuf::internal::win32::dup;
using google::protobuf::internal::win32::dup2;
using google::protobuf::internal::win32::close;
using google::protobuf::internal::win32::open;
using google::protobuf::internal::win32::write;
#endif
// Disable the whole test when we use tcmalloc for "draconian" heap checks, in
// which case tcmalloc will print warnings that fail the plugin tests.
#if !GOOGLE_PROTOBUF_HEAP_CHECK_DRACONIAN
#if defined(_WIN32)
#ifndef STDIN_FILENO
#define STDIN_FILENO 0
#endif
#ifndef STDOUT_FILENO
#define STDOUT_FILENO 1
#endif
#ifndef F_OK
#define F_OK 00 // not defined by MSVC for whatever reason
#endif
#endif
namespace {
bool FileExists(const string& path) {
......
......@@ -33,7 +33,7 @@
// Sanjay Ghemawat, Jeff Dean, and others.
#ifdef _MSC_VER
#include <io.h>
#include <direct.h>
#else
#include <unistd.h>
#endif
......@@ -53,19 +53,21 @@
#include <google/protobuf/compiler/parser.h>
#include <google/protobuf/io/tokenizer.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/stubs/io_win32.h>
#include <google/protobuf/stubs/strutil.h>
namespace google {
namespace protobuf {
namespace compiler {
#ifdef _WIN32
#ifndef F_OK
#define F_OK 00 // not defined by MSVC for whatever reason
#endif
#include <ctype.h>
// DO NOT include <io.h>, instead create functions in io_win32.{h,cc} and import
// them like we do below.
using google::protobuf::internal::win32::access;
using google::protobuf::internal::win32::open;
#endif
namespace google {
namespace protobuf {
namespace compiler {
// Returns true if the text looks like a Windows-style absolute path, starting
// with a drive letter. Example: "C:\foo". TODO(kenton): Share this with
// copy in command_line_interface.cc?
......
......@@ -28,9 +28,7 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifdef _MSC_VER
#include <io.h>
#else
#ifndef _MSC_VER
#include <unistd.h>
#endif
#include <climits>
......@@ -49,8 +47,15 @@
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/io_win32.h>
#include <google/protobuf/stubs/strutil.h>
#if defined(_WIN32)
// DO NOT include <io.h>, instead create functions in io_win32.{h,cc} and import
// them like we do below.
using google::protobuf::internal::win32::open;
#endif
// NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some
// error cases, so it seems to be ok to use as a back door for errors.
......
......@@ -36,18 +36,12 @@
#include <set>
#ifdef _WIN32
#include <io.h>
#include <fcntl.h>
#ifndef STDIN_FILENO
#define STDIN_FILENO 0
#endif
#ifndef STDOUT_FILENO
#define STDOUT_FILENO 1
#endif
#else
#include <unistd.h>
#endif
#include <google/protobuf/stubs/io_win32.h>
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/compiler/plugin.pb.h>
......@@ -55,6 +49,11 @@
#include <google/protobuf/descriptor.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#if defined(_WIN32)
// DO NOT include <io.h>, instead create functions in io_win32.{h,cc} and import
// them like we do below.
using google::protobuf::internal::win32::setmode;
#endif
namespace google {
namespace protobuf {
......@@ -150,8 +149,8 @@ int PluginMain(int argc, char* argv[], const CodeGenerator* generator) {
}
#ifdef _WIN32
_setmode(STDIN_FILENO, _O_BINARY);
_setmode(STDOUT_FILENO, _O_BINARY);
setmode(STDIN_FILENO, _O_BINARY);
setmode(STDOUT_FILENO, _O_BINARY);
#endif
CodeGeneratorRequest request;
......
......@@ -32,9 +32,7 @@
// Based on original Protocol Buffers design by
// Sanjay Ghemawat, Jeff Dean, and others.
#ifdef _MSC_VER
#include <io.h>
#else
#ifndef _MSC_VER
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
......@@ -43,9 +41,9 @@
#include <errno.h>
#include <iostream>
#include <algorithm>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/io_win32.h>
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/stl_util.h>
......@@ -58,6 +56,13 @@ namespace io {
// Win32 lseek is broken: If invoked on a non-seekable file descriptor, its
// return value is undefined. We re-define it to always produce an error.
#define lseek(fd, offset, origin) ((off_t)-1)
// DO NOT include <io.h>, instead create functions in io_win32.{h,cc} and import
// them like we do below.
using google::protobuf::internal::win32::access;
using google::protobuf::internal::win32::close;
using google::protobuf::internal::win32::open;
using google::protobuf::internal::win32::read;
using google::protobuf::internal::win32::write;
#endif
namespace {
......
......@@ -47,9 +47,7 @@
// implementations.
#ifdef _MSC_VER
#include <io.h>
#else
#ifndef _MSC_VER
#include <unistd.h>
#endif
#include <stdlib.h>
......@@ -72,6 +70,7 @@
#endif
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/io_win32.h>
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/testing/googletest.h>
#include <google/protobuf/testing/file.h>
......@@ -84,6 +83,12 @@ namespace {
#ifdef _WIN32
#define pipe(fds) _pipe(fds, 4096, O_BINARY)
// DO NOT include <io.h>, instead create functions in io_win32.{h,cc} and import
// them like we do below.
using google::protobuf::internal::win32::access;
using google::protobuf::internal::win32::mkdir;
using google::protobuf::internal::win32::open;
using google::protobuf::internal::win32::close;
#endif
#ifndef O_BINARY
......
......@@ -37,9 +37,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#ifdef _MSC_VER
#include <io.h>
#else
#ifndef _MSC_VER
#include <unistd.h>
#endif
#include <sstream>
......@@ -56,6 +54,7 @@
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/stubs/common.h>
#include <google/protobuf/stubs/io_win32.h>
#include <google/protobuf/stubs/logging.h>
#include <google/protobuf/testing/googletest.h>
#include <gtest/gtest.h>
......@@ -63,6 +62,13 @@
namespace google {
namespace protobuf {
#if defined(_WIN32)
// DO NOT include <io.h>, instead create functions in io_win32.{h,cc} and import
// them like we do below.
using google::protobuf::internal::win32::close;
using google::protobuf::internal::win32::open;
#endif
#ifndef O_BINARY
#ifdef _O_BINARY
#define O_BINARY _O_BINARY
......
This diff is collapsed.
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Author: laszlocsomor@google.com (Laszlo Csomor)
//
// This file contains the declarations for Windows implementations of
// commonly used POSIX functions such as open(2) and access(2), as well
// as macro definitions for flags of these functions.
//
// By including this file you'll redefine open/access/etc. to
// ::google::protobuf::internal::win32::{open/access/etc.}.
// Make sure you don't include a header that attempts to redeclare or
// redefine these functions, that'll lead to confusing compilation
// errors. It's best to #include this file as the last one to ensure that.
//
// This file is only used on Windows, it's empty on other platforms.
#ifndef GOOGLE_PROTOBUF_STUBS_IO_WIN32_H__
#define GOOGLE_PROTOBUF_STUBS_IO_WIN32_H__
#if defined(_WIN32)
#include <string>
namespace google {
namespace protobuf {
namespace internal {
namespace win32 {
FILE* fopen(const char* path, const char* mode);
int access(const char* path, int mode);
int chdir(const char* path);
int close(int fd);
int dup(int fd);
int dup2(int fd1, int fd2);
int mkdir(const char* path, int _mode);
int open(const char* path, int flags, int mode = 0);
int read(int fd, void* buffer, size_t size);
int setmode(int fd, int mode);
int stat(const char* path, struct _stat* buffer);
int write(int fd, const void* buffer, size_t size);
std::wstring testonly_path_to_winpath(const std::string& path);
} // namespace win32
} // namespace internal
} // namespace protobuf
} // namespace google
#ifndef W_OK
#define W_OK 02 // not defined by MSVC for whatever reason
#endif
#ifndef F_OK
#define F_OK 00 // not defined by MSVC for whatever reason
#endif
#ifndef STDIN_FILENO
#define STDIN_FILENO 0
#endif
#ifndef STDOUT_FILENO
#define STDOUT_FILENO 1
#endif
#endif // defined(_WIN32)
#endif // GOOGLE_PROTOBUF_STUBS_IO_WIN32_H__
This diff is collapsed.
......@@ -38,24 +38,28 @@
#ifdef _MSC_VER
#define WIN32_LEAN_AND_MEAN // yeah, right
#include <windows.h> // Find*File(). :(
#include <io.h>
#include <direct.h>
// #include <direct.h>
#else
#include <dirent.h>
#include <unistd.h>
#endif
#include <errno.h>
#include <google/protobuf/stubs/io_win32.h>
namespace google {
namespace protobuf {
#ifdef _WIN32
#define mkdir(name, mode) mkdir(name)
// Windows doesn't have symbolic links.
#define lstat stat
#ifndef F_OK
#define F_OK 00 // not defined by MSVC for whatever reason
#endif
// DO NOT include <io.h>, instead create functions in io_win32.{h,cc} and import
// them like we do below.
using google::protobuf::internal::win32::access;
using google::protobuf::internal::win32::chdir;
using google::protobuf::internal::win32::fopen;
using google::protobuf::internal::win32::mkdir;
using google::protobuf::internal::win32::stat;
#endif
bool File::Exists(const string& name) {
......@@ -113,6 +117,9 @@ void File::WriteStringToFileOrDie(const string& contents, const string& name) {
}
bool File::CreateDir(const string& name, int mode) {
if (!name.empty()) {
GOOGLE_CHECK_OK(name.back() != '.');
}
return mkdir(name.c_str(), mode) == 0;
}
......
......@@ -33,14 +33,14 @@
#include <google/protobuf/testing/googletest.h>
#include <google/protobuf/testing/file.h>
#include <google/protobuf/stubs/io_win32.h>
#include <google/protobuf/stubs/strutil.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <stdlib.h>
#ifdef _MSC_VER
#include <io.h>
#include <direct.h>
// #include <direct.h>
#else
#include <unistd.h>
#endif
......@@ -53,7 +53,13 @@ namespace google {
namespace protobuf {
#ifdef _WIN32
#define mkdir(name, mode) mkdir(name)
// DO NOT include <io.h>, instead create functions in io_win32.{h,cc} and import
// them like we do below.
using google::protobuf::internal::win32::close;
using google::protobuf::internal::win32::dup2;
using google::protobuf::internal::win32::dup;
using google::protobuf::internal::win32::mkdir;
using google::protobuf::internal::win32::open;
#endif
#ifndef O_BINARY
......@@ -111,14 +117,32 @@ string GetTemporaryDirectoryName() {
char b[L_tmpnam + 1]; // HPUX multithread return 0 if s is 0
string result = tmpnam(b);
#ifdef _WIN32
// Avoid a trailing dot by changing it to an underscore. On Win32 the names of
// files and directories can, but should not, end with dot.
//
// In MS-DOS and FAT16 filesystem the filenames were 8dot3 style so it didn't
// make sense to have a name ending in dot without an extension, so the shell
// silently ignored trailing dots. To this day the Win32 API still maintains
// this behavior and silently ignores trailing dots in path arguments of
// functions such as CreateFile{A,W}. Even POSIX API function implementations
// seem to wrap the Win32 API functions (e.g. CreateDirectoryA) and behave
// this way.
// It's possible to avoid this behavior and create files / directories with
// trailing dots (using CreateFileW / CreateDirectoryW and prefixing the path
// with "\\?\") but these will be degenerate in the sense that you cannot
// chdir into such directories (or navigate into them with Windows Explorer)
// nor can you open such files with some programs (e.g. Notepad).
if (result.back() == '.') {
result[result.size() - 1] = '_';
}
// On Win32, tmpnam() returns a file prefixed with '\', but which is supposed
// to be used in the current working directory. WTF?
if (HasPrefixString(result, "\\")) {
result.erase(0, 1);
}
// The Win32 API accepts forward slashes as a path delimiter even though
// backslashes are standard. Let's avoid confusion and use only forward
// slashes.
// The Win32 API accepts forward slashes as a path delimiter as long as the
// path doesn't use the "\\?\" prefix.
// Let's avoid confusion and use only forward slashes.
result = StringReplace(result, "\\", "/", true);
#endif // _WIN32
return result;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment