Subversion Repositories Kolibri OS

Rev

Rev 8946 | Rev 9003 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. #ifndef INCLUDE_FILESYSTEM_H
  2. #define INCLUDE_FILESYSTEM_H
  3. #print "[include <fs.h>]\n"
  4.  
  5. #ifndef INCLUDE_DATE_H
  6. #include "../lib/date.h"
  7. #endif
  8.  
  9. #ifndef INCLUDE_COLLECTION_H
  10. #include "../lib/collection.h"
  11. #endif
  12.  
  13. //===================================================//
  14. //                                                   //
  15. //              Basic System Functions               //
  16. //                                                   //
  17. //===================================================//
  18.  
  19. :struct F70{
  20.         dword   func;
  21.         dword   param1;
  22.         dword   param2;
  23.         dword   param3;
  24.         dword   param4;
  25.         char    rezerv;
  26.         dword   name;
  27. } f70;
  28.  
  29. :struct BDVK {
  30.         dword   readonly:1, hidden:1, system:1, volume_label:1, isfolder:1, notarchived:1, :0;
  31.         byte    type_name;
  32.         byte    rez1, rez2, selected;
  33.         dword   timecreate;
  34.         date    datecreate;
  35.         dword   timelastaccess;
  36.         date    datelastaccess;
  37.         dword   timelastedit;
  38.         date    datelastedit;
  39.         dword   sizelo;
  40.         dword   sizehi;
  41.         char    name[518];
  42. };
  43. #define ATR_READONLY 1
  44. #define ATR_HIDDEN 2
  45. #define ATR_SYSTEM 4
  46. #define ATR_VOL_LABEL 8
  47. #define ATR_FOLDER 0x10
  48. #define ATR_NONARH 0x20
  49.  
  50.  
  51. :dword GetFileInfo(dword file_path, bdvk_struct)
  52. {    
  53.     f70.func = 5;
  54.     f70.param1 =
  55.     f70.param2 =
  56.     f70.param3 = 0;
  57.     f70.param4 = bdvk_struct;
  58.     f70.rezerv = 0;
  59.     f70.name = file_path;
  60.     $mov eax,70
  61.     $mov ebx,#f70.func
  62.     $int 0x40
  63. }
  64.  
  65. :dword SetFileInfo(dword file_path, bdvk_struct)
  66. {    
  67.     f70.func = 6;
  68.     f70.param1 =
  69.     f70.param2 =
  70.     f70.param3 = 0;
  71.     f70.param4 = bdvk_struct;
  72.     f70.rezerv = 0;
  73.     f70.name = file_path;
  74.     $mov eax,70
  75.     $mov ebx,#f70.func
  76.     $int 0x40
  77. }
  78.  
  79. :signed int RunProgram(dword run_path, run_param)
  80. {      
  81.     f70.func = 7;
  82.     f70.param1 =
  83.     f70.param3 =
  84.     f70.param4 =
  85.     f70.rezerv = 0;
  86.     f70.param2 = run_param;
  87.     f70.name = run_path;
  88.     $mov eax,70
  89.     $mov ebx,#f70.func
  90.     $int 0x40
  91. }
  92.  
  93. :int CreateDir(dword new_folder_path)
  94. {
  95.         f70.func = 9;
  96.         f70.param1 =
  97.         f70.param2 =
  98.         f70.param3 =
  99.         f70.param4 =
  100.         f70.rezerv = 0;
  101.         f70.name = new_folder_path;
  102.         $mov eax,70
  103.         $mov ebx,#f70.func
  104.         $int 0x40
  105. }
  106.  
  107. :int DeleteFile(dword del_file_path)
  108. {    
  109.         f70.func = 8;
  110.         f70.param1 =
  111.         f70.param2 =
  112.         f70.param3 =
  113.         f70.param4 =
  114.         f70.rezerv = 0;
  115.         f70.name = del_file_path;
  116.         $mov eax,70
  117.         $mov ebx,#f70.func
  118.         $int 0x40
  119. }
  120.  
  121. :int ReadFile(dword offset, data_size, buffer, file_path)
  122. {
  123.         f70.func = 0;
  124.         f70.param1 = offset;
  125.         f70.param2 = 0;
  126.         f70.param3 = data_size;
  127.         f70.param4 = buffer;
  128.         f70.rezerv = 0;
  129.         f70.name = file_path;
  130.         $mov eax,70
  131.         $mov ebx,#f70.func
  132.         $int 0x40
  133. }
  134.  
  135. :int CreateFile(dword data_size, buffer, file_path)
  136. {
  137.         f70.func = 2;
  138.         f70.param1 = 0;
  139.         f70.param2 = 0;
  140.         f70.param3 = data_size;
  141.         f70.param4 = buffer;
  142.         f70.rezerv = 0;
  143.         f70.name = file_path;
  144.         $mov eax,70
  145.         $mov ebx,#f70.func
  146.         $int 0x40
  147. }
  148.  
  149.   ////////////////////////////////////////
  150.  //     WriteInFileThatAlredyExists    //
  151. ////////////////////////////////////////
  152. :int WriteFile(dword offset, data_size, buffer, file_path)
  153. {
  154.         f70.func = 3;
  155.         f70.param1 = offset;
  156.         f70.param2 = 0;
  157.         f70.param3 = data_size;
  158.         f70.param4 = buffer;
  159.         f70.rezerv = 0;
  160.         f70.name = file_path;
  161.         $mov eax,70
  162.         $mov ebx,#f70.func
  163.         $int 0x40
  164. }
  165.  
  166. :int RenameMove(dword path_to, path_from)
  167. {
  168.         f70.func = 10;
  169.         f70.param1 =
  170.         f70.param2 =
  171.         f70.param3 = 0;
  172.         f70.param4 = path_to;
  173.         f70.rezerv = 0;
  174.         f70.name = path_from;
  175.         $mov eax,70
  176.         $mov ebx,#f70.func
  177.         $int 0x40
  178. }
  179.  
  180. :int ReadDir(dword file_count, read_buffer, dir_path)
  181. {
  182.         f70.func = 1;
  183.         f70.param1 =
  184.         f70.param2 =
  185.         f70.rezerv = 0;
  186.         f70.param3 = file_count;
  187.         f70.param4 = read_buffer;
  188.         f70.name = dir_path;
  189.         $mov eax,70
  190.         $mov ebx,#f70.func
  191.         $int 0x40
  192. }
  193.  
  194. //ECX - buf pointer
  195. inline fastcall void SetCurDir( ECX)
  196. {
  197.         EAX=30;
  198.         EBX=1;
  199.         $int 0x40
  200. }
  201.  
  202. //ECX - buf pointer
  203. //EDX - buf size
  204. inline fastcall void GetCurDir( ECX, EDX)
  205. {
  206.         EAX=30;
  207.         EBX=2;
  208.         $int 0x40
  209. }
  210.  
  211. :void read_file(dword path1, buf, size)
  212. {
  213.         EAX = 68;
  214.         EBX = 27;
  215.         ECX = path1;
  216.         $int 0x40;
  217.         ESDWORD[size] = EDX;
  218.         ESDWORD[buf] = EAX;
  219. }
  220.  
  221. //===================================================//
  222. //                                                   //
  223. //                        Misc                       //
  224. //                                                   //
  225. //===================================================//
  226.  
  227. :bool dir_exists(dword fpath)
  228. {
  229.         char buf[32];
  230.         if (!ReadDir(0, #buf, fpath)) return true;
  231.         return false;
  232. }
  233.  
  234. :dword get_file_size(dword _path)
  235. {
  236.         BDVK bdvk;
  237.         if (GetFileInfo(_path, #bdvk)!=0) return 0;
  238.         else return bdvk.sizelo;
  239. }
  240.  
  241. /*
  242. // This implementation of dir_exists() is faster than
  243. // previous but here virtual folders like
  244. // '/' and '/tmp' are not recognised as FOLDERS
  245. // by GetFileInfo() => BDVK.isfolder attribute :(
  246.  
  247. :bool dir_exists(dword fpath)
  248. {
  249.         BDVK fpath_atr;
  250.         if (GetFileInfo(fpath, #fpath_atr) != 0) return false;
  251.         return fpath_atr.isfolder;
  252. }
  253. */
  254.  
  255. :bool file_exists(dword fpath)
  256. {
  257.         BDVK ReadFile_atr;
  258.         if (! GetFileInfo(fpath, #ReadFile_atr)) return true;
  259.         return false;
  260. }
  261.  
  262. enum
  263. {
  264.         DIRS_ALL,
  265.         DIRS_NOROOT,
  266.         DIRS_ONLYREAL
  267. };
  268. :int GetDir(dword dir_buf, file_count, path, doptions)
  269. dword buf, fcount, error;
  270. char readbuf[32];
  271. {
  272.         error = ReadDir(0, #readbuf, path);
  273.         if (!error)
  274.         {
  275.                 fcount = ESDWORD[#readbuf+8];
  276.                 buf = malloc(fcount+1*304+32);
  277.                 ReadDir(fcount, buf, path);
  278.                 //fcount=EBX;
  279.  
  280.                 if (doptions == DIRS_ONLYREAL)
  281.                 {
  282.                         if (!strcmp(".",buf+72)) {fcount--; memmov(buf,buf+304,fcount*304);}
  283.                         if (!strcmp("..",buf+72)) {fcount--; memmov(buf,buf+304,fcount*304);}
  284.                 }
  285.                 if (doptions == DIRS_NOROOT)
  286.                 {
  287.                         if (!strcmp(".",buf+72)) {fcount--; memmov(buf,buf+304,fcount*304);}
  288.                 }
  289.  
  290.                 ESDWORD[dir_buf] = buf;
  291.                 ESDWORD[file_count] = fcount;
  292.         }
  293.         else
  294.         {
  295.                 ESDWORD[dir_buf] = 0;
  296.                 ESDWORD[file_count] = 0;
  297.         }
  298.         return error;
  299. }
  300.  
  301. :dword abspath(dword relative_path) //GetAbsolutePathFromRelative()
  302. {
  303.         char absolute_path[4096];
  304.         if (ESBYTE[relative_path]=='/')
  305.         {
  306.                 strcpy(#absolute_path, relative_path);
  307.         }
  308.         else
  309.         {
  310.                 strcpy(#absolute_path, I_Path);
  311.                 absolute_path[strrchr(#absolute_path, '/')] = '\0';
  312.                 strcat(#absolute_path, relative_path);
  313.         }
  314.         return #absolute_path;
  315. }
  316.  
  317. :dword GetIni(dword ini_path, ini_name) //search it on /kolibrios/ then on /sys/
  318. {
  319.         strcpy(ini_path, "/kolibrios/settings/");
  320.         strcat(ini_path, ini_name);
  321.         if (!file_exists(ini_path)) {
  322.                 strcpy(ini_path, "/sys/SETTINGS/");
  323.                 strcat(ini_path, ini_name);
  324.         }
  325.         return ini_path;
  326. }
  327.  
  328. :dword notify(dword notify_param)
  329. {
  330.         return RunProgram("/sys/@notify", notify_param);
  331. }
  332.  
  333. :void die(dword _last_msg)
  334. {
  335.         notify(_last_msg);
  336.         ExitProcess();
  337. }
  338.  
  339. :bool file_name_is_8_3(dword name)
  340. {
  341.         strlen(name);
  342.         if (EAX>12) return false;
  343.         $push eax
  344.         strrchr(name, '.');
  345.         $pop ebx
  346.  
  347.         //EAX = dot pos
  348.         //EBX = name length
  349.  
  350.         if (EAX) {
  351.                 if (EBX-EAX>3) return false;
  352.         } else {
  353.                 if (EBX>8) return false;
  354.         }
  355.         return true;
  356. }
  357.  
  358. //===================================================//
  359. //                                                   //
  360. //                   Convert Size                    //
  361. //                                                   //
  362. //===================================================//
  363.  
  364. :byte ConvertSize_size_prefix[8];
  365. :dword ConvertSize(dword bytes)
  366. {
  367.   byte size_nm[4];
  368.   if (bytes>=1073741824) strlcpy(#size_nm, "Gb",2);
  369.   else if (bytes>=1048576) strlcpy(#size_nm, "Mb",2);
  370.   else if (bytes>=1024) strlcpy(#size_nm, "Kb",2);
  371.   else strlcpy(#size_nm, "b ",2);
  372.   while (bytes>1023) bytes >>= 10;
  373.   sprintf(#ConvertSize_size_prefix,"%d %s",bytes,#size_nm);
  374.   return #ConvertSize_size_prefix;
  375. }
  376.  
  377. :dword ConvertSize64(dword bytes_lo, bytes_hi)
  378. {
  379.   if (bytes_hi > 0) {
  380.         if (bytes_lo>=1073741824) bytes_lo >>= 30; else bytes_lo = 0;
  381.         sprintf(#ConvertSize_size_prefix,"%d Gb",bytes_hi<<2 + bytes_lo);
  382.         return #ConvertSize_size_prefix;
  383.   }
  384.   else return ConvertSize(bytes_lo);
  385. }
  386.  
  387. :unsigned char size[25];
  388. :dword ConvertSizeToKb(unsigned int bytes)
  389. {
  390.         dword kb_line;
  391.  
  392.         if (bytes >= 1024)
  393.         {
  394.                 kb_line = itoa(bytes / 1024);
  395.                 strcpy(#size, kb_line);
  396.                 strcat(#size, " Kb");          
  397.         }
  398.         else {
  399.                 kb_line = itoa(bytes);
  400.                 strcpy(#size, kb_line);
  401.                 strcat(#size, " b");
  402.         }
  403.  
  404.         return #size;
  405. }
  406.  
  407. //===================================================//
  408. //                                                   //
  409. //                      Copy                         //
  410. //                                                   //
  411. //===================================================//
  412.  
  413. :int CopyFileAtOnce(dword size, copyFrom, copyTo)
  414. dword cbuf;
  415. int error;
  416. {
  417.         cbuf = malloc(size);
  418.         if (error = ReadFile(0, size, cbuf, copyFrom))
  419.         {
  420.                 debugln("Error: CopyFileAtOnce->ReadFile");
  421.         }
  422.         else
  423.         {
  424.                 if (error = CreateFile(size, cbuf, copyTo)) debugln("Error: CopyFileAtOnce->CreateFile");
  425.         }
  426.         free(cbuf);
  427.         return error;
  428. }
  429.  
  430. :int CopyFileByBlocks(dword size, copyFrom, copyTo)
  431. dword cbuf;
  432. int error=-1;
  433. dword offpos=0;
  434. int block_size=1024*1024*4; //copy by 4 MiB
  435. {
  436.         if (GetFreeRAM()>1024*78) {
  437.                 //Set block size 32 MiB
  438.                 block_size <<= 3;
  439.         }
  440.         cbuf = malloc(block_size);
  441.         if (error = CreateFile(0, 0, copyTo))
  442.         {
  443.                 debugln("Error: CopyFileByBlocks->CreateFile");
  444.                 size = -1;     
  445.         }
  446.         while(offpos < size)
  447.         {
  448.                 error = ReadFile(offpos, block_size, cbuf, copyFrom);
  449.                 if (error = 6) { //File ended before last byte was readed
  450.                         block_size = EBX;
  451.                         if (block_size+offpos>=size) error=0;
  452.                 }
  453.                 else
  454.                         if (error!=0) {
  455.                                 debugln("Error: CopyFileByBlocks->ReadFile");
  456.                                 break;
  457.                         }
  458.                 if (error = WriteFile(offpos, block_size, cbuf, copyTo)) {
  459.                         debugln("Error: CopyFileByBlocks->WriteFile");
  460.                         break;
  461.                 }
  462.                 offpos += block_size;
  463.         }
  464.         free(cbuf);
  465.         return error;
  466. }
  467.  
  468. //===================================================//
  469. //                                                   //
  470. //                  Directory Size                   //
  471. //                                                   //
  472. //===================================================//
  473.  
  474. :struct DIR_SIZE
  475. {
  476.         BDVK dir_info;
  477.         dword folders;
  478.         dword files;
  479.         dword bytes;
  480.         dword get();   
  481.         dword calculate_loop();
  482. };
  483.  
  484. :dword DIR_SIZE::get(dword way1)
  485. {
  486.         folders = files = bytes = 0;
  487.         if (!way1) return 0;
  488.         calculate_loop(way1);
  489. }
  490.  
  491. :dword DIR_SIZE::calculate_loop(dword way)
  492. {
  493.         dword dirbuf, fcount, i, filename;
  494.         dword cur_file;
  495.         if (!way) return 0;
  496.         if (dir_exists(way))
  497.         {
  498.                 cur_file = malloc(4096);
  499.                 // In the process of recursive descent, memory must be allocated dynamically,
  500.                 // because the static memory -> was a bug !!! But unfortunately pass away to sacrifice speed.
  501.                 GetDir(#dirbuf, #fcount, way, DIRS_ONLYREAL);
  502.                 for (i=0; i<fcount; i++)
  503.                 {
  504.                         filename = i*304+dirbuf+72;
  505.                         sprintf(cur_file,"%s/%s",way,filename);
  506.                        
  507.                         if (ESDWORD[filename-40] & ATR_FOLDER )
  508.                         {
  509.                                 folders++;
  510.                                 calculate_loop(cur_file);
  511.                         }
  512.                         else
  513.                         {
  514.                                 GetFileInfo(cur_file, #dir_info);
  515.                                 bytes += dir_info.sizelo;
  516.                                 files++;
  517.                         }
  518.                 }
  519.                 free(cur_file);
  520.                 free(dirbuf);
  521.         }
  522.         return files;
  523. }
  524.  
  525.  
  526. #endif