コード例 #1
1
ファイル: FileDescriptor.cpp プロジェクト: facebook/watchman
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));
}
コード例 #2
0
ファイル: Pipe.cpp プロジェクト: facebookexperimental/eden
// 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;
}