VirtualBox

Changeset 76305 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Dec 20, 2018 12:03:23 AM (6 years ago)
Author:
vboxsync
Message:

Runtime/fs/extvfs: Updates, reading data from ext2/ext3 filesystems seems to work to some extent

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/fs/extvfs.cpp

    r76304 r76305  
    6161#endif
    6262
     63/** All supported incompatible features. */
     64#define RTFSEXT_INCOMPAT_FEATURES_SUPP      (EXT_SB_FEAT_INCOMPAT_DIR_FILETYPE)
    6365
    6466/*********************************************************************************************************************************
     
    127129    /** Set if we've reached the end of the directory enumeration. */
    128130    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;
    129135} RTFSEXTDIR;
    130136/** Pointer to an open directory instance. */
    131137typedef RTFSEXTDIR *PRTFSEXTDIR;
     138
     139
     140/**
     141 * Open file instance.
     142 */
     143typedef 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. */
     153typedef RTFSEXTFILE *PRTFSEXTFILE;
    132154
    133155
     
    170192    size_t              cbInode;
    171193
     194    /** Incompatible features selected for this filesystem. */
     195    uint32_t            fFeaturesIncompat;
     196
     197
    172198    /** @name Block group cache.
    173199     * @{ */
     
    196222*   Internal Functions                                                                                                           *
    197223*********************************************************************************************************************************/
     224static int rtFsExtVol_OpenDirByInode(PRTFSEXTVOL pThis, uint32_t iInode, PRTVFSDIR phVfsDir);
    198225
    199226#ifdef LOG_ENABLED
     
    443470    }
    444471}
     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 */
     482static 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}
    445505#endif
    446506
     
    9641024
    9651025
     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 */
     1037static 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 */
     1099static 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 */
     1153static 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 */
     1168static 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 */
     1178static 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 */
     1236static 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 */
     1246static 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 */
     1256static 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 */
     1267static 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 */
     1277static 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 */
     1288static 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 */
     1298static 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 */
     1329static 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 */
     1340static 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 */
     1350static 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 */
     1361static 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 */
     1412static 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 */
     1463static 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
    9661510/*
    9671511 *
     
    10521596        return VERR_WRITE_PROTECT;
    10531597
     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
    10541636    LogFlow(("rtFsExtDir_Open(%s): returns %Rrc\n", pszEntry, rc));
    10551637    return rc;
     
    11221704
    11231705    pThis->fNoMoreFiles = false;
     1706    pThis->offEntry     = 0;
     1707    pThis->idxEntry     = 0;
    11241708    return VINF_SUCCESS;
    11251709}
     
    11331717{
    11341718    PRTFSEXTDIR     pThis = (PRTFSEXTDIR)pvThis;
    1135     int             rc = VINF_SUCCESS;
     1719    PRTFSEXTINODE   pInode = pThis->pInode;
    11361720    LogFlowFunc(("\n"));
    11371721
    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;
    11461784}
    11471785
     
    12191857    }
    12201858
    1221     RT_NOREF(phVfsDir, g_rtFsExtDirOps);
    12221859    return rc;
    12231860}
     1861
    12241862
    12251863
     
    12311869 *
    12321870 */
    1233 
    12341871
    12351872/**
     
    12721909
    12731910
     1911static 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
    12741922/**
    12751923 * @interface_method_impl{RTVFSOBJOPS::Obj,pfnClose}
     
    12831931    pThis->BlockGroupRoot = NULL;
    12841932    RTListInit(&pThis->LstBlockGroupLru);
     1933
     1934    /* Destroy the inode tree. */
     1935    RTAvlU32Destroy(&pThis->InodeRoot, rtFsExtVolInodeTreeDestroy, pThis);
     1936    pThis->InodeRoot = NULL;
     1937    RTListInit(&pThis->LstInodeLru);
    12851938
    12861939    /*
     
    14242077static int rtFsExtVolLoadAndParseSuperBlockV1(PRTFSEXTVOL pThis, PCEXTSUPERBLOCK pSb, PRTERRINFO pErrInfo)
    14252078{
    1426     if (RT_LE2H_U32(pSb->fFeaturesIncompat) != 0)
     2079    if ((RT_LE2H_U32(pSb->fFeaturesIncompat) & ~RTFSEXT_INCOMPAT_FEATURES_SUPP) != 0)
    14272080        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);
    14292082    if (   RT_LE2H_U32(pSb->fFeaturesCompatRo) != 0
    14302083        && !(pThis->fMntFlags & RTVFSMNT_F_READ_ONLY))
    14312084        return RTERRINFO_LOG_SET_F(pErrInfo, VERR_VFS_UNSUPPORTED_FORMAT, "EXT filesystem contains unsupported readonly features: %RX32",
    14322085                                   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);
    14332102
    14342103    return VINF_SUCCESS;
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette