Changeset 99085 in vbox for trunk/src/VBox/Additions/common
- Timestamp:
- Mar 21, 2023 12:15:00 PM (23 months ago)
- Location:
- trunk/src/VBox/Additions/common
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
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
Note:
See TracChangeset
for help on using the changeset viewer.