OvmfPkg/FswHfsPlus/fsw_hfsplus.c
/* Get the next directory entry when reading a directory. This function is
 * called during directory iteration to retrieve the next directory entry.
 * A dnode is constructed for the entry and returned. The core makes sure
 * that fsw_hfsplus_dno_fill has been called and the dnode is actually a
 * directory. The shandle provided by the caller is used to record the
 * position in the directory between calls.
 */
Get the next directory entry when reading a directory. This function is
called during directory iteration to retrieve the next directory entry.
A dnode is constructed for the entry and returned. The core makes sure
that fsw_hfsplus_dno_fill has been called and the dnode is actually a
directory. The shandle provided by the caller is used to record the
position in the directory between calls.
Get the next directory entry when reading a directory . This function is called during directory iteration to retrieve the next directory entry . A dnode is constructed for the entry and returned . The core makes sure that fsw_hfsplus_dno_fill has been called and the dnode is actually a directory . The shandle provided by the caller is used to record the position in the directory between calls .
static fsw_status_t
fsw_hfsplus_dir_read(struct fsw_hfsplus_volume *v, struct fsw_hfsplus_dnode *d,
                     struct fsw_shandle *sh, struct fsw_hfsplus_dnode **d_out)
{
    BTNodeDescriptor     *btnode;
    fsw_u32              child_dno_id, child_dno_type;
    HFSPlusCatalogKey    sk, *tk;
    HFSPlusCatalogRecord *rec;
    struct fsw_string    name;
    int                  i;
    fsw_status_t         status;
DEBUG ((EFI_D_INFO, "GLS: dir_read.1: sh->pos=%ld\n", sh->pos));
    status = fsw_alloc(v->catf->bt_ndsz, &btnode);
    if (status)
        return status;
    sk.parentID = d->g.dnode_id;
    sk.nodeName.length = 0;
    sk.keyLength = sizeof(sk.parentID) + sizeof(sk.nodeName.length);
    status = fsw_hfsplus_bt_search(v->catf,
                                   (HFSPlusBTKey *)&sk, fsw_hfsplus_cat_cmp,
                                   sh->pos,
                                   btnode, (HFSPlusBTKey **)&tk);
    if (status)
        goto done;
    rec = fsw_hfsplus_bt_rec_skip_key((HFSPlusBTKey *)tk);
    if (fsw_u32_be_swap(tk->parentID) != sk.parentID) {
        status = FSW_NOT_FOUND;
        goto done;
    }
    name.type = FSW_STRING_TYPE_UTF16;
    name.len = fsw_u16_be_swap(tk->nodeName.length);
    name.size = name.len * 2;
    status = fsw_alloc(name.size, &name.data);
    if (status)
        goto done;
    for (i = 0; i < name.len; i++)
        ((fsw_u16 *)name.data)[i] = fsw_u16_be_swap(tk->nodeName.unicode[i]);
    switch (fsw_u16_be_swap(rec->recordType)) {
    case kHFSPlusFolderRecord:
        child_dno_id = fsw_u32_be_swap(rec->folderRecord.folderID);
        child_dno_type = FSW_DNODE_TYPE_DIR;
        break;
    case kHFSPlusFileRecord:
        child_dno_id = fsw_u32_be_swap(rec->fileRecord.fileID);
        child_dno_type = FSW_DNODE_TYPE_FILE;
        break;
    case kHFSPlusFolderThreadRecord:
DEBUG ((EFI_D_INFO, "GLS: dir_read.3: folder thread: "));
for (i = 0; i < fsw_u16_be_swap(rec->threadRecord.nodeName.length); i++)
  DEBUG ((EFI_D_INFO, "%c", fsw_u16_be_swap(rec->threadRecord.nodeName.unicode[i])));
DEBUG ((EFI_D_INFO, "\n"));
DEBUG ((EFI_D_INFO, "GLS: OldParentID=%d, NewParentID=%d\n", sk.parentID,
                    fsw_u32_be_swap(rec->threadRecord.parentID)));
    default:
DEBUG ((EFI_D_INFO, "GLS: dir_read.2: recordType=%d\n",
                    fsw_u16_be_swap(rec->recordType)));
        child_dno_id = 0;
        child_dno_type = FSW_DNODE_TYPE_UNKNOWN;
        break;
    }
    status = fsw_dnode_create(d, child_dno_id, child_dno_type, &name, d_out);
    if (status)
        goto done;
    fsw_strfree(&name);
    switch (child_dno_type) {
    case FSW_DNODE_TYPE_DIR:
        (*d_out)->ct = fsw_u32_be_swap(rec->folderRecord.createDate);
        (*d_out)->mt = fsw_u32_be_swap(rec->folderRecord.contentModDate);
        (*d_out)->at = fsw_u32_be_swap(rec->folderRecord.accessDate);
        break;
    case FSW_DNODE_TYPE_FILE:
        (*d_out)->g.size =
            fsw_u64_be_swap(rec->fileRecord.dataFork.logicalSize);
        fsw_memcpy((*d_out)->extents, &rec->fileRecord.dataFork.extents,
                   sizeof(HFSPlusExtentRecord));
        (*d_out)->ct = fsw_u32_be_swap(rec->fileRecord.createDate);
        (*d_out)->mt = fsw_u32_be_swap(rec->fileRecord.contentModDate);
        (*d_out)->at = fsw_u32_be_swap(rec->fileRecord.accessDate);
        break;
    default:
        (*d_out)->ct = 0;
        (*d_out)->mt = 0;
        (*d_out)->at = 0;
        break;
    }
    sh->pos++;
done:
    fsw_free(btnode);
    return status;
}
static fsw_status_t fsw_hfsplus_dir_read ( struct fsw_hfsplus_volume * v , struct fsw_hfsplus_dnode * d , struct fsw_shandle * sh , struct fsw_hfsplus_dnode * * d_out ) { BTNodeDescriptor * btnode ; fsw_u32 child_dno_id , child_dno_type ; HFSPlusCatalogKey sk , * tk ; HFSPlusCatalogRecord * rec ; struct fsw_string name ; int i ; fsw_status_t status ; DEBUG ( ( EFI_D_INFO , " \n " , sh -> pos ) ) ; status = fsw_alloc ( v -> catf -> bt_ndsz , & btnode ) ; if ( status ) return status ; sk . parentID = d -> g . dnode_id ; sk . nodeName . length = 0 ; sk . keyLength = sizeof ( sk . parentID ) + sizeof ( sk . nodeName . length ) ; status = fsw_hfsplus_bt_search ( v -> catf , ( HFSPlusBTKey * ) & sk , fsw_hfsplus_cat_cmp , sh -> pos , btnode , ( HFSPlusBTKey * * ) & tk ) ; if ( status ) goto done ; rec = fsw_hfsplus_bt_rec_skip_key ( ( HFSPlusBTKey * ) tk ) ; if ( fsw_u32_be_swap ( tk -> parentID ) != sk . parentID ) { status = FSW_NOT_FOUND ; goto done ; } name . type = FSW_STRING_TYPE_UTF16 ; name . len = fsw_u16_be_swap ( tk -> nodeName . length ) ; name . size = name . len * 2 ; status = fsw_alloc ( name . size , & name . data ) ; if ( status ) goto done ; for ( i = 0 ; i < name . len ; i ++ ) ( ( fsw_u16 * ) name . data ) [ i ] = fsw_u16_be_swap ( tk -> nodeName . unicode [ i ] ) ; switch ( fsw_u16_be_swap ( rec -> recordType ) ) { case kHFSPlusFolderRecord : child_dno_id = fsw_u32_be_swap ( rec -> folderRecord . folderID ) ; child_dno_type = FSW_DNODE_TYPE_DIR ; break ; case kHFSPlusFileRecord : child_dno_id = fsw_u32_be_swap ( rec -> fileRecord . fileID ) ; child_dno_type = FSW_DNODE_TYPE_FILE ; break ; case kHFSPlusFolderThreadRecord : DEBUG ( ( EFI_D_INFO , " " ) ) ; for ( i = 0 ; i < fsw_u16_be_swap ( rec -> threadRecord . nodeName . length ) ; i ++ ) DEBUG ( ( EFI_D_INFO , " " , fsw_u16_be_swap ( rec -> threadRecord . nodeName . unicode [ i ] ) ) ) ; DEBUG ( ( EFI_D_INFO , " \n " ) ) ; DEBUG ( ( EFI_D_INFO , " \n " , sk . parentID , fsw_u32_be_swap ( rec -> threadRecord . parentID ) ) ) ; default : DEBUG ( ( EFI_D_INFO , " \n " , fsw_u16_be_swap ( rec -> recordType ) ) ) ; child_dno_id = 0 ; child_dno_type = FSW_DNODE_TYPE_UNKNOWN ; break ; } status = fsw_dnode_create ( d , child_dno_id , child_dno_type , & name , d_out ) ; if ( status ) goto done ; fsw_strfree ( & name ) ; switch ( child_dno_type ) { case FSW_DNODE_TYPE_DIR : ( * d_out ) -> ct = fsw_u32_be_swap ( rec -> folderRecord . createDate ) ; ( * d_out ) -> mt = fsw_u32_be_swap ( rec -> folderRecord . contentModDate ) ; ( * d_out ) -> at = fsw_u32_be_swap ( rec -> folderRecord . accessDate ) ; break ; case FSW_DNODE_TYPE_FILE : ( * d_out ) -> g . size = fsw_u64_be_swap ( rec -> fileRecord . dataFork . logicalSize ) ; fsw_memcpy ( ( * d_out ) -> extents , & rec -> fileRecord . dataFork . extents , sizeof ( HFSPlusExtentRecord ) ) ; ( * d_out ) -> ct = fsw_u32_be_swap ( rec -> fileRecord . createDate ) ; ( * d_out ) -> mt = fsw_u32_be_swap ( rec -> fileRecord . contentModDate ) ; ( * d_out ) -> at = fsw_u32_be_swap ( rec -> fileRecord . accessDate ) ; break ; default : ( * d_out ) -> ct = 0 ; ( * d_out ) -> mt = 0 ; ( * d_out ) -> at = 0 ; break ; } sh -> pos ++ ; done : fsw_free ( btnode ) ; return status ; }
Get the next directory entry when reading a directory.
Get the next directory entry when reading a directory .
// FIXME: can we factor out common bits shared with dir_get() ? // pre-allocate bt-node buffer for use by search function: // search catalog file for first child of 'd' (a.k.a. "./"): // NOTE: keyLength not used in search, setting only for completeness: // did we exhaust all child dnodes of 'd'? // get child name // figure out type of child dnode: //        break; // allocate child dnode: // done with child name: // grab additional child dnode status data: // advance caller's state to next directory entry: