<commit_before>#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <sys/dirent.h>
#include <sys/iosupport.h>
#include <sys/param.h>
#include <unistd.h>

#include "runtime/devices/romfs_dev.h"
#include "runtime/devices/fs_dev.h"
#include "runtime/util/utf.h"
#include "services/fs.h"
#include "runtime/env.h"
#include "nro.h"

typedef enum {
    RomfsSource_FsFile,
    RomfsSource_FsStorage,
} RomfsSource;

typedef struct romfs_mount
{
    devoptab_t         device;
    bool               setup;
    RomfsSource        fd_type;
    s32                id;
    FsFile             fd;
    FsStorage          fd_storage;
    time_t             mtime;
    u64                offset;
    romfs_header       header;
    romfs_dir          *cwd;
    u32                *dirHashTable, *fileHashTable;
    void               *dirTable, *fileTable;
    char               name[32];
} romfs_mount;

extern int __system_argc;
extern char** __system_argv;

static char __thread __component[PATH_MAX+1];

#define romFS_root(m)   ((romfs_dir*)(m)->dirTable)
#define romFS_dir(m,x)  ((romfs_dir*) ((u8*)(m)->dirTable  + (x)))
#define romFS_file(m,x) ((romfs_file*)((u8*)(m)->fileTable + (x)))
#define romFS_none      ((u32)~0)
#define romFS_dir_mode  (S_IFDIR | S_IRUSR | S_IRGRP | S_IROTH)
#define romFS_file_mode (S_IFREG | S_IRUSR | S_IRGRP | S_IROTH)

static ssize_t _romfs_read(romfs_mount *mount, u64 offset, void* buffer, u64 size)
{
    u64 pos = mount->offset + offset;
    size_t read = 0;
    Result rc = 0;
    if(mount->fd_type == RomfsSource_FsFile)
    {
        rc = fsFileRead(&mount->fd, pos, buffer, size, &read);
    }
    else if(mount->fd_type == RomfsSource_FsStorage)
    {
        rc = fsStorageRead(&mount->fd_storage, pos, buffer, size);
        read = size;
    }
    if (R_FAILED(rc)) return -1;
    return read;
}

static bool _romfs_read_chk(romfs_mount *mount, u64 offset, void* buffer, u64 size)
{
    return _romfs_read(mount, offset, buffer, size) == size;
}

//-----------------------------------------------------------------------------

static int       romfs_open(struct _reent *r, void *fileStruct, const char *path, int flags, int mode);
static int       romfs_close(struct _reent *r, void *fd);
static ssize_t   romfs_read(struct _reent *r, void *fd, char *ptr, size_t len);
static off_t     romfs_seek(struct _reent *r, void *fd, off_t pos, int dir);
static int       romfs_fstat(struct _reent *r, void *fd, struct stat *st);
static int       romfs_stat(struct _reent *r, const char *path, struct stat *st);
static int       romfs_chdir(struct _reent *r, const char *path);
static DIR_ITER* romfs_diropen(struct _reent *r, DIR_ITER *dirState, const char *path);
static int       romfs_dirreset(struct _reent *r, DIR_ITER *dirState);
static int       romfs_dirnext(struct _reent *r, DIR_ITER *dirState, char *filename, struct stat *filestat);
static int       romfs_dirclose(struct _reent *r, DIR_ITER *dirState);

typedef struct
{
    romfs_mount *mount;
    romfs_file  *file;
    u64         offset, pos;
} romfs_fileobj;

typedef struct
{
    romfs_mount *mount;
    romfs_dir* dir;
    u32        state;
    u32        childDir;
    u32        childFile;
} romfs_diriter;

static devoptab_t romFS_devoptab =
{
    .structSize   = sizeof(romfs_fileobj),
    .open_r       = romfs_open,
    .close_r      = romfs_close,
    .read_r       = romfs_read,
    .seek_r       = romfs_seek,
    .fstat_r      = romfs_fstat,
    .stat_r       = romfs_stat,
    .chdir_r      = romfs_chdir,
    .dirStateSize = sizeof(romfs_diriter),
    .diropen_r    = romfs_diropen,
    .dirreset_r   = romfs_dirreset,
    .dirnext_r    = romfs_dirnext,
    .dirclose_r   = romfs_dirclose,
};

static bool romfs_initialised = false;
static romfs_mount romfs_mounts[32];

//-----------------------------------------------------------------------------

static Result romfsMountCommon(const char *name, romfs_mount *mount);
static void romfsInitMtime(romfs_mount *mount);

static void _romfsResetMount(romfs_mount *mount, s32 id) {
    memset(mount, 0, sizeof(*mount));
    memcpy(&mount->device, &romFS_devoptab, sizeof(romFS_devoptab));
    mount->device.name = mount->name;
    mount->device.deviceData = mount;
    mount->id = id;
}

static void _romfsInit(void)
{
    u32 i;
    u32 total = sizeof(romfs_mounts) / sizeof(romfs_mount);

    if(!romfs_initialised)
    {
        for(i = 0; i < total; i++)
        {
            _romfsResetMount(&romfs_mounts[i], i);
        }

        romfs_initialised = true;
    }
}

static romfs_mount *romfsFindMount(const char *name)
{
    u32 i;
    u32 total = sizeof(romfs_mounts) / sizeof(romfs_mount);
    romfs_mount *mount = NULL;

    _romfsInit();

    for(i=0; i<total; i++)
    {
        mount = &romfs_mounts[i];

        if(name==NULL) //Find an unused mount entry.
        {
            if(!mount->setup)
                return mount;
        }
        else if(mount->setup) //Find the mount with the input name.
        {
            if(strncmp(mount->name, name, strlen(mount->name))==0)
                return mount;
        }
    }

    return NULL;
}

__attribute__((weak)) const char* __romfs_path = NULL;

static romfs_mount* romfs_alloc(void)
{
    return romfsFindMount(NULL);
}

static void romfs_free(romfs_mount *mount)
{
    free(mount->fileTable);
    free(mount->fileHashTable);
    free(mount->dirTable);
    free(mount->dirHashTable);
    _romfsResetMount(mount, mount->id);
}

static void romfs_mountclose(romfs_mount *mount)
{
    if(mount->fd_type == RomfsSource_FsFile)fsFileClose(&mount->fd);
    if(mount->fd_type == RomfsSource_FsStorage)fsStorageClose(&mount->fd_storage);
    romfs_free(mount);
}

Result romfsMount(const char *name)
{
    romfs_mount *mount = romfs_alloc();
    if(mount == NULL)
        return 99;

    if (!envIsNso())
    {
        // RomFS embedded in a NRO

        mount->fd_type = RomfsSource_FsFile;

        FsFileSystem *sdfs = fsdevGetDefaultFileSystem();
        if(sdfs==NULL)
        {
            romfs_free(mount);
            return 1;
        }

        const char* filename = __romfs_path;
        if (__system_argc > 0 && __system_argv[0])
            filename = __system_argv[0];
        if (!filename)
        {
            romfs_free(mount);
            return 1;
        }

        if (strncmp(filename, "sdmc:/", 6) == 0)
            filename += 5;
        else if (strncmp(filename, "nxlink:/", 8) == 0)
        {
            strncpy(__component, "/switch",     PATH_MAX);
            strncat(__component, filename+7, PATH_MAX);
            __component[PATH_MAX] = 0;
            filename = __component;
        }
        else
        {
            romfs_free(mount);
            return 2;
        }

        Result rc = fsFsOpenFile(sdfs, filename, FS_OPEN_READ, &mount->fd);
        if (R_FAILED(rc))
        {
            romfs_free(mount);
            return rc;
        }

        romfsInitMtime(mount);

        NroHeader hdr;
        NroAssetHeader asset_header;

        if (!_romfs_read_chk(mount, sizeof(NroStart), &hdr, sizeof(hdr))) goto _fail0;
        if (hdr.magic != NROHEADER_MAGIC) goto _fail0;
        if (!_romfs_read_chk(mount, hdr.size, &asset_header, sizeof(asset_header))) goto _fail0;

        if (asset_header.magic != NROASSETHEADER_MAGIC
            || asset_header.version > NROASSETHEADER_VERSION
            || asset_header.romfs.offset == 0
            || asset_header.romfs.size == 0)
        goto _fail0;

        mount->offset = hdr.size + asset_header.romfs.offset;
    }
    else
    {
        // Regular RomFS

        mount->fd_type = RomfsSource_FsStorage;

        Result rc = fsOpenDataStorageByCurrentProcess(&mount->fd_storage);
        if (R_FAILED(rc))
        {
            romfs_free(mount);
            return rc;
        }

        romfsInitMtime(mount);
    }

    return romfsMountCommon(name, mount);

_fail0:
    romfs_mountclose(mount);
    return 10;
}

Result romfsMountFromFile(FsFile file, u64 offset, const char *name)
{
    romfs_mount *mount = romfs_alloc();
    if(mount == NULL)
        return 99;

    mount->fd_type = RomfsSource_FsFile;
    mount->fd     = file;
    mount->offset = offset;

    return romfsMountCommon(name, mount);
}

Result romfsMountFromStorage(FsStorage storage, u64 offset, const char *name)
{
    romfs_mount *mount = romfs_alloc();
    if(mount == NULL)
        return 99;

    mount->fd_type = RomfsSource_FsStorage;
    mount->fd_storage = storage;
    mount->offset = offset;

    return romfsMountCommon(name, mount);
}

Result romfsMountFromFsdev(const char *path, u64 offset, const char *name)
{
    FsFileSystem *tmpfs = NULL;
    char filepath[FS_MAX_PATH];

    memset(filepath, 0, sizeof(filepath));

    if(fsdevTranslatePath(path, &tmpfs, filepath)==-1)
        return MAKERESULT(Module_Libnx, LibnxError_BadInput);

    romfs_mount *mount = romfs_alloc();
    if(mount == NULL)
        return 99;

    mount->fd_type = RomfsSource_FsFile;
    mount->offset = offset;

    Result rc = fsFsOpenFile(tmpfs, filepath, FS_OPEN_READ, &mount->fd);
    if (R_FAILED(rc))
    {
        romfs_free(mount);
        return rc;
    }

    return romfsMountCommon(name, mount);
}

Result romfsMountFromDataArchive(u64 dataId, FsStorageId storageId, const char *name) {
    FsStorage storage;

    Result rc = fsOpenDataStorageByDataId(&storage, dataId, storageId);
    if (R_FAILED(rc))
        return rc;

    return romfsMountFromStorage(storage, 0, name);
}

