@@ -244,20 +244,51 @@ code copy_directory_ex(const path& from, const path& to) NOEXCEPT
244244
245245int open (const path& filename) NOEXCEPT
246246{
247+ // TODO: provide as parameter for random vs. sequential accesss.
248+ auto random{ true };
249+
247250 const auto path = system::to_extended_path (filename);
248251 int file_descriptor{};
249252
250- // _wsopen_s and open set errno on failure.
251- // _wsopen_s and wstring do not throw (but are unannotated).
252253#if defined(HAVE_MSC)
253- // sets file_descriptor = -1 on error.
254- _wsopen_s (&file_descriptor, path.c_str (),
255- O_RDWR | _O_BINARY | _O_RANDOM, _SH_DENYWR, _S_IREAD | _S_IWRITE);
254+ // _wsopen_s and wstring do not throw (but are unannotated).
255+ // sets file_descriptor = -1 and errno on error.
256+ ::_wsopen_s (&file_descriptor, path.c_str(),
257+ O_RDWR | _O_BINARY | (random ? _O_RANDOM : _O_SEQUENTIAL),
258+ _SH_DENYWR, _S_IREAD | _S_IWRITE);
256259#else
257- // returns -1 on failure.
258- file_descriptor = ::open (path.c_str (),
259- O_RDWR, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
260+ // open sets errno on failure.
261+ file_descriptor = ::open (path.c_str (), O_RDWR, S_IRUSR | S_IWUSR);
262+ if (file_descriptor != -1 )
263+ {
264+ // _O_RANDOM equivalent, posix_fadvise returns error on failure.
265+ const auto advice = random ? POSIX_FADV_RANDOM : POSIX_FADV_SEQUENTIAL;
266+ const auto result = ::posix_fadvise (file_descriptor, 0 , 0 , advice);
267+ if (!is_zero (result))
268+ {
269+ close (file_descriptor);
270+ file_descriptor = -1 ;
271+ errno = result;
272+ }
273+ else
274+ {
275+ // _SH_DENYWR equivalent.
276+ const struct flock lock
277+ {
278+ .l_type = F_WRLCK, .l_whence = SEEK_SET, .l_start = 0 , .l_len = 0
279+ };
280+
281+ if (::fcntl (file_descriptor, F_SETLK, &lock) == -1 )
282+ {
283+ const auto last = errno;
284+ close (file_descriptor);
285+ file_descriptor = -1 ;
286+ errno = last;
287+ }
288+ }
289+ }
260290#endif
291+
261292 return file_descriptor;
262293}
263294
0 commit comments