VirtualBox

source: kBuild/trunk/src/lib/nt/ntopenat.c@ 3646

Last change on this file since 3646 was 3601, checked in by bird, 16 months ago

ntopenat: On CIFS shared we may get errno == EINVAL when trying to _open a directory.

File size: 5.3 KB
Line 
1/* $Id: ntdir.c 3007 2016-11-06 16:46:43Z bird $ */
2/** @file
3 * MSC + NT openat API.
4 */
5
6/*
7 * Copyright (c) 2005-2021 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
25 * IN THE SOFTWARE.
26 *
27 * Alternatively, the content of this file may be used under the terms of the
28 * GPL version 2 or later, or LGPL version 2.1 or later.
29 */
30
31
32/*******************************************************************************
33* Header Files *
34*******************************************************************************/
35#include <errno.h>
36#include <assert.h>
37#include <fcntl.h>
38#include <io.h>
39
40#include "ntstuff.h"
41#include "nthlp.h"
42#include "ntopenat.h"
43#include "ntstat.h"
44
45
46#define IS_ALPHA(ch) ( ((ch) >= 'A' && (ch) <= 'Z') || ((ch) >= 'a' && (ch) <= 'z') )
47#define IS_SLASH(ch) ((ch) == '\\' || (ch) == '/')
48
49
50
51static int birdOpenInt(const char *pszPath, int fFlags, unsigned __int16 fMode)
52{
53 /*
54 * Try open it using the CRT's open function, but deal with opening
55 * directories as the CRT doesn't allow doing that.
56 */
57 int const iErrnoSaved = errno;
58 int iErrno;
59 int fd = open(pszPath, fFlags, fMode);
60 if ( fd < 0
61 && ((iErrno = errno) == EACCES || iErrno == ENOENT || iErrno == EISDIR || iErrno == EINVAL /*CIFS*/)
62 && (fFlags & (_O_WRONLY | _O_RDWR | _O_RDONLY)) == _O_RDONLY
63 && (fFlags & (_O_CREAT | _O_TRUNC | _O_EXCL)) == 0 )
64 {
65 BirdStat_T Stat;
66 if (!birdStatFollowLink(pszPath, &Stat))
67 {
68 if (S_ISDIR(Stat.st_mode))
69 {
70 HANDLE hDir;
71 errno = iErrnoSaved;
72 hDir = birdOpenFile(pszPath,
73 FILE_READ_DATA | FILE_READ_ATTRIBUTES | SYNCHRONIZE,
74 FILE_ATTRIBUTE_NORMAL,
75 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
76 FILE_OPEN,
77 FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT,
78 OBJ_CASE_INSENSITIVE);
79 if (hDir != INVALID_HANDLE_VALUE)
80 {
81 fd = _open_osfhandle((intptr_t)hDir, fFlags);
82 if (fd >= 0)
83 return fd;
84 birdCloseFile(hDir);
85 }
86 }
87 else
88 errno = EACCES;
89 }
90 else
91 errno = EACCES;
92 }
93 return fd;
94}
95
96
97int birdOpen(const char *pszPath, int fFlags, ...)
98{
99 unsigned __int16 fMode;
100 va_list va;
101 va_start(va, fFlags);
102 fMode = va_arg(va, unsigned __int16);
103 va_end(va);
104 return birdOpenInt(pszPath, fFlags, fMode);
105}
106
107
108
109/**
110 * Implements opendir.
111 */
112int birdOpenAt(int fdDir, const char *pszPath, int fFlags, ...)
113{
114 HANDLE hDir;
115
116 /*
117 * Retrieve the mode mask.
118 */
119 unsigned __int16 fMode;
120 va_list va;
121 va_start(va, fFlags);
122 fMode = va_arg(va, unsigned __int16);
123 va_end(va);
124
125 /*
126 * Just call 'open' directly if we can get away with it:
127 */
128 if (fdDir == AT_FDCWD)
129 return birdOpenInt(pszPath, fFlags, fMode);
130
131 if (IS_SLASH(pszPath[0]))
132 {
133 if (IS_SLASH(pszPath[1]) && !IS_SLASH(pszPath[2]) && pszPath[2] != '\0')
134 return birdOpenInt(pszPath, fFlags, fMode);
135 }
136 else if (IS_ALPHA(pszPath[0]) && pszPath[1] == ':')
137 {
138 if (IS_SLASH(pszPath[2]))
139 return birdOpenInt(pszPath, fFlags, fMode);
140 /*
141 * Drive letter relative path like "C:kernel32.dll".
142 * We could try use fdDir as the CWD here if it refers to the same drive,
143 * however that's can be implemented later...
144 */
145 return birdOpenInt(pszPath, fFlags, fMode);
146 }
147
148 /*
149 * Otherwise query the path of fdDir and construct an absolute path from all that.
150 * This isn't atomic and safe and stuff, but it gets the work done for now.
151 */
152 hDir = (HANDLE)_get_osfhandle(fdDir);
153 if (hDir != INVALID_HANDLE_VALUE)
154 {
155 /** @todo implement me. */
156 __debugbreak();
157 errno = EBADF;
158 }
159 return -1;
160}
161
162
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette