Changeset 76305 in vbox for trunk/src/VBox
- Timestamp:
- Dec 20, 2018 12:03:23 AM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/fs/extvfs.cpp
r76304 r76305 61 61 #endif 62 62 63 /** All supported incompatible features. */ 64 #define RTFSEXT_INCOMPAT_FEATURES_SUPP (EXT_SB_FEAT_INCOMPAT_DIR_FILETYPE) 63 65 64 66 /********************************************************************************************************************************* … … 127 129 /** Set if we've reached the end of the directory enumeration. */ 128 130 bool fNoMoreFiles; 131 /** Current offset into the directory where the next entry should be read. */ 132 uint64_t offEntry; 133 /** Next entry index (for logging purposes). */ 134 uint32_t idxEntry; 129 135 } RTFSEXTDIR; 130 136 /** Pointer to an open directory instance. */ 131 137 typedef RTFSEXTDIR *PRTFSEXTDIR; 138 139 140 /** 141 * Open file instance. 142 */ 143 typedef struct RTFSEXTFILE 144 { 145 /** Volume this directory belongs to. */ 146 PRTFSEXTVOL pVol; 147 /** The underlying inode structure. */ 148 PRTFSEXTINODE pInode; 149 /** Current offset into the file for I/O. */ 150 RTFOFF offFile; 151 } RTFSEXTFILE; 152 /** Pointer to an open file instance. */ 153 typedef RTFSEXTFILE *PRTFSEXTFILE; 132 154 133 155 … … 170 192 size_t cbInode; 171 193 194 /** Incompatible features selected for this filesystem. */ 195 uint32_t fFeaturesIncompat; 196 197 172 198 /** @name Block group cache. 173 199 * @{ */ … … 196 222 * Internal Functions * 197 223 *********************************************************************************************************************************/ 224 static int rtFsExtVol_OpenDirByInode(PRTFSEXTVOL pThis, uint32_t iInode, PRTVFSDIR phVfsDir); 198 225 199 226 #ifdef LOG_ENABLED … … 443 470 } 444 471 } 472 473 474 /** 475 * Logs a ext filesystem directory entry. 476 * 477 * @returns nothing. 478 * @param pThis The ext volume instance. 479 * @param idxDirEntry Directory entry index number. 480 * @param pDirEntry The directory entry. 481 */ 482 static void rtFsExtDirEntry_Log(PRTFSEXTVOL pThis, uint32_t idxDirEntry, PCEXTDIRENTRYEX pDirEntry) 483 { 484 if (LogIs2Enabled()) 485 { 486 int cbName = 0; 487 488 Log2(("EXT: Directory entry %#RX32:\n", idxDirEntry)); 489 Log2(("EXT: iInodeRef %#RX32\n", RT_LE2H_U32(pDirEntry->Core.iInodeRef))); 490 Log2(("EXT: cbRecord %#RX32\n", RT_LE2H_U32(pDirEntry->Core.cbRecord))); 491 if (pThis->fFeaturesIncompat & EXT_SB_FEAT_INCOMPAT_DIR_FILETYPE) 492 { 493 Log2(("EXT: cbName %#RU8\n", pDirEntry->Core.u.v2.cbName)); 494 Log2(("EXT: uType %#RX8\n", pDirEntry->Core.u.v2.uType)); 495 cbName = pDirEntry->Core.u.v2.cbName; 496 } 497 else 498 { 499 Log2(("EXT: cbName %#RU16\n", RT_LE2H_U16(pDirEntry->Core.u.v1.cbName))); 500 cbName = RT_LE2H_U16(pDirEntry->Core.u.v1.cbName); 501 } 502 Log2(("EXT: achName %*s\n", cbName, &pDirEntry->Core.achName[0])); 503 } 504 } 445 505 #endif 446 506 … … 964 1024 965 1025 1026 /** 1027 * Maps the given inode block to the destination filesystem block. 1028 * 1029 * @returns IPRT status code. 1030 * @param pThis The ext volume instance. 1031 * @param pInode The inode structure to read from. 1032 * @param iBlock The inode block to map. 1033 * @param piBlockFs Where to store the filesystem block on success. 1034 * 1035 * @todo Optimize 1036 */ 1037 static int rtFsExtInode_MapBlockToFs(PRTFSEXTVOL pThis, PRTFSEXTINODE pInode, uint64_t iBlock, uint64_t *piBlockFs) 1038 { 1039 int rc = VINF_SUCCESS; 1040 1041 /* The first 12 inode blocks are directly mapped from the inode. */ 1042 if (iBlock <= 11) 1043 *piBlockFs = pInode->aiBlocks[iBlock]; 1044 else 1045 { 1046 uint32_t cEntriesPerBlockMap = pThis->cbBlock << sizeof(uint32_t); 1047 uint32_t *paBlockMap = (uint32_t *)RTMemTmpAllocZ(cEntriesPerBlockMap * sizeof(uint32_t)); 1048 1049 if (!paBlockMap) 1050 return VERR_NO_MEMORY; 1051 1052 if (iBlock <= cEntriesPerBlockMap + 11) 1053 { 1054 /* Indirect block. */ 1055 uint64_t offRead = rtFsExtBlockIdxToDiskOffset(pThis, pInode->aiBlocks[12]); 1056 rc = RTVfsFileReadAt(pThis->hVfsBacking, offRead, paBlockMap, pThis->cbBlock, NULL); 1057 if (RT_SUCCESS(rc)) 1058 *piBlockFs = RT_LE2H_U32(paBlockMap[iBlock - 12]); 1059 } 1060 else if (iBlock <= cEntriesPerBlockMap * cEntriesPerBlockMap + cEntriesPerBlockMap + 11) 1061 { 1062 /* Double indirect block. */ 1063 iBlock -= 12; 1064 uint64_t offRead = rtFsExtBlockIdxToDiskOffset(pThis, pInode->aiBlocks[13]); 1065 rc = RTVfsFileReadAt(pThis->hVfsBacking, offRead, paBlockMap, pThis->cbBlock, NULL); 1066 if (RT_SUCCESS(rc)) 1067 { 1068 uint32_t idxBlockL2 = iBlock / cEntriesPerBlockMap; 1069 uint32_t idxBlockL1 = iBlock % cEntriesPerBlockMap; 1070 offRead = rtFsExtBlockIdxToDiskOffset(pThis, RT_LE2H_U32(paBlockMap[idxBlockL2])); 1071 rc = RTVfsFileReadAt(pThis->hVfsBacking, offRead, paBlockMap, pThis->cbBlock, NULL); 1072 if (RT_SUCCESS(rc)) 1073 *piBlockFs = RT_LE2H_U32(paBlockMap[idxBlockL1]); 1074 } 1075 } 1076 else 1077 { 1078 /* Triple indirect block. */ 1079 rc = VERR_NOT_IMPLEMENTED; 1080 } 1081 1082 RTMemTmpFree(paBlockMap); 1083 } 1084 1085 return rc; 1086 } 1087 1088 1089 /** 1090 * Reads data from the given inode at the given byte offset. 1091 * 1092 * @returns IPRT status code. 1093 * @param pThis The ext volume instance. 1094 * @param pInode The inode structure to read from. 1095 * @param off The byte offset to start reading from. 1096 * @param pvBuf Where to store the read data to. 1097 * @param pcbRead Where to return the amount of data read. 1098 */ 1099 static int rtFsExtInode_Read(PRTFSEXTVOL pThis, PRTFSEXTINODE pInode, uint64_t off, void *pvBuf, size_t cbRead, size_t *pcbRead) 1100 { 1101 int rc = VINF_SUCCESS; 1102 uint8_t *pbBuf = (uint8_t *)pvBuf; 1103 1104 if (((uint64_t)pInode->ObjInfo.cbObject < off + cbRead)) 1105 { 1106 if (!pcbRead) 1107 return VERR_EOF; 1108 else 1109 cbRead = (uint64_t)pInode->ObjInfo.cbObject - off; 1110 } 1111 1112 while ( cbRead 1113 && RT_SUCCESS(rc)) 1114 { 1115 uint64_t iBlockStart = rtFsExtDiskOffsetToBlockIdx(pThis, off); 1116 uint32_t offBlockStart = off % pThis->cbBlock; 1117 1118 /* Resolve the inode block to the proper filesystem block. */ 1119 uint64_t iBlockFs = 0; 1120 rc = rtFsExtInode_MapBlockToFs(pThis, pInode, iBlockStart, &iBlockFs); 1121 if (RT_SUCCESS(rc)) 1122 { 1123 size_t cbThisRead = RT_MIN(cbRead, pThis->cbBlock - offBlockStart); 1124 uint64_t offRead = rtFsExtBlockIdxToDiskOffset(pThis, iBlockFs); 1125 rc = RTVfsFileReadAt(pThis->hVfsBacking, offRead + offBlockStart, pbBuf, cbThisRead, NULL); 1126 if (RT_SUCCESS(rc)) 1127 { 1128 pbBuf += cbThisRead; 1129 cbRead -= cbThisRead; 1130 off += cbThisRead; 1131 if (pcbRead) 1132 *pcbRead += cbThisRead; 1133 } 1134 } 1135 } 1136 1137 return rc; 1138 } 1139 1140 1141 1142 /* 1143 * 1144 * File operations. 1145 * File operations. 1146 * File operations. 1147 * 1148 */ 1149 1150 /** 1151 * @interface_method_impl{RTVFSOBJOPS,pfnClose} 1152 */ 1153 static DECLCALLBACK(int) rtFsExtFile_Close(void *pvThis) 1154 { 1155 PRTFSEXTFILE pThis = (PRTFSEXTFILE)pvThis; 1156 LogFlow(("rtFsExtFile_Close(%p/%p)\n", pThis, pThis->pInode)); 1157 1158 rtFsExtInodeRelease(pThis->pVol, pThis->pInode); 1159 pThis->pInode = NULL; 1160 pThis->pVol = NULL; 1161 return VINF_SUCCESS; 1162 } 1163 1164 1165 /** 1166 * @interface_method_impl{RTVFSOBJOPS,pfnQueryInfo} 1167 */ 1168 static DECLCALLBACK(int) rtFsExtFile_QueryInfo(void *pvThis, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAddAttr) 1169 { 1170 PRTFSEXTFILE pThis = (PRTFSEXTFILE)pvThis; 1171 return rtFsExtInode_QueryInfo(pThis->pInode, pObjInfo, enmAddAttr); 1172 } 1173 1174 1175 /** 1176 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnRead} 1177 */ 1178 static DECLCALLBACK(int) rtFsExtFile_Read(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbRead) 1179 { 1180 PRTFSEXTFILE pThis = (PRTFSEXTFILE)pvThis; 1181 AssertReturn(pSgBuf->cSegs == 1, VERR_INTERNAL_ERROR_3); 1182 RT_NOREF(fBlocking); 1183 1184 if (off == -1) 1185 off = pThis->offFile; 1186 else 1187 AssertReturn(off >= 0, VERR_INTERNAL_ERROR_3); 1188 1189 int rc; 1190 size_t cbRead = pSgBuf->paSegs[0].cbSeg; 1191 if (!pcbRead) 1192 { 1193 rc = rtFsExtInode_Read(pThis->pVol, pThis->pInode, (uint64_t)off, pSgBuf->paSegs[0].pvSeg, cbRead, NULL); 1194 if (RT_SUCCESS(rc)) 1195 pThis->offFile = off + cbRead; 1196 Log6(("rtFsExtFile_Read: off=%#RX64 cbSeg=%#x -> %Rrc\n", off, pSgBuf->paSegs[0].cbSeg, rc)); 1197 } 1198 else 1199 { 1200 PRTFSEXTINODE pInode = pThis->pInode; 1201 if (off >= pInode->ObjInfo.cbObject) 1202 { 1203 *pcbRead = 0; 1204 rc = VINF_EOF; 1205 } 1206 else 1207 { 1208 if (off + cbRead <= (uint64_t)pInode->ObjInfo.cbObject) 1209 rc = rtFsExtInode_Read(pThis->pVol, pThis->pInode, (uint64_t)off, pSgBuf->paSegs[0].pvSeg, cbRead, NULL); 1210 else 1211 { 1212 /* Return VINF_EOF if beyond end-of-file. */ 1213 cbRead = (size_t)(pInode->ObjInfo.cbObject - off); 1214 rc = rtFsExtInode_Read(pThis->pVol, pThis->pInode, off, pSgBuf->paSegs[0].pvSeg, cbRead, NULL); 1215 if (RT_SUCCESS(rc)) 1216 rc = VINF_EOF; 1217 } 1218 if (RT_SUCCESS(rc)) 1219 { 1220 pThis->offFile = off + cbRead; 1221 *pcbRead = cbRead; 1222 } 1223 else 1224 *pcbRead = 0; 1225 } 1226 Log6(("rtFsExtFile_Read: off=%#RX64 cbSeg=%#x -> %Rrc *pcbRead=%#x\n", off, pSgBuf->paSegs[0].cbSeg, rc, *pcbRead)); 1227 } 1228 1229 return rc; 1230 } 1231 1232 1233 /** 1234 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnWrite} 1235 */ 1236 static DECLCALLBACK(int) rtFsExtFile_Write(void *pvThis, RTFOFF off, PCRTSGBUF pSgBuf, bool fBlocking, size_t *pcbWritten) 1237 { 1238 RT_NOREF(pvThis, off, pSgBuf, fBlocking, pcbWritten); 1239 return VERR_WRITE_PROTECT; 1240 } 1241 1242 1243 /** 1244 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnFlush} 1245 */ 1246 static DECLCALLBACK(int) rtFsExtFile_Flush(void *pvThis) 1247 { 1248 RT_NOREF(pvThis); 1249 return VINF_SUCCESS; 1250 } 1251 1252 1253 /** 1254 * @interface_method_impl{RTVFSIOSTREAMOPS,pfnTell} 1255 */ 1256 static DECLCALLBACK(int) rtFsExtFile_Tell(void *pvThis, PRTFOFF poffActual) 1257 { 1258 PRTFSEXTFILE pThis = (PRTFSEXTFILE)pvThis; 1259 *poffActual = pThis->offFile; 1260 return VINF_SUCCESS; 1261 } 1262 1263 1264 /** 1265 * @interface_method_impl{RTVFSOBJSETOPS,pfnMode} 1266 */ 1267 static DECLCALLBACK(int) rtFsExtFile_SetMode(void *pvThis, RTFMODE fMode, RTFMODE fMask) 1268 { 1269 RT_NOREF(pvThis, fMode, fMask); 1270 return VERR_WRITE_PROTECT; 1271 } 1272 1273 1274 /** 1275 * @interface_method_impl{RTVFSOBJSETOPS,pfnSetTimes} 1276 */ 1277 static DECLCALLBACK(int) rtFsExtFile_SetTimes(void *pvThis, PCRTTIMESPEC pAccessTime, PCRTTIMESPEC pModificationTime, 1278 PCRTTIMESPEC pChangeTime, PCRTTIMESPEC pBirthTime) 1279 { 1280 RT_NOREF(pvThis, pAccessTime, pModificationTime, pChangeTime, pBirthTime); 1281 return VERR_WRITE_PROTECT; 1282 } 1283 1284 1285 /** 1286 * @interface_method_impl{RTVFSOBJSETOPS,pfnSetOwner} 1287 */ 1288 static DECLCALLBACK(int) rtFsExtFile_SetOwner(void *pvThis, RTUID uid, RTGID gid) 1289 { 1290 RT_NOREF(pvThis, uid, gid); 1291 return VERR_WRITE_PROTECT; 1292 } 1293 1294 1295 /** 1296 * @interface_method_impl{RTVFSFILEOPS,pfnSeek} 1297 */ 1298 static DECLCALLBACK(int) rtFsExtFile_Seek(void *pvThis, RTFOFF offSeek, unsigned uMethod, PRTFOFF poffActual) 1299 { 1300 PRTFSEXTFILE pThis = (PRTFSEXTFILE)pvThis; 1301 RTFOFF offNew; 1302 switch (uMethod) 1303 { 1304 case RTFILE_SEEK_BEGIN: 1305 offNew = offSeek; 1306 break; 1307 case RTFILE_SEEK_END: 1308 offNew = pThis->pInode->ObjInfo.cbObject + offSeek; 1309 break; 1310 case RTFILE_SEEK_CURRENT: 1311 offNew = (RTFOFF)pThis->offFile + offSeek; 1312 break; 1313 default: 1314 return VERR_INVALID_PARAMETER; 1315 } 1316 if (offNew >= 0) 1317 { 1318 pThis->offFile = offNew; 1319 *poffActual = offNew; 1320 return VINF_SUCCESS; 1321 } 1322 return VERR_NEGATIVE_SEEK; 1323 } 1324 1325 1326 /** 1327 * @interface_method_impl{RTVFSFILEOPS,pfnQuerySize} 1328 */ 1329 static DECLCALLBACK(int) rtFsExtFile_QuerySize(void *pvThis, uint64_t *pcbFile) 1330 { 1331 PRTFSEXTFILE pThis = (PRTFSEXTFILE)pvThis; 1332 *pcbFile = (uint64_t)pThis->pInode->ObjInfo.cbObject; 1333 return VINF_SUCCESS; 1334 } 1335 1336 1337 /** 1338 * @interface_method_impl{RTVFSFILEOPS,pfnSetSize} 1339 */ 1340 static DECLCALLBACK(int) rtFsExtFile_SetSize(void *pvThis, uint64_t cbFile, uint32_t fFlags) 1341 { 1342 RT_NOREF(pvThis, cbFile, fFlags); 1343 return VERR_WRITE_PROTECT; 1344 } 1345 1346 1347 /** 1348 * @interface_method_impl{RTVFSFILEOPS,pfnQueryMaxSize} 1349 */ 1350 static DECLCALLBACK(int) rtFsExtFile_QueryMaxSize(void *pvThis, uint64_t *pcbMax) 1351 { 1352 RT_NOREF(pvThis); 1353 *pcbMax = INT64_MAX; /** @todo */ 1354 return VINF_SUCCESS; 1355 } 1356 1357 1358 /** 1359 * EXT file operations. 1360 */ 1361 static const RTVFSFILEOPS g_rtFsExtFileOps = 1362 { 1363 { /* Stream */ 1364 { /* Obj */ 1365 RTVFSOBJOPS_VERSION, 1366 RTVFSOBJTYPE_FILE, 1367 "EXT File", 1368 rtFsExtFile_Close, 1369 rtFsExtFile_QueryInfo, 1370 RTVFSOBJOPS_VERSION 1371 }, 1372 RTVFSIOSTREAMOPS_VERSION, 1373 RTVFSIOSTREAMOPS_FEAT_NO_SG, 1374 rtFsExtFile_Read, 1375 rtFsExtFile_Write, 1376 rtFsExtFile_Flush, 1377 NULL /*PollOne*/, 1378 rtFsExtFile_Tell, 1379 NULL /*pfnSkip*/, 1380 NULL /*pfnZeroFill*/, 1381 RTVFSIOSTREAMOPS_VERSION, 1382 }, 1383 RTVFSFILEOPS_VERSION, 1384 0, 1385 { /* ObjSet */ 1386 RTVFSOBJSETOPS_VERSION, 1387 RT_UOFFSETOF(RTVFSFILEOPS, ObjSet) - RT_UOFFSETOF(RTVFSFILEOPS, Stream.Obj), 1388 rtFsExtFile_SetMode, 1389 rtFsExtFile_SetTimes, 1390 rtFsExtFile_SetOwner, 1391 RTVFSOBJSETOPS_VERSION 1392 }, 1393 rtFsExtFile_Seek, 1394 rtFsExtFile_QuerySize, 1395 rtFsExtFile_SetSize, 1396 rtFsExtFile_QueryMaxSize, 1397 RTVFSFILEOPS_VERSION 1398 }; 1399 1400 1401 /** 1402 * Creates a new VFS file from the given regular file inode. 1403 * 1404 * @returns IPRT status code. 1405 * @param pThis The ext volume instance. 1406 * @param fOpen Open flags passed. 1407 * @param iInode The inode for the file. 1408 * @param phVfsFile Where to store the VFS file handle on success. 1409 * @param pErrInfo Where to record additional error information on error, optional. 1410 * @param pszWhat Logging prefix. 1411 */ 1412 static int rtFsExtVol_NewFile(PRTFSEXTVOL pThis, uint64_t fOpen, uint32_t iInode, 1413 PRTVFSFILE phVfsFile, PRTERRINFO pErrInfo, const char *pszWhat) 1414 { 1415 /* 1416 * Load the inode and check that it really is a file. 1417 */ 1418 PRTFSEXTINODE pInode = NULL; 1419 int rc = rtFsExtInodeLoad(pThis, iInode, &pInode); 1420 if (RT_SUCCESS(rc)) 1421 { 1422 if (RTFS_IS_FILE(pInode->ObjInfo.Attr.fMode)) 1423 { 1424 PRTFSEXTFILE pNewFile; 1425 rc = RTVfsNewFile(&g_rtFsExtFileOps, sizeof(*pNewFile), fOpen, pThis->hVfsSelf, NIL_RTVFSLOCK, 1426 phVfsFile, (void **)&pNewFile); 1427 if (RT_SUCCESS(rc)) 1428 { 1429 pNewFile->pVol = pThis; 1430 pNewFile->pInode = pInode; 1431 pNewFile->offFile = 0; 1432 } 1433 } 1434 else 1435 rc = RTERRINFO_LOG_SET_F(pErrInfo, VERR_NOT_A_FILE, "%s: fMode=%#RX32", pszWhat, pInode->ObjInfo.Attr.fMode); 1436 1437 if (RT_FAILURE(rc)) 1438 rtFsExtInodeRelease(pThis, pInode); 1439 } 1440 1441 return rc; 1442 } 1443 1444 1445 1446 /* 1447 * 1448 * EXT directory code. 1449 * EXT directory code. 1450 * EXT directory code. 1451 * 1452 */ 1453 1454 /** 1455 * Looks up an entry in the given directory inode. 1456 * 1457 * @returns IPRT status code. 1458 * @param pThis The ext volume instance. 1459 * @param pInode The directory inode structure to. 1460 * @param pszEntry The entry to lookup. 1461 * @param piInode Where to store the inode number if the entry was found. 1462 */ 1463 static int rtFsExtDir_Lookup(PRTFSEXTVOL pThis, PRTFSEXTINODE pInode, const char *pszEntry, uint32_t *piInode) 1464 { 1465 uint64_t offEntry = 0; 1466 int rc = VERR_FILE_NOT_FOUND; 1467 uint32_t idxDirEntry = 0; 1468 size_t cchEntry = strlen(pszEntry); 1469 1470 if (cchEntry > 255) 1471 return VERR_FILENAME_TOO_LONG; 1472 1473 while (offEntry < (uint64_t)pInode->ObjInfo.cbObject) 1474 { 1475 EXTDIRENTRYEX DirEntry; 1476 size_t cbThis = RT_MIN(sizeof(DirEntry), (uint64_t)pInode->ObjInfo.cbObject - offEntry); 1477 int rc2 = rtFsExtInode_Read(pThis, pInode, offEntry, &DirEntry, cbThis, NULL); 1478 if (RT_SUCCESS(rc2)) 1479 { 1480 #ifdef LOG_ENABLED 1481 rtFsExtDirEntry_Log(pThis, idxDirEntry, &DirEntry); 1482 #endif 1483 1484 uint16_t cbName = pThis->fFeaturesIncompat & EXT_SB_FEAT_INCOMPAT_DIR_FILETYPE 1485 ? DirEntry.Core.u.v2.cbName 1486 : RT_LE2H_U16(DirEntry.Core.u.v1.cbName); 1487 if ( cchEntry == cbName 1488 && !memcmp(pszEntry, &DirEntry.Core.achName[0], cchEntry)) 1489 { 1490 *piInode = RT_LE2H_U32(DirEntry.Core.iInodeRef); 1491 rc = VINF_SUCCESS; 1492 break; 1493 } 1494 1495 offEntry += RT_LE2H_U16(DirEntry.Core.cbRecord); 1496 idxDirEntry++; 1497 } 1498 else 1499 { 1500 rc = rc2; 1501 break; 1502 } 1503 } 1504 1505 return rc; 1506 } 1507 1508 1509 966 1510 /* 967 1511 * … … 1052 1596 return VERR_WRITE_PROTECT; 1053 1597 1598 /* 1599 * Lookup the entry. 1600 */ 1601 uint32_t iInode = 0; 1602 rc = rtFsExtDir_Lookup(pVol, pThis->pInode, pszEntry, &iInode); 1603 if (RT_SUCCESS(rc)) 1604 { 1605 PRTFSEXTINODE pInode = NULL; 1606 rc = rtFsExtInodeLoad(pVol, iInode, &pInode); 1607 if (RT_SUCCESS(rc)) 1608 { 1609 if (RTFS_IS_DIRECTORY(pInode->ObjInfo.Attr.fMode)) 1610 { 1611 RTVFSDIR hVfsDir; 1612 rc = rtFsExtVol_OpenDirByInode(pVol, iInode, &hVfsDir); 1613 if (RT_SUCCESS(rc)) 1614 { 1615 *phVfsObj = RTVfsObjFromDir(hVfsDir); 1616 RTVfsDirRelease(hVfsDir); 1617 AssertStmt(*phVfsObj != NIL_RTVFSOBJ, rc = VERR_INTERNAL_ERROR_3); 1618 } 1619 } 1620 else if (RTFS_IS_FILE(pInode->ObjInfo.Attr.fMode)) 1621 { 1622 RTVFSFILE hVfsFile; 1623 rc = rtFsExtVol_NewFile(pVol, fOpen, iInode, &hVfsFile, NULL, pszEntry); 1624 if (RT_SUCCESS(rc)) 1625 { 1626 *phVfsObj = RTVfsObjFromFile(hVfsFile); 1627 RTVfsFileRelease(hVfsFile); 1628 AssertStmt(*phVfsObj != NIL_RTVFSOBJ, rc = VERR_INTERNAL_ERROR_3); 1629 } 1630 } 1631 else 1632 rc = VERR_NOT_SUPPORTED; 1633 } 1634 } 1635 1054 1636 LogFlow(("rtFsExtDir_Open(%s): returns %Rrc\n", pszEntry, rc)); 1055 1637 return rc; … … 1122 1704 1123 1705 pThis->fNoMoreFiles = false; 1706 pThis->offEntry = 0; 1707 pThis->idxEntry = 0; 1124 1708 return VINF_SUCCESS; 1125 1709 } … … 1133 1717 { 1134 1718 PRTFSEXTDIR pThis = (PRTFSEXTDIR)pvThis; 1135 int rc = VINF_SUCCESS;1719 PRTFSEXTINODE pInode = pThis->pInode; 1136 1720 LogFlowFunc(("\n")); 1137 1721 1138 RT_NOREF(pThis, rc, pDirEntry, pcbDirEntry, enmAddAttr); 1139 1140 /* 1141 * The End. 1142 */ 1143 LogFlowFunc(("no more files\n")); 1144 pThis->fNoMoreFiles = true; 1145 return VERR_NO_MORE_FILES; 1722 if (pThis->fNoMoreFiles) 1723 return VERR_NO_MORE_FILES; 1724 1725 EXTDIRENTRYEX DirEntry; 1726 size_t cbThis = RT_MIN(sizeof(DirEntry), (uint64_t)pInode->ObjInfo.cbObject - pThis->offEntry); 1727 int rc = rtFsExtInode_Read(pThis->pVol, pInode, pThis->offEntry, &DirEntry, cbThis, NULL); 1728 if (RT_SUCCESS(rc)) 1729 { 1730 #ifdef LOG_ENABLED 1731 rtFsExtDirEntry_Log(pThis->pVol, pThis->idxEntry, &DirEntry); 1732 #endif 1733 1734 /* 0 inode entry means unused entry. */ 1735 /** @todo Can there be unused entries somewhere in the middle? */ 1736 uint32_t iInodeRef = RT_LE2H_U32(DirEntry.Core.iInodeRef); 1737 if (iInodeRef != 0) 1738 { 1739 uint16_t cbName = pThis->pVol->fFeaturesIncompat & EXT_SB_FEAT_INCOMPAT_DIR_FILETYPE 1740 ? DirEntry.Core.u.v2.cbName 1741 : RT_LE2H_U16(DirEntry.Core.u.v1.cbName); 1742 1743 if (cbName <= 255) 1744 { 1745 size_t const cbDirEntry = *pcbDirEntry; 1746 1747 *pcbDirEntry = RT_UOFFSETOF_DYN(RTDIRENTRYEX, szName[cbName + 2]); 1748 if (*pcbDirEntry <= cbDirEntry) 1749 { 1750 /* Load the referenced inode. */ 1751 PRTFSEXTINODE pInodeRef; 1752 rc = rtFsExtInodeLoad(pThis->pVol, iInodeRef, &pInodeRef); 1753 if (RT_SUCCESS(rc)) 1754 { 1755 memcpy(&pDirEntry->szName[0], &DirEntry.Core.achName[0], cbName); 1756 pDirEntry->szName[cbName] = '\0'; 1757 pDirEntry->cbName = cbName; 1758 rc = rtFsExtInode_QueryInfo(pInode, &pDirEntry->Info, enmAddAttr); 1759 if (RT_SUCCESS(rc)) 1760 { 1761 pThis->offEntry += RT_LE2H_U16(DirEntry.Core.cbRecord); 1762 pThis->idxEntry++; 1763 rtFsExtInodeRelease(pThis->pVol, pInode); 1764 return VINF_SUCCESS; 1765 } 1766 rtFsExtInodeRelease(pThis->pVol, pInode); 1767 } 1768 } 1769 else 1770 rc = VERR_BUFFER_OVERFLOW; 1771 } 1772 else 1773 rc = VERR_FILENAME_TOO_LONG; 1774 } 1775 else 1776 { 1777 rc = VERR_NO_MORE_FILES; 1778 LogFlowFunc(("no more files\n")); 1779 pThis->fNoMoreFiles = true; 1780 } 1781 } 1782 1783 return rc; 1146 1784 } 1147 1785 … … 1219 1857 } 1220 1858 1221 RT_NOREF(phVfsDir, g_rtFsExtDirOps);1222 1859 return rc; 1223 1860 } 1861 1224 1862 1225 1863 … … 1231 1869 * 1232 1870 */ 1233 1234 1871 1235 1872 /** … … 1272 1909 1273 1910 1911 static DECLCALLBACK(int) rtFsExtVolInodeTreeDestroy(PAVLU32NODECORE pCore, void *pvUser) 1912 { 1913 RT_NOREF(pvUser); 1914 1915 PRTFSEXTINODE pInode = (PRTFSEXTINODE)pCore; 1916 Assert(!pInode->cRefs); 1917 RTMemFree(pInode); 1918 return VINF_SUCCESS; 1919 } 1920 1921 1274 1922 /** 1275 1923 * @interface_method_impl{RTVFSOBJOPS::Obj,pfnClose} … … 1283 1931 pThis->BlockGroupRoot = NULL; 1284 1932 RTListInit(&pThis->LstBlockGroupLru); 1933 1934 /* Destroy the inode tree. */ 1935 RTAvlU32Destroy(&pThis->InodeRoot, rtFsExtVolInodeTreeDestroy, pThis); 1936 pThis->InodeRoot = NULL; 1937 RTListInit(&pThis->LstInodeLru); 1285 1938 1286 1939 /* … … 1424 2077 static int rtFsExtVolLoadAndParseSuperBlockV1(PRTFSEXTVOL pThis, PCEXTSUPERBLOCK pSb, PRTERRINFO pErrInfo) 1425 2078 { 1426 if ( RT_LE2H_U32(pSb->fFeaturesIncompat) != 0)2079 if ((RT_LE2H_U32(pSb->fFeaturesIncompat) & ~RTFSEXT_INCOMPAT_FEATURES_SUPP) != 0) 1427 2080 return RTERRINFO_LOG_SET_F(pErrInfo, VERR_VFS_UNSUPPORTED_FORMAT, "EXT filesystem contains unsupported incompatible features: %RX32", 1428 RT_LE2H_U32(pSb->fFeaturesIncompat) );2081 RT_LE2H_U32(pSb->fFeaturesIncompat) & ~RTFSEXT_INCOMPAT_FEATURES_SUPP); 1429 2082 if ( RT_LE2H_U32(pSb->fFeaturesCompatRo) != 0 1430 2083 && !(pThis->fMntFlags & RTVFSMNT_F_READ_ONLY)) 1431 2084 return RTERRINFO_LOG_SET_F(pErrInfo, VERR_VFS_UNSUPPORTED_FORMAT, "EXT filesystem contains unsupported readonly features: %RX32", 1432 2085 RT_LE2H_U32(pSb->fFeaturesCompatRo)); 2086 2087 pThis->f64Bit = false; 2088 pThis->cBlockShift = 10 + RT_LE2H_U32(pSb->cLogBlockSize); 2089 pThis->cbBlock = UINT64_C(1) << pThis->cBlockShift; 2090 pThis->cbInode = RT_LE2H_U16(pSb->cbInode); 2091 pThis->cbBlkGrpDesc = sizeof(EXTBLOCKGROUPDESC32); 2092 pThis->cBlocksPerGroup = RT_LE2H_U32(pSb->cBlocksPerGroup); 2093 pThis->cInodesPerGroup = RT_LE2H_U32(pSb->cInodesPerBlockGroup); 2094 pThis->cBlockGroups = RT_LE2H_U32(pSb->cBlocksTotalLow) / pThis->cBlocksPerGroup; 2095 pThis->cbBlockBitmap = pThis->cBlocksPerGroup / 8; 2096 if (pThis->cBlocksPerGroup % 8) 2097 pThis->cbBlockBitmap++; 2098 pThis->cbInodeBitmap = pThis->cInodesPerGroup / 8; 2099 if (pThis->cInodesPerGroup % 8) 2100 pThis->cbInodeBitmap++; 2101 pThis->fFeaturesIncompat = RT_LE2H_U32(pSb->fFeaturesIncompat); 1433 2102 1434 2103 return VINF_SUCCESS;
Note:
See TracChangeset
for help on using the changeset viewer.