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;

                                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;

                                        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, ZMAllocIdent(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;

                        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 = ZMAllocIdent(fbuf);
                                tmph->user_data1 = size;
                        }
                        else
                                HashRemDel(tmph, sys_task->hash_table);
                }
                else if (attr & RS_ATTR_RESIDENT)
                        HashGenericAdd(absname, HTT_FILE, ZMAllocIdent(fbuf), size, 0, sys_task);
                DirContextDel(dirc);
        }
        Free(absname);

        return c;
}