Subversion Repositories Kolibri OS

Rev

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