VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/win/dir-win.cpp@ 28800

Last change on this file since 28800 was 28800, checked in by vboxsync, 15 years ago

Automated rebranding to Oracle copyright/license strings via filemuncher

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 14.9 KB
Line 
1/* $Id: dir-win.cpp 28800 2010-04-27 08:22:32Z vboxsync $ */
2/** @file
3 * IPRT - Directory, win32.
4 */
5
6/*
7 * Copyright (C) 2006-2007 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*******************************************************************************
29* Header Files *
30*******************************************************************************/
31#define LOG_GROUP RTLOGGROUP_DIR
32#include <Windows.h>
33#include <io.h>
34
35#include <iprt/dir.h>
36#include <iprt/path.h>
37#include <iprt/alloc.h>
38#include <iprt/string.h>
39#include <iprt/assert.h>
40#include <iprt/param.h>
41#include <iprt/err.h>
42#include <iprt/file.h>
43#include <iprt/log.h>
44#include "internal/fs.h"
45#include "internal/path.h"
46#include "internal/dir.h"
47
48
49
50RTDECL(int) RTDirCreate(const char *pszPath, RTFMODE fMode)
51{
52 /*
53 * Validate the file mode.
54 */
55 int rc;
56 fMode = rtFsModeNormalize(fMode, pszPath, 0);
57 if (rtFsModeIsValidPermissions(fMode))
58 {
59 /*
60 * Convert to UTF-16.
61 */
62 PRTUTF16 pwszString;
63 rc = RTStrToUtf16(pszPath, &pwszString);
64 AssertRC(rc);
65 if (RT_SUCCESS(rc))
66 {
67 /*
68 * Create the directory.
69 */
70 if (CreateDirectoryW((LPCWSTR)pwszString, NULL))
71 rc = VINF_SUCCESS;
72 else
73 rc = RTErrConvertFromWin32(GetLastError());
74
75 /*
76 * Turn off indexing of directory through Windows Indexing Service
77 */
78 if (RT_SUCCESS(rc))
79 {
80 if (SetFileAttributesW((LPCWSTR)pwszString, FILE_ATTRIBUTE_NOT_CONTENT_INDEXED))
81 rc = VINF_SUCCESS;
82 else
83 rc = RTErrConvertFromWin32(GetLastError());
84 }
85
86 RTUtf16Free(pwszString);
87 }
88 }
89 else
90 {
91 AssertMsgFailed(("Invalid file mode! %RTfmode\n", fMode));
92 rc = VERR_INVALID_FMODE;
93 }
94
95 LogFlow(("RTDirCreate(%p:{%s}, %RTfmode): returns %Rrc\n", pszPath, pszPath, fMode, rc));
96 return rc;
97}
98
99
100RTDECL(int) RTDirRemove(const char *pszPath)
101{
102 /*
103 * Convert to UTF-16.
104 */
105 PRTUTF16 pwszString;
106 int rc = RTStrToUtf16(pszPath, &pwszString);
107 AssertRC(rc);
108 if (RT_SUCCESS(rc))
109 {
110 /*
111 * Remove the directory.
112 */
113 if (RemoveDirectoryW((LPCWSTR)pwszString))
114 rc = VINF_SUCCESS;
115 else
116 rc = RTErrConvertFromWin32(GetLastError());
117
118 RTUtf16Free(pwszString);
119 }
120
121 LogFlow(("RTDirRemove(%p:{%s}): returns %Rrc\n", pszPath, pszPath, rc));
122 return rc;
123}
124
125
126RTDECL(int) RTDirFlush(const char *pszPath)
127{
128 return VERR_NOT_SUPPORTED;
129}
130
131
132int rtOpenDirNative(PRTDIR pDir, char *pszPathBuf)
133{
134 /*
135 * Setup the search expression.
136 *
137 * pszPathBuf is pointing to the return 4K return buffer for the RTPathReal()
138 * call in rtDirOpenCommon(), so all we gota do is check that we don't overflow
139 * it when adding the wildcard expression.
140 */
141 size_t cchExpr;
142 const char *pszExpr;
143 if (pDir->enmFilter == RTDIRFILTER_WINNT)
144 {
145 pszExpr = pDir->pszFilter;
146 cchExpr = pDir->cchFilter + 1;
147 }
148 else
149 {
150 pszExpr = "*";
151 cchExpr = sizeof("*");
152 }
153 if (pDir->cchPath + cchExpr > RTPATH_MAX)
154 return VERR_FILENAME_TOO_LONG;
155 memcpy(pszPathBuf + pDir->cchPath, pszExpr, cchExpr);
156
157
158 /*
159 * Attempt opening the search.
160 */
161 int rc = VINF_SUCCESS;
162#ifndef RT_DONT_CONVERT_FILENAMES
163 PRTUTF16 pwszName;
164 rc = RTStrToUtf16(pszPathBuf, &pwszName);
165 if (RT_SUCCESS(rc))
166 {
167 pDir->hDir = FindFirstFileW((LPCWSTR)pwszName, &pDir->Data);
168#else
169 pDir->hDir = FindFirstFileA(pszPathBuf, &pDir->Data);
170#endif
171 if (pDir->hDir != INVALID_HANDLE_VALUE)
172 pDir->fDataUnread = true;
173 /* theoretical case of an empty directory. */
174 else if (GetLastError() == ERROR_NO_MORE_FILES)
175 pDir->fDataUnread = false;
176 else
177 rc = RTErrConvertFromWin32(GetLastError());
178#ifndef RT_DONT_CONVERT_FILENAMES
179 RTUtf16Free(pwszName);
180 }
181#endif
182
183 return rc;
184}
185
186
187RTDECL(int) RTDirClose(PRTDIR pDir)
188{
189 /*
190 * Validate input.
191 */
192 if (!pDir)
193 return VERR_INVALID_PARAMETER;
194 if (pDir->u32Magic != RTDIR_MAGIC)
195 {
196 AssertMsgFailed(("Invalid pDir=%p\n", pDir));
197 return VERR_INVALID_PARAMETER;
198 }
199
200 /*
201 * Close the handle.
202 */
203 pDir->u32Magic++;
204 if (pDir->hDir != INVALID_HANDLE_VALUE)
205 {
206 BOOL fRc = FindClose(pDir->hDir);
207 Assert(fRc);
208 pDir->hDir = INVALID_HANDLE_VALUE;
209 }
210 RTStrFree(pDir->pszName);
211 pDir->pszName = NULL;
212 RTMemFree(pDir);
213
214 return VINF_SUCCESS;
215}
216
217
218RTDECL(int) RTDirRead(PRTDIR pDir, PRTDIRENTRY pDirEntry, size_t *pcbDirEntry)
219{
220 /*
221 * Validate input.
222 */
223 if (!pDir || pDir->u32Magic != RTDIR_MAGIC)
224 {
225 AssertMsgFailed(("Invalid pDir=%p\n", pDir));
226 return VERR_INVALID_PARAMETER;
227 }
228 if (!pDirEntry)
229 {
230 AssertMsgFailed(("Invalid pDirEntry=%p\n", pDirEntry));
231 return VERR_INVALID_PARAMETER;
232 }
233 size_t cbDirEntry = sizeof(*pDirEntry);
234 if (pcbDirEntry)
235 {
236 cbDirEntry = *pcbDirEntry;
237 if (cbDirEntry < RT_UOFFSETOF(RTDIRENTRY, szName[2]))
238 {
239 AssertMsgFailed(("Invalid *pcbDirEntry=%d (min %d)\n", *pcbDirEntry, RT_OFFSETOF(RTDIRENTRY, szName[2])));
240 return VERR_INVALID_PARAMETER;
241 }
242 }
243
244 /*
245 * Fetch data?
246 */
247 if (!pDir->fDataUnread)
248 {
249#ifdef RT_DONT_CONVERT_FILENAMES
250 BOOL fRc = FindNextFileA(pDir->hDir, &pDir->Data);
251
252#else
253 RTStrFree(pDir->pszName);
254 pDir->pszName = NULL;
255
256 BOOL fRc = FindNextFileW(pDir->hDir, &pDir->Data);
257#endif
258 if (!fRc)
259 {
260 int iErr = GetLastError();
261 if (pDir->hDir == INVALID_HANDLE_VALUE || iErr == ERROR_NO_MORE_FILES)
262 return VERR_NO_MORE_FILES;
263 return RTErrConvertFromWin32(iErr);
264 }
265 }
266
267#ifndef RT_DONT_CONVERT_FILENAMES
268 /*
269 * Convert the filename to UTF-8.
270 */
271 if (!pDir->pszName)
272 {
273 int rc = RTUtf16ToUtf8((PCRTUTF16)pDir->Data.cFileName, &pDir->pszName);
274 if (RT_FAILURE(rc))
275 {
276 pDir->pszName = NULL;
277 return rc;
278 }
279 pDir->cchName = strlen(pDir->pszName);
280 }
281#endif
282
283 /*
284 * Check if we've got enough space to return the data.
285 */
286#ifdef RT_DONT_CONVERT_FILENAMES
287 const char *pszName = pDir->Data.cName;
288 const size_t cchName = strlen(pszName);
289#else
290 const char *pszName = pDir->pszName;
291 const size_t cchName = pDir->cchName;
292#endif
293 const size_t cbRequired = RT_OFFSETOF(RTDIRENTRY, szName[1]) + cchName;
294 if (pcbDirEntry)
295 *pcbDirEntry = cbRequired;
296 if (cbRequired > cbDirEntry)
297 return VERR_BUFFER_OVERFLOW;
298
299 /*
300 * Setup the returned data.
301 */
302 pDir->fDataUnread = false;
303 pDirEntry->INodeId = 0; /** @todo we can use the fileid here if we must (see GetFileInformationByHandle). */
304 pDirEntry->enmType = pDir->Data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
305 ? RTDIRENTRYTYPE_DIRECTORY : RTDIRENTRYTYPE_FILE;
306 pDirEntry->cbName = (uint16_t)cchName;
307 Assert(pDirEntry->cbName == cchName);
308 memcpy(pDirEntry->szName, pszName, cchName + 1);
309
310 return VINF_SUCCESS;
311}
312
313
314RTDECL(int) RTDirReadEx(PRTDIR pDir, PRTDIRENTRYEX pDirEntry, size_t *pcbDirEntry, RTFSOBJATTRADD enmAdditionalAttribs, uint32_t fFlags)
315{
316 /** @todo Symlinks: Find[First|Next]FileW will return info about
317 the link, so RTPATH_F_FOLLOW_LINK is not handled correctly. */
318 /*
319 * Validate input.
320 */
321 if (!pDir || pDir->u32Magic != RTDIR_MAGIC)
322 {
323 AssertMsgFailed(("Invalid pDir=%p\n", pDir));
324 return VERR_INVALID_PARAMETER;
325 }
326 if (!pDirEntry)
327 {
328 AssertMsgFailed(("Invalid pDirEntry=%p\n", pDirEntry));
329 return VERR_INVALID_PARAMETER;
330 }
331 if ( enmAdditionalAttribs < RTFSOBJATTRADD_NOTHING
332 || enmAdditionalAttribs > RTFSOBJATTRADD_LAST)
333 {
334 AssertMsgFailed(("Invalid enmAdditionalAttribs=%p\n", enmAdditionalAttribs));
335 return VERR_INVALID_PARAMETER;
336 }
337 AssertMsgReturn(RTPATH_F_IS_VALID(fFlags, 0), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
338 size_t cbDirEntry = sizeof(*pDirEntry);
339 if (pcbDirEntry)
340 {
341 cbDirEntry = *pcbDirEntry;
342 if (cbDirEntry < RT_UOFFSETOF(RTDIRENTRYEX, szName[2]))
343 {
344 AssertMsgFailed(("Invalid *pcbDirEntry=%d (min %d)\n", *pcbDirEntry, RT_OFFSETOF(RTDIRENTRYEX, szName[2])));
345 return VERR_INVALID_PARAMETER;
346 }
347 }
348
349 /*
350 * Fetch data?
351 */
352 if (!pDir->fDataUnread)
353 {
354#ifdef RT_DONT_CONVERT_FILENAMES
355 BOOL fRc = FindNextFileA(pDir->hDir, &pDir->Data);
356
357#else
358 RTStrFree(pDir->pszName);
359 pDir->pszName = NULL;
360
361 BOOL fRc = FindNextFileW(pDir->hDir, &pDir->Data);
362#endif
363 if (!fRc)
364 {
365 int iErr = GetLastError();
366 if (pDir->hDir == INVALID_HANDLE_VALUE || iErr == ERROR_NO_MORE_FILES)
367 return VERR_NO_MORE_FILES;
368 return RTErrConvertFromWin32(iErr);
369 }
370 }
371
372#ifndef RT_DONT_CONVERT_FILENAMES
373 /*
374 * Convert the filename to UTF-8.
375 */
376 if (!pDir->pszName)
377 {
378 int rc = RTUtf16ToUtf8((PCRTUTF16)pDir->Data.cFileName, &pDir->pszName);
379 if (RT_FAILURE(rc))
380 {
381 pDir->pszName = NULL;
382 return rc;
383 }
384 pDir->cchName = strlen(pDir->pszName);
385 }
386#endif
387
388 /*
389 * Check if we've got enough space to return the data.
390 */
391#ifdef RT_DONT_CONVERT_FILENAMES
392 const char *pszName = pDir->Data.cName;
393 const size_t cchName = strlen(pszName);
394#else
395 const char *pszName = pDir->pszName;
396 const size_t cchName = pDir->cchName;
397#endif
398 const size_t cbRequired = RT_OFFSETOF(RTDIRENTRYEX, szName[1]) + cchName;
399 if (pcbDirEntry)
400 *pcbDirEntry = cbRequired;
401 if (cbRequired > cbDirEntry)
402 return VERR_BUFFER_OVERFLOW;
403
404 /*
405 * Setup the returned data.
406 */
407 pDir->fDataUnread = false;
408 pDirEntry->cbName = (uint16_t)cchName;
409 Assert(pDirEntry->cbName == cchName);
410 memcpy(pDirEntry->szName, pszName, cchName + 1);
411#ifndef RT_DONT_CONVERT_FILENAMES /* this ain't nice since the whole point of this define is not to drag in conversion... */
412 if (pDir->Data.cAlternateFileName[0])
413 {
414 /* copy and calc length */
415 PCRTUTF16 pwszSrc = (PCRTUTF16)pDir->Data.cAlternateFileName;
416 PRTUTF16 pwszDst = pDirEntry->wszShortName;
417 while (*pwszSrc)
418 *pwszDst++ = *pwszSrc++;
419 pDirEntry->cwcShortName = pwszDst - &pDirEntry->wszShortName[0];
420 /* zero the rest */
421 const PRTUTF16 pwszEnd = &pDirEntry->wszShortName[RT_ELEMENTS(pDirEntry->wszShortName)];
422 while (pwszDst < pwszEnd)
423 *pwszDst++ = '\0';
424 }
425 else
426#endif
427 {
428 memset(pDirEntry->wszShortName, 0, sizeof(pDirEntry->wszShortName));
429 pDirEntry->cwcShortName = 0;
430 }
431
432 pDirEntry->Info.cbObject = ((uint64_t)pDir->Data.nFileSizeHigh << 32)
433 | (uint64_t)pDir->Data.nFileSizeLow;
434 pDirEntry->Info.cbAllocated = pDirEntry->Info.cbObject;
435
436 Assert(sizeof(uint64_t) == sizeof(pDir->Data.ftCreationTime));
437 RTTimeSpecSetNtTime(&pDirEntry->Info.BirthTime, *(uint64_t *)&pDir->Data.ftCreationTime);
438 RTTimeSpecSetNtTime(&pDirEntry->Info.AccessTime, *(uint64_t *)&pDir->Data.ftLastAccessTime);
439 RTTimeSpecSetNtTime(&pDirEntry->Info.ModificationTime, *(uint64_t *)&pDir->Data.ftLastWriteTime);
440 pDirEntry->Info.ChangeTime = pDirEntry->Info.ModificationTime;
441
442 pDirEntry->Info.Attr.fMode = rtFsModeFromDos((pDir->Data.dwFileAttributes << RTFS_DOS_SHIFT) & RTFS_DOS_MASK_NT,
443 pszName, cchName);
444
445 /*
446 * Requested attributes (we cannot provide anything actually).
447 */
448 switch (enmAdditionalAttribs)
449 {
450 case RTFSOBJATTRADD_EASIZE:
451 pDirEntry->Info.Attr.enmAdditional = RTFSOBJATTRADD_EASIZE;
452 pDirEntry->Info.Attr.u.EASize.cb = 0;
453 break;
454
455 case RTFSOBJATTRADD_UNIX:
456 pDirEntry->Info.Attr.enmAdditional = RTFSOBJATTRADD_UNIX;
457 pDirEntry->Info.Attr.u.Unix.uid = ~0U;
458 pDirEntry->Info.Attr.u.Unix.gid = ~0U;
459 pDirEntry->Info.Attr.u.Unix.cHardlinks = 1;
460 pDirEntry->Info.Attr.u.Unix.INodeIdDevice = 0; /** @todo Use the volume serial number (see GetFileInformationByHandle). */
461 pDirEntry->Info.Attr.u.Unix.INodeId = 0; /** @todo Use the fileid (see GetFileInformationByHandle). */
462 pDirEntry->Info.Attr.u.Unix.fFlags = 0;
463 pDirEntry->Info.Attr.u.Unix.GenerationId = 0;
464 pDirEntry->Info.Attr.u.Unix.Device = 0;
465 break;
466
467 case RTFSOBJATTRADD_NOTHING:
468 pDirEntry->Info.Attr.enmAdditional = RTFSOBJATTRADD_NOTHING;
469 break;
470
471 default:
472 AssertMsgFailed(("Impossible!\n"));
473 return VERR_INTERNAL_ERROR;
474 }
475
476 return VINF_SUCCESS;
477}
478
479
480RTDECL(int) RTDirRename(const char *pszSrc, const char *pszDst, unsigned fRename)
481{
482 /*
483 * Validate input.
484 */
485 AssertMsgReturn(VALID_PTR(pszSrc), ("%p\n", pszSrc), VERR_INVALID_POINTER);
486 AssertMsgReturn(VALID_PTR(pszDst), ("%p\n", pszDst), VERR_INVALID_POINTER);
487 AssertMsgReturn(*pszSrc, ("%p\n", pszSrc), VERR_INVALID_PARAMETER);
488 AssertMsgReturn(*pszDst, ("%p\n", pszDst), VERR_INVALID_PARAMETER);
489 AssertMsgReturn(!(fRename & ~RTPATHRENAME_FLAGS_REPLACE), ("%#x\n", fRename), VERR_INVALID_PARAMETER);
490
491 /*
492 * Call the worker.
493 */
494 int rc = rtPathWin32MoveRename(pszSrc, pszDst,
495 fRename & RTPATHRENAME_FLAGS_REPLACE ? MOVEFILE_REPLACE_EXISTING : 0,
496 RTFS_TYPE_DIRECTORY);
497
498 LogFlow(("RTDirRename(%p:{%s}, %p:{%s}, %#x): returns %Rrc\n", pszSrc, pszSrc, pszDst, pszDst, fRename, rc));
499 return rc;
500}
501
Note: See TracBrowser for help on using the repository browser.

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