Result romfsMountCommon(const char *name, romfs_mount *mount)
{
    memset(mount->name, 0, sizeof(mount->name));
    strncpy(mount->name, name, sizeof(mount->name)-1);

    if (_romfs_read(mount, 0, &mount->header, sizeof(mount->header)) != sizeof(mount->header))
        goto fail;

    mount->dirHashTable = (u32*)malloc(mount->header.dirHashTableSize);
    if (!mount->dirHashTable)
        goto fail;
    if (!_romfs_read_chk(mount, mount->header.dirHashTableOff, mount->dirHashTable, mount->header.dirHashTableSize))
        goto fail;

    mount->dirTable = malloc(mount->header.dirTableSize);
    if (!mount->dirTable)
        goto fail;
    if (!_romfs_read_chk(mount, mount->header.dirTableOff, mount->dirTable, mount->header.dirTableSize))
        goto fail;

    mount->fileHashTable = (u32*)malloc(mount->header.fileHashTableSize);
    if (!mount->fileHashTable)
        goto fail;
    if (!_romfs_read_chk(mount, mount->header.fileHashTableOff, mount->fileHashTable, mount->header.fileHashTableSize))
        goto fail;

    mount->fileTable = malloc(mount->header.fileTableSize);
    if (!mount->fileTable)
        goto fail;
    if (!_romfs_read_chk(mount, mount->header.fileTableOff, mount->fileTable, mount->header.fileTableSize))
        goto fail;

    mount->cwd = romFS_root(mount);

    // add device if this is the first one
    if(AddDevice(&mount->device) < 0)
        goto fail;

    return 0;

fail:
    romfs_mountclose(mount);
    return 10;<commit_msg>romfs_dev: fix unmounting/corruption when mounting multiple.<commit_after>#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <sys/dirent.h>
#include <sys/iosupport.h>
#include <sys/param.h>
#include <unistd.h>

#include "runtime/devices/romfs_dev.h"
#include "runtime/devices/fs_dev.h"
#include "runtime/util/utf.h"
#include "services/fs.h"
#include "runtime/env.h"
#include "nro.h"

typedef enum {
    RomfsSource_FsFile,
    RomfsSource_FsStorage,
} RomfsSource;

typedef struct romfs_mount
{
    devoptab_t         device;
    bool               setup;
    RomfsSource        fd_type;
    s32                id;
    FsFile             fd;
    FsStorage          fd_storage;
    time_t             mtime;
    u64                offset;
    romfs_header       header;
    romfs_dir          *cwd;
    u32                *dirHashTable, *fileHashTable;
    void               *dirTable, *fileTable;
    char               name[32];
} romfs_mount;

extern int __system_argc;
extern char** __system_argv;

static char __thread __component[PATH_MAX+1];

#define romFS_root(m)   ((romfs_dir*)(m)->dirTable)
#define romFS_dir(m,x)  ((romfs_dir*) ((u8*)(m)->dirTable  + (x)))
#define romFS_file(m,x) ((romfs_file*)((u8*)(m)->fileTable + (x)))
#define romFS_none      ((u32)~0)
#define romFS_dir_mode  (S_IFDIR | S_IRUSR | S_IRGRP | S_IROTH)
#define romFS_file_mode (S_IFREG | S_IRUSR | S_IRGRP | S_IROTH)

static ssize_t _romfs_read(romfs_mount *mount, u64 offset, void* buffer, u64 size)
{
    u64 pos = mount->offset + offset;
    size_t read = 0;
    Result rc = 0;
    if(mount->fd_type == RomfsSource_FsFile)
    {
        rc = fsFileRead(&mount->fd, pos, buffer, size, &read);
    }
    else if(mount->fd_type == RomfsSource_FsStorage)
    {
        rc = fsStorageRead(&mount->fd_storage, pos, buffer, size);
        read = size;
    }
    if (R_FAILED(rc)) return -1;
    return read;
}

static bool _romfs_read_chk(romfs_mount *mount, u64 offset, void* buffer, u64 size)
{
    return _romfs_read(mount, offset, buffer, size) == size;
}

//-----------------------------------------------------------------------------

static int       romfs_open(struct _reent *r, void *fileStruct, const char *path, int flags, int mode);
static int       romfs_close(struct _reent *r, void *fd);
static ssize_t   romfs_read(struct _reent *r, void *fd, char *ptr, size_t len);
static off_t     romfs_seek(struct _reent *r, void *fd, off_t pos, int dir);
static int       romfs_fstat(struct _reent *r, void *fd, struct stat *st);
static int       romfs_stat(struct _reent *r, const char *path, struct stat *st);
static int       romfs_chdir(struct _reent *r, const char *path);
static DIR_ITER* romfs_diropen(struct _reent *r, DIR_ITER *dirState, const char *path);
static int       romfs_dirreset(struct _reent *r, DIR_ITER *dirState);
static int       romfs_dirnext(struct _reent *r, DIR_ITER *dirState, char *filename, struct stat *filestat);
static int       romfs_dirclose(struct _reent *r, DIR_ITER *dirState);

typedef struct
{
    romfs_mount *mount;
    romfs_file  *file;
    u64         offset, pos;
} romfs_fileobj;

typedef struct
{
    romfs_mount *mount;
    romfs_dir* dir;
    u32        state;
    u32        childDir;
    u32        childFile;
} romfs_diriter;

static devoptab_t romFS_devoptab =
{
    .structSize   = sizeof(romfs_fileobj),
    .open_r       = romfs_open,
    .close_r      = romfs_close,
    .read_r       = romfs_read,
    .seek_r       = romfs_seek,
    .fstat_r      = romfs_fstat,
    .stat_r       = romfs_stat,
    .chdir_r      = romfs_chdir,
    .dirStateSize = sizeof(romfs_diriter),
    .diropen_r    = romfs_diropen,
    .dirreset_r   = romfs_dirreset,
    .dirnext_r    = romfs_dirnext,
    .dirclose_r   = romfs_dirclose,
};

static bool romfs_initialised = false;
static romfs_mount romfs_mounts[32];

//-----------------------------------------------------------------------------

static Result romfsMountCommon(const char *name, romfs_mount *mount);
static void romfsInitMtime(romfs_mount *mount);

static void _romfsResetMount(romfs_mount *mount, s32 id) {
    memset(mount, 0, sizeof(*mount));
    memcpy(&mount->device, &romFS_devoptab, sizeof(romFS_devoptab));
    mount->device.name = mount->name;
    mount->device.deviceData = mount;
    mount->id = id;
}

static void _romfsInit(void)
{
    u32 i;
    u32 total = sizeof(romfs_mounts) / sizeof(romfs_mount);

    if(!romfs_initialised)
    {
        for(i = 0; i < total; i++)
        {
            _romfsResetMount(&romfs_mounts[i], i);
        }

        romfs_initialised = true;
    }
}

static romfs_mount *romfsFindMount(const char *name)
{
    u32 i;
    u32 total = sizeof(romfs_mounts) / sizeof(romfs_mount);
    romfs_mount *mount = NULL;

    _romfsInit();

    for(i=0; i<total; i++)
    {
        mount = &romfs_mounts[i];

        if(name==NULL) //Find an unused mount entry.
        {
            if(!mount->setup)
                return mount;
        }
        else if(mount->setup) //Find the mount with the input name.
        {
            if(strncmp(mount->name, name, strlen(mount->name))==0)
                return mount;
        }
    }

    return NULL;
}

__attribute__((weak)) const char* __romfs_path = NULL;

static romfs_mount* romfs_alloc(void)
{
    return romfsFindMount(NULL);
}

static void romfs_free(romfs_mount *mount)
{
    free(mount->fileTable);
    free(mount->fileHashTable);
    free(mount->dirTable);
    free(mount->dirHashTable);
    _romfsResetMount(mount, mount->id);
}

static void romfs_mountclose(romfs_mount *mount)
{
    if(mount->fd_type == RomfsSource_FsFile)fsFileClose(&mount->fd);
    if(mount->fd_type == RomfsSource_FsStorage)fsStorageClose(&mount->fd_storage);
    romfs_free(mount);
}

Result romfsMount(const char *name)
{
    romfs_mount *mount = romfs_alloc();
    if(mount == NULL)
        return 99;

    if (!envIsNso())
    {
        // RomFS embedded in a NRO

        mount->fd_type = RomfsSource_FsFile;

        FsFileSystem *sdfs = fsdevGetDefaultFileSystem();
        if(sdfs==NULL)
        {
            romfs_free(mount);
            return 1;
        }

        const char* filename = __romfs_path;
        if (__system_argc > 0 && __system_argv[0])
            filename = __system_argv[0];
        if (!filename)
        {
            romfs_free(mount);
            return 1;
        }

        if (strncmp(filename, "sdmc:/", 6) == 0)
            filename += 5;
        else if (strncmp(filename, "nxlink:/", 8) == 0)
        {
            strncpy(__component, "/switch",     PATH_MAX);
            strncat(__component, filename+7, PATH_MAX);
            __component[PATH_MAX] = 0;
            filename = __component;
        }
        else
        {
            romfs_free(mount);
            return 2;
        }

        Result rc = fsFsOpenFile(sdfs, filename, FS_OPEN_READ, &mount->fd);
        if (R_FAILED(rc))
        {
            romfs_free(mount);
            return rc;
        }

        romfsInitMtime(mount);

        NroHeader hdr;
        NroAssetHeader asset_header;

        if (!_romfs_read_chk(mount, sizeof(NroStart), &hdr, sizeof(hdr))) goto _fail0;
        if (hdr.magic != NROHEADER_MAGIC) goto _fail0;
        if (!_romfs_read_chk(mount, hdr.size, &asset_header, sizeof(asset_header))) goto _fail0;

        if (asset_header.magic != NROASSETHEADER_MAGIC
            || asset_header.version > NROASSETHEADER_VERSION
            || asset_header.romfs.offset == 0
            || asset_header.romfs.size == 0)
        goto _fail0;

        mount->offset = hdr.size + asset_header.romfs.offset;
    }
    else
    {
        // Regular RomFS

        mount->fd_type = RomfsSource_FsStorage;

        Result rc = fsOpenDataStorageByCurrentProcess(&mount->fd_storage);
        if (R_FAILED(rc))
        {
            romfs_free(mount);
            return rc;
        }

        romfsInitMtime(mount);
    }

    return romfsMountCommon(name, mount);

_fail0:
    romfs_mountclose(mount);
    return 10;
}

Result romfsMountFromFile(FsFile file, u64 offset, const char *name)
{
    romfs_mount *mount = romfs_alloc();
    if(mount == NULL)
        return 99;

    mount->fd_type = RomfsSource_FsFile;
    mount->fd     = file;
    mount->offset = offset;

    return romfsMountCommon(name, mount);
}

Result romfsMountFromStorage(FsStorage storage, u64 offset, const char *name)
{
    romfs_mount *mount = romfs_alloc();
    if(mount == NULL)
        return 99;

    mount->fd_type = RomfsSource_FsStorage;
    mount->fd_storage = storage;
    mount->offset = offset;

    return romfsMountCommon(name, mount);
}

Result romfsMountFromFsdev(const char *path, u64 offset, const char *name)
{
    FsFileSystem *tmpfs = NULL;
    char filepath[FS_MAX_PATH];

    memset(filepath, 0, sizeof(filepath));

    if(fsdevTranslatePath(path, &tmpfs, filepath)==-1)
        return MAKERESULT(Module_Libnx, LibnxError_BadInput);

    romfs_mount *mount = romfs_alloc();
    if(mount == NULL)
        return 99;

    mount->fd_type = RomfsSource_FsFile;
    mount->offset = offset;

    Result rc = fsFsOpenFile(tmpfs, filepath, FS_OPEN_READ, &mount->fd);
    if (R_FAILED(rc))
    {
        romfs_free(mount);
        return rc;
    }

    return romfsMountCommon(name, mount);
}

Result romfsMountFromDataArchive(u64 dataId, FsStorageId storageId, const char *name) {
    FsStorage storage;

    Result rc = fsOpenDataStorageByDataId(&storage, dataId, storageId);
    if (R_FAILED(rc))
        return rc;

    return romfsMountFromStorage(storage, 0, name);
}

Result romfsMountCommon(const char *name, romfs_mount *mount)
{
    memset(mount->name, 0, sizeof(mount->name));
    strncpy(mount->name, name, sizeof(mount->name)-1);

    if (_romfs_read(mount, 0, &mount->header, sizeof(mount->header)) != sizeof(mount->header))
        goto fail;

    mount->dirHashTable = (u32*)malloc(mount->header.dirHashTableSize);
    if (!mount->dirHashTable)
        goto fail;
    if (!_romfs_read_chk(mount, mount->header.dirHashTableOff, mount->dirHashTable, mount->header.dirHashTableSize))
        goto fail;

    mount->dirTable = malloc(mount->header.dirTableSize);
    if (!mount->dirTable)
        goto fail;
    if (!_romfs_read_chk(mount, mount->header.dirTableOff, mount->dirTable, mount->header.dirTableSize))
        goto fail;

    mount->fileHashTable = (u32*)malloc(mount->header.fileHashTableSize);
    if (!mount->fileHashTable)
        goto fail;
    if (!_romfs_read_chk(mount, mount->header.fileHashTableOff, mount->fileHashTable, mount->header.fileHashTableSize))
        goto fail;

    mount->fileTable = malloc(mount->header.fileTableSize);
    if (!mount->fileTable)
        goto fail;
    if (!_romfs_read_chk(mount, mount->header.fileTableOff, mount->fileTable, mount->header.fileTableSize))
        goto fail;

    mount->cwd = romFS_root(mount);

    // add device if this is the first one
    if(AddDevice(&mount->device) < 0)
        goto fail;

    mount->setup = true;
    return 0;

fail:
    romfs_mountclose(mount);
    return 10;
{'fraction_non_alphanumeric': 0.1307080206166923, 'fraction_numerical': 0.009313681164662265, 'mean_word_length': 2.60009765625, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 172, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4212680', 'n_tokens_mistral': 7764, 'n_tokens_neox': 7483, 'n_words': 1612}