VirtualBox

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

Last change on this file since 44528 was 44528, checked in by vboxsync, 12 years ago

header (C) fixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 14.9 KB
Line 
1/* $Id: dir-win.cpp 44528 2013-02-04 14:27:54Z vboxsync $ */
2/** @file
3 * IPRT - Directory, win32.
4 */
5
6/*
7 * Copyright (C) 2006-2013 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, uint32_t fCreate)
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 rtDirNativeOpen(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 cbExpr;
142 const char *pszExpr;
143 if (pDir->enmFilter == RTDIRFILTER_WINNT)
144 {
145 pszExpr = pDir->pszFilter;
146 cbExpr = pDir->cchFilter + 1;
147 }
148 else
149 {
150 pszExpr = "*";
151 cbExpr = sizeof("*");
152 }
153 if (pDir->cchPath + cbExpr > RTPATH_MAX)
154 return VERR_FILENAME_TOO_LONG;
155 memcpy(pszPathBuf + pDir->cchPath, pszExpr, cbExpr);
156
157
158 /*
159 * Attempt opening the search.
160 */
161 int rc = VINF_SUCCESS;
162 PRTUTF16 pwszName;
163 rc = RTStrToUtf16(pszPathBuf, &pwszName);
164 if (RT_SUCCESS(rc))
165 {
166 pDir->hDir = FindFirstFileW((LPCWSTR)pwszName, &pDir->Data);
167 if (pDir->hDir != INVALID_HANDLE_VALUE)
168 pDir->fDataUnread = true;
169 else
170 {
171 DWORD dwErr = GetLastError();
172 /* Theoretical case of an empty directory or more normal case of no matches. */
173 if ( dwErr == ERROR_FILE_NOT_FOUND
174 || dwErr == ERROR_NO_MORE_FILES /* ???*/)
175 pDir->fDataUnread = false;
176 else
177 rc = RTErrConvertFromWin32(GetLastError());
178 }
179 RTUtf16Free(pwszName);
180 }
181
182 return rc;
183}
184
185
186RTDECL(int) RTDirClose(PRTDIR pDir)
187{
188 /*
189 * Validate input.
190 */
191 if (!pDir)
192 return VERR_INVALID_PARAMETER;
193 if (pDir->u32Magic != RTDIR_MAGIC)
194 {
195 AssertMsgFailed(("Invalid pDir=%p\n", pDir));
196 return VERR_INVALID_PARAMETER;
197 }
198
199 /*
200 * Close the handle.
201 */
202 pDir->u32Magic++;
203 if (pDir->hDir != INVALID_HANDLE_VALUE)
204 {
205 BOOL fRc = FindClose(pDir->hDir);
206 Assert(fRc);
207 pDir->hDir = INVALID_HANDLE_VALUE;
208 }
209 RTStrFree(pDir->pszName);
210 pDir->pszName = NULL;
211 RTMemFree(pDir);
212
213 return VINF_SUCCESS;
214}
215
216
217RTDECL(int) RTDirRead(PRTDIR pDir, PRTDIRENTRY pDirEntry, size_t *pcbDirEntry)
218{
219 /*
220 * Validate input.
221 */
222 if (!pDir || pDir->u32Magic != RTDIR_MAGIC)
223 {
224 AssertMsgFailed(("Invalid pDir=%p\n", pDir));
225 return VERR_INVALID_PARAMETER;
226 }
227 if (!pDirEntry)
228 {
229 AssertMsgFailed(("Invalid pDirEntry=%p\n", pDirEntry));
230 return VERR_INVALID_PARAMETER;
231 }
232 size_t cbDirEntry = sizeof(*pDirEntry);
233 if (pcbDirEntry)
234 {
235 cbDirEntry = *pcbDirEntry;
236 if (cbDirEntry < RT_UOFFSETOF(RTDIRENTRY, szName[2]))
237 {
238 AssertMsgFailed(("Invalid *pcbDirEntry=%d (min %d)\n", *pcbDirEntry, RT_OFFSETOF(RTDIRENTRY, szName[2])));
239 return VERR_INVALID_PARAMETER;
240 }
241 }
242
243 /*
244 * Fetch data?
245 */
246 if (!pDir->fDataUnread)
247 {
248 RTStrFree(pDir->pszName);
249 pDir->pszName = NULL;
250
251 BOOL fRc = FindNextFileW(pDir->hDir, &pDir->Data);
252 if (!fRc)
253 {
254 int iErr = GetLastError();
255 if (pDir->hDir == INVALID_HANDLE_VALUE || iErr == ERROR_NO_MORE_FILES)
256 return VERR_NO_MORE_FILES;
257 return RTErrConvertFromWin32(iErr);
258 }
259 }
260
261 /*
262 * Convert the filename to UTF-8.
263 */
264 if (!pDir->pszName)
265 {
266 int rc = RTUtf16ToUtf8((PCRTUTF16)pDir->Data.cFileName, &pDir->pszName);
267 if (RT_FAILURE(rc))
268 {
269 pDir->pszName = NULL;
270 return rc;
271 }
272 pDir->cchName = strlen(pDir->pszName);
273 }
274
275 /*
276 * Check if we've got enough space to return the data.
277 */
278 const char *pszName = pDir->pszName;
279 const size_t cchName = pDir->cchName;
280 const size_t cbRequired = RT_OFFSETOF(RTDIRENTRY, szName[1]) + cchName;
281 if (pcbDirEntry)
282 *pcbDirEntry = cbRequired;
283 if (cbRequired > cbDirEntry)
284 return VERR_BUFFER_OVERFLOW;
285
286 /*
287 * Setup the returned data.
288 */
289 pDir->fDataUnread = false;
290 pDirEntry->INodeId = 0; /** @todo we can use the fileid here if we must (see GetFileInformationByHandle). */
291 pDirEntry->enmType = pDir->Data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
292 ? RTDIRENTRYTYPE_DIRECTORY : RTDIRENTRYTYPE_FILE;
293 pDirEntry->cbName = (uint16_t)cchName;
294 Assert(pDirEntry->cbName == cchName);
295 memcpy(pDirEntry->szName, pszName, cchName + 1);
296
297 return VINF_SUCCESS;
298}
299
300
301RTDECL(int) RTDirReadEx(PRTDIR pDir, PRTDIRENTRYEX pDirEntry, size_t *pcbDirEntry, RTFSOBJATTRADD enmAdditionalAttribs, uint32_t fFlags)
302{
303 /** @todo Symlinks: Find[First|Next]FileW will return info about
304 the link, so RTPATH_F_FOLLOW_LINK is not handled correctly. */
305 /*
306 * Validate input.
307 */
308 if (!pDir || pDir->u32Magic != RTDIR_MAGIC)
309 {
310 AssertMsgFailed(("Invalid pDir=%p\n", pDir));
311 return VERR_INVALID_PARAMETER;
312 }
313 if (!pDirEntry)
314 {
315 AssertMsgFailed(("Invalid pDirEntry=%p\n", pDirEntry));
316 return VERR_INVALID_PARAMETER;
317 }
318 if ( enmAdditionalAttribs < RTFSOBJATTRADD_NOTHING
319 || enmAdditionalAttribs > RTFSOBJATTRADD_LAST)
320 {
321 AssertMsgFailed(("Invalid enmAdditionalAttribs=%p\n", enmAdditionalAttribs));
322 return VERR_INVALID_PARAMETER;
323 }
324 AssertMsgReturn(RTPATH_F_IS_VALID(fFlags, 0), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
325 size_t cbDirEntry = sizeof(*pDirEntry);
326 if (pcbDirEntry)
327 {
328 cbDirEntry = *pcbDirEntry;
329 if (cbDirEntry < RT_UOFFSETOF(RTDIRENTRYEX, szName[2]))
330 {
331 AssertMsgFailed(("Invalid *pcbDirEntry=%d (min %d)\n", *pcbDirEntry, RT_OFFSETOF(RTDIRENTRYEX, szName[2])));
332 return VERR_INVALID_PARAMETER;
333 }
334 }
335
336 /*
337 * Fetch data?
338 */
339 if (!pDir->fDataUnread)
340 {
341 RTStrFree(pDir->pszName);
342 pDir->pszName = NULL;
343
344 BOOL fRc = FindNextFileW(pDir->hDir, &pDir->Data);
345 if (!fRc)
346 {
347 int iErr = GetLastError();
348 if (pDir->hDir == INVALID_HANDLE_VALUE || iErr == ERROR_NO_MORE_FILES)
349 return VERR_NO_MORE_FILES;
350 return RTErrConvertFromWin32(iErr);
351 }
352 }
353
354 /*
355 * Convert the filename to UTF-8.
356 */
357 if (!pDir->pszName)
358 {
359 int rc = RTUtf16ToUtf8((PCRTUTF16)pDir->Data.cFileName, &pDir->pszName);
360 if (RT_FAILURE(rc))
361 {
362 pDir->pszName = NULL;
363 return rc;
364 }
365 pDir->cchName = strlen(pDir->pszName);
366 }
367
368 /*
369 * Check if we've got enough space to return the data.
370 */
371 const char *pszName = pDir->pszName;
372 const size_t cchName = pDir->cchName;
373 const size_t cbRequired = RT_OFFSETOF(RTDIRENTRYEX, szName[1]) + cchName;
374 if (pcbDirEntry)
375 *pcbDirEntry = cbRequired;
376 if (cbRequired > cbDirEntry)
377 return VERR_BUFFER_OVERFLOW;
378
379 /*
380 * Setup the returned data.
381 */
382 pDir->fDataUnread = false;
383 pDirEntry->cbName = (uint16_t)cchName;
384 Assert(pDirEntry->cbName == cchName);
385 memcpy(pDirEntry->szName, pszName, cchName + 1);
386 if (pDir->Data.cAlternateFileName[0])
387 {
388 /* copy and calc length */
389 PCRTUTF16 pwszSrc = (PCRTUTF16)pDir->Data.cAlternateFileName;
390 PRTUTF16 pwszDst = pDirEntry->wszShortName;
391 uint32_t off = 0;
392 while (pwszSrc[off] && off < RT_ELEMENTS(pDirEntry->wszShortName) - 1U)
393 {
394 pwszDst[off] = pwszSrc[off];
395 off++;
396 }
397 pDirEntry->cwcShortName = (uint16_t)off;
398
399 /* zero the rest */
400 do
401 pwszDst[off++] = '\0';
402 while (off < RT_ELEMENTS(pDirEntry->wszShortName));
403 }
404 else
405 {
406 memset(pDirEntry->wszShortName, 0, sizeof(pDirEntry->wszShortName));
407 pDirEntry->cwcShortName = 0;
408 }
409
410 pDirEntry->Info.cbObject = ((uint64_t)pDir->Data.nFileSizeHigh << 32)
411 | (uint64_t)pDir->Data.nFileSizeLow;
412 pDirEntry->Info.cbAllocated = pDirEntry->Info.cbObject;
413
414 Assert(sizeof(uint64_t) == sizeof(pDir->Data.ftCreationTime));
415 RTTimeSpecSetNtTime(&pDirEntry->Info.BirthTime, *(uint64_t *)&pDir->Data.ftCreationTime);
416 RTTimeSpecSetNtTime(&pDirEntry->Info.AccessTime, *(uint64_t *)&pDir->Data.ftLastAccessTime);
417 RTTimeSpecSetNtTime(&pDirEntry->Info.ModificationTime, *(uint64_t *)&pDir->Data.ftLastWriteTime);
418 pDirEntry->Info.ChangeTime = pDirEntry->Info.ModificationTime;
419
420 pDirEntry->Info.Attr.fMode = rtFsModeFromDos((pDir->Data.dwFileAttributes << RTFS_DOS_SHIFT) & RTFS_DOS_MASK_NT,
421 pszName, cchName);
422
423 /*
424 * Requested attributes (we cannot provide anything actually).
425 */
426 switch (enmAdditionalAttribs)
427 {
428 case RTFSOBJATTRADD_EASIZE:
429 pDirEntry->Info.Attr.enmAdditional = RTFSOBJATTRADD_EASIZE;
430 pDirEntry->Info.Attr.u.EASize.cb = 0;
431 break;
432
433 case RTFSOBJATTRADD_UNIX:
434 pDirEntry->Info.Attr.enmAdditional = RTFSOBJATTRADD_UNIX;
435 pDirEntry->Info.Attr.u.Unix.uid = ~0U;
436 pDirEntry->Info.Attr.u.Unix.gid = ~0U;
437 pDirEntry->Info.Attr.u.Unix.cHardlinks = 1;
438 pDirEntry->Info.Attr.u.Unix.INodeIdDevice = 0; /** @todo Use the volume serial number (see GetFileInformationByHandle). */
439 pDirEntry->Info.Attr.u.Unix.INodeId = 0; /** @todo Use the fileid (see GetFileInformationByHandle). */
440 pDirEntry->Info.Attr.u.Unix.fFlags = 0;
441 pDirEntry->Info.Attr.u.Unix.GenerationId = 0;
442 pDirEntry->Info.Attr.u.Unix.Device = 0;
443 break;
444
445 case RTFSOBJATTRADD_NOTHING:
446 pDirEntry->Info.Attr.enmAdditional = RTFSOBJATTRADD_NOTHING;
447 break;
448
449 case RTFSOBJATTRADD_UNIX_OWNER:
450 pDirEntry->Info.Attr.enmAdditional = RTFSOBJATTRADD_UNIX_OWNER;
451 pDirEntry->Info.Attr.u.UnixOwner.uid = ~0U;
452 pDirEntry->Info.Attr.u.UnixOwner.szName[0] = '\0'; /** @todo return something sensible here. */
453 break;
454
455 case RTFSOBJATTRADD_UNIX_GROUP:
456 pDirEntry->Info.Attr.enmAdditional = RTFSOBJATTRADD_UNIX_GROUP;
457 pDirEntry->Info.Attr.u.UnixGroup.gid = ~0U;
458 pDirEntry->Info.Attr.u.UnixGroup.szName[0] = '\0';
459 break;
460
461 default:
462 AssertMsgFailed(("Impossible!\n"));
463 return VERR_INTERNAL_ERROR;
464 }
465
466 return VINF_SUCCESS;
467}
468
469
470RTDECL(int) RTDirRename(const char *pszSrc, const char *pszDst, unsigned fRename)
471{
472 /*
473 * Validate input.
474 */
475 AssertMsgReturn(VALID_PTR(pszSrc), ("%p\n", pszSrc), VERR_INVALID_POINTER);
476 AssertMsgReturn(VALID_PTR(pszDst), ("%p\n", pszDst), VERR_INVALID_POINTER);
477 AssertMsgReturn(*pszSrc, ("%p\n", pszSrc), VERR_INVALID_PARAMETER);
478 AssertMsgReturn(*pszDst, ("%p\n", pszDst), VERR_INVALID_PARAMETER);
479 AssertMsgReturn(!(fRename & ~RTPATHRENAME_FLAGS_REPLACE), ("%#x\n", fRename), VERR_INVALID_PARAMETER);
480
481 /*
482 * Call the worker.
483 */
484 int rc = rtPathWin32MoveRename(pszSrc, pszDst,
485 fRename & RTPATHRENAME_FLAGS_REPLACE ? MOVEFILE_REPLACE_EXISTING : 0,
486 RTFS_TYPE_DIRECTORY);
487
488 LogFlow(("RTDirRename(%p:{%s}, %p:{%s}, %#x): returns %Rrc\n", pszSrc, pszSrc, pszDst, pszDst, fRename, rc));
489 return rc;
490}
491
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