Index: CMakeLists.txt =================================================================== --- CMakeLists.txt +++ CMakeLists.txt @@ -54,6 +54,7 @@ option(LIBCXX_ENABLE_WERROR "Fail and stop if a warning is triggered." OFF) option(LIBCXX_ENABLE_CXX1Y "Enable -std=c++1y and use of c++1y language features if the compiler supports it." OFF) option(LIBCXX_ENABLE_SHARED "Build libc++ as a shared library." ON) +option(LIBCXX_ENABLE_GLOBAL_FILESYSTEM_NAMESPACE "Build libc++ with support for the global filesystem namespace." ON) option(LIBCXX_ENABLE_THREADS "Build libc++ with support for threads." ON) option(LIBCXX_BUILD_32_BITS "Build 32 bit libc++" OFF) option(LIBCXX_ENABLE_MONOTONIC_CLOCK @@ -232,6 +233,11 @@ add_definitions(-D_CRT_SECURE_NO_WARNINGS) endif() +# LIBCXX_ENABLE_GLOBAL_FILESYSTEM_NAMESPACE configuration +if (NOT LIBCXX_ENABLE_GLOBAL_FILESYSTEM_NAMESPACE) + add_definitions(-D_LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE) +endif() + # LIBCXX_ENABLE_THREADS configuration if (NOT LIBCXX_ENABLE_THREADS) add_definitions(-D_LIBCPP_HAS_NO_THREADS) Index: include/__config =================================================================== --- include/__config +++ include/__config @@ -719,4 +719,12 @@ _LIBCPP_HAS_NO_THREADS is defined. #endif +// Systems that use capability-based security (FreeBSD with Capsicum, +// Nuxi CloudABI) may only provide local filesystem access (using *at()). +// Functions like open(), rename(), unlink() and stat() should not be +// used, as they attempt to access the global filesystem namespace. +#ifdef __CloudABI__ +#define _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE +#endif + #endif // _LIBCPP_CONFIG Index: include/cstdio =================================================================== --- include/cstdio +++ include/cstdio @@ -144,14 +144,18 @@ using ::fpos_t; using ::size_t; +#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE using ::remove; using ::rename; using ::tmpfile; using ::tmpnam; +#endif using ::fclose; using ::fflush; +#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE using ::fopen; using ::freopen; +#endif using ::setbuf; using ::setvbuf; using ::fprintf; Index: include/fstream =================================================================== --- include/fstream +++ include/fstream @@ -206,8 +206,10 @@ // 27.9.1.4 Members: bool is_open() const; +#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE basic_filebuf* open(const char* __s, ios_base::openmode __mode); basic_filebuf* open(const string& __s, ios_base::openmode __mode); +#endif basic_filebuf* close(); protected: @@ -463,6 +465,7 @@ return __file_ != 0; } +#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE template basic_filebuf<_CharT, _Traits>* basic_filebuf<_CharT, _Traits>::open(const char* __s, ios_base::openmode __mode) @@ -550,6 +553,7 @@ { return open(__s.c_str(), __mode); } +#endif template basic_filebuf<_CharT, _Traits>* @@ -1005,8 +1009,10 @@ typedef typename traits_type::off_type off_type; basic_ifstream(); +#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE explicit basic_ifstream(const char* __s, ios_base::openmode __mode = ios_base::in); explicit basic_ifstream(const string& __s, ios_base::openmode __mode = ios_base::in); +#endif #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES basic_ifstream(basic_ifstream&& __rhs); #endif @@ -1018,8 +1024,10 @@ basic_filebuf* rdbuf() const; bool is_open() const; +#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE void open(const char* __s, ios_base::openmode __mode = ios_base::in); void open(const string& __s, ios_base::openmode __mode = ios_base::in); +#endif void close(); private: @@ -1033,6 +1041,7 @@ { } +#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE template inline _LIBCPP_INLINE_VISIBILITY basic_ifstream<_CharT, _Traits>::basic_ifstream(const char* __s, ios_base::openmode __mode) @@ -1050,6 +1059,7 @@ if (__sb_.open(__s, __mode | ios_base::in) == 0) this->setstate(ios_base::failbit); } +#endif #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES @@ -1107,6 +1117,7 @@ return __sb_.is_open(); } +#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE template void basic_ifstream<_CharT, _Traits>::open(const char* __s, ios_base::openmode __mode) @@ -1126,6 +1137,7 @@ else this->setstate(ios_base::failbit); } +#endif template inline _LIBCPP_INLINE_VISIBILITY @@ -1163,8 +1175,10 @@ basic_filebuf* rdbuf() const; bool is_open() const; +#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE void open(const char* __s, ios_base::openmode __mode = ios_base::out); void open(const string& __s, ios_base::openmode __mode = ios_base::out); +#endif void close(); private: @@ -1178,6 +1192,7 @@ { } +#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE template inline _LIBCPP_INLINE_VISIBILITY basic_ofstream<_CharT, _Traits>::basic_ofstream(const char* __s, ios_base::openmode __mode) @@ -1195,6 +1210,7 @@ if (__sb_.open(__s, __mode | ios_base::out) == 0) this->setstate(ios_base::failbit); } +#endif #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES @@ -1252,6 +1268,7 @@ return __sb_.is_open(); } +#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE template void basic_ofstream<_CharT, _Traits>::open(const char* __s, ios_base::openmode __mode) @@ -1271,6 +1288,7 @@ else this->setstate(ios_base::failbit); } +#endif template inline _LIBCPP_INLINE_VISIBILITY @@ -1295,8 +1313,10 @@ typedef typename traits_type::off_type off_type; basic_fstream(); +#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE explicit basic_fstream(const char* __s, ios_base::openmode __mode = ios_base::in | ios_base::out); explicit basic_fstream(const string& __s, ios_base::openmode __mode = ios_base::in | ios_base::out); +#endif #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES basic_fstream(basic_fstream&& __rhs); #endif @@ -1308,8 +1328,10 @@ basic_filebuf* rdbuf() const; bool is_open() const; +#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE void open(const char* __s, ios_base::openmode __mode = ios_base::in | ios_base::out); void open(const string& __s, ios_base::openmode __mode = ios_base::in | ios_base::out); +#endif void close(); private: @@ -1323,6 +1345,7 @@ { } +#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE template inline _LIBCPP_INLINE_VISIBILITY basic_fstream<_CharT, _Traits>::basic_fstream(const char* __s, ios_base::openmode __mode) @@ -1340,6 +1363,7 @@ if (__sb_.open(__s, __mode) == 0) this->setstate(ios_base::failbit); } +#endif #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES @@ -1397,6 +1421,7 @@ return __sb_.is_open(); } +#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE template void basic_fstream<_CharT, _Traits>::open(const char* __s, ios_base::openmode __mode) @@ -1416,6 +1441,7 @@ else this->setstate(ios_base::failbit); } +#endif template inline _LIBCPP_INLINE_VISIBILITY Index: test/CMakeLists.txt =================================================================== --- test/CMakeLists.txt +++ test/CMakeLists.txt @@ -42,6 +42,7 @@ pythonize_bool(LIBCXX_ENABLE_RTTI) pythonize_bool(LIBCXX_ENABLE_SHARED) pythonize_bool(LIBCXX_BUILD_32_BITS) + pythonize_bool(LIBCXX_ENABLE_GLOBAL_FILESYSTEM_NAMESPACE) pythonize_bool(LIBCXX_ENABLE_THREADS) pythonize_bool(LIBCXX_ENABLE_MONOTONIC_CLOCK) # The tests shouldn't link to any ABI library when it has been linked into Index: test/libcxx/test/config.py =================================================================== --- test/libcxx/test/config.py +++ test/libcxx/test/config.py @@ -347,6 +347,7 @@ # Configure feature flags. self.configure_compile_flags_exceptions() self.configure_compile_flags_rtti() + self.configure_compile_flags_no_global_filesystem_namespace() enable_32bit = self.get_lit_bool('enable_32bit', False) if enable_32bit: self.cxx.flags += ['-m32'] @@ -395,6 +396,15 @@ self.config.available_features.add('libcpp-no-rtti') self.cxx.compile_flags += ['-fno-rtti', '-D_LIBCPP_NO_RTTI'] + def configure_compile_flags_no_global_filesystem_namespace(self): + enable_global_filesystem_namespace = self.get_lit_bool( + 'enable_global_filesystem_namespace', True) + if not enable_global_filesystem_namespace: + self.config.available_features.add( + 'libcpp-has-no-global-filesystem-namespace') + self.cxx.compile_flags += [ + '-D_LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE'] + def configure_compile_flags_no_threads(self): self.cxx.compile_flags += ['-D_LIBCPP_HAS_NO_THREADS'] self.config.available_features.add('libcpp-has-no-threads') Index: test/lit.site.cfg.in =================================================================== --- test/lit.site.cfg.in +++ test/lit.site.cfg.in @@ -8,6 +8,7 @@ config.enable_rtti = "@LIBCXX_ENABLE_RTTI@" config.enable_shared = "@LIBCXX_ENABLE_SHARED@" config.enable_32bit = "@LIBCXX_BUILD_32_BITS@" +config.enable_global_filesystem_namespace = "@LIBCXX_ENABLE_GLOBAL_FILESYSTEM_NAMESPACE@" config.enable_threads = "@LIBCXX_ENABLE_THREADS@" config.enable_monotonic_clock = "@LIBCXX_ENABLE_MONOTONIC_CLOCK@" config.cxx_abi = "@LIBCXX_CXX_ABI_LIBNAME@" Index: test/std/input.output/file.streams/c.files/cstdio.pass.cpp =================================================================== --- test/std/input.output/file.streams/c.files/cstdio.pass.cpp +++ test/std/input.output/file.streams/c.files/cstdio.pass.cpp @@ -88,14 +88,18 @@ std::size_t s = 0; char* cp = 0; std::va_list va; +#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); +#endif static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); +#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); +#endif static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); static_assert((std::is_same::value), ""); Index: test/std/input.output/file.streams/c.files/no.global.filesystem.namespace/fopen.fail.cpp =================================================================== --- test/std/input.output/file.streams/c.files/no.global.filesystem.namespace/fopen.fail.cpp +++ test/std/input.output/file.streams/c.files/no.global.filesystem.namespace/fopen.fail.cpp @@ -0,0 +1,15 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include + +int main() { + // fopen is not available on systems without a global filesystem namespace. + std::fopen("", ""); +} Index: test/std/input.output/file.streams/c.files/no.global.filesystem.namespace/lit.local.cfg =================================================================== --- test/std/input.output/file.streams/c.files/no.global.filesystem.namespace/lit.local.cfg +++ test/std/input.output/file.streams/c.files/no.global.filesystem.namespace/lit.local.cfg @@ -0,0 +1,2 @@ +if 'libcpp-has-no-global-filesystem-namespace' not in config.available_features: + config.unsupported = True Index: test/std/input.output/file.streams/fstreams/lit.local.cfg =================================================================== --- test/std/input.output/file.streams/fstreams/lit.local.cfg +++ test/std/input.output/file.streams/fstreams/lit.local.cfg @@ -0,0 +1,2 @@ +if 'libcpp-has-no-global-filesystem-namespace' in config.available_features: + config.unsupported = True Index: test/std/localization/locales/locale.convenience/conversions/conversions.buffer/lit.local.cfg =================================================================== --- test/std/localization/locales/locale.convenience/conversions/conversions.buffer/lit.local.cfg +++ test/std/localization/locales/locale.convenience/conversions/conversions.buffer/lit.local.cfg @@ -0,0 +1,2 @@ +if 'libcpp-has-no-global-filesystem-namespace' in config.available_features: + config.unsupported = True Index: test/support/platform_support.h =================================================================== --- test/support/platform_support.h +++ test/support/platform_support.h @@ -15,6 +15,8 @@ #ifndef PLATFORM_SUPPORT_H #define PLATFORM_SUPPORT_H +#include <__config> + // locale names #ifdef _WIN32 // WARNING: Windows does not support UTF-8 codepages. @@ -65,6 +67,7 @@ } #endif +#ifndef _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE inline std::string get_temp_file_name() @@ -90,5 +93,6 @@ return Name; #endif } +#endif // _LIBCPP_HAS_NO_GLOBAL_FILESYSTEM_NAMESPACE #endif // PLATFORM_SUPPORT_H