Changeset 99085 in vbox
- Timestamp:
- Mar 21, 2023 12:15:00 PM (2 years ago)
- svn:sync-xref-src-repo-rev:
- 156450
- Location:
- trunk
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/GuestHost/GuestControl.h
r98824 r99085 432 432 /** GSTCTL_PATH_F_XXX flag valid mask. */ 433 433 #define GSTCTL_PATH_F_VALID_MASK UINT32_C(0x00000007) 434 /** @} */ 435 436 /** @name GSTCTL_DIRLIST_F_XXX - Flags for guest directory listings. 437 * @{ */ 438 /** No guest listing flags specified. */ 439 #define GSTCTL_DIRLIST_F_NONE UINT32_C(0) 440 /** GSTCTL_DIRLIST_F_XXX valid mask. */ 441 #define GSTCTL_DIRLIST_F_VALID_MASK UINT32_C(0x00000000) 434 442 /** @} */ 435 443 … … 553 561 554 562 /** The maximum size (in bytes) of an entry file name (at least RT_UOFFSETOF(GSTCTLDIRENTRYEX, szName[2]). */ 555 #define GSTCTL_DIRENTRY_MAX_SIZE 4096 556 563 #define GSTCTL_DIRENTRY_MAX_SIZE 4096 564 /** Maximum characters of the resolved user name. Including terminator. */ 565 #define GSTCTL_DIRENTRY_MAX_USER_NAME 255 566 /** Maximum characters of the resolved user groups list. Including terminator. */ 567 #define GSTCTL_DIRENTRY_MAX_USER_GROUPS _1K 568 /** The resolved user groups delimiter as a string. */ 569 #define GSTCTL_DIRENTRY_GROUPS_DELIMITER_STR "\r\n" 570 571 /** 572 * Guest directory entry header. 573 * 574 * This is needed for (un-)packing multiple directory entries with its resolved user name + groups 575 * with the HOST_MSG_DIR_LIST command. 576 * 577 * The order of the attributes also mark their packed order, so be careful when changing this! 578 * 579 * @since 7.1. 580 */ 581 #pragma pack(1) 582 typedef struct GSTCTLDIRENTRYLISTHDR 583 { 584 /** Size (in bytes) of the directory header). */ 585 uint32_t cbDirEntryEx; 586 /** Size (in bytes) of the resolved user name as a string 587 * Includes terminator. */ 588 uint32_t cbUser; 589 /** Size (in bytes) of the resolved user groups as a string. 590 * Delimited by GSTCTL_DIRENTRY_GROUPS_DELIMITER_STR. Includes terminator. */ 591 uint32_t cbGroups; 592 } GSTCTLDIRENTRYBLOCK; 593 /** Pointer to a guest directory header entry. */ 594 typedef GSTCTLDIRENTRYLISTHDR *PGSTCTLDIRENTRYLISTHDR; 595 #pragma pack() 557 596 } /* namespace guestControl */ 558 597 -
trunk/include/VBox/HostServices/GuestControlSvc.h
r98824 r99085 232 232 */ 233 233 HOST_MSG_DIR_CREATE = 314, 234 /** 235 * Lists one or multiple directory entries at once. 236 * 237 * @since 7.1 238 */ 239 HOST_MSG_DIR_LIST = 315, 234 240 #endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */ 235 241 /** … … 302 308 RT_CASE_RET_STR(HOST_MSG_DIR_REWIND); 303 309 RT_CASE_RET_STR(HOST_MSG_DIR_CREATE); 310 RT_CASE_RET_STR(HOST_MSG_DIR_LIST); 304 311 #endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */ 305 312 RT_CASE_RET_STR(HOST_MSG_DIR_REMOVE); … … 729 736 /** Guest directory was rewind. */ 730 737 GUEST_DIR_NOTIFYTYPE_REWIND = 22, 738 /** Guest directory listing. */ 739 GUEST_DIR_NOTIFYTYPE_LIST = 23, 731 740 #endif 732 741 /** Information about an open guest directory. */ … … 1092 1101 HGCMFunctionParameter flags; 1093 1102 } HGCMMsgDirCreate; 1103 1104 /** 1105 * Lists the entries of a directory on the guest. 1106 */ 1107 typedef struct HGCMMsgDirList 1108 { 1109 VBGLIOCHGCMCALL hdr; 1110 /** Context ID. */ 1111 HGCMFunctionParameter context; 1112 /** Handle of directory listing to list. */ 1113 HGCMFunctionParameter handle; 1114 /** Number of entries to read at once. 1115 * Specify UINT32_MAX to read as much as possible. 0 is not allowed. */ 1116 HGCMFunctionParameter num_entries; 1117 /** Listing flags (GSTCTL_DIRLIST_F_XXX). */ 1118 HGCMFunctionParameter flags; 1119 } HGCMMsgDirList; 1094 1120 #endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */ 1095 1121 … … 1528 1554 { 1529 1555 /** 1530 * Parameters used for \a type GUEST_DIR_NOTIFYTYPE_OPEN.1556 * Parameters used for \a reply_hdr.type GUEST_DIR_NOTIFYTYPE_OPEN. 1531 1557 * 1532 1558 * @since 7.1 … … 1538 1564 } open; 1539 1565 /** 1540 * Parameters used for \a type GUEST_DIR_NOTIFYTYPE_READ.1566 * Parameters used for \a reply_hdr.type GUEST_DIR_NOTIFYTYPE_READ. 1541 1567 * 1542 1568 * @since 7.1 … … 1550 1576 /** Resolved group IDs as a string. 1551 1577 * 1552 * Multiple groups are delimited by "\r\n", whereas1578 * Multiple groups are delimited by GSTCTL_DIRENTRY_GROUPS_DELIMITER_STR, whereas 1553 1579 * the first group always is the primary group. */ 1554 1580 HGCMFunctionParameter groups; 1555 1581 } read; 1582 /** 1583 * Parameters used for \a reply_hdr.type GUEST_DIR_NOTIFYTYPE_LIST. 1584 * 1585 * @since 7.1 1586 */ 1587 struct 1588 { 1589 /** Number of entries in \a buffer. */ 1590 HGCMFunctionParameter num_entries; 1591 /** Buffer containing the GSTCTLDIRENTRYEX entries, immediately followed 1592 * by resolved user + groups as a string (empty strings if not resolved). 1593 * 1594 * Only will be sent if \a num_entries > 0. */ 1595 HGCMFunctionParameter buffer; 1596 } list; 1556 1597 } u; 1557 1598 } HGCMReplyDirNotify; … … 1582 1623 /** Resolved group IDs as a string. 1583 1624 * 1584 * Multiple groups are delimited by "\r\n", whereas1625 * Multiple groups are delimited by GSTCTL_DIRENTRY_GROUPS_DELIMITER_STR, whereas 1585 1626 * the first group always is the primary group. */ 1586 1627 HGCMFunctionParameter groups; -
trunk/include/VBox/VBoxGuestLib.h
r98824 r99085 1122 1122 VBGLR3DECL(int) VbglR3GuestCtrlDirGetRead(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle); 1123 1123 VBGLR3DECL(int) VbglR3GuestCtrlDirGetRewind(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle); 1124 VBGLR3DECL(int) VbglR3GuestCtrlDirGetList(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle, uint32_t *pcEntries, uint32_t *pfFlags); 1124 1125 /** @} */ 1125 1126 # endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */ … … 1155 1156 VBGLR3DECL(int) VbglR3GuestCtrlDirCbRead(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc, PGSTCTLDIRENTRYEX pEntry, uint32_t cbSize); 1156 1157 VBGLR3DECL(int) VbglR3GuestCtrlDirCbRewind(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc); 1158 VBGLR3DECL(int) VbglR3GuestCtrlDirCbList(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc, uint32_t cEntries, void *pvBuf, uint32_t cbBuf); 1157 1159 /** @} */ 1158 1160 # endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */ -
trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibGuestCtrl.cpp
r98824 r99085 1129 1129 return rc; 1130 1130 } 1131 1132 1133 /** 1134 * Retrieves a HOST_MSG_DIR_LIST message. 1135 * 1136 * @returns VBox status code. 1137 * @param pCtx Guest control command context to use. 1138 * @param puHandle Where to return the directory handle to rewind. 1139 * @param pcEntries Where to return the number of directory entries to read. 1140 * @param pfFlags Where to return the directory listing flags. 1141 */ 1142 VBGLR3DECL(int) VbglR3GuestCtrlDirGetList(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t *puHandle, uint32_t *pcEntries, uint32_t *pfFlags) 1143 { 1144 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 1145 AssertReturn(pCtx->uNumParms == 4, VERR_INVALID_PARAMETER); 1146 1147 AssertPtrReturn(puHandle, VERR_INVALID_POINTER); 1148 AssertPtrReturn(pcEntries, VERR_INVALID_POINTER); 1149 AssertPtrReturn(pfFlags, VERR_INVALID_POINTER); 1150 1151 int rc; 1152 do 1153 { 1154 HGCMMsgDirList Msg; 1155 VBGL_HGCM_HDR_INIT(&Msg.hdr, pCtx->uClientID, vbglR3GuestCtrlGetMsgFunctionNo(pCtx->uClientID), pCtx->uNumParms); 1156 VbglHGCMParmUInt32Set(&Msg.context, HOST_MSG_DIR_LIST); 1157 VbglHGCMParmUInt32Set(&Msg.handle, 0); 1158 VbglHGCMParmUInt32Set(&Msg.num_entries, 0); 1159 VbglHGCMParmUInt32Set(&Msg.flags, 0); 1160 1161 rc = VbglR3HGCMCall(&Msg.hdr, sizeof(Msg)); 1162 if (RT_SUCCESS(rc)) 1163 { 1164 Msg.context.GetUInt32(&pCtx->uContextID); 1165 Msg.handle.GetUInt32(puHandle); 1166 Msg.num_entries.GetUInt32(pcEntries); 1167 Msg.flags.GetUInt32(pfFlags); 1168 } 1169 } while (rc == VERR_INTERRUPTED && g_fVbglR3GuestCtrlHavePeekGetCancel); 1170 return rc; 1171 } 1131 1172 #endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */ 1132 1173 … … 2280 2321 { 2281 2322 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 2282 AssertPtrReturn(pszUser, VERR_INVALID_POINTER);2283 AssertPtrReturn(pszGroups, VERR_INVALID_POINTER);2284 2323 2285 2324 HGCMReplyDirNotify Msg; … … 2332 2371 2333 2372 return VbglR3HGCMCall(&Msg.reply_hdr.hdr, RT_UOFFSET_AFTER(HGCMReplyDirNotify, u)); 2373 } 2374 2375 2376 /** 2377 * Replies to a HOST_MSG_DIR_LIST message. 2378 * 2379 * @returns VBox status code. 2380 * @param pCtx Guest control command context to use. 2381 * @param uRc Guest rc of operation (note: IPRT-style signed int). 2382 * @þaram cEntries Number of directory entries to send. 2383 * @param pvBuf Buffer of directory entries to send. 2384 * @param cbBuf Size (in bytes) of \a pvBuf. 2385 */ 2386 VBGLR3DECL(int) VbglR3GuestCtrlDirCbList(PVBGLR3GUESTCTRLCMDCTX pCtx, uint32_t uRc, 2387 uint32_t cEntries, void *pvBuf, uint32_t cbBuf) 2388 { 2389 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 2390 2391 HGCMReplyDirNotify Msg; 2392 VBGL_HGCM_HDR_INIT(&Msg.reply_hdr.hdr, pCtx->uClientID, GUEST_MSG_DIR_NOTIFY, GSTCTL_HGCM_REPLY_HDR_PARMS + 2); 2393 VbglHGCMParmUInt32Set(&Msg.reply_hdr.context, pCtx->uContextID); 2394 VbglHGCMParmUInt32Set(&Msg.reply_hdr.type, GUEST_DIR_NOTIFYTYPE_LIST); 2395 VbglHGCMParmUInt32Set(&Msg.reply_hdr.rc, uRc); 2396 2397 VbglHGCMParmUInt32Set(&Msg.u.list.num_entries, cEntries); 2398 VbglHGCMParmPtrSet(&Msg.u.list.buffer, pvBuf, cbBuf); 2399 2400 return VbglR3HGCMCall(&Msg.reply_hdr.hdr, RT_UOFFSET_AFTER(HGCMReplyDirNotify, u.list)); 2334 2401 } 2335 2402 #endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */ -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControl.h
r98824 r99085 87 87 /** Additional attributes enumeration to use for reading directory entries. */ 88 88 GSTCTLFSOBJATTRADD enmReadAttrAdd; 89 /** Scratch buffer for holding the directory reading entry. 90 * Currently NOT serialized, i.e. only can be used for one read at a time. */ 91 PRTDIRENTRYEX pDirEntryEx; 92 /** Size (in bytes) of \a pDirEntryEx. */ 93 size_t cbDirEntryEx; 89 94 } VBOXSERVICECTRLDIR; 90 95 /** Pointer to a guest directory. */ … … 233 238 /** The gid cache for this session. */ 234 239 VGSVCIDCACHE GidCache; 235 /** Scratch buffer for holding the directory reading entry.236 * Currently NOT serialized, i.e. only can be used for one read at a time. */237 PRTDIRENTRYEX pDirEntryEx;238 /** Size (in bytes) of \a pDirEntryEx. */239 size_t cbDirEntryEx;240 240 #endif 241 241 } VBOXSERVICECTRLSESSION; -
trunk/src/VBox/Additions/common/VBoxService/VBoxServiceControlSession.cpp
r98831 r99085 113 113 if (!pDir) 114 114 return VINF_SUCCESS; 115 116 RTMemFree(pDir->pDirEntryEx); 115 117 116 118 int rc; … … 1038 1040 pDir->enmReadAttrAdd = enmAttrAdd; 1039 1041 1042 pDir->cbDirEntryEx = GSTCTL_DIRENTRY_MAX_SIZE; 1043 pDir->pDirEntryEx = (PRTDIRENTRYEX)RTMemAlloc(pDir->cbDirEntryEx); 1044 AssertPtrReturn(pDir->pDirEntryEx, VERR_NO_MEMORY); 1045 1040 1046 if (RT_SUCCESS(rc)) 1041 1047 { … … 1134 1140 1135 1141 1142 /** 1143 * Worker function for reading a next guest directory entry. 1144 * 1145 * @returns VBox status code. 1146 * @param pSession Guest Control session to use. 1147 * @param pDir Guest directory to read the next entry for. 1148 * @param ppDirEntryEx Where to store the pointer to the next guest directory entry on success. 1149 * @param pcbDirEntryEx Where to return the size (in bytes) of \a ppGstCtlDirEntryEx on success. 1150 * @param ppszUser Where to return the resolved user name string. 1151 * @param ppszGroups Where to return the resolved groups string. 1152 */ 1153 static int vgsvcGstCtrlSessionDirReadNext(const PVBOXSERVICECTRLSESSION pSession, 1154 PVBOXSERVICECTRLDIR pDir, 1155 PGSTCTLDIRENTRYEX *ppDirEntryEx, size_t *pcbDirEntryEx, 1156 const char **ppszUser, const char **ppszGroups) 1157 { 1158 PRTDIRENTRYEX pDirEntryEx = pDir->pDirEntryEx; 1159 1160 size_t cbDirEntryEx = pDir->cbDirEntryEx; 1161 int rc = RTDirReadEx(pDir->hDir, pDir->pDirEntryEx, &cbDirEntryEx, (RTFSOBJATTRADD)pDir->enmReadAttrAdd, pDir->fRead); 1162 1163 VGSvcVerbose(2, "[Dir %s] Read next entry '%s' -> %Rrc (%zu bytes)\n", 1164 pDir->pszPathAbs, RT_SUCCESS(rc) ? pDirEntryEx->szName : "<None>", rc, cbDirEntryEx); 1165 1166 if (RT_FAILURE(rc)) 1167 return rc; 1168 1169 /* Paranoia. */ 1170 AssertReturn(cbDirEntryEx <= pDir->cbDirEntryEx, VERR_BUFFER_OVERFLOW); 1171 1172 *ppszUser = VGSvcIdCacheGetUidName(&pSession->UidCache, 1173 pDirEntryEx->Info.Attr.u.Unix.uid, pDirEntryEx->szName, pDir->pszPathAbs); 1174 *ppszGroups = VGSvcIdCacheGetGidName(&pSession->GidCache, 1175 pDirEntryEx->Info.Attr.u.Unix.gid, pDirEntryEx->szName, pDir->pszPathAbs); 1176 1177 VGSvcVerbose(2, "[Dir %s] Entry '%s': %zu bytes, uid=%s (%d), gid=%s (%d)\n", 1178 pDir->pszPathAbs, pDirEntryEx->szName, pDirEntryEx->Info.cbObject, 1179 *ppszUser, pDirEntryEx->Info.Attr.u.UnixOwner.uid, 1180 *ppszGroups, pDirEntryEx->Info.Attr.u.UnixGroup.gid); 1181 1182 /* 1183 * For now we ASSUME that RTDIRENTRYEX == GSTCTLDIRENTRYEX, which implies that we simply can cast RTDIRENTRYEX 1184 * to GSTCTLDIRENTRYEX. This might change in the future, however, so be extra cautious here. 1185 * 1186 * Ditto for RTFSOBJATTRADD == GSTCTLFSOBJATTRADD. 1187 */ 1188 AssertCompile(sizeof(GSTCTLDIRENTRYEX) == sizeof(RTDIRENTRYEX)); 1189 AssertCompile(RT_OFFSETOF(GSTCTLDIRENTRYEX, Info) == RT_OFFSETOF(RTDIRENTRYEX, Info)); 1190 AssertCompile(RT_OFFSETOF(GSTCTLDIRENTRYEX, cbName) == RT_OFFSETOF(RTDIRENTRYEX, cbName)); 1191 AssertCompile(RT_OFFSETOF(GSTCTLDIRENTRYEX, szName) == RT_OFFSETOF(RTDIRENTRYEX, szName)); 1192 AssertCompile(RT_OFFSETOF(GSTCTLFSOBJINFO, Attr) == RT_OFFSETOF(RTFSOBJINFO, Attr)); 1193 1194 if (RT_SUCCESS(rc)) 1195 { 1196 *ppDirEntryEx = (PGSTCTLDIRENTRYEX)pDirEntryEx; 1197 *pcbDirEntryEx = cbDirEntryEx; 1198 } 1199 1200 return rc; 1201 } 1202 1203 1136 1204 static int vgsvcGstCtrlSessionHandleDirRead(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx) 1137 1205 { … … 1149 1217 if (pDir) 1150 1218 { 1151 PRTDIRENTRYEX pDirEntryEx = pSession->pDirEntryEx; 1152 1153 size_t cbDirEntry = pSession->cbDirEntryEx; 1154 rc = RTDirReadEx(pDir->hDir, pDirEntryEx, &cbDirEntry, (RTFSOBJATTRADD)pDir->enmReadAttrAdd, pDir->fRead); 1155 1156 /* Paranoia. */ 1157 AssertStmt(cbDirEntry <= pSession->cbDirEntryEx, rc = VERR_BUFFER_OVERFLOW); 1158 1159 VGSvcVerbose(2, "[Dir %s] Read next entry '%s' -> %Rrc (%zu bytes)\n", 1160 pDir->pszPathAbs, RT_SUCCESS(rc) ? pDirEntryEx->szName : "<None>", rc, cbDirEntry); 1161 1162 const char *pszUser = VGSvcIdCacheGetUidName(&pSession->UidCache, 1163 pDirEntryEx->Info.Attr.u.Unix.uid, pDirEntryEx->szName, pDir->pszPathAbs); 1164 const char *pszGroup = VGSvcIdCacheGetGidName(&pSession->GidCache, 1165 pDirEntryEx->Info.Attr.u.Unix.gid, pDirEntryEx->szName, pDir->pszPathAbs); 1166 1167 VGSvcVerbose(2, "[Dir %s] Entry '%s': %zu bytes, uid=%s (%d), gid=%s (%d)\n", 1168 pDir->pszPathAbs, pDirEntryEx->szName, pDirEntryEx->Info.cbObject, 1169 pszUser ? pszUser : "", pDirEntryEx->Info.Attr.u.UnixOwner.uid, 1170 pszGroup ? pszGroup : "", pDirEntryEx->Info.Attr.u.UnixGroup.gid); 1171 1172 /* 1173 * For now we ASSUME that RTDIRENTRYEX == GSTCTLDIRENTRYEX, which implies that we simply can cast RTDIRENTRYEX 1174 * to GSTCTLDIRENTRYEX. This might change in the future, however, so be extra cautious here. 1175 * 1176 * Ditto for RTFSOBJATTRADD == GSTCTLFSOBJATTRADD. 1177 */ 1178 AssertCompile(sizeof(GSTCTLDIRENTRYEX) == sizeof(RTDIRENTRYEX)); 1179 AssertCompile(RT_OFFSETOF(GSTCTLDIRENTRYEX, Info) == RT_OFFSETOF(RTDIRENTRYEX, Info)); 1180 AssertCompile(RT_OFFSETOF(GSTCTLDIRENTRYEX, cbName) == RT_OFFSETOF(RTDIRENTRYEX, cbName)); 1181 AssertCompile(RT_OFFSETOF(GSTCTLDIRENTRYEX, szName) == RT_OFFSETOF(RTDIRENTRYEX, szName)); 1182 AssertCompile(RT_OFFSETOF(GSTCTLFSOBJINFO, Attr) == RT_OFFSETOF(RTFSOBJINFO, Attr)); 1183 1184 PGSTCTLDIRENTRYEX pGstCtlDirEntryEx = (PGSTCTLDIRENTRYEX)pDirEntryEx; 1185 1186 int rc2 = VbglR3GuestCtrlDirCbReadEx(pHostCtx, rc, pGstCtlDirEntryEx, (uint32_t)cbDirEntry, pszUser, pszGroup); 1219 PGSTCTLDIRENTRYEX pDirEntryEx; 1220 size_t cbDirEntryEx; 1221 const char *pszUser = NULL; 1222 const char *pszGroups = NULL; 1223 rc = vgsvcGstCtrlSessionDirReadNext(pSession, pDir, 1224 &pDirEntryEx, &cbDirEntryEx, &pszUser, &pszGroups); 1225 1226 VGSvcVerbose(2, "[Dir %s] %Rrc\n", pDir->pszPathAbs, rc); 1227 1228 int rc2; 1229 if (RT_SUCCESS(rc)) 1230 rc2 = VbglR3GuestCtrlDirCbReadEx(pHostCtx, rc, pDirEntryEx, cbDirEntryEx, pszUser, pszGroups); 1231 else 1232 rc2 = VbglR3GuestCtrlDirCbRead(pHostCtx, rc, NULL /* pEntry */, 0 /* cbSize */); 1187 1233 if (RT_FAILURE(rc2)) 1188 1234 VGSvcError("Failed to report directory read status (%Rrc), rc=%Rrc\n", rc, rc2); 1235 1236 VGSvcVerbose(2, "[Dir %s] 2 %Rrc\n", pDir->pszPathAbs, rc); 1189 1237 1190 1238 if (rc == VERR_NO_MORE_FILES) /* Directory reading done. */ … … 1308 1356 } 1309 1357 VGSvcVerbose(5, "Creating directory returned rc=%Rrc\n", rc); 1358 return rc; 1359 } 1360 1361 static int vgsvcGstCtrlSessionHandleDirList(const PVBOXSERVICECTRLSESSION pSession, PVBGLR3GUESTCTRLCMDCTX pHostCtx) 1362 { 1363 AssertPtrReturn(pSession, VERR_INVALID_POINTER); 1364 AssertPtrReturn(pHostCtx, VERR_INVALID_POINTER); 1365 1366 /* 1367 * Retrieve the request. 1368 */ 1369 uint32_t uHandle; 1370 uint32_t cEntries; 1371 uint32_t cEntriesRead = 0; 1372 uint32_t fFlags; 1373 int rc = VbglR3GuestCtrlDirGetList(pHostCtx, &uHandle, &cEntries, &fFlags); 1374 if (RT_SUCCESS(rc)) 1375 { 1376 size_t cbGrowSize = _64K; 1377 void *pvBuf = RTMemAlloc(cbGrowSize); 1378 if (!pvBuf) 1379 rc = VERR_NO_MEMORY; 1380 size_t cbBufUsed = 0; 1381 if (RT_SUCCESS(rc)) 1382 { 1383 if (!(fFlags & ~GSTCTL_DIRLIST_F_VALID_MASK)) 1384 { 1385 size_t cbBufSize = cbGrowSize; 1386 1387 PVBOXSERVICECTRLDIR pDir = vgsvcGstCtrlSessionDirAcquire(pSession, uHandle); 1388 if (pDir) 1389 { 1390 PGSTCTLDIRENTRYEX pDirEntryEx; 1391 size_t cbDirEntryEx; 1392 const char *pszUser = NULL; 1393 const char *pszGroups = NULL; 1394 1395 while (cEntries--) 1396 { 1397 rc = vgsvcGstCtrlSessionDirReadNext(pSession, pDir, 1398 &pDirEntryEx, &cbDirEntryEx, &pszUser, &pszGroups); 1399 if (RT_FAILURE(rc)) /* Might be VERR_NO_MORE_FILES. */ 1400 break; 1401 1402 size_t const cbHdr = sizeof(GSTCTLDIRENTRYLISTHDR); 1403 size_t const cbUser = strlen(pszUser) + 1; /* Include terminator. */ 1404 size_t const cbGroups = strlen(pszGroups) + 1; /* Ditto. */ 1405 size_t const cbTotal = cbHdr + cbDirEntryEx + cbUser + cbGroups; 1406 1407 if (cbBufSize - cbBufUsed < cbTotal) /* Grow buffer, if needed. */ 1408 { 1409 AssertBreakStmt(cbTotal <= cbGrowSize, VERR_BUFFER_OVERFLOW); 1410 pvBuf = RTMemRealloc(pvBuf, cbBufSize + cbGrowSize); 1411 AssertPtrBreakStmt(pvBuf, VERR_NO_MEMORY); 1412 cbBufSize += cbGrowSize; 1413 } 1414 1415 GSTCTLDIRENTRYLISTHDR Hdr; 1416 Hdr.cbDirEntryEx = cbDirEntryEx; 1417 Hdr.cbUser = cbUser; 1418 Hdr.cbGroups = cbGroups; 1419 1420 memcpy((uint8_t *)pvBuf + cbBufUsed, &Hdr, cbHdr); 1421 cbBufUsed += cbHdr; 1422 memcpy((uint8_t *)pvBuf + cbBufUsed, pDirEntryEx, cbDirEntryEx); 1423 cbBufUsed += cbDirEntryEx; 1424 memcpy((uint8_t *)pvBuf + cbBufUsed, pszUser, cbUser); 1425 cbBufUsed += cbUser; 1426 memcpy((uint8_t *)pvBuf + cbBufUsed, pszGroups, cbGroups); 1427 cbBufUsed += cbGroups; 1428 1429 Assert(cbBufUsed <= cbBufSize); 1430 cEntriesRead++; 1431 } 1432 1433 vgsvcGstCtrlSessionDirRelease(pDir); 1434 } 1435 1436 VGSvcVerbose(4, "Read %RU32 directory entries (requested %RU32 entries) -> %zu bytes, rc=%Rrc\n", 1437 cEntriesRead, cEntries, cbBufUsed, rc); 1438 1439 /* Directory reading done? */ 1440 if ( cEntriesRead 1441 && rc == VERR_NO_MORE_FILES) 1442 rc = VINF_SUCCESS; 1443 1444 /* Note: Subsequent calls will return VERR_NO_MORE_FILES to the host. */ 1445 } 1446 else 1447 { 1448 VGSvcError("Unsupported directory listing flags: %#x (all %#x)\n", (fFlags & ~GSTCTL_DIRLIST_F_VALID_MASK), fFlags); 1449 rc = VERR_NOT_SUPPORTED; 1450 } 1451 } 1452 1453 /* 1454 * Report result back to host. 1455 */ 1456 int rc2 = VbglR3GuestCtrlDirCbList(pHostCtx, rc, cEntriesRead, pvBuf, (uint32_t)cbBufUsed); 1457 if (RT_FAILURE(rc2)) 1458 VGSvcError("Failed to report directory listing (%Rrc), rc=%Rrc\n", rc, rc2); 1459 1460 if (rc == VERR_NO_MORE_FILES) /* Directory reading done? */ 1461 rc = VINF_SUCCESS; 1462 1463 RTMemFree(pvBuf); 1464 } 1465 else 1466 { 1467 VGSvcError("Error fetching parameters for directory listing operation: %Rrc\n", rc); 1468 VbglR3GuestCtrlMsgSkip(pHostCtx->uClientID, rc, UINT32_MAX); 1469 } 1470 VGSvcVerbose(5, "Listing directory returned rc=%Rrc\n", rc); 1310 1471 return rc; 1311 1472 } … … 2123 2284 rc = vgsvcGstCtrlSessionHandleDirCreate(pSession, pHostCtx); 2124 2285 break; 2286 2287 case HOST_MSG_DIR_LIST: 2288 if (fImpersonated) 2289 rc = vgsvcGstCtrlSessionHandleDirList(pSession, pHostCtx); 2290 break; 2125 2291 #endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */ 2126 2292 … … 2726 2892 int rc = VGSvcGstCtrlSessionClose(pSession); 2727 2893 2728 #ifdef VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS2729 RTMemFree(pSession->pDirEntryEx);2730 #endif2731 2732 2894 /* Destroy critical section. */ 2733 2895 RTCritSectDelete(&pSession->CritSect); … … 2755 2917 RT_ZERO(pSession->UidCache); 2756 2918 RT_ZERO(pSession->GidCache); 2757 2758 pSession->cbDirEntryEx = GSTCTL_DIRENTRY_MAX_SIZE;2759 pSession->pDirEntryEx = (PRTDIRENTRYEX)RTMemAlloc(pSession->cbDirEntryEx);2760 AssertPtrReturn(pSession->pDirEntryEx, VERR_NO_MEMORY);2761 2919 #endif 2762 2920 -
trunk/src/VBox/Main/idl/VirtualBox.xidl
r98964 r99085 16425 16425 <interface 16426 16426 name="IDirectory" extends="$unknown" 16427 uuid=" c7b24ad6-dba7-486c-b1ed-5f16d8d6da22"16427 uuid="a508e094-bf24-4eca-80c6-467766a1e4c0" 16428 16428 wsmap="managed" 16429 16429 reservedMethods="4" reservedAttributes="8" … … 16464 16464 directory entry will not be possible anymore. 16465 16465 </desc> 16466 </method> 16467 16468 <method name="list"> 16469 <desc> 16470 Lists directory entries of this directory. 16471 <result name="VBOX_E_OBJECT_NOT_FOUND"> 16472 No more directory entries to read. 16473 </result> 16474 </desc> 16475 <param name="maxEntries" type="unsigned long" dir="in"> 16476 <desc>Maximum entries to return per call. The guest might decide to return less than the given maximum, depending on 16477 the guest OS.</desc> 16478 </param> 16479 <param name="objInfo" type="IFsObjInfo" safearray="yes" dir="return"> 16480 <desc>Array of object information of the current directory entry read. Also see 16481 <link to="IFsObjInfo"/>.</desc> 16482 </param> 16466 16483 </method> 16467 16484 -
trunk/src/VBox/Main/include/GuestCtrlImplPrivate.h
r99011 r99085 1457 1457 1458 1458 1459 /******************************************************************************* 1460 * Callback data structures.*1461 **1462 * These structures make up the actual low level HGCM callback data sent from*1463 * the guest back to the host.*1464 *******************************************************************************/1459 /********************************************************************************************************************************* 1460 * Callback data structures. * 1461 * * 1462 * These structures make up the actual low level HGCM callback data sent from * 1463 * the guest back to the host. * 1464 ********************************************************************************************************************************/ 1465 1465 1466 1466 /** … … 1636 1636 1637 1637 /** 1638 * Callback data for a single GSTCTLDIRENTRYEX entry. 1639 */ 1640 typedef struct CALLBACKDATA_DIR_ENTRY 1641 { 1642 /** Pointer to directory entry information. */ 1643 PGSTCTLDIRENTRYEX pDirEntryEx; 1644 /** Size (in bytes) of directory entry information. */ 1645 uint32_t cbDirEntryEx; 1646 /** Resolved user name. 1647 * This is the object owner for UNIX-y Oses. */ 1648 char *pszUser; 1649 /** Size (in bytes) of \a pszUser. */ 1650 uint32_t cbUser; 1651 /** Resolved user group(s). */ 1652 char *pszGroups; 1653 /** Size (in bytes) of \a pszGroups. */ 1654 uint32_t cbGroups; 1655 } CALLBACKDATA_DIR_ENTRY; 1656 /** Pointer to a CALLBACKDATA_DIR_ENTRY struct. */ 1657 typedef CALLBACKDATA_DIR_ENTRY *PCALLBACKDATA_DIR_ENTRY; 1658 1659 /** 1638 1660 * Callback data for guest directory operations. 1639 1661 */ … … 1661 1683 struct 1662 1684 { 1663 /** Pointer to directory entry information. */ 1664 PGSTCTLDIRENTRYEX pEntry; 1665 /** Size (in bytes) of directory entry information. */ 1666 uint32_t cbEntry; 1667 /** Resolved user name. 1668 * This is the object owner for UNIX-y Oses. */ 1669 char *pszUser; 1670 /** Size (in bytes) of \a pszUser. */ 1671 uint32_t cbUser; 1672 /** Resolved user group(s). */ 1673 char *pszGroups; 1674 /** Size (in bytes) of \a pszGroups. */ 1675 uint32_t cbGroups; 1685 /** Single entry read. */ 1686 CALLBACKDATA_DIR_ENTRY Entry; 1676 1687 } read; 1688 struct 1689 { 1690 /** Number of entries in \a paEntries. */ 1691 uint32_t cEntries; 1692 /** Array of entries read. */ 1693 CALLBACKDATA_DIR_ENTRY **paEntries; 1694 } list; 1677 1695 } u; 1678 1696 } CALLBACKDATA_DIR_NOTIFY; -
trunk/src/VBox/Main/include/GuestDirectoryImpl.h
r98709 r99085 72 72 EventSource *i_getEventSource(void) { return mEventSource; } 73 73 int i_onDirNotify(PVBOXGUESTCTRLHOSTCBCTX pCbCtx, PVBOXGUESTCTRLHOSTCALLBACK pSvcCbData); 74 int i_listInternal(uint32_t cMaxEntries, uint32_t fFlags, std::vector<GuestFsObjData> &vecObjData, int *pvrcGuest); 75 int i_listEx(uint32_t cMaxEntries, uint32_t fFlags, std::vector<ComObjPtr<GuestFsObjInfo>> &vecObjInfo, int *pvrcGuest); 76 int i_list(uint32_t cMaxEntries, std::vector<ComObjPtr<GuestFsObjInfo>> &vecObjInfo, int *pvrcGuest); 74 77 int i_read(ComObjPtr<GuestFsObjInfo> &fsObjInfo, int *pvrcGuest); 75 78 int i_readInternal(GuestFsObjData &objData, int *pvrcGuest); … … 89 92 * @{ */ 90 93 static Utf8Str i_guestErrorToString(int vrcGuest, const char *pcszWhat); 94 static void i_dirNotifyDataDestroy(PCALLBACKDATA_DIR_NOTIFY pDirNotify); 91 95 /** @} */ 92 96 … … 105 109 HRESULT getId(ULONG *aId); 106 110 HRESULT getStatus(DirectoryStatus_T *aStatus); 111 HRESULT list(ULONG aMaxEntries, std::vector<ComPtr<IFsObjInfo> > &aObjInfos); 107 112 HRESULT read(ComPtr<IFsObjInfo> &aObjInfo); 108 113 HRESULT rewind(void); -
trunk/src/VBox/Main/src-client/GuestDirectoryImpl.cpp
r99073 r99085 467 467 HGCMSvcGetU32(&pSvcCbData->mpaParms[idx++], &dataCb.rc); 468 468 469 int vrcGuest = (int)dataCb.rc; /* uint32_t vs. int. */469 int const vrcGuest = (int)dataCb.rc; /* uint32_t vs. int. */ 470 470 471 471 LogFlowThisFunc(("uType=%RU32, vrcGuest=%Rrc\n", dataCb.uType, vrcGuest)); … … 523 523 ("type=%u\n", pSvcCbData->mpaParms[idx].type), 524 524 vrc = VERR_WRONG_PARAMETER_TYPE); 525 PGSTCTLDIRENTRYEX p Entry;526 uint32_t cb Entry;527 vrc = HGCMSvcGetPv(&pSvcCbData->mpaParms[idx++], (void **)&p Entry, &cbEntry);525 PGSTCTLDIRENTRYEX pDirEntryEx; 526 uint32_t cbDirEntryEx; 527 vrc = HGCMSvcGetPv(&pSvcCbData->mpaParms[idx++], (void **)&pDirEntryEx, &cbDirEntryEx); 528 528 AssertRCBreak(vrc); 529 AssertBreakStmt( cb Entry>= RT_UOFFSETOF(GSTCTLDIRENTRYEX, szName[2])530 && cb Entry <= GSTCTL_DIRENTRY_MAX_SIZE,VERR_INVALID_PARAMETER);531 dataCb.u.read. pEntry = (PGSTCTLDIRENTRYEX)RTMemDup(pEntry, cbEntry);532 AssertPtrBreakStmt(dataCb.u.read. pEntry, vrc = VERR_NO_MEMORY);533 dataCb.u.read. cbEntry = cbEntry;529 AssertBreakStmt( cbDirEntryEx >= RT_UOFFSETOF(GSTCTLDIRENTRYEX, szName[2]) 530 && cbDirEntryEx <= GSTCTL_DIRENTRY_MAX_SIZE, vrc = VERR_INVALID_PARAMETER); 531 dataCb.u.read.Entry.pDirEntryEx = (PGSTCTLDIRENTRYEX)RTMemDup(pDirEntryEx, cbDirEntryEx); 532 AssertPtrBreakStmt(dataCb.u.read.Entry.pDirEntryEx, vrc = VERR_NO_MEMORY); 533 dataCb.u.read.Entry.cbDirEntryEx = cbDirEntryEx; 534 534 535 535 char *pszUser; … … 537 537 vrc = HGCMSvcGetStr(&pSvcCbData->mpaParms[idx++], &pszUser, &cbUser); 538 538 AssertRCBreak(vrc); 539 dataCb.u.read.pszUser = RTStrDup(pszUser); 540 AssertPtrBreakStmt(dataCb.u.read.pszUser, vrc = VERR_NO_MEMORY); 541 dataCb.u.read.cbUser = cbUser; 539 AssertBreakStmt(cbUser <= GSTCTL_DIRENTRY_MAX_USER_NAME, vrc = VERR_TOO_MUCH_DATA); 540 dataCb.u.read.Entry.pszUser = RTStrDup(pszUser); 541 AssertPtrBreakStmt(dataCb.u.read.Entry.pszUser, vrc = VERR_NO_MEMORY); 542 dataCb.u.read.Entry.cbUser = cbUser; 542 543 543 544 char *pszGroups; … … 545 546 vrc = HGCMSvcGetStr(&pSvcCbData->mpaParms[idx++], &pszGroups, &cbGroups); 546 547 AssertRCBreak(vrc); 547 dataCb.u.read.pszGroups = RTStrDup(pszGroups); 548 AssertPtrBreakStmt(dataCb.u.read.pszGroups, vrc = VERR_NO_MEMORY); 549 dataCb.u.read.cbGroups = cbGroups; 548 AssertBreakStmt(cbGroups <= GSTCTL_DIRENTRY_MAX_USER_GROUPS, vrc = VERR_TOO_MUCH_DATA); 549 dataCb.u.read.Entry.pszGroups = RTStrDup(pszGroups); 550 AssertPtrBreakStmt(dataCb.u.read.Entry.pszGroups, vrc = VERR_NO_MEMORY); 551 dataCb.u.read.Entry.cbGroups = cbGroups; 550 552 551 553 /** @todo ACLs not implemented yet. */ 552 554 553 GuestFsObjData fsObjData(dataCb.u.read. pEntry->szName);554 vrc = fsObjData.FromGuestFsObjInfo(&dataCb.u.read. pEntry->Info);555 GuestFsObjData fsObjData(dataCb.u.read.Entry.pDirEntryEx->szName); 556 vrc = fsObjData.FromGuestFsObjInfo(&dataCb.u.read.Entry.pDirEntryEx->Info); 555 557 AssertRCBreak(vrc); 556 558 ComObjPtr<GuestFsObjInfo> ptrFsObjInfo; … … 561 563 562 564 ::FireGuestDirectoryReadEvent(mEventSource, mSession, this, 563 dataCb.u.read.pEntry->szName, ptrFsObjInfo, dataCb.u.read.pszUser, dataCb.u.read.pszGroups); 565 dataCb.u.read.Entry.pDirEntryEx->szName, ptrFsObjInfo, 566 dataCb.u.read.Entry.pszUser, dataCb.u.read.Entry.pszGroups); 564 567 break; 565 568 } … … 569 572 /* Note: This does not change the overall status of the directory (i.e. open). */ 570 573 ::FireGuestDirectoryStateChangedEvent(mEventSource, mSession, this, DirectoryStatus_Rewind, errorInfo); 574 break; 575 } 576 577 case GUEST_DIR_NOTIFYTYPE_LIST: 578 { 579 ASSERT_GUEST_MSG_STMT_BREAK(pSvcCbData->mParms >= 4, ("mParms=%u\n", pSvcCbData->mParms), 580 vrc = VERR_WRONG_PARAMETER_COUNT); 581 ASSERT_GUEST_MSG_STMT_BREAK(pSvcCbData->mpaParms[idx].type == VBOX_HGCM_SVC_PARM_32BIT, 582 ("type=%u\n", pSvcCbData->mpaParms[idx].type), 583 vrc = VERR_WRONG_PARAMETER_TYPE); 584 585 vrc = HGCMSvcGetU32(&pSvcCbData->mpaParms[idx++], &dataCb.u.list.cEntries); 586 AssertRCBreak(vrc); 587 /* We limit this for now to 64K entries max per call. 588 * The guest does not do this check, so we could de/increase this limit in the future. */ 589 AssertBreakStmt(dataCb.u.list.cEntries <= _64K, vrc = VERR_TOO_MUCH_DATA); 590 591 if (!dataCb.u.list.cEntries) /* No entries sent? Bail out early. */ 592 break; 593 594 /* 595 * Fetch buffer with packed directory entries. 596 */ 597 ASSERT_GUEST_MSG_STMT_BREAK(pSvcCbData->mParms == 5, ("mParms=%u\n", pSvcCbData->mParms), 598 vrc = VERR_WRONG_PARAMETER_COUNT); 599 ASSERT_GUEST_MSG_STMT_BREAK(pSvcCbData->mpaParms[idx].type == VBOX_HGCM_SVC_PARM_PTR, 600 ("type=%u\n", pSvcCbData->mpaParms[idx].type), 601 vrc = VERR_WRONG_PARAMETER_TYPE); 602 void *pvBuf; 603 uint32_t cbBuf; 604 vrc = HGCMSvcGetPv(&pSvcCbData->mpaParms[idx], &pvBuf, &cbBuf); 605 AssertRCBreak(vrc); 606 AssertBreakStmt(cbBuf >= sizeof(GSTCTLDIRENTRYEX), vrc = VERR_INVALID_PARAMETER); 607 dataCb.u.list.paEntries = (PCALLBACKDATA_DIR_ENTRY *)RTMemAllocZ(dataCb.u.list.cEntries * sizeof(PCALLBACKDATA_DIR_ENTRY)); 608 AssertPtrBreakStmt(dataCb.u.list.paEntries, vrc = VERR_NO_MEMORY); 609 610 /* 611 * Unpack directory entries. 612 */ 613 size_t offBuf = 0; 614 for (uint32_t i = 0; i < dataCb.u.list.cEntries; i++) 615 { 616 dataCb.u.list.paEntries[i] = (PCALLBACKDATA_DIR_ENTRY)RTMemAlloc(sizeof(CALLBACKDATA_DIR_ENTRY)); 617 AssertPtrBreakStmt(dataCb.u.list.paEntries[i], vrc = VERR_NO_MEMORY); 618 619 PCALLBACKDATA_DIR_ENTRY pEntry = dataCb.u.list.paEntries[i]; 620 621 PGSTCTLDIRENTRYLISTHDR const pHdr = (PGSTCTLDIRENTRYLISTHDR)((uint8_t *)pvBuf + offBuf); 622 AssertBreakStmt(pHdr->cbDirEntryEx <= GSTCTL_DIRENTRY_MAX_SIZE, vrc = VERR_TOO_MUCH_DATA); 623 AssertBreakStmt(pHdr->cbUser <= GSTCTL_DIRENTRY_MAX_USER_NAME, vrc = VERR_TOO_MUCH_DATA); 624 AssertBreakStmt(pHdr->cbGroups <= GSTCTL_DIRENTRY_MAX_USER_GROUPS, vrc = VERR_TOO_MUCH_DATA); 625 offBuf += sizeof(GSTCTLDIRENTRYLISTHDR); 626 627 AssertBreakStmt( pHdr->cbDirEntryEx >= RT_UOFFSETOF(GSTCTLDIRENTRYEX, szName[2]) 628 && pHdr->cbDirEntryEx <= GSTCTL_DIRENTRY_MAX_SIZE, vrc = VERR_INVALID_PARAMETER); 629 pEntry->pDirEntryEx = (PGSTCTLDIRENTRYEX)RTMemDup((uint8_t *)pvBuf + offBuf, pHdr->cbDirEntryEx); 630 AssertPtrBreakStmt(pEntry->pDirEntryEx, vrc = VERR_NO_MEMORY); 631 pEntry->cbDirEntryEx = pHdr->cbDirEntryEx; 632 offBuf += pHdr->cbDirEntryEx; 633 634 if (pHdr->cbUser) 635 { 636 pEntry->pszUser = (char *)RTMemDup((uint8_t *)pvBuf + offBuf, pHdr->cbUser); 637 AssertPtrBreakStmt(pEntry->pszUser, vrc = VERR_NO_MEMORY); 638 pEntry->cbUser = pHdr->cbUser; 639 offBuf += pHdr->cbUser; 640 } 641 642 if (pHdr->cbGroups) 643 { 644 pEntry->pszGroups = (char *)RTMemDup((uint8_t *)pvBuf + offBuf, pHdr->cbGroups); 645 AssertPtrBreakStmt(pEntry->pszGroups, vrc = VERR_NO_MEMORY); 646 pEntry->cbGroups = pHdr->cbGroups; 647 offBuf += pHdr->cbGroups; 648 } 649 650 #ifdef DEBUG 651 GuestFsObjData obj; 652 AssertRC(obj.FromGuestFsObjInfo(&pEntry->pDirEntryEx->Info, pEntry->pszUser, pEntry->pszGroups)); 653 AssertRC(RTStrValidateEncodingEx(pEntry->pszUser, pHdr->cbUser, RTSTR_VALIDATE_ENCODING_ZERO_TERMINATED)); 654 AssertRC(RTStrValidateEncodingEx(pEntry->pszGroups, pHdr->cbGroups, RTSTR_VALIDATE_ENCODING_ZERO_TERMINATED)); 655 #endif 656 } 657 658 if (RT_SUCCESS(vrc)) 659 { 660 Assert(offBuf == cbBuf); 661 } 662 else /* Roll back on error. */ 663 { 664 GuestDirectory::i_dirNotifyDataDestroy(&dataCb); 665 } 571 666 break; 572 667 } … … 606 701 607 702 /** 608 * Convertsa given guest directory error to a string.703 * Static helper function to convert a given guest directory error to a string. 609 704 * 610 705 * @returns Error string. … … 627 722 CASE_MSG(VERR_CANT_CREATE, tr("Guest directory \"%s\" cannot be created"), pcszWhat); 628 723 CASE_MSG(VERR_DIR_NOT_EMPTY, tr("Guest directory \"%s\" is not empty"), pcszWhat); 724 CASE_MSG(VERR_NO_MORE_FILES, tr("Guest directory \"%s\" has no more entries"), pcszWhat); 725 CASE_MSG(VERR_PATH_NOT_FOUND, tr("Path of guest directory \"%s\" not found"), pcszWhat); 629 726 default: 630 727 strErr.printf(tr("Error %Rrc for guest directory \"%s\" occurred\n"), vrcGuest, pcszWhat); … … 635 732 636 733 return strErr; 734 } 735 736 /** 737 * Static helper function to destroy direction notification callback data. 738 * 739 * @param pDirNotify Pointer to direction notification callback data to destroy. 740 */ 741 /* static */ 742 void GuestDirectory::i_dirNotifyDataDestroy(PCALLBACKDATA_DIR_NOTIFY pDirNotify) 743 { 744 if (!pDirNotify) 745 return; 746 747 switch (pDirNotify->uType) 748 { 749 case GUEST_DIR_NOTIFYTYPE_LIST: 750 { 751 for (uint32_t i = 0; i < pDirNotify->u.list.cEntries; i++) 752 { 753 PCALLBACKDATA_DIR_ENTRY const pEntry = pDirNotify->u.list.paEntries[i]; 754 AssertPtrBreak(pEntry); 755 RTStrFree(pEntry->pszUser); 756 RTStrFree(pEntry->pszGroups); 757 RTMemFree(pEntry->pDirEntryEx); 758 RTMemFree(pEntry); 759 } 760 RTMemFree(pDirNotify->u.list.paEntries); 761 pDirNotify->u.list.paEntries = NULL; 762 pDirNotify->u.list.cEntries = 0; 763 break; 764 } 765 766 default: 767 break; 768 } 637 769 } 638 770 … … 745 877 * Reads the next directory entry, internal version. 746 878 * 747 * @return VBox status code. Will return VERR_NO_MORE_FILES if no more entries are available. 879 * @return VBox status code. 880 * @retval VERR_GSTCTL_GUEST_ERROR / VERR_NO_MORE_FILES if no more entries are available. 748 881 * @param objData Where to store the read directory entry as internal object data. 749 882 * @param pvrcGuest Where to store the guest result code in case VERR_GSTCTL_GUEST_ERROR is returned. … … 790 923 { 791 924 AssertReturn(pDirNotify->uType == GUEST_DIR_NOTIFYTYPE_READ, VERR_INVALID_PARAMETER); 792 AssertPtrReturn(pDirNotify->u.read. pEntry, VERR_INVALID_POINTER);793 objData.Init(pDirNotify->u.read. pEntry->szName);794 vrc = objData.FromGuestFsObjInfo(&pDirNotify->u.read. pEntry->Info,795 pDirNotify->u.read. pszUser, pDirNotify->u.read.pszGroups);796 RTMemFree(pDirNotify->u.read. pEntry);797 RTStrFree(pDirNotify->u.read. pszUser);798 RTStrFree(pDirNotify->u.read. pszGroups);925 AssertPtrReturn(pDirNotify->u.read.Entry.pDirEntryEx, VERR_INVALID_POINTER); 926 objData.Init(pDirNotify->u.read.Entry.pDirEntryEx->szName); 927 vrc = objData.FromGuestFsObjInfo(&pDirNotify->u.read.Entry.pDirEntryEx->Info, 928 pDirNotify->u.read.Entry.pszUser, pDirNotify->u.read.Entry.pszGroups); 929 RTMemFree(pDirNotify->u.read.Entry.pDirEntryEx); 930 RTStrFree(pDirNotify->u.read.Entry.pszUser); 931 RTStrFree(pDirNotify->u.read.Entry.pszGroups); 799 932 } 800 933 else 801 934 { 802 if (pvrcGuest) 803 *pvrcGuest = vrcGuest; 935 *pvrcGuest = vrcGuest; 804 936 vrc = VERR_GSTCTL_GUEST_ERROR; 805 937 } … … 851 983 } 852 984 else 985 { 986 #ifdef DEBUG 987 curBlock.DumpToLog(); 988 #endif 853 989 vrc = VERR_PATH_NOT_FOUND; 990 } 854 991 } 855 992 else … … 866 1003 867 1004 /** 1005 * Worker for listing the next directory entries. 1006 * 1007 * @return VBox status code. 1008 * @retval VERR_GSTCTL_GUEST_ERROR / VERR_NO_MORE_FILES if no more entries are available after this iteration. 1009 * \a vecObjData will contain the rest of the entries then (if any). 1010 * @param cMaxEntries How many directory entries to read at max. 1011 * @param fFlags Flags of type GSTCTL_DIRLIST_F_XXX. 1012 * @param vecObjData Where to store the read directory entries on success. 1013 * @param pvrcGuest Where to store the guest result code in case VERR_GSTCTL_GUEST_ERROR is returned. 1014 */ 1015 int GuestDirectory::i_listInternal(uint32_t cMaxEntries, uint32_t fFlags, std::vector<GuestFsObjData> &vecObjData, int *pvrcGuest) 1016 { 1017 int vrc; 1018 1019 #ifdef VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS 1020 if (mSession->i_getParent()->i_getGuestControlFeatures0() & VBOX_GUESTCTRL_GF_0_TOOLBOX_AS_CMDS) 1021 { 1022 GuestWaitEvent *pEvent = NULL; 1023 GuestEventTypes eventTypes; 1024 try 1025 { 1026 vrc = registerWaitEvent(eventTypes, &pEvent); 1027 } 1028 catch (std::bad_alloc &) 1029 { 1030 vrc = VERR_NO_MEMORY; 1031 } 1032 1033 if (RT_FAILURE(vrc)) 1034 return vrc; 1035 1036 /* Prepare HGCM call. */ 1037 VBOXHGCMSVCPARM paParms[4]; 1038 int i = 0; 1039 HGCMSvcSetU32(&paParms[i++], pEvent->ContextID()); 1040 HGCMSvcSetU32(&paParms[i++], mObjectID /* Directory handle */); 1041 HGCMSvcSetU32(&paParms[i++], cMaxEntries); 1042 HGCMSvcSetU32(&paParms[i++], 0 /* Flags */); 1043 1044 vrc = sendMessage(HOST_MSG_DIR_LIST, i, paParms); 1045 if (RT_SUCCESS(vrc)) 1046 { 1047 vrc = pEvent->Wait(30 * 1000); 1048 if (RT_SUCCESS(vrc)) 1049 { 1050 PCALLBACKDATA_DIR_NOTIFY const pDirNotify = (PCALLBACKDATA_DIR_NOTIFY)pEvent->Payload().Raw(); 1051 AssertPtrReturn(pDirNotify, VERR_INVALID_POINTER); 1052 int vrcGuest = (int)pDirNotify->rc; 1053 if ( RT_SUCCESS(vrcGuest) 1054 /* Guest indicates that there are no more entries to read. 1055 * We still need to check if we have read something with this iteration though. */ 1056 || vrcGuest == VERR_NO_MORE_FILES) 1057 { 1058 AssertReturn(pDirNotify->uType == GUEST_DIR_NOTIFYTYPE_LIST, VERR_INVALID_PARAMETER); 1059 1060 try 1061 { 1062 vecObjData.resize(pDirNotify->u.list.cEntries); 1063 } 1064 catch (std::bad_alloc &) 1065 { 1066 vrc = VERR_NO_MEMORY; 1067 } 1068 1069 if (RT_SUCCESS(vrc)) 1070 { 1071 for (size_t a = 0; a < pDirNotify->u.list.cEntries; a++) 1072 { 1073 PCALLBACKDATA_DIR_ENTRY const pEntry = pDirNotify->u.list.paEntries[a]; 1074 AssertPtr(pEntry); 1075 1076 AssertPtr(pEntry->pDirEntryEx); 1077 vecObjData[a].Init(pEntry->pDirEntryEx->szName); 1078 int vrc2 = vecObjData[a].FromGuestFsObjInfo(&pEntry->pDirEntryEx->Info, pEntry->pszUser, pEntry->pszGroups); 1079 if (RT_SUCCESS(vrc)) 1080 vrc = vrc2; 1081 } 1082 } 1083 } 1084 else 1085 { 1086 *pvrcGuest = vrcGuest; 1087 vrc = VERR_GSTCTL_GUEST_ERROR; 1088 } 1089 1090 GuestDirectory::i_dirNotifyDataDestroy(pDirNotify); 1091 } 1092 else if (pEvent->HasGuestError()) 1093 *pvrcGuest = pEvent->GuestResult(); 1094 } 1095 } 1096 else 1097 #endif /* VBOX_WITH_GSTCTL_TOOLBOX_AS_CMDS */ 1098 { 1099 RT_NOREF(cMaxEntries, fFlags, vecObjData, pvrcGuest); 1100 vrc = VERR_NOT_SUPPORTED; 1101 } 1102 1103 return vrc; 1104 } 1105 1106 /** 1107 * Lists the next directory entries. 1108 * 1109 * @return VBox status code. 1110 * @retval VERR_GSTCTL_GUEST_ERROR / VERR_NO_MORE_FILES if no more entries are available after this iteration. 1111 * \a vecObjData will contain the rest of the entries then (if any). 1112 * @param cMaxEntries How many directory entries to read at max. 1113 * @param fFlags Flags of type GSTCTL_DIRLIST_F_XXX. 1114 * @param vecObjInfo Where to store the read directory entries on success. 1115 * @param pvrcGuest Where to store the guest result code in case VERR_GSTCTL_GUEST_ERROR is returned. 1116 */ 1117 int GuestDirectory::i_listEx(uint32_t cMaxEntries, uint32_t fFlags, std::vector<ComObjPtr<GuestFsObjInfo>> &vecObjInfo, 1118 int *pvrcGuest) 1119 { 1120 AssertPtrReturn(pvrcGuest, VERR_INVALID_POINTER); 1121 AssertReturn(!(fFlags & ~GSTCTL_DIRLIST_F_VALID_MASK), VERR_INVALID_PARAMETER); 1122 1123 std::vector<GuestFsObjData> vecObjDataInt; 1124 int vrc = i_listInternal(cMaxEntries, fFlags, vecObjDataInt, pvrcGuest); 1125 if ( RT_SUCCESS(vrc) 1126 || ( vrc == VERR_GSTCTL_GUEST_ERROR 1127 && *pvrcGuest == VERR_NO_MORE_FILES)) 1128 { 1129 try 1130 { 1131 vecObjInfo.resize(vecObjDataInt.size()); 1132 for (size_t i = 0; i < vecObjDataInt.size(); i++) 1133 { 1134 HRESULT hrc = vecObjInfo[i].createObject(); 1135 ComAssertComRCBreak(hrc, vrc = VERR_COM_UNEXPECTED); 1136 1137 vrc = vecObjInfo[i]->init(vecObjDataInt[i]); 1138 if (RT_FAILURE(vrc)) 1139 break; 1140 } 1141 } 1142 catch (std::bad_alloc &) 1143 { 1144 vrc = VERR_NO_MEMORY; 1145 } 1146 } 1147 1148 return vrc; 1149 } 1150 1151 /** 1152 * Lists the next directory entries. 1153 * 1154 * @return VBox status code. 1155 * @retval VERR_GSTCTL_GUEST_ERROR / VERR_NO_MORE_FILES if no more entries are available after this iteration. 1156 * \a vecObjData will contain the rest of the entries then (if any). 1157 * @param cMaxEntries How many directory entries to read at max. 1158 * @param vecObjInfo Where to store the read directory entries on success. 1159 * @param pvrcGuest Where to store the guest result code in case VERR_GSTCTL_GUEST_ERROR is returned. 1160 */ 1161 int GuestDirectory::i_list(uint32_t cMaxEntries, std::vector<ComObjPtr<GuestFsObjInfo>> &vecObjInfo, int *pvrcGuest) 1162 { 1163 return i_listEx(cMaxEntries, GSTCTL_DIRLIST_F_NONE, vecObjInfo, pvrcGuest); 1164 } 1165 1166 /** 868 1167 * Reads the next directory entry. 869 1168 * 870 * @return VBox status code. Will return VERR_NO_MORE_FILES if no more entries are available. 1169 * @return VBox status code. 1170 * @retval VERR_GSTCTL_GUEST_ERROR / VERR_NO_MORE_FILES if no more entries are available. 871 1171 * @param fsObjInfo Where to store the read directory entry. 872 1172 * @param pvrcGuest Where to store the guest result code in case VERR_GSTCTL_GUEST_ERROR is returned. … … 894 1194 else /* Otherwise ask the guest for the next object data. */ 895 1195 { 896 897 1196 GuestFsObjData objData; 898 1197 vrc = i_readInternal(objData, pvrcGuest); … … 1124 1423 } 1125 1424 1425 HRESULT GuestDirectory::list(ULONG aMaxEntries, std::vector<ComPtr<IFsObjInfo> > &aObjInfos) 1426 { 1427 AutoCaller autoCaller(this); 1428 if (FAILED(autoCaller.hrc())) return autoCaller.hrc(); 1429 1430 LogFlowThisFuncEnter(); 1431 1432 HRESULT hrc = S_OK; 1433 1434 std::vector<ComObjPtr<GuestFsObjInfo> > vecObjInfo; 1435 int vrcGuest = VERR_IPE_UNINITIALIZED_STATUS; 1436 int vrc = i_list(aMaxEntries, vecObjInfo, &vrcGuest); 1437 1438 /* Don't propagate an error to API callers when this is the last listing (i.e. no more files). 1439 * For subsequent reads the API caller gets an appropriate error then. */ 1440 if ( vrc == VERR_GSTCTL_GUEST_ERROR 1441 && vrcGuest == VERR_NO_MORE_FILES 1442 && vecObjInfo.size()) 1443 vrc = VINF_SUCCESS; 1444 1445 if (RT_SUCCESS(vrc)) 1446 { 1447 try 1448 { 1449 aObjInfos.resize(vecObjInfo.size()); 1450 1451 for (size_t i = 0; i < vecObjInfo.size(); i++) 1452 { 1453 hrc = vecObjInfo[i].queryInterfaceTo(aObjInfos[i].asOutParam()); 1454 ComAssertComRCBreakRC(hrc); 1455 } 1456 } 1457 catch (std::bad_alloc &) 1458 { 1459 hrc = E_OUTOFMEMORY; 1460 } 1461 } 1462 else 1463 { 1464 switch (vrc) 1465 { 1466 case VERR_GSTCTL_GUEST_ERROR: 1467 { 1468 GuestErrorInfo ge(GuestErrorInfo::Type_Directory, vrcGuest, mData.mOpenInfo.mPath.c_str()); 1469 hrc = setErrorBoth(VBOX_E_IPRT_ERROR, vrcGuest, tr("Listing guest directory failed: %s"), 1470 GuestBase::getErrorAsString(ge).c_str()); 1471 1472 /* Return a dedicated error code when directory reading is done. See SDK reference. */ 1473 if (vrcGuest == VERR_NO_MORE_FILES) 1474 hrc = VBOX_E_OBJECT_NOT_FOUND; 1475 break; 1476 } 1477 1478 default: 1479 hrc = setErrorBoth(VBOX_E_IPRT_ERROR, vrc, tr("Listing guest directory \"%s\" returned unhandled error: %Rrc\n"), 1480 mData.mOpenInfo.mPath.c_str(), vrc); 1481 break; 1482 } 1483 } 1484 1485 LogFlowThisFunc(("Returning hrc=%Rhrc / vrc=%Rrc\n", hrc, vrc)); 1486 return hrc; 1487 } 1488 1126 1489 HRESULT GuestDirectory::read(ComPtr<IFsObjInfo> &aObjInfo) 1127 1490 { … … 1151 1514 GuestErrorInfo::Type_ToolLs 1152 1515 #else 1153 GuestErrorInfo::Type_ Fs1516 GuestErrorInfo::Type_Directory 1154 1517 #endif 1155 1518 , vrcGuest, mData.mOpenInfo.mPath.c_str()); 1156 1519 hrc = setErrorBoth(VBOX_E_IPRT_ERROR, vrcGuest, tr("Reading guest directory failed: %s"), 1157 1520 GuestBase::getErrorAsString(ge).c_str()); 1521 1522 /* Return a dedicated error code when directory reading is done. See SDK reference. */ 1523 if (vrcGuest == VERR_NO_MORE_FILES) 1524 hrc = VBOX_E_OBJECT_NOT_FOUND; 1158 1525 break; 1159 1526 } … … 1164 1531 mData.mOpenInfo.mPath.c_str(), mData.mProcessTool.getRc()); 1165 1532 break; 1166 #endif 1533 1167 1534 case VERR_PATH_NOT_FOUND: 1168 1535 hrc = setErrorBoth(VBOX_E_IPRT_ERROR, vrc, tr("Reading guest directory \"%s\" failed: Path not found"), … … 1175 1542 mData.mOpenInfo.mPath.c_str()); 1176 1543 break; 1177 1544 #endif 1178 1545 default: 1179 1546 hrc = setErrorBoth(VBOX_E_IPRT_ERROR, vrc, tr("Reading guest directory \"%s\" returned unhandled error: %Rrc\n"), -
trunk/src/VBox/ValidationKit/tests/additions/tdAddGuestCtrl.py
r98655 r99085 2024 2024 return True; 2025 2025 2026 def gctrlReadDirTree(self, oTest, oGuestSession, fIsError, sSubDir = None):2026 def gctrlReadDirTree(self, oTest, oGuestSession, fIsError, fUseDirList = False, cEntriesPerRead = 0, sSubDir = None): 2027 2027 """ 2028 2028 Helper function to recursively read a guest directory tree specified in the current test. … … 2039 2039 cOthers = 0; # Other files. 2040 2040 2041 cEntriesToRead = cEntriesPerRead; # Only used when listing directories. 2042 aFsObjInfo = []; 2043 2041 2044 # Open the directory: 2042 reporter.log2('Directory="%s", filter="%s", afFlags="%s"' % (limitString(sCurDir), sFilter, afFlags)); 2045 reporter.log2('Directory="%s", filter="%s", afFlags="%s", fUseDirList=%s, cEntriesPerRead=%d' 2046 % (limitString(sCurDir), sFilter, afFlags, fUseDirList, cEntriesPerRead)); 2043 2047 try: 2044 2048 oCurDir = oGuestSession.directoryOpen(sCurDir, sFilter, afFlags); … … 2048 2052 2049 2053 # Read the directory. 2054 fDone = False; 2050 2055 while fRc is True: 2056 reporter.log3('Reading next batch ...'); 2057 aFsObjInfo = []; 2051 2058 try: 2052 oFsObjInfo = oCurDir.read(); 2059 if not fUseDirList: 2060 aFsObjInfo.append(oCurDir.read()); 2061 else: 2062 if not cEntriesToRead: 2063 cEntriesToRead = random.randrange(1, 32768); 2064 aFsObjInfo = oCurDir.list(cEntriesToRead); 2053 2065 except Exception as oXcpt: 2054 2066 if vbox.ComError.notEqual(oXcpt, vbox.ComError.VBOX_E_OBJECT_NOT_FOUND): 2055 if self.oTstDrv.fpApiVer > 5.2:2056 reporter.errorXcpt('Error reading directory "%s":' % (sCurDir,));2067 if fUseDirList: 2068 fRc = reporter.errorXcpt('Error listing directory "%s" (cEntriesToRead=%d):' % (sCurDir, cEntriesToRead)); 2057 2069 else: 2058 # Unlike fileOpen, directoryOpen will not fail if the directory does not exist. 2059 reporter.maybeErrXcpt(fIsError, 'Error reading directory "%s":' % (sCurDir,)); 2070 if self.oTstDrv.fpApiVer > 5.2: 2071 reporter.errorXcpt('Error reading directory "%s":' % (sCurDir,)); 2072 else: 2073 # Unlike fileOpen, directoryOpen will not fail if the directory does not exist. 2074 reporter.maybeErrXcpt(fIsError, 'Error reading directory "%s":' % (sCurDir,)); 2060 2075 fRc = False; 2061 2076 else: 2062 2077 reporter.log2('\tNo more directory entries for "%s"' % (limitString(sCurDir),)); 2078 fDone = True; 2063 2079 break; 2064 2080 2065 try: 2066 sName = oFsObjInfo.name; 2067 eType = oFsObjInfo.type; 2068 except: 2069 fRc = reporter.errorXcpt(); 2081 if fDone or not fRc: # Abort reading? 2070 2082 break; 2071 2083 2072 if sName in ('.', '..', ): 2073 if eType != vboxcon.FsObjType_Directory: 2074 fRc = reporter.error('Wrong type for "%s": %d, expected %d (Directory)' 2075 % (sName, eType, vboxcon.FsObjType_Directory)); 2076 elif eType == vboxcon.FsObjType_Directory: 2077 reporter.log2(' Directory "%s"' % limitString(oFsObjInfo.name)); 2078 aSubResult = self.gctrlReadDirTree(oTest, oGuestSession, fIsError, 2079 oTestVm.pathJoin(sSubDir, sName) if sSubDir else sName); 2080 fRc = aSubResult[0]; 2081 cDirs += aSubResult[1] + 1; 2082 cFiles += aSubResult[2]; 2083 cOthers += aSubResult[3]; 2084 elif eType is vboxcon.FsObjType_File: 2085 reporter.log4(' File "%s"' % oFsObjInfo.name); 2086 cFiles += 1; 2087 elif eType is vboxcon.FsObjType_Symlink: 2088 reporter.log4(' Symlink "%s" -- not tested yet' % oFsObjInfo.name); 2089 cOthers += 1; 2090 elif oTestVm.isWindows() \ 2091 or oTestVm.isOS2() \ 2092 or eType not in (vboxcon.FsObjType_Fifo, vboxcon.FsObjType_DevChar, vboxcon.FsObjType_DevBlock, 2093 vboxcon.FsObjType_Socket, vboxcon.FsObjType_WhiteOut): 2094 fRc = reporter.error('Directory "%s" contains invalid directory entry "%s" (type %d)' % 2095 (sCurDir, oFsObjInfo.name, oFsObjInfo.type,)); 2096 else: 2097 cOthers += 1; 2084 reporter.log3('Processing next batch (%d items)...' % (len(aFsObjInfo))); 2085 for oFsObjInfo in aFsObjInfo: 2086 try: 2087 sName = oFsObjInfo.name; 2088 eType = oFsObjInfo.type; 2089 except: 2090 fRc = reporter.errorXcpt(); 2091 break; 2092 2093 if sName in ('.', '..', ): 2094 if eType != vboxcon.FsObjType_Directory: 2095 fRc = reporter.error('Wrong type for "%s": %d, expected %d (Directory)' 2096 % (sName, eType, vboxcon.FsObjType_Directory)); 2097 elif eType == vboxcon.FsObjType_Directory: 2098 reporter.log2(' Directory "%s"' % limitString(oFsObjInfo.name)); 2099 aSubResult = self.gctrlReadDirTree(oTest, oGuestSession, fIsError, 2100 fUseDirList, cEntriesPerRead, 2101 oTestVm.pathJoin(sSubDir, sName) if sSubDir else sName); 2102 fRc = aSubResult[0]; 2103 cDirs += aSubResult[1] + 1; 2104 cFiles += aSubResult[2]; 2105 cOthers += aSubResult[3]; 2106 elif eType is vboxcon.FsObjType_File: 2107 reporter.log4(' File "%s"' % oFsObjInfo.name); 2108 cFiles += 1; 2109 elif eType is vboxcon.FsObjType_Symlink: 2110 reporter.log4(' Symlink "%s" -- not tested yet' % oFsObjInfo.name); 2111 cOthers += 1; 2112 elif oTestVm.isWindows() \ 2113 or oTestVm.isOS2() \ 2114 or eType not in (vboxcon.FsObjType_Fifo, vboxcon.FsObjType_DevChar, vboxcon.FsObjType_DevBlock, 2115 vboxcon.FsObjType_Socket, vboxcon.FsObjType_WhiteOut): 2116 fRc = reporter.error('Directory "%s" contains invalid directory entry "%s" (type %d)' % 2117 (sCurDir, oFsObjInfo.name, oFsObjInfo.type,)); 2118 else: 2119 cOthers += 1; 2098 2120 2099 2121 # Close the directory … … 2105 2127 return (fRc, cDirs, cFiles, cOthers); 2106 2128 2107 def gctrlReadDirTree2(self, oGuestSession, oDir ): # type: (testfileset.TestDir) -> bool2129 def gctrlReadDirTree2(self, oGuestSession, oDir, fUseDirList = False, cEntriesPerRead = 0): # type: (testfileset.TestDir) -> bool 2108 2130 """ 2109 2131 Helper function to recursively read a guest directory tree specified in the current test. … … 2121 2143 2122 2144 # Read the directory. 2123 dLeftUpper = dict(oDir.dChildrenUpper); 2124 cDot = 0; 2125 cDotDot = 0; 2126 fRc = True; 2145 dLeftUpper = dict(oDir.dChildrenUpper); 2146 cDot = 0; 2147 cDotDot = 0; 2148 fRc = True; 2149 cEntriesToRead = cEntriesPerRead; # Only used when listing directories. 2150 aFsObjInfo = []; 2127 2151 while True: 2152 reporter.log3('Reading next batch ...'); 2153 aFsObjInfo = []; 2128 2154 try: 2129 oFsObjInfo = oCurDir.read(); 2155 if not fUseDirList: 2156 aFsObjInfo.append(oCurDir.read()); 2157 else: 2158 if not cEntriesToRead: 2159 cEntriesToRead = random.randrange(1, 32768); 2160 aFsObjInfo = oCurDir.list(cEntriesToRead); 2130 2161 except Exception as oXcpt: 2131 2162 if vbox.ComError.notEqual(oXcpt, vbox.ComError.VBOX_E_OBJECT_NOT_FOUND): 2132 fRc = reporter.errorXcpt('Error reading directory "%s":' % (oDir.sPath,)); 2163 if fUseDirList: 2164 fRc = reporter.errorXcpt('Error listing directory "%s" (cEntriesToRead=%d):' % (oDir.sPath, cEntriesToRead)); 2165 else: 2166 fRc = reporter.errorXcpt('Error reading directory "%s":' % (oDir.sPath)); 2167 else: 2168 reporter.log2('\tNo more directory entries for "%s"' % (limitString(oDir.sPath),)); 2133 2169 break; 2134 2170 2135 try: 2136 sName = oFsObjInfo.name; 2137 eType = oFsObjInfo.type; 2138 cbFile = oFsObjInfo.objectSize; 2139 ## @todo check further attributes. 2140 except: 2141 fRc = reporter.errorXcpt(); 2142 break; 2143 2144 # '.' and '..' entries are not present in oDir.aoChildren, so special treatment: 2145 if sName in ('.', '..', ): 2146 if eType != vboxcon.FsObjType_Directory: 2147 fRc = reporter.error('Wrong type for "%s": %d, expected %d (Directory)' 2148 % (sName, eType, vboxcon.FsObjType_Directory)); 2149 if sName == '.': cDot += 1; 2150 else: cDotDot += 1; 2151 else: 2152 # Find the child and remove it from the dictionary. 2153 sNameUpper = sName.upper(); 2154 oFsObj = dLeftUpper.get(sNameUpper); 2155 if oFsObj is None: 2156 fRc = reporter.error('Unknown object "%s" found in "%s" (type %s, size %s)!' 2157 % (sName, oDir.sPath, eType, cbFile,)); 2171 reporter.log3('Processing next batch (%d items)...' % (len(aFsObjInfo))); 2172 for oFsObjInfo in aFsObjInfo: 2173 try: 2174 sName = oFsObjInfo.name; 2175 eType = oFsObjInfo.type; 2176 cbFile = oFsObjInfo.objectSize; 2177 ## @todo check further attributes. 2178 except: 2179 fRc = reporter.errorXcpt(); 2180 break; 2181 2182 # '.' and '..' entries are not present in oDir.aoChildren, so special treatment: 2183 if sName in ('.', '..', ): 2184 if eType != vboxcon.FsObjType_Directory: 2185 fRc = reporter.error('Wrong type for "%s": %d, expected %d (Directory)' 2186 % (sName, eType, vboxcon.FsObjType_Directory)); 2187 if sName == '.': cDot += 1; 2188 else: cDotDot += 1; 2158 2189 else: 2159 del dLeftUpper[sNameUpper]; 2160 2161 # Check type 2162 if isinstance(oFsObj, testfileset.TestDir): 2163 if eType != vboxcon.FsObjType_Directory: 2164 fRc = reporter.error('%s: expected directory (%d), got eType=%d!' 2165 % (oFsObj.sPath, vboxcon.FsObjType_Directory, eType,)); 2166 elif isinstance(oFsObj, testfileset.TestFile): 2167 if eType != vboxcon.FsObjType_File: 2168 fRc = reporter.error('%s: expected file (%d), got eType=%d!' 2169 % (oFsObj.sPath, vboxcon.FsObjType_File, eType,)); 2190 # Find the child and remove it from the dictionary. 2191 sNameUpper = sName.upper(); 2192 oFsObj = dLeftUpper.get(sNameUpper); 2193 if oFsObj is None: 2194 fRc = reporter.error('Unknown object "%s" found in "%s" (type %s, size %s)!' 2195 % (sName, oDir.sPath, eType, cbFile,)); 2170 2196 else: 2171 fRc = reporter.error('%s: WTF? type=%s' % (oFsObj.sPath, type(oFsObj),)); 2172 2173 # Check the name. 2174 if oFsObj.sName != sName: 2175 fRc = reporter.error('%s: expected name "%s", got "%s" instead!' % (oFsObj.sPath, oFsObj.sName, sName,)); 2176 2177 # Check the size if a file. 2178 if isinstance(oFsObj, testfileset.TestFile) and cbFile != oFsObj.cbContent: 2179 fRc = reporter.error('%s: expected size %s, got %s instead!' % (oFsObj.sPath, oFsObj.cbContent, cbFile,)); 2180 2181 ## @todo check timestamps and attributes. 2197 del dLeftUpper[sNameUpper]; 2198 2199 # Check type 2200 if isinstance(oFsObj, testfileset.TestDir): 2201 if eType != vboxcon.FsObjType_Directory: 2202 fRc = reporter.error('%s: expected directory (%d), got eType=%d!' 2203 % (oFsObj.sPath, vboxcon.FsObjType_Directory, eType,)); 2204 elif isinstance(oFsObj, testfileset.TestFile): 2205 if eType != vboxcon.FsObjType_File: 2206 fRc = reporter.error('%s: expected file (%d), got eType=%d!' 2207 % (oFsObj.sPath, vboxcon.FsObjType_File, eType,)); 2208 else: 2209 fRc = reporter.error('%s: WTF? type=%s' % (oFsObj.sPath, type(oFsObj),)); 2210 2211 # Check the name. 2212 if oFsObj.sName != sName: 2213 fRc = reporter.error('%s: expected name "%s", got "%s" instead!' % (oFsObj.sPath, oFsObj.sName, sName,)); 2214 2215 # Check the size if a file. 2216 if isinstance(oFsObj, testfileset.TestFile) and cbFile != oFsObj.cbContent: 2217 fRc = reporter.error('%s: expected size %s, got %s instead!' % (oFsObj.sPath, oFsObj.cbContent, cbFile,)); 2218 2219 ## @todo check timestamps and attributes. 2182 2220 2183 2221 # Close the directory … … 2203 2241 for oFsObj in oDir.aoChildren: 2204 2242 if isinstance(oFsObj, testfileset.TestDir): 2205 fRc = self.gctrlReadDirTree2(oGuestSession, oFsObj ) and fRc;2243 fRc = self.gctrlReadDirTree2(oGuestSession, oFsObj, fUseDirList, cEntriesPerRead) and fRc; 2206 2244 2207 2245 return fRc; … … 3823 3861 if fRc is not True: 3824 3862 break; 3825 (fRc2, cDirs, cFiles, cOthers) = self.gctrlReadDirTree(oCurTest, oCurGuestSession, oCurRes.fRc); 3863 fUseDirList = False; 3864 cEntriesPerRead = random.randrange(1, 32768); 3865 if self.oTstDrv.fpApiVer >= 7.1: # Listing directories only is available for >= VBox 7.1. 3866 fUseDirList = random.choice( [True, False] ); 3867 (fRc2, cDirs, cFiles, cOthers) = self.gctrlReadDirTree(oCurTest, oCurGuestSession, oCurRes.fRc, 3868 fUseDirList, cEntriesPerRead); 3826 3869 fRc = oCurTest.closeSession() and fRc; 3827 3870 … … 3867 3910 for oDir in (self.oTestFiles.oEmptyDir, self.oTestFiles.oManyDir, self.oTestFiles.oTreeDir): 3868 3911 reporter.log('Checking "%s" ...' % (oDir.sPath,)); 3869 fRc = self.gctrlReadDirTree2(oCurGuestSession, oDir) and fRc; 3912 fUseDirList = False; 3913 cEntriesPerRead = random.randrange(1, 32768); 3914 if self.oTstDrv.fpApiVer >= 7.1: # Listing directories only is available for >= VBox 7.1. 3915 fUseDirList = random.choice( [True, False] ); 3916 fRc = self.gctrlReadDirTree2(oCurGuestSession, oDir, fUseDirList, cEntriesPerRead) and fRc; 3870 3917 fRc = oCurTest.closeSession() and fRc; 3871 3918
Note:
See TracChangeset
for help on using the changeset viewer.