source: trunk/src/lib/nt/ntopenat.c@ 3682

Last change on this file since 3682 was 3682, checked in by bird, 4 weeks ago

lib/nt,kmk: Fixed around rm/unlink semantics and general support for long file names in lib/nt.

File size: 5.2 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 "nthlpmisc.h"
43#include "ntopenat.h"
44#include "ntstat.h"
45
46
47static int birdOpenInt(const char *pszPath, int fFlags, unsigned __int16 fMode)
48{
49 /*
50 * Try open it using the CRT's open function, but deal with opening
51 * directories as the CRT doesn't allow doing that.
52 */
53 int const iErrnoSaved = errno;
54 int iErrno;
55 int fd = open(pszPath, fFlags, fMode);
56 if ( fd < 0
57 && ((iErrno = errno) == EACCES || iErrno == ENOENT || iErrno == EISDIR || iErrno == EINVAL /*CIFS*/)
58 && (fFlags & (_O_WRONLY | _O_RDWR | _O_RDONLY)) == _O_RDONLY
59 && (fFlags & (_O_CREAT | _O_TRUNC | _O_EXCL)) == 0 )
60 {
61 BirdStat_T Stat;
62 if (!birdStatFollowLink(pszPath, &Stat))
63 {
64 if (S_ISDIR(Stat.st_mode))
65 {
66 HANDLE hDir;
67 errno = iErrnoSaved;
68 hDir = birdOpenFile(pszPath,
69 FILE_READ_DATA | FILE_READ_ATTRIBUTES | SYNCHRONIZE,
70 FILE_ATTRIBUTE_NORMAL,
71 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
72 FILE_OPEN,
73 FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT,
74 OBJ_CASE_INSENSITIVE);
75 if (hDir != INVALID_HANDLE_VALUE)
76 {
77 fd = _open_osfhandle((intptr_t)hDir, fFlags);
78 if (fd >= 0)
79 return fd;
80 birdCloseFile(hDir);
81 }
82 }
83 else
84 errno = EACCES;
85 }
86 else
87 errno = EACCES;
88 }
89 return fd;
90}
91
92
93/**
94 * Implements open.
95 */
96int birdOpen(const char *pszPath, int fFlags, ...)
97{
98 unsigned __int16 fMode;
99 va_list va;
100 va_start(va, fFlags);
101 fMode = va_arg(va, unsigned __int16);
102 va_end(va);
103 return birdOpenInt(pszPath, fFlags, fMode);
104}
105
106
107
108/**
109 * Implements opendir.
110 */
111int birdOpenAt(int fdDir, const char *pszPath, int fFlags, ...)
112{
113 HANDLE hDir;
114
115 /*
116 * Retrieve the mode mask.
117 */
118 unsigned __int16 fMode;
119 va_list va;
120 va_start(va, fFlags);
121 fMode = va_arg(va, unsigned __int16);
122 va_end(va);
123
124 /*
125 * Just call 'open' directly if we can get away with it:
126 */
127 if (fdDir == AT_FDCWD)
128 return birdOpenInt(pszPath, fFlags, fMode);
129
130 if (IS_SLASH(pszPath[0]))
131 {
132 if (IS_SLASH(pszPath[1]) && !IS_SLASH(pszPath[2]) && pszPath[2] != '\0')
133 return birdOpenInt(pszPath, fFlags, fMode);
134 }
135 else if (IS_ALPHA(pszPath[0]) && pszPath[1] == ':')
136 {
137 if (IS_SLASH(pszPath[2]))
138 return birdOpenInt(pszPath, fFlags, fMode);
139 /*
140 * Drive letter relative path like "C:kernel32.dll".
141 * We could try use fdDir as the CWD here if it refers to the same drive,
142 * however that's can be implemented later...
143 */
144 return birdOpenInt(pszPath, fFlags, fMode);
145 }
146
147 /*
148 * Otherwise query the path of fdDir and construct an absolute path from all that.
149 * This isn't atomic and safe and stuff, but it gets the work done for now.
150 */
151 hDir = (HANDLE)_get_osfhandle(fdDir);
152 if (hDir != INVALID_HANDLE_VALUE)
153 {
154 /** @todo implement me. */
155 __debugbreak();
156 errno = EBADF;
157 }
158 return -1;
159}
160
Note: See TracBrowser for help on using the repository browser.