FileDescriptor openFileHandle(const char *path, const OpenFileHandleOptions &opts) { #ifndef _WIN32 int flags = (!opts.followSymlinks ? O_NOFOLLOW : 0) | (opts.closeOnExec ? O_CLOEXEC : 0) | #ifdef O_PATH (opts.metaDataOnly ? O_PATH : 0) | #endif ((opts.readContents && opts.writeContents) ? O_RDWR : (opts.writeContents ? O_WRONLY : opts.readContents ? O_RDONLY : 0)) | (opts.create ? O_CREAT : 0) | (opts.exclusiveCreate ? O_EXCL : 0) | (opts.truncate ? O_TRUNC : 0); auto fd = open(path, flags); if (fd == -1) { int err = errno; throw std::system_error( err, std::generic_category(), to<std::string>("open: ", path)); } FileDescriptor file(fd); #else // _WIN32 DWORD access = 0, share = 0, create = 0, attrs = 0; DWORD err; auto sec = SECURITY_ATTRIBUTES(); if (!strcmp(path, "/dev/null")) { path = "NUL:"; } auto wpath = w_string_piece(path).asWideUNC(); if (opts.metaDataOnly) { access = 0; } else { if (opts.writeContents) { access |= GENERIC_WRITE; } if (opts.readContents) { access |= GENERIC_READ; } } // We want more posix-y behavior by default share = FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE; sec.nLength = sizeof(sec); sec.bInheritHandle = TRUE; if (opts.closeOnExec) { sec.bInheritHandle = FALSE; } if (opts.create && opts.exclusiveCreate) { create = CREATE_NEW; } else if (opts.create && opts.truncate) { create = CREATE_ALWAYS; } else if (opts.create) { create = OPEN_ALWAYS; } else if (opts.truncate) { create = TRUNCATE_EXISTING; } else { create = OPEN_EXISTING; } attrs = FILE_FLAG_POSIX_SEMANTICS | FILE_FLAG_BACKUP_SEMANTICS; if (!opts.followSymlinks) { attrs |= FILE_FLAG_OPEN_REPARSE_POINT; } FileDescriptor file(intptr_t( CreateFileW(wpath.c_str(), access, share, &sec, create, attrs, nullptr))); err = GetLastError(); if (!file) { throw std::system_error( err, std::system_category(), std::string("CreateFileW for openFileHandle: ") + path); } #endif if (!opts.strictNameChecks) { return file; } auto opened = file.getOpenedPath(); if (w_string_piece(opened).pathIsEqual(path)) { #if !CAN_OPEN_SYMLINKS CaseSensitivity caseSensitive = opts.caseSensitive; if (caseSensitive == CaseSensitivity::Unknown) { caseSensitive = getCaseSensitivityForPath(path); } if (caseSensitive == CaseSensitivity::CaseInSensitive) { // We need to perform one extra check for case-insensitive // paths to make sure that we didn't accidentally open // the wrong case name. checkCanonicalBaseName(path); } #endif return file; } throw std::system_error( ENOENT, std::generic_category(), to<std::string>("open(", path, "): opened path doesn't match canonical path ", opened)); }
// Pipe constructor will either use security attr or the inherit flag. // If the security attribute is nullptr it will create one and will use the // inherit flag for it. Pipe::Pipe(PSECURITY_ATTRIBUTES securityAttr, bool inherit) { auto sec = SECURITY_ATTRIBUTES(); if (securityAttr == nullptr) { sec.nLength = sizeof(sec); sec.bInheritHandle = inherit; sec.lpSecurityDescriptor = nullptr; securityAttr = &sec; } if (!CreatePipe(&readHandle, &writeHandle, securityAttr, NULL)) { throw makeWin32ErrorExplicit(GetLastError(), "Failed to create a pipe"); } XLOG(DBG5) << "Handle Created: Read: " << readHandle << " Write: " << writeHandle << std::endl; }