Changeset 77684 in vbox for trunk/src/VBox
- Timestamp:
- Mar 13, 2019 4:39:57 PM (6 years ago)
- Location:
- trunk/src/VBox/Runtime
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r3/posix/fileio-posix.cpp
r77234 r77684 64 64 #include <iprt/err.h> 65 65 #include <iprt/log.h> 66 #include <iprt/thread.h> 66 67 #include "internal/file.h" 67 68 #include "internal/fs.h" … … 81 82 82 83 84 /********************************************************************************************************************************* 85 * Defined Constants And Macros * 86 *********************************************************************************************************************************/ 87 #ifdef O_CLOEXEC 88 static int volatile g_fHave_O_CLOEXEC = 0; /* {-1,0,1}; since Linux 2.6.23 */ 89 #endif 90 91 92 83 93 RTDECL(bool) RTFileExists(const char *pszPath) 84 94 { … … 100 110 101 111 112 #ifdef O_CLOEXEC 113 /** Worker for RTFileOpenEx that detects whether the kernel supports 114 * O_CLOEXEC or not, setting g_fHave_O_CLOEXEC to 1 or -1 accordingly. */ 115 static int rtFileOpenExDetectCloExecSupport(void) 116 { 117 /* 118 * Open /dev/null with O_CLOEXEC and see if FD_CLOEXEC is set or not. 119 */ 120 int fHave_O_CLOEXEC = -1; 121 int fd = open("/dev/null", O_RDONLY | O_CLOEXEC, 0); 122 if (fd >= 0) 123 { 124 int fFlags = fcntl(fd, F_GETFD, 0); 125 fHave_O_CLOEXEC = fFlags > 0 && (fFlags & FD_CLOEXEC) ? 1 : -1; 126 close(fd); 127 } 128 else 129 AssertMsg(errno == EINVAL, ("%d\n", errno)); 130 g_fHave_O_CLOEXEC = fHave_O_CLOEXEC; 131 return fHave_O_CLOEXEC; 132 } 133 #endif 134 135 102 136 RTR3DECL(int) RTFileOpen(PRTFILE pFile, const char *pszFilename, uint64_t fOpen) 103 137 { 138 return RTFileOpenEx(pszFilename, fOpen, pFile, NULL); 139 } 140 141 142 RTDECL(int) RTFileOpenEx(const char *pszFilename, uint64_t fOpen, PRTFILE phFile, PRTFILEACTION penmActionTaken) 143 { 104 144 /* 105 145 * Validate input. 106 146 */ 107 AssertPtrReturn(pFile, VERR_INVALID_POINTER); 108 *pFile = NIL_RTFILE; 147 AssertPtrReturn(phFile, VERR_INVALID_POINTER); 148 *phFile = NIL_RTFILE; 149 if (penmActionTaken) 150 *penmActionTaken = RTFILEACTION_INVALID; 109 151 AssertPtrReturn(pszFilename, VERR_INVALID_POINTER); 110 152 … … 116 158 return rc; 117 159 #ifndef O_NONBLOCK 118 if (fOpen & RTFILE_O_NON_BLOCK) 119 { 120 AssertMsgFailed(("Invalid parameters! fOpen=%#llx\n", fOpen)); 121 return VERR_INVALID_PARAMETER; 122 } 160 AssertReturn(!(fOpen & RTFILE_O_NON_BLOCK), VERR_INVALID_FLAGS); 123 161 #endif 124 162 … … 138 176 #endif 139 177 #ifdef O_CLOEXEC 140 static int s_fHave_O_CLOEXEC = 0; /* {-1,0,1}; since Linux 2.6.23 */ 141 if (!(fOpen & RTFILE_O_INHERIT) && s_fHave_O_CLOEXEC >= 0) 178 int fHave_O_CLOEXEC = g_fHave_O_CLOEXEC; 179 if ( !(fOpen & RTFILE_O_INHERIT) 180 && ( fHave_O_CLOEXEC > 0 181 || ( fHave_O_CLOEXEC == 0 182 && (fHave_O_CLOEXEC = rtFileOpenExDetectCloExecSupport()) > 0))) 142 183 fOpenMode |= O_CLOEXEC; 143 184 #endif … … 168 209 case RTFILE_O_CREATE: fOpenMode |= O_CREAT | O_EXCL; break; 169 210 case RTFILE_O_CREATE_REPLACE: fOpenMode |= O_CREAT | O_TRUNC; break; /** @todo replacing needs fixing, this is *not* a 1:1 mapping! */ 170 } 171 if (fOpen & RTFILE_O_TRUNCATE) 211 default: 212 AssertMsgFailed(("fOpen=%#llx\n", fOpen)); 213 fOpen = (fOpen & ~RTFILE_O_ACTION_MASK) | RTFILE_O_OPEN; 214 break; 215 216 } 217 if ( (fOpen & RTFILE_O_TRUNCATE) 218 && (fOpen & RTFILE_O_ACTION_MASK) != RTFILE_O_CREATE) 172 219 fOpenMode |= O_TRUNC; 173 220 … … 184 231 break; 185 232 default: 186 AssertMsgFailed(("RTFileOpen received an invalid RW value, fOpen=%#llx\n", fOpen)); 187 return VERR_INVALID_PARAMETER; 233 AssertMsgFailedReturn(("RTFileOpen received an invalid RW value, fOpen=%#llx\n", fOpen), VERR_INVALID_FLAGS); 188 234 } 189 235 … … 193 239 : RT_FILE_PERMISSION; 194 240 195 /** @todo sharing !*/241 /** @todo sharing? */ 196 242 197 243 /* … … 203 249 return (rc); 204 250 205 int fh = open(pszNativeFilename, fOpenMode, fMode); 206 int iErr = errno; 207 208 #ifdef O_CLOEXEC 209 if ( (fOpenMode & O_CLOEXEC) 210 && s_fHave_O_CLOEXEC == 0) 211 { 212 if (fh < 0 && iErr == EINVAL) 213 { 214 s_fHave_O_CLOEXEC = -1; 215 fh = open(pszNativeFilename, fOpenMode, fMode); 216 iErr = errno; 217 } 218 else if (fh >= 0) 219 s_fHave_O_CLOEXEC = fcntl(fh, F_GETFD, 0) > 0 ? 1 : -1; 220 } 221 #endif 251 int fh; 252 int iErr; 253 if (!penmActionTaken) 254 { 255 fh = open(pszNativeFilename, fOpenMode, fMode); 256 iErr = errno; 257 } 258 else 259 { 260 /* We need to know exactly which action was taken by open, Windows & 261 OS/2 style. Can be tedious and subject to races: */ 262 switch (fOpen & RTFILE_O_ACTION_MASK) 263 { 264 case RTFILE_O_OPEN: 265 Assert(!(fOpenMode & O_CREAT)); 266 Assert(!(fOpenMode & O_EXCL)); 267 fh = open(pszNativeFilename, fOpenMode, fMode); 268 iErr = errno; 269 if (fh >= 0) 270 *penmActionTaken = fOpenMode & O_TRUNC ? RTFILEACTION_TRUNCATED : RTFILEACTION_OPENED; 271 break; 272 273 case RTFILE_O_CREATE: 274 Assert(fOpenMode & O_CREAT); 275 Assert(fOpenMode & O_EXCL); 276 fh = open(pszNativeFilename, fOpenMode, fMode); 277 iErr = errno; 278 if (fh >= 0) 279 *penmActionTaken = RTFILEACTION_CREATED; 280 else if (iErr == EEXIST) 281 *penmActionTaken = RTFILEACTION_ALREADY_EXISTS; 282 break; 283 284 case RTFILE_O_OPEN_CREATE: 285 case RTFILE_O_CREATE_REPLACE: 286 { 287 Assert(fOpenMode & O_CREAT); 288 Assert(!(fOpenMode & O_EXCL)); 289 int iTries = 64; 290 while (iTries-- > 0) 291 { 292 /* Yield the CPU if we've raced too long. */ 293 if (iTries < 4) 294 RTThreadSleep(2 - (iTries & 1)); 295 296 /* Try exclusive creation first: */ 297 fh = open(pszNativeFilename, fOpenMode | O_EXCL, fMode); 298 iErr = errno; 299 if (fh >= 0) 300 { 301 *penmActionTaken = RTFILEACTION_CREATED; 302 break; 303 } 304 if (iErr != EEXIST) 305 break; 306 307 /* If the file exists, try open it: */ 308 fh = open(pszNativeFilename, fOpenMode & ~O_CREAT, fMode); 309 iErr = errno; 310 if (fh >= 0) 311 { 312 if ((fOpen & RTFILE_O_ACTION_MASK) == RTFILE_O_OPEN_CREATE) 313 *penmActionTaken = fOpenMode & O_TRUNC ? RTFILEACTION_TRUNCATED : RTFILEACTION_OPENED; 314 else 315 *penmActionTaken = RTFILEACTION_REPLACED; 316 break; 317 } 318 if (iErr != ENOENT) 319 break; 320 } 321 Assert(iTries >= 0); 322 if (iTries < 0) 323 { 324 /* Thanks for the race, but we need to get on with things. */ 325 fh = open(pszNativeFilename, fOpenMode, fMode); 326 iErr = errno; 327 if (fh >= 0) 328 *penmActionTaken = RTFILEACTION_OPENED; 329 } 330 break; 331 } 332 333 default: 334 AssertMsgFailed(("fOpen=%#llx fOpenMode=%#x\n", fOpen, fOpenMode)); 335 iErr = EINVAL; 336 fh = -1; 337 break; 338 } 339 } 222 340 223 341 rtPathFreeNative(pszNativeFilename, pszFilename); … … 234 352 #endif 235 353 #ifdef O_CLOEXEC 236 && s_fHave_O_CLOEXEC <= 0354 && fHave_O_CLOEXEC <= 0 237 355 #endif 238 356 ) … … 329 447 if (iErr == 0) 330 448 { 331 *p File = (RTFILE)(uintptr_t)fh;332 Assert((intptr_t)*p File == fh);449 *phFile = (RTFILE)(uintptr_t)fh; 450 Assert((intptr_t)*phFile == fh); 333 451 LogFlow(("RTFileOpen(%p:{%RTfile}, %p:{%s}, %#llx): returns %Rrc\n", 334 p File, *pFile, pszFilename, pszFilename, fOpen, rc));452 phFile, *phFile, pszFilename, pszFilename, fOpen, rc)); 335 453 return VINF_SUCCESS; 336 454 } -
trunk/src/VBox/Runtime/testcase/Makefile.kmk
r77681 r77684 70 70 tstRTFileModeStringToFlags \ 71 71 tstFileLock \ 72 tstRTFileOpenEx-1 \ 72 73 tstFork \ 73 74 tstRTFsQueries \ … … 160 161 tstRTNtPath-1 \ 161 162 ntGetTimerResolution \ 162 tstRTDarwinMachKernel \ 163 tstRTFileOpenEx-1 163 tstRTDarwinMachKernel 164 164 165 165 PROGRAMS.linux += \
Note:
See TracChangeset
for help on using the changeset viewer.