hfs_parse_resource_fork(TSK_FS_FILE * fs_file)
{

    RES_DESCRIPTOR *result = NULL;
    RES_DESCRIPTOR *last = NULL;
    TSK_FS_INFO *fs_info;
    hfs_fork *fork_info;
    hfs_fork *resForkInfo;
    uint64_t resSize;
    const TSK_FS_ATTR *rAttr;
    hfs_resource_fork_header rfHeader;
    hfs_resource_fork_header *resHead;
    uint32_t dataOffset;
    uint32_t mapOffset;
    uint32_t mapLength;
    char *map;
    int attrReadResult;
    int attrReadResult1;
    int attrReadResult2;
    hfs_resource_fork_map_header *mapHdr;
    uint16_t typeListOffset;
    uint16_t nameListOffset;
    unsigned char hasNameList;
    char *nameListBegin = NULL;
    hfs_resource_type_list *typeList;
    uint16_t numTypes;
    hfs_resource_type_list_item *tlItem;
    int mindx;                  // index for looping over resource types

    if (fs_file == NULL) {
        error_detected(TSK_ERR_FS_ARG,
            "hfs_parse_resource_fork: null fs_file");
        return NULL;
    }


    if (fs_file->meta == NULL) {
        error_detected(TSK_ERR_FS_ARG,
            "hfs_parse_resource_fork: fs_file has null metadata");
        return NULL;
    }

    if (fs_file->meta->content_ptr == NULL) {
        if (tsk_verbose)
            fprintf(stderr,
                "hfs_parse_resource_fork: fs_file has null fork data structures, so no resources.\n");
        return NULL;
    }

    // Extract the fs
    fs_info = fs_file->fs_info;
    if (fs_info == NULL) {
        error_detected(TSK_ERR_FS_ARG,
            "hfs_parse_resource_fork: null fs within fs_info");
        return NULL;
    }

    // Try to look at the Resource Fork for an HFS+ file
    // Should be able to cast this to hfs_fork *
    fork_info = (hfs_fork *) fs_file->meta->content_ptr;        // The data fork
    // The resource fork is the second one.
    resForkInfo = &fork_info[1];
    resSize = tsk_getu64(fs_info->endian, resForkInfo->logic_sz);
    //uint32_t numBlocks = tsk_getu32(fs_info->endian, resForkInfo->total_blk);
    //uint32_t clmpSize = tsk_getu32(fs_info->endian, resForkInfo->clmp_sz);

    // Hmm, certainly no resources here!
    if (resSize == 0) {
        return NULL;
    }

    // OK, resource size must be > 0

    // find the attribute for the resource fork
    rAttr =
        tsk_fs_file_attr_get_type(fs_file, TSK_FS_ATTR_TYPE_HFS_RSRC,
        HFS_FS_ATTR_ID_RSRC, TRUE);


    if (rAttr == NULL) {
        error_returned
            ("hfs_parse_resource_fork: could not get the resource fork attribute");
        return NULL;
    }

    // JUST read the resource fork header


    attrReadResult1 =
        tsk_fs_attr_read(rAttr, 0, (char *) &rfHeader,
        sizeof(hfs_resource_fork_header), TSK_FS_FILE_READ_FLAG_NONE);

    if (attrReadResult1 < 0
        || attrReadResult1 != sizeof(hfs_resource_fork_header)) {
        error_returned
            (" hfs_parse_resource_fork: trying to read the resource fork header");
        return NULL;
    }

    // Begin to parse the resource fork
    resHead = &rfHeader;
    dataOffset = tsk_getu32(fs_info->endian, resHead->dataOffset);
    mapOffset = tsk_getu32(fs_info->endian, resHead->mapOffset);
    //uint32_t dataLength = tsk_getu32(fs_info->endian, resHead->dataLength);
    mapLength = tsk_getu32(fs_info->endian, resHead->mapLength);

    // Read in the WHOLE map
    map = (char *) tsk_malloc(mapLength);
    if (map == NULL) {
        error_returned
            ("- hfs_parse_resource_fork: could not allocate space for the resource fork map");
        return NULL;
    }

    attrReadResult =
        tsk_fs_attr_read(rAttr, (uint64_t) mapOffset, map,
        (size_t) mapLength, TSK_FS_FILE_READ_FLAG_NONE);

    if (attrReadResult < 0 || attrReadResult != mapLength) {
        error_returned
            ("- hfs_parse_resource_fork: could not read the map");
        free(map);
        return NULL;
    }

    mapHdr = (hfs_resource_fork_map_header *) map;

    typeListOffset = tsk_getu16(fs_info->endian, mapHdr->typeListOffset);

    nameListOffset = tsk_getu16(fs_info->endian, mapHdr->nameListOffset);

    if (nameListOffset >= mapLength || nameListOffset == 0) {
        hasNameList = FALSE;
    }
    else {
        hasNameList = TRUE;
        nameListBegin = map + nameListOffset;
    }

    typeList = (hfs_resource_type_list *) (map + typeListOffset);
    numTypes = tsk_getu16(fs_info->endian, typeList->typeCount) + 1;

    for (mindx = 0; mindx < numTypes; ++mindx) {
        uint16_t numRes;
        uint16_t refOff;
        int pindx;              // index for looping over resources
        uint16_t rID;
        uint32_t rOffset;

        tlItem = &(typeList->type[mindx]);
        numRes = tsk_getu16(fs_info->endian, tlItem->count) + 1;
        refOff = tsk_getu16(fs_info->endian, tlItem->offset);


        for (pindx = 0; pindx < numRes; ++pindx) {
            int16_t nameOffset;
            char *nameBuffer;
            RES_DESCRIPTOR *rsrc;
            char lenBuff[4];    // first 4 bytes of a resource encodes its length
            uint32_t rLen;      // Resource length

            hfs_resource_refListItem *item =
                ((hfs_resource_refListItem *) (((uint8_t *) typeList) +
                    refOff)) + pindx;
            nameOffset = tsk_gets16(fs_info->endian, item->resNameOffset);
            nameBuffer = NULL;

            if (hasNameList && nameOffset != -1) {
                char *name = nameListBegin + nameOffset;
                uint8_t nameLen = (uint8_t) name[0];
                nameBuffer = tsk_malloc(nameLen + 1);
                if (nameBuffer == NULL) {
                    error_returned
                        ("hfs_parse_resource_fork: allocating space for the name of a resource");
                    free_res_descriptor(result);
                    return NULL;
                }
                memcpy(nameBuffer, name + 1, nameLen);
                nameBuffer[nameLen] = (char) 0;
            }
            else {
                nameBuffer = tsk_malloc(7);
                if (nameBuffer == NULL) {
                    error_returned
                        ("hfs_parse_resource_fork: allocating space for the (null) name of a resource");
                    free_res_descriptor(result);
                    return NULL;
                }
                memcpy(nameBuffer, "<none>", 6);
                nameBuffer[6] = (char) 0;
            }

            rsrc = (RES_DESCRIPTOR *) tsk_malloc(sizeof(RES_DESCRIPTOR));
            if (rsrc == NULL) {
                error_returned
                    ("hfs_parse_resource_fork: space for a resource descriptor");
                free_res_descriptor(result);
                return NULL;
            }

            // Build the linked list
            if (result == NULL)
                result = rsrc;
            if (last != NULL)
                last->next = rsrc;
            last = rsrc;
            rsrc->next = NULL;

            rID = tsk_getu16(fs_info->endian, item->resID);
            rOffset =
                tsk_getu24(fs_info->endian,
                item->resDataOffset) + dataOffset;

            // Just read the first four bytes of the resource to get its length.  It MUST
            // be at least 4 bytes long
            attrReadResult2 = tsk_fs_attr_read(rAttr, (uint64_t) rOffset,
                lenBuff, (size_t) 4, TSK_FS_FILE_READ_FLAG_NONE);

            if (attrReadResult2 != 4) {
                error_returned
                    ("- hfs_parse_resource_fork: could not read the 4-byte length at beginning of resource");
                free_res_descriptor(result);
                return NULL;
            }
            rLen = tsk_getu32(TSK_BIG_ENDIAN, lenBuff); //TODO

            rsrc->id = rID;
            rsrc->offset = rOffset + 4;
            memcpy(rsrc->type, tlItem->type, 4);
            rsrc->type[4] = (char) 0;
            rsrc->length = rLen;
            rsrc->name = nameBuffer;

        }                       // END loop over resources of one type

    }                           // END loop over resource types

    return result;
}