#ifndef INCLUDE_FILESYSTEM_H #define INCLUDE_FILESYSTEM_H #print "[include ]\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