Changeset 47534 in vbox for trunk/src/VBox/Runtime/r3/win/dir-win.cpp
- Timestamp:
- Aug 4, 2013 1:52:13 PM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r3/win/dir-win.cpp
r44528 r47534 1 1 /* $Id$ */ 2 2 /** @file 3 * IPRT - Directory, win32.3 * IPRT - Directory, Windows. 4 4 */ 5 5 … … 31 31 #define LOG_GROUP RTLOGGROUP_DIR 32 32 #include <Windows.h> 33 #include <io.h>34 33 35 34 #include <iprt/dir.h> 36 35 #include <iprt/path.h> 37 #include <iprt/ alloc.h>36 #include <iprt/mem.h> 38 37 #include <iprt/string.h> 39 38 #include <iprt/assert.h> 40 #include <iprt/param.h>41 39 #include <iprt/err.h> 42 40 #include <iprt/file.h> … … 44 42 #include "internal/fs.h" 45 43 #include "internal/path.h" 46 #include "internal/dir.h"47 44 48 45 … … 130 127 131 128 132 int 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 overflow139 * 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 else149 {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 else170 {171 DWORD dwErr = GetLastError();172 /* Theoretical case of an empty directory or more normal case of no matches. */173 if ( dwErr == ERROR_FILE_NOT_FOUND174 || dwErr == ERROR_NO_MORE_FILES /* ???*/)175 pDir->fDataUnread = false;176 else177 rc = RTErrConvertFromWin32(GetLastError());178 }179 RTUtf16Free(pwszName);180 }181 182 return rc;183 }184 185 186 RTDECL(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 217 RTDECL(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_DIRECTORY292 ? 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 301 RTDECL(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 about304 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_NOTHING319 || 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 do401 pwszDst[off++] = '\0';402 while (off < RT_ELEMENTS(pDirEntry->wszShortName));403 }404 else405 {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 470 129 RTDECL(int) RTDirRename(const char *pszSrc, const char *pszDst, unsigned fRename) 471 130 {
Note:
See TracChangeset
for help on using the changeset viewer.