99#include < limits>
1010#include < stdexcept>
1111
12+ #if RDF_PLATFORM_WINDOWS
13+ // Define NOMINMAX to prevent conflict between <limits> and <windows.h> include files.
14+ #define NOMINMAX
15+
16+ #include < corecrt_io.h>
17+ #include < fcntl.h>
18+ #include < io.h>
19+ #include < windows.h>
20+ #endif // #if RDF_PLATFORM_WINDOWS
21+
1222#include < algorithm>
1323// We use map so we don't have to provide a hash function for chunkId, which
1424// is a bit tricky with C++11 and old compilers
@@ -245,6 +255,11 @@ namespace internal
245255 std::unique_ptr<IStream> OpenFile (const char * filename,
246256 rdfStreamAccess access,
247257 rdfFileMode fileMode);
258+
259+ std::unique_ptr<IStream> OpenSharedFile (const char * filename,
260+ rdfStreamAccess access,
261+ rdfFileMode fileMode);
262+
248263 std::unique_ptr<IStream> CreateFile (const char * filename);
249264
250265 std::unique_ptr<IStream> CreateReadOnlyMemoryStream (const std::int64_t bufferSize,
@@ -1054,11 +1069,72 @@ namespace internal
10541069 }
10551070
10561071 // ////////////////////////////////////////////////////////////////////
1057- std::unique_ptr<IStream> OpenFile (const char * filename,
1072+ std::unique_ptr<IStream> OpenSharedFile (const char * filename,
1073+ rdfStreamAccess accessMode,
1074+ rdfFileMode fileMode)
1075+ {
1076+ #if RDF_PLATFORM_WINDOWS
1077+ const char * mode = nullptr ;
1078+
1079+ // For a shareable file on Windows, the file needs to be opened with the CreateFile() function.
1080+ unsigned long desired_access = 0 ;
1081+ unsigned long share_mode = FILE_SHARE_READ | FILE_SHARE_WRITE;
1082+ unsigned long creation_disposition = 0 ;
1083+ unsigned long flags_and_attributes = FILE_ATTRIBUTE_NORMAL;
1084+
1085+ if (accessMode == rdfStreamAccess::rdfStreamAccessRead) {
1086+ desired_access |= GENERIC_READ;
1087+ if (fileMode == rdfFileModeOpen) {
1088+ creation_disposition = OPEN_EXISTING;
1089+ mode = " rb" ;
1090+ } else if (fileMode == rdfFileModeCreate) {
1091+ throw std::runtime_error (" Cannot create file in read-only mode" );
1092+ }
1093+ } else if (accessMode == rdfStreamAccess::rdfStreamAccessReadWrite) {
1094+ desired_access |= GENERIC_READ | GENERIC_WRITE;
1095+ if (fileMode == rdfFileModeOpen) {
1096+ creation_disposition = OPEN_EXISTING;
1097+ mode = " r+b" ;
1098+ } else if (fileMode == rdfFileModeCreate) {
1099+ creation_disposition = OPEN_EXISTING;
1100+ mode = " w+b" ;
1101+ }
1102+ } else {
1103+ assert (false );
1104+ }
1105+
1106+ HANDLE object_handle = ::CreateFile (filename,
1107+ desired_access,
1108+ share_mode,
1109+ NULL ,
1110+ creation_disposition,
1111+ flags_and_attributes,
1112+ NULL );
1113+
1114+ // Convert the object handle to a file descriptor.
1115+ int file_handle = _open_osfhandle ((intptr_t )object_handle, _O_BINARY);
1116+ auto fd = _fdopen (file_handle, mode);
1117+ if (fd == nullptr ) {
1118+ CloseHandle (object_handle);
1119+ throw std::runtime_error (" Error opening file" );
1120+ }
1121+
1122+ // Disable inheritance of the file handle.
1123+ SetHandleInformation (object_handle, HANDLE_FLAG_INHERIT, 0 );
1124+ return rdf_make_unique<Filestream>(fd, accessMode);
1125+ #else
1126+ return OpenFile (filename, accessMode, fileMode);
1127+ #endif // #if RDF_PLATFORM_WINDOWS
1128+ }
1129+
1130+
1131+
1132+ std::unique_ptr<IStream> OpenFile (const char * filename,
10581133 rdfStreamAccess accessMode,
10591134 rdfFileMode fileMode)
10601135 {
10611136 const char * mode = nullptr ;
1137+
10621138 if (accessMode == rdfStreamAccessRead) {
10631139 if (fileMode == rdfFileModeOpen) {
10641140 mode = " rb" ;
@@ -1080,6 +1156,10 @@ namespace internal
10801156 throw std::runtime_error (" Could not open file" );
10811157 }
10821158
1159+ #if RDF_PLATFORM_WINDOWS
1160+ // Disable inheritance of the file handle.
1161+ SetHandleInformation ((HANDLE)_get_osfhandle (_fileno (fd)), HANDLE_FLAG_INHERIT, 0 );
1162+ #endif // #if RDF_PLATFORM_WINDOWS
10831163 return rdf_make_unique<Filestream>(fd, accessMode);
10841164 }
10851165
@@ -1090,7 +1170,12 @@ namespace internal
10901170 if (fd == nullptr ) {
10911171 throw std::runtime_error (" Could not create file" );
10921172 }
1093-
1173+ #if RDF_PLATFORM_WINDOWS
1174+ else {
1175+ // Disable inheritance of the file handle.
1176+ SetHandleInformation ((HANDLE)_get_osfhandle (_fileno (fd)), HANDLE_FLAG_INHERIT, 0 );
1177+ }
1178+ #endif // #if RDF_PLATFORM_WINDOWS
10941179 return rdf_make_unique<Filestream>(fd, rdfStreamAccessReadWrite);
10951180 }
10961181
@@ -1155,8 +1240,7 @@ to open an existing file for read/write or create a new one.
11551240The creation file mode requires read/write access, as creating a new file
11561241for read-only would result in an unusable stream.
11571242*/
1158- int RDF_EXPORT rdfStreamFromFile (const rdfStreamFromFileCreateInfo* info,
1159- rdfStream** handle)
1243+ int RDF_EXPORT rdfStreamFromFile (const rdfStreamFromFileCreateInfo* info, rdfStream** handle)
11601244{
11611245 RDF_C_API_BEGIN
11621246
@@ -1174,8 +1258,16 @@ int RDF_EXPORT rdfStreamFromFile(const rdfStreamFromFileCreateInfo* info,
11741258
11751259 *handle = new rdfStream;
11761260 try {
1177- (*handle)->stream =
1178- rdf::internal::OpenFile (info->filename , info->accessMode , info->fileMode );
1261+ if (info->is_shareable )
1262+ {
1263+ (*handle)->stream =
1264+ rdf::internal::OpenSharedFile (info->filename , info->accessMode , info->fileMode );
1265+ }
1266+ else
1267+ {
1268+ (*handle)->stream =
1269+ rdf::internal::OpenFile (info->filename , info->accessMode , info->fileMode );
1270+ }
11791271 } catch (...) {
11801272 delete *handle;
11811273 *handle = nullptr ;
0 commit comments