File my_win_sopen()

in mysql_sys/my_winfile.cc [230:370]


File my_win_sopen(const char *path, int oflag, int shflag, int pmode) {
  DBUG_TRACE;
  WindowsErrorGuard weg;
  if (check_if_legal_filename(path)) {
    assert(GetLastError() == ERROR_SUCCESS);
    errno = EACCES;
    return -1;
  }

  SECURITY_ATTRIBUTES SecurityAttributes;
  SecurityAttributes.nLength = sizeof(SecurityAttributes);
  SecurityAttributes.lpSecurityDescriptor = nullptr;
  SecurityAttributes.bInheritHandle = !(oflag & _O_NOINHERIT);

  // Decode the (requested) OS file access flags
  DWORD fileaccess;
  switch (oflag & (_O_RDONLY | _O_WRONLY | _O_RDWR)) {
    case _O_RDONLY: /* read access */
      fileaccess = GENERIC_READ;
      break;
    case _O_WRONLY: /* write access */
      fileaccess = GENERIC_WRITE;
      break;
    case _O_RDWR: /* read and write access */
      fileaccess = GENERIC_READ | GENERIC_WRITE;
      break;
    default: /* error, bad oflag */
      errno = EINVAL;
      return -1;
  }

  // Decode OS file sharing flags
  DWORD fileshare;
  switch (shflag) {
    case _SH_DENYRW: /* exclusive access except delete */
      fileshare = FILE_SHARE_DELETE;
      break;
    case _SH_DENYWR: /* share read and delete access */
      fileshare = FILE_SHARE_READ | FILE_SHARE_DELETE;
      break;
    case _SH_DENYRD: /* share write and delete access */
      fileshare = FILE_SHARE_WRITE | FILE_SHARE_DELETE;
      break;
    case _SH_DENYNO: /* share read, write and delete access */
      fileshare = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
      break;
    case _SH_DENYRWD: /* exclusive access */
      fileshare = 0L;
      break;
    case _SH_DENYWRD: /* share read access */
      fileshare = FILE_SHARE_READ;
      break;
    case _SH_DENYRDD: /* share write access */
      fileshare = FILE_SHARE_WRITE;
      break;
    case _SH_DENYDEL: /* share read and write access */
      fileshare = FILE_SHARE_READ | FILE_SHARE_WRITE;
      break;
    default: /* error, bad shflag */
      errno = EINVAL;
      return -1;
  }

  // Decode OS method of opening/creating
  DWORD filecreate;
  switch (oflag & (_O_CREAT | _O_EXCL | _O_TRUNC)) {
    case 0:
    case _O_EXCL: /* ignore EXCL w/o CREAT */
      filecreate = OPEN_EXISTING;
      break;

    case _O_CREAT:
      filecreate = OPEN_ALWAYS;
      break;

    case _O_CREAT | _O_EXCL:
    case _O_CREAT | _O_TRUNC | _O_EXCL:
      filecreate = CREATE_NEW;
      break;

    case _O_TRUNC:
    case _O_TRUNC | _O_EXCL: /* ignore EXCL w/o CREAT */
      filecreate = TRUNCATE_EXISTING;
      break;

    case _O_CREAT | _O_TRUNC:
      filecreate = CREATE_ALWAYS;
      break;

    default:
      /* this can't happen ... all cases are covered */
      errno = EINVAL;
      return -1;
  }

  // Decode OS file attribute flags if _O_CREAT was specified
  DWORD fileattrib;
  fileattrib = FILE_ATTRIBUTE_NORMAL; /* default */

  int mask;
  if (oflag & _O_CREAT) {
    _umask((mask = _umask(0)));
    assert(errno == 0);
    if (!((pmode & ~mask) & _S_IWRITE)) fileattrib = FILE_ATTRIBUTE_READONLY;
  }

  /* Set temporary file (delete-on-close) attribute if requested. */
  if (oflag & _O_TEMPORARY) {
    fileattrib |= FILE_FLAG_DELETE_ON_CLOSE;
    fileaccess |= DELETE;
  }

  /* Set temporary file (delay-flush-to-disk) attribute if requested.*/
  if (oflag & _O_SHORT_LIVED) fileattrib |= FILE_ATTRIBUTE_TEMPORARY;

  /* Set sequential or random access attribute if requested. */
  if (oflag & _O_SEQUENTIAL)
    fileattrib |= FILE_FLAG_SEQUENTIAL_SCAN;
  else if (oflag & _O_RANDOM)
    fileattrib |= FILE_FLAG_RANDOM_ACCESS;

  /* try to open/create the file  */
  HANDLE osfh = CreateFile(path, fileaccess, fileshare, &SecurityAttributes,
                           filecreate, fileattrib, nullptr);

  if (osfh == INVALID_HANDLE_VALUE) {
    /*
       Note that it's not necessary to
       call _free_osfhnd (it hasn't been used yet).
    */
    return -1;
  }

  int fh = RegisterHandle(osfh, oflag & (_O_APPEND | _O_RDONLY | _O_TEXT));
  if (fh == -1) {
    // No scope_guard for this since we only close in one place.
    CloseHandle(osfh);
    return -1;
  }
  return fh;
}