VirtualBox

source: kBuild/trunk/src/lib/nt/ntdir.c@ 2702

Last change on this file since 2702 was 2702, checked in by bird, 12 years ago

kmk/WindowsNT: Avoiding unnecessary stat() calls. Reimplemented stat(), lstat(), fstat(), opendir(), readdir(), and closedir() using native NT APIs.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 9.2 KB
Line 
1/* $Id: ntdir.c 2702 2013-11-21 00:11:08Z bird $ */
2/** @file
3 * MSC + NT opendir, readdir, telldir, seekdir, and closedir.
4 */
5
6/*
7 * Copyright (c) 2005-2013 knut st. osmundsen <[email protected]>
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 <stdio.h>
36#include <errno.h>
37#include <malloc.h>
38
39#include "ntstuff.h"
40#include "nthlp.h"
41#include "ntdir.h"
42
43
44/**
45 * Internal worker for birdStatModTimeOnly.
46 */
47static BirdDir_T *birdDirOpenInternal(const char *pszPath, const char *pszFilter, int fMinimalInfo)
48{
49 HANDLE hFile = birdOpenFile(pszPath,
50 FILE_READ_DATA | SYNCHRONIZE,
51 FILE_ATTRIBUTE_NORMAL,
52 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
53 FILE_OPEN,
54 FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT,
55 OBJ_CASE_INSENSITIVE);
56 if (hFile != INVALID_HANDLE_VALUE)
57 {
58 /*
59 * Allocate a handle.
60 */
61 BirdDir_T *pDir = (BirdDir_T *)birdMemAlloc(sizeof(*pDir));
62 if (pDir)
63 {
64 pDir->uMagic = BIRD_DIR_MAGIC;
65 pDir->pvHandle = (void *)hFile;
66 pDir->uDev = 0;
67 pDir->offPos = 0;
68 pDir->fHaveData = 0;
69 pDir->fFirst = 1;
70 pDir->iInfoClass = fMinimalInfo ? MyFileNamesInformation : MyFileIdFullDirectoryInformation;
71 pDir->offBuf = 0;
72 pDir->cbBuf = 0;
73 pDir->pabBuf = NULL;
74 return pDir;
75 }
76
77 birdCloseFile(hFile);
78 birdSetErrnoToNoMem();
79 }
80
81 return NULL;
82}
83
84
85/**
86 * Implements opendir.
87 */
88BirdDir_T *birdDirOpen(const char *pszPath)
89{
90 return birdDirOpenInternal(pszPath, NULL, 1 /*fMinimalInfo*/);
91}
92
93
94static int birdDirReadMore(BirdDir_T *pDir)
95{
96 MY_NTSTATUS rcNt;
97 MY_IO_STATUS_BLOCK Ios;
98 int fFirst;
99
100 /*
101 * Retrieve the volume serial number + creation time and create the
102 * device number the first time around. Also allocate a buffer.
103 */
104 fFirst = pDir->fFirst;
105 if (fFirst)
106 {
107 union
108 {
109 MY_FILE_FS_VOLUME_INFORMATION VolInfo;
110 unsigned char abBuf[1024];
111 } uBuf;
112
113 Ios.Information = 0;
114 Ios.u.Status = -1;
115 rcNt = g_pfnNtQueryVolumeInformationFile((HANDLE)pDir->pvHandle, &Ios, &uBuf, sizeof(uBuf), MyFileFsVolumeInformation);
116 if (MY_NT_SUCCESS(rcNt))
117 rcNt = Ios.u.Status;
118 if (MY_NT_SUCCESS(rcNt))
119 pDir->uDev = uBuf.VolInfo.VolumeSerialNumber
120 | (uBuf.VolInfo.VolumeCreationTime.QuadPart << 32);
121 else
122 pDir->uDev = 0;
123
124 /*
125 * Allocate a buffer.
126 */
127 pDir->cbBuf = 0x20000;
128 pDir->pabBuf = birdMemAlloc(pDir->cbBuf);
129 if (!pDir->pabBuf)
130 return birdSetErrnoToNoMem();
131
132 pDir->fFirst = 0;
133 }
134
135 /*
136 * Read another buffer full.
137 */
138 Ios.Information = 0;
139 Ios.u.Status = -1;
140
141 rcNt = g_pfnNtQueryDirectoryFile((HANDLE)pDir->pvHandle,
142 NULL, /* hEvent */
143 NULL, /* pfnApcComplete */
144 NULL, /* pvApcCompleteCtx */
145 &Ios,
146 pDir->pabBuf,
147 pDir->cbBuf,
148 (MY_FILE_INFORMATION_CLASS)pDir->iInfoClass,
149 FALSE, /* fReturnSingleEntry */
150 NULL, /* Filter / restart pos. */
151 FALSE); /* fRestartScan */
152 if (!MY_NT_SUCCESS(rcNt))
153 {
154 int rc;
155 if (rcNt == MY_STATUS_NO_MORE_FILES)
156 rc = 0;
157 else
158 rc = birdSetErrnoFromNt(rcNt);
159 pDir->fHaveData = 0;
160 pDir->offBuf = pDir->cbBuf;
161 return rc;
162 }
163
164 pDir->offBuf = 0;
165 pDir->fHaveData = 1;
166
167 return 0;
168}
169
170
171static int birdDirCopyNameToEntry(WCHAR const *pwcName, ULONG cbName, BirdDirEntry_T *pEntry)
172{
173 int cchOut = WideCharToMultiByte(CP_ACP, 0,
174 pwcName, cbName / sizeof(WCHAR),
175 pEntry->d_name, sizeof(pEntry->d_name) - 1,
176 NULL, NULL);
177 if (cchOut > 0)
178 {
179 pEntry->d_name[cchOut] = '\0';
180 pEntry->d_namlen = (unsigned __int16)cchOut;
181 pEntry->d_reclen = (unsigned __int16)((size_t)&pEntry->d_name[cchOut + 1] - (size_t)pEntry);
182 return 0;
183 }
184 return -1;
185}
186
187
188
189/**
190 * Implements readdir_r().
191 */
192int birdDirReadReentrant(BirdDir_T *pDir, BirdDirEntry_T *pEntry, BirdDirEntry_T **ppResult)
193{
194 int fSkipEntry;
195
196 *ppResult = NULL;
197
198 if (!pDir || pDir->uMagic != BIRD_DIR_MAGIC)
199 return birdSetErrnoToBadFileNo();
200
201 do
202 {
203 ULONG offNext;
204 ULONG cbMinCur;
205
206 /*
207 * Read more?
208 */
209 if (!pDir->fHaveData)
210 {
211 if (birdDirReadMore(pDir) != 0)
212 return -1;
213 if (!pDir->fHaveData)
214 return 0;
215 }
216
217 /*
218 * Convert the NT data to the unixy output structure.
219 */
220 fSkipEntry = 0;
221 switch (pDir->iInfoClass)
222 {
223 case MyFileNamesInformation:
224 {
225 MY_FILE_NAMES_INFORMATION *pInfo = (MY_FILE_NAMES_INFORMATION *)&pDir->pabBuf[pDir->offBuf];
226 if ( pDir->offBuf >= pDir->cbBuf - MIN_SIZEOF_MY_FILE_NAMES_INFORMATION
227 || pInfo->FileNameLength >= pDir->cbBuf
228 || pDir->offBuf + pInfo->FileNameLength + MIN_SIZEOF_MY_FILE_NAMES_INFORMATION > pDir->cbBuf)
229 {
230 fSkipEntry = 1;
231 continue;
232 }
233
234 pEntry->d_ino = 0;
235 pEntry->d_size = 0;
236 pEntry->d_type = DT_UNKNOWN;
237 pEntry->d_dirsymlink = 0;
238 pEntry->d_reclen = 0;
239 pEntry->d_namlen = 0;
240 if (birdDirCopyNameToEntry(pInfo->FileName, pInfo->FileNameLength, pEntry) != 0)
241 fSkipEntry = 1;
242
243 cbMinCur = MIN_SIZEOF_MY_FILE_NAMES_INFORMATION + pInfo->FileNameLength;
244 offNext = pInfo->NextEntryOffset;
245 break;
246 }
247
248 //case MyFileIdBothDirectoryInformation:
249 //{
250 // MY_FILE_BOTH_DIR_INFORMATION
251 //
252 //}
253
254 default:
255 return birdSetErrnoToBadFileNo();
256 }
257
258 /*
259 * Advance.
260 */
261 if ( offNext >= cbMinCur
262 && offNext < pDir->cbBuf)
263 pDir->offBuf += offNext;
264 else
265 {
266 pDir->fHaveData = 0;
267 pDir->offBuf = pDir->cbBuf;
268 }
269 pDir->offPos++;
270 } while (fSkipEntry);
271
272
273 /*
274 * Successful return.
275 */
276 *ppResult = pEntry;
277 return 0;
278}
279
280
281/**
282 * Implements readdir().
283 */
284BirdDirEntry_T *birdDirRead(BirdDir_T *pDir)
285{
286 BirdDirEntry_T *pRet = NULL;
287 birdDirReadReentrant(pDir, &pDir->DirEntry, &pRet);
288 return pRet;
289}
290
291
292/**
293 * Implements telldir().
294 */
295long birdDirTell(BirdDir_T *pDir)
296{
297 if (!pDir || pDir->uMagic != BIRD_DIR_MAGIC)
298 return birdSetErrnoToBadFileNo();
299 return pDir->offPos;
300}
301
302
303void birdDirSeek(BirdDir_T *pDir, long offDir);
304
305
306/**
307 * Implements closedir().
308 */
309int birdDirClose(BirdDir_T *pDir)
310{
311 if (!pDir || pDir->uMagic != BIRD_DIR_MAGIC)
312 return birdSetErrnoToBadFileNo();
313
314 pDir->uMagic++;
315 birdCloseFile((HANDLE)pDir->pvHandle);
316 pDir->pvHandle = (void *)INVALID_HANDLE_VALUE;
317 birdMemFree(pDir->pabBuf);
318 pDir->pabBuf = NULL;
319 birdMemFree(pDir);
320
321 return 0;
322}
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