U8 *FileRead(U8 *filename, I64 *_size=NULL, I64 *_attr=NULL)
{//Read whole file from disk.
    CHashGeneric    *tmph;
    U8              *absname, *res = NULL;
    I64              size = 0, attr = 0;
    CDirContext     *dirc;

    absname = FileNameAbs(filename);
    if (tmph = HashFind(absname, sys_task->hash_table, HTT_FILE))
    {
        size = tmph->user_data1;
        res = MAlloc(size + 1);
        MemCopy(res, tmph->user_data0, size);
        res[size] = 0; //Terminate
        attr = FileAttr(tmph->str, attr);
    }
    else
    {
        if (dirc = DirContextNew(absname))
        {
            switch (dirc->drive->fs_type)
            {
                case FSt_REDSEA:
                    res = RedSeaFileRead(dirc->drive, Fs->cur_dir, dirc->mask, &size, &attr);
                    break;

                case FSt_FAT32:
                    res = FAT32FileRead(dirc->drive, Fs->cur_dir, dirc->mask, &size, &attr);
                    break;

                case FSt_ISO9660:
                    res = ISOFileRead(dirc->drive, Fs->cur_dir, dirc->mask, &size, &attr);
                    break;

                default:
                    PrintErr("File System Not Supported\n");
            }
            DirContextDel(dirc);
        }
    }

    if (!res)
    {
        if (dirc = DirContextNew(absname))
        {
            while (!res && StrCompare(Fs->cur_dir, "/"))
            {
                Cd("..");
                switch (Fs->cur_dv->fs_type)
                {
                    case FSt_REDSEA:
                        res = RedSeaFileRead(dirc->drive, Fs->cur_dir, dirc->mask, &size, &attr);
                        break;

                    case FSt_FAT32:
                        res = FAT32FileRead(dirc->drive, Fs->cur_dir, dirc->mask, &size, &attr);
                        break;

                    case FSt_ISO9660:
                        res = ISOFileRead(dirc->drive, Fs->cur_dir, dirc->mask, &size, &attr);
                        break;

                    default:
                        PrintErr("File System Not Supported\n");
                }
            }
            DirContextDel(dirc);
        }
    }
    if (!res)
        PrintErr("File not found: \"%s\".\n", filename);
    if (res && attr & RS_ATTR_RESIDENT)
        HashGenericAdd(absname, HTT_FILE, SysMAllocIdent(res), size, 0, sys_task);

    if (_attr)
        *_attr = attr;
    if (_size)
        *_size = size;
    Free(absname);

    return res;
}

I64 FileWrite(U8 *filename, U8 *fbuf, I64 size, CDate cdt=0, I64 attr=0)
{//Write whole file to disk.
    I64              c = 0;
    CHashGeneric    *tmph;
    CDirContext     *dirc;
    U8              *absname = FileNameAbs(filename);

    if (dirc = DirContextNew(filename, FALSE, TRUE))
    {
        attr = FileAttr(dirc->mask, attr);
        if (!cdt)
            cdt = Now;
        switch (dirc->drive->fs_type)
        {
            case FSt_REDSEA:
                c = RedSeaFileWrite(dirc->drive, Fs->cur_dir, dirc->mask, fbuf, size, cdt, attr);
                break;

            case FSt_FAT32:
                c = FAT32FileWrite(dirc->drive, Fs->cur_dir, dirc->mask, fbuf, size, cdt, attr);
                break;

            case FSt_ISO9660:
                PrintErr("File System Not Writable\n");
                break;

            default:
                PrintErr("File System Not Supported\n");
        }
        if (tmph = HashFind(absname, sys_task->hash_table, HTT_FILE))
        {
            if (attr & RS_ATTR_RESIDENT)
            {
                Free(tmph->user_data0);
                tmph->user_data0 = SysMAllocIdent(fbuf);
                tmph->user_data1 = size;
            }
            else
                HashRemDel(tmph, sys_task->hash_table);
        }
        else if (attr & RS_ATTR_RESIDENT)
            HashGenericAdd(absname, HTT_FILE, SysMAllocIdent(fbuf), size, 0, sys_task);
        DirContextDel(dirc);
    }
    Free(absname);

    return c;
}