kolibrios/programs/cmm/lib/fs.h
Kirill Lipatov (Leency) 684ee81f3e Eolite: show correct size in bytes in Properties dialog (thanks Mario for the code snippet)
git-svn-id: svn://kolibrios.org@9693 a494cfbc-eb01-0410-851d-a64ba20cac60
2022-02-06 23:16:38 +00:00

543 lines
11 KiB
C

#ifndef INCLUDE_FILESYSTEM_H
#define INCLUDE_FILESYSTEM_H
#print "[include <fs.h>]\n"
#ifndef INCLUDE_DATE_H
#include "../lib/date.h"
#endif
#ifndef INCLUDE_COLLECTION_H
#include "../lib/collection.h"
#endif
#define PATHLEN 4096
//===================================================//
// //
// Basic System Functions //
// //
//===================================================//
:struct F70{
dword func;
dword param1;
dword param2;
dword param3;
dword param4;
char rezerv;
dword name;
} f70;
:struct BDVK {
dword readonly:1, hidden:1, system:1, volume_label:1, isfolder:1, notarchived:1, :0;
byte type_name, rez1, rez2, selected; //name encoding
time timecreate; //+8
date datecreate;
time timelastaccess;
date datelastaccess;
time timelastedit;
date datelastedit;
dword sizelo;
dword sizehi;
char name[520];
};
#define ATR_READONLY 1
#define ATR_HIDDEN 2
#define ATR_SYSTEM 4
#define ATR_VOL_LABEL 8
#define ATR_FOLDER 0x10
#define ATR_NONARH 0x20
:dword GetFileInfo(dword file_path, bdvk_struct)
{
f70.func = 5;
f70.param1 =
f70.param2 =
f70.param3 = 0;
f70.param4 = bdvk_struct;
f70.rezerv = 0;
f70.name = file_path;
$mov eax,70
$mov ebx,#f70.func
$int 0x40
}
:dword GetVolumeLabel(dword _path)
{
BDVK bdvk;
//if (ESBYTE[_path+1]=='k') || (ESBYTE[_path+2]=='y') return NULL;
f70.func = 5;
f70.param1 = 0;
f70.param2 = 1;
f70.param3 = 1;
f70.param4 = #bdvk;
f70.rezerv = 0;
f70.name = _path;
$mov eax,70
$mov ebx,#f70.func
$int 0x40
return #bdvk.name;
}
:dword SetFileInfo(dword file_path, bdvk_struct)
{
f70.func = 6;
f70.param1 =
f70.param2 =
f70.param3 = 0;
f70.param4 = bdvk_struct;
f70.rezerv = 0;
f70.name = file_path;
$mov eax,70
$mov ebx,#f70.func
$int 0x40
}
:signed int RunProgram(dword run_path, run_param)
{
f70.func = 7;
f70.param1 =
f70.param3 =
f70.param4 =
f70.rezerv = 0;
f70.param2 = run_param;
f70.name = run_path;
$mov eax,70
$mov ebx,#f70.func
$int 0x40
}
:int CreateDir(dword new_folder_path)
{
f70.func = 9;
f70.param1 =
f70.param2 =
f70.param3 =
f70.param4 =
f70.rezerv = 0;
f70.name = new_folder_path;
$mov eax,70
$mov ebx,#f70.func
$int 0x40
}
:int DeleteFile(dword del_file_path)
{
f70.func = 8;
f70.param1 =
f70.param2 =
f70.param3 =
f70.param4 =
f70.rezerv = 0;
f70.name = del_file_path;
$mov eax,70
$mov ebx,#f70.func
$int 0x40
}
:int ReadFile(dword offset, data_size, buffer, file_path)
{
f70.func = 0;
f70.param1 = offset;
f70.param2 = 0;
f70.param3 = data_size;
f70.param4 = buffer;
f70.rezerv = 0;
f70.name = file_path;
$mov eax,70
$mov ebx,#f70.func
$int 0x40
}
:int CreateFile(dword data_size, buffer, file_path)
{
f70.func = 2;
f70.param1 = 0;
f70.param2 = 0;
f70.param3 = data_size;
f70.param4 = buffer;
f70.rezerv = 0;
f70.name = file_path;
$mov eax,70
$mov ebx,#f70.func
$int 0x40
}
////////////////////////////////////////
// WriteInFileThatAlredyExists //
////////////////////////////////////////
:int WriteFile(dword offset, data_size, buffer, file_path)
{
f70.func = 3;
f70.param1 = offset;
f70.param2 = 0;
f70.param3 = data_size;
f70.param4 = buffer;
f70.rezerv = 0;
f70.name = file_path;
$mov eax,70
$mov ebx,#f70.func
$int 0x40
}
:int RenameMove(dword path_to, path_from)
{
f70.func = 10;
f70.param1 =
f70.param2 =
f70.param3 = 0;
f70.param4 = path_to;
f70.rezerv = 0;
f70.name = path_from;
$mov eax,70
$mov ebx,#f70.func
$int 0x40
}
:int ReadDir(dword file_count, read_buffer, dir_path)
{
f70.func = 1;
f70.param1 =
f70.param2 =
f70.rezerv = 0;
f70.param3 = file_count;
f70.param4 = read_buffer;
f70.name = dir_path;
$mov eax,70
$mov ebx,#f70.func
$int 0x40
}
//ECX - buf pointer
inline fastcall void SetCurDir( ECX)
{
EAX=30;
EBX=1;
$int 0x40
}
//ECX - buf pointer
//EDX - buf size
inline fastcall void GetCurDir( ECX, EDX)
{
EAX=30;
EBX=2;
$int 0x40
}
:void read_file(dword path1, buf, size)
{
EAX = 68;
EBX = 27;
ECX = path1;
$int 0x40;
ESDWORD[size] = EDX;
ESDWORD[buf] = EAX;
}
//===================================================//
// //
// Misc //
// //
//===================================================//
:bool dir_exists(dword fpath)
{
char buf[32];
if (!ReadDir(0, #buf, fpath)) return true;
return false;
}
:dword get_file_size(dword _path)
{
BDVK bdvk;
if (GetFileInfo(_path, #bdvk)!=0) return 0;
else return bdvk.sizelo;
}
/* This implementation of dir_exists() is faster than
previous but here virtual folders like
'/' and '/tmp' are not recognised as FOLDERS
by GetFileInfo() => BDVK.isfolder attribute :( */
bool real_dir_exists(dword fpath)
{
BDVK fpath_atr;
if (GetFileInfo(fpath, #fpath_atr) != 0) return false;
return fpath_atr.isfolder;
}
:bool file_exists(dword fpath)
{
BDVK ReadFile_atr;
if (! GetFileInfo(fpath, #ReadFile_atr)) return true;
return false;
}
enum
{
DIRS_ALL,
DIRS_NOROOT,
DIRS_ONLYREAL
};
:int GetDir(dword dir_buf, file_count, path, doptions)
dword buf, fcount, error;
char readbuf[32];
{
error = ReadDir(0, #readbuf, path);
if (!error)
{
fcount = ESDWORD[#readbuf+8];
buf = malloc(fcount+1*304+32);
ReadDir(fcount, buf, path);
//fcount=EBX;
if (doptions == DIRS_ONLYREAL)
{
if (!strcmp(".",buf+72)) {fcount--; memmov(buf,buf+304,fcount*304);}
if (!strcmp("..",buf+72)) {fcount--; memmov(buf,buf+304,fcount*304);}
}
if (doptions == DIRS_NOROOT)
{
if (!strcmp(".",buf+72)) {fcount--; memmov(buf,buf+304,fcount*304);}
}
ESDWORD[dir_buf] = buf;
ESDWORD[file_count] = fcount;
}
else
{
ESDWORD[dir_buf] = 0;
ESDWORD[file_count] = 0;
}
return error;
}
:dword abspath(dword relative_path) //GetAbsolutePathFromRelative()
{
char absolute_path[PATHLEN];
if (ESBYTE[relative_path]=='/')
{
strcpy(#absolute_path, relative_path);
}
else
{
strcpy(#absolute_path, I_Path);
absolute_path[strrchr(#absolute_path, '/')] = '\0';
strcat(#absolute_path, relative_path);
}
return #absolute_path;
}
:dword GetIni(dword ini_path, ini_name) //search it on /kolibrios/ then on /sys/
{
strcpy(ini_path, "/kolibrios/settings/");
strcat(ini_path, ini_name);
if (!file_exists(ini_path)) {
strcpy(ini_path, "/sys/SETTINGS/");
strcat(ini_path, ini_name);
}
return ini_path;
}
:dword notify(dword notify_param)
{
return RunProgram("/sys/@notify", notify_param);
}
:void die(dword _last_msg)
{
notify(_last_msg);
ExitProcess();
}
:bool file_name_is_8_3(dword name)
{
strlen(name);
if (EAX>12) return false;
$push eax
strrchr(name, '.');
$pop ebx
//EAX = dot pos
//EBX = name length
if (EAX) {
if (EBX-EAX>3) return false;
} else {
if (EBX>8) return false;
}
return true;
}
//===================================================//
// //
// Convert Size //
// //
//===================================================//
:byte ConvertSize_size_prefix[8];
:dword ConvertSize(dword bytes)
{
byte size_nm[4];
if (bytes>=1073741824) strlcpy(#size_nm, "GB",2);
else if (bytes>=1048576) strlcpy(#size_nm, "MB",2);
else if (bytes>=1024) strlcpy(#size_nm, "KB",2);
else strlcpy(#size_nm, "B ",2);
while (bytes>1023) bytes >>= 10;
sprintf(#ConvertSize_size_prefix,"%d %s",bytes,#size_nm);
return #ConvertSize_size_prefix;
}
:dword ConvertSize64(dword bytes_lo, bytes_hi)
{
if (bytes_hi > 0) {
if (bytes_lo>=1073741824) bytes_lo >>= 30; else bytes_lo = 0;
sprintf(#ConvertSize_size_prefix,"%d GB",bytes_hi<<2 + bytes_lo);
return #ConvertSize_size_prefix;
}
else return ConvertSize(bytes_lo);
}
:unsigned char size[25];
:dword ConvertSizeToKb(unsigned int bytes)
{
dword kb_line;
if (bytes >= 1024)
{
kb_line = itoa(bytes / 1024);
strcpy(#size, kb_line);
strcat(#size, " KB");
}
else {
kb_line = itoa(bytes);
strcpy(#size, kb_line);
strcat(#size, " B");
}
return #size;
}
//===================================================//
// //
// Copy //
// //
//===================================================//
:int CopyFileAtOnce(dword size, copyFrom, copyTo)
dword cbuf;
int error;
{
cbuf = malloc(size);
if (error = ReadFile(0, size, cbuf, copyFrom))
{
debugln("Error: CopyFileAtOnce->ReadFile");
}
else
{
if (error = CreateFile(size, cbuf, copyTo)) debugln("Error: CopyFileAtOnce->CreateFile");
}
free(cbuf);
return error;
}
:int CopyFileByBlocks(dword size, copyFrom, copyTo)
dword cbuf;
int error=-1;
dword offpos=0;
int block_size=1024*1024*4; //copy by 4 MiB
{
if (GetFreeRAM()>1024*78) {
//Set block size 32 MiB
block_size <<= 3;
}
cbuf = malloc(block_size);
if (error = CreateFile(0, 0, copyTo))
{
debugln("Error: CopyFileByBlocks->CreateFile");
size = -1;
}
while(offpos < size)
{
error = ReadFile(offpos, block_size, cbuf, copyFrom);
if (error = 6) { //File ended before last byte was readed
block_size = EBX;
if (block_size+offpos>=size) error=0;
}
else
if (error!=0) {
debugln("Error: CopyFileByBlocks->ReadFile");
break;
}
if (error = WriteFile(offpos, block_size, cbuf, copyTo)) {
debugln("Error: CopyFileByBlocks->WriteFile");
break;
}
offpos += block_size;
}
free(cbuf);
return error;
}
//===================================================//
// //
// Directory Size //
// //
//===================================================//
:struct DIR_SIZE
{
BDVK dir_info;
dword folders;
dword files;
dword sizelo;
dword sizehi;
dword get();
dword calculate_loop();
};
:dword DIR_SIZE::get(dword way1)
{
folders = files = sizelo = sizehi = 0;
if (!way1) return 0;
calculate_loop(way1);
}
:dword DIR_SIZE::calculate_loop(dword way)
{
dword dirbuf, fcount, i, filename;
dword cur_file;
if (!way) return 0;
if (dir_exists(way))
{
cur_file = malloc(PATHLEN);
// In the process of recursive descent, memory must be allocated dynamically,
// because the static memory -> was a bug !!! But unfortunately pass away to sacrifice speed.
GetDir(#dirbuf, #fcount, way, DIRS_ONLYREAL);
for (i=0; i<fcount; i++)
{
filename = i*304+dirbuf+72;
sprintf(cur_file,"%s/%s",way,filename);
if (ESDWORD[filename-40] & ATR_FOLDER )
{
folders++;
calculate_loop(cur_file);
}
else
{
GetFileInfo(cur_file, #dir_info);
sizelo += dir_info.sizelo;
sizehi += dir_info.sizehi;
files++;
}
}
free(cur_file);
free(dirbuf);
}
return files;
}
#endif