home *** CD-ROM | disk | FTP | other *** search
/ Geek 6 / Geek-006.iso / linux / video / xmovie-1.5.3.tar.gz / xmovie-1.5.3.tar / xmovie-1.5.3 / guicast / filesystem.C < prev    next >
C/C++ Source or Header  |  2000-11-29  |  12KB  |  661 lines

  1. #include <pwd.h>
  2. #include <stddef.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <sys/types.h>
  7. #include <sys/stat.h>
  8. #include <time.h>
  9. #include <dirent.h>
  10. #include <unistd.h>
  11.  
  12. #include "filesystem.h"
  13.  
  14. FileItem::FileItem()
  15. {
  16.     path = 0;
  17.     name = 0;
  18.     reset();
  19. }
  20.  
  21. FileItem::FileItem(char *path, char *name, int is_dir, long size, int month, int day, int year)
  22. {
  23.     this->path = new char[strlen(path)];
  24.     this->name = new char[strlen(name)];
  25.     strcpy(this->path, path);
  26.     strcpy(this->name, name);
  27.     is_dir = is_dir;
  28.     size = size;
  29.     month = month;
  30.     day = day;
  31.     year = year;
  32. }
  33.  
  34. FileItem::~FileItem()
  35. {
  36.     reset();
  37. }
  38.  
  39. int FileItem::reset()
  40. {
  41.     if(this->path) delete this->path;
  42.     if(this->name) delete this->name;
  43.     path = 0;
  44.     name = 0;
  45.     is_dir = 0;
  46.     size = 0;
  47.     month = 0;
  48.     day = 0;
  49.     year = 0;
  50.     return 0;
  51. }
  52.  
  53. int FileItem::set_path(char *path)
  54. {
  55.     if(this->path) delete this->path;
  56.     this->path = new char[strlen(path) + 1];
  57.     strcpy(this->path, path);
  58.     return 0;
  59. }
  60.  
  61. int FileItem::set_name(char *name)
  62. {
  63.     if(this->name) delete this->name;
  64.     this->name = new char[strlen(name) + 1];
  65.     strcpy(this->name, name);
  66.     return 0;
  67. }
  68.  
  69.  
  70. FileSystem::FileSystem()
  71. {
  72. //     if(need_home)
  73. //     {
  74. // // ========================= set to user's home directory
  75. //           uid_t uid;
  76. //           struct passwd *pw;
  77. // 
  78. //           uid = getuid();             /* get user id */
  79. //           pw = getpwuid(uid);         /* get info for user */
  80. //           sprintf(current_dir, "%s", pw->pw_dir);
  81. // 
  82. //      }
  83. // ========================= set to current directory
  84.     reset_parameters();
  85.     getcwd(current_dir, 1024);
  86. }
  87.  
  88. FileSystem::~FileSystem()
  89. {
  90.     delete_directory();
  91. }
  92.  
  93. int FileSystem::reset_parameters()
  94. {
  95.      show_all_files = 0;
  96.     want_directory = 0;
  97.     strcpy(filter, "");
  98.     strcpy(current_dir, "");
  99.     return 0;
  100. }
  101.  
  102. int FileSystem::delete_directory()
  103. {
  104.     for(int i = 0; i < dir_list.total; i++)
  105.     {
  106.         delete dir_list.values[i];
  107.     }
  108.     dir_list.remove_all();
  109.     return 0;
  110. }
  111.  
  112.  
  113.  
  114. int FileSystem::sort(ArrayList<FileItem*> *dir_list)
  115. {
  116.     int changed;
  117.     FileItem *temp;
  118.     int i;
  119.     
  120.     changed = 1;
  121.     while(changed)
  122.     {
  123.         changed = 0;
  124.         for(i = 0; i < dir_list->total - 1; i++)
  125.         {
  126.             if(strcmp(dir_list->values[i]->name, dir_list->values[i + 1]->name) > 0)
  127.             {
  128.                 temp = dir_list->values[i];
  129.                 dir_list->values[i] = dir_list->values[i+1];
  130.                 dir_list->values[i+1] = temp;
  131.                 changed = 1;
  132.             }
  133.         }
  134.     }
  135.     return 0;
  136. }
  137.  
  138. int FileSystem::combine(ArrayList<FileItem*> *dir_list, ArrayList<FileItem*> *file_list)
  139. {
  140.     int i;
  141.     FileItem *new_entry, *entry;
  142.     
  143.     sort(dir_list);
  144.     for(i = 0; i < dir_list->total; i++)
  145.     {
  146.         this->dir_list.append(dir_list->values[i]);
  147.     }
  148.  
  149.     sort(file_list);
  150.     for(i = 0; i < file_list->total; i++)
  151.     {
  152.         this->dir_list.append(file_list->values[i]);
  153.     }
  154.     return 0;
  155. }
  156.  
  157. int FileSystem::is_root_dir(char *path)
  158. {
  159.     if(!strcmp(current_dir, "/")) return 1;
  160.     return 0;
  161. }
  162.  
  163. int FileSystem::test_filter(FileItem *file)
  164. {
  165.     char *filter1 = 0, *filter2 = filter, *subfilter1, *subfilter2;
  166.     int total_filters = 0;
  167.     int result = 0;
  168.     int done = 0, token_done;
  169.     int token_number = 0;
  170.  
  171. // Don't filter directories
  172.     if(file->is_dir) return 0;
  173. // Empty filename string
  174.     if(!file->name) return 1;
  175.  
  176.     do
  177.     {
  178. // Get next token
  179.         filter1 = strchr(filter2, '[');
  180.         string[0] = 0;
  181.  
  182. // Get next filter
  183.         if(filter1)
  184.         {
  185.             filter1++;
  186.             filter2 = strchr(filter1, ']');
  187.  
  188.             if(filter2)
  189.             {
  190.                 int i;
  191.                 for(i = 0; filter1 + i < filter2; i++)
  192.                     string[i] = filter1[i];
  193.                 string[i] = 0;
  194.             }
  195.             else
  196.             {
  197.                 strcpy(string, filter1);
  198.                 done = 1;
  199.             }
  200.         }
  201.         else
  202.         {
  203.             if(!token_number) 
  204.                 strcpy(string, filter);
  205.             else
  206.                 done = 1;
  207.         }
  208.  
  209. // Process the token
  210.         if(string[0] != 0)
  211.         {
  212.             char *path = file->name;
  213.             subfilter1 = string;
  214.             token_done = 0;
  215.             result = 0;
  216.  
  217.             do
  218.             {
  219.                 string2[0] = 0;
  220.                 subfilter2 = strchr(subfilter1, '*');
  221.  
  222.                 if(subfilter2)
  223.                 {
  224.                     int i;
  225.                     for(i = 0; subfilter1 + i < subfilter2; i++)
  226.                         string2[i] = subfilter1[i];
  227.                     
  228.                     string2[i] = 0;
  229.                 }
  230.                 else
  231.                 {
  232.                     strcpy(string2, subfilter1);
  233.                     token_done = 1;
  234.                 }
  235.  
  236.                 if(string2[0] != 0)
  237.                 {
  238. // Subfilter must exist at some later point in the string
  239.                     if(subfilter1 > string)
  240.                     {
  241.                         if(!strstr(path, string2)) 
  242.                         {
  243.                             result = 1;
  244.                             token_done = 1;
  245.                         }
  246.                         else
  247.                         path = strstr(path, string2) + strlen(string2);
  248.                     }
  249.                     else
  250. // Subfilter must exist at this point in the string
  251.                     {
  252.                         if(strncasecmp(path, string2, strlen(string2))) 
  253.                         {
  254.                             result = 1;
  255.                             token_done = 1;
  256.                         }
  257.                         else
  258.                         path += strlen(string2);
  259.                     }
  260.  
  261. // String must terminate after subfilter
  262.                     if(!subfilter2)
  263.                     {
  264.                         if(*path != 0)
  265.                         {
  266.                             result = 1;
  267.                             token_done = 1;
  268.                         }
  269.                     }
  270.                 }
  271.                 subfilter1 = subfilter2 + 1;
  272. // Let pass if no subfilter
  273.             }while(!token_done && !result);
  274.         }
  275.         token_number++;
  276.     }while(!done && result);
  277.  
  278.     return result;
  279. }
  280.  
  281.  
  282. int FileSystem::update(char *new_dir)
  283. {
  284.     DIR *dirstream;
  285.     struct dirent *new_filename;
  286.     struct stat ostat;
  287.     struct tm *mod_time;
  288.     int i, j, k, include_this;
  289.     FileItem *new_file;
  290.     char full_path[1024], name_only[1024];
  291.     ArrayList<FileItem*>directories;
  292.     ArrayList<FileItem*>files;
  293.  
  294.     delete_directory();
  295.     if(new_dir != 0) strcpy(current_dir, new_dir);
  296.     dirstream = opendir(current_dir);
  297.     if(!dirstream) return 1;          // failed to open directory
  298.  
  299.     while(new_filename = readdir(dirstream))
  300.     {
  301.         include_this = 1;
  302.  
  303. // File is directory heirarchy
  304.         if(!strcmp(new_filename->d_name, ".") || 
  305.             !strcmp(new_filename->d_name, "..")) include_this = 0;
  306.  
  307. // File is hidden and we don't want all files
  308.         if(include_this && !show_all_files && new_filename->d_name[0] == '.') include_this = 0;
  309.  
  310. // file not hidden
  311.           if(include_this)
  312.         {
  313.             new_file = new FileItem;
  314.             sprintf(full_path, "%s", current_dir);
  315.             if(!is_root_dir(current_dir)) strcat(full_path, "/");
  316.             strcat(full_path, new_filename->d_name);
  317.             strcpy(name_only, new_filename->d_name);
  318.             new_file->set_path(full_path);
  319.             new_file->set_name(name_only);
  320.  
  321. // Get information about the file.
  322.             if(!stat(full_path, &ostat))
  323.             {
  324.                 new_file->size = ostat.st_size;
  325.                 mod_time = localtime(&(ostat.st_mtime));
  326.                 new_file->month = mod_time->tm_mon + 1;
  327.                 new_file->day = mod_time->tm_mday;
  328.                 new_file->year = mod_time->tm_year + 1900;
  329.  
  330.                 if(S_ISDIR(ostat.st_mode))
  331.                 {
  332.                     strcat(name_only, "/"); // is a directory
  333.                     new_file->is_dir = 1;
  334.                 }
  335.  
  336. // File is excluded from filter
  337.                 if(include_this && test_filter(new_file)) include_this = 0;
  338.  
  339. // File is not a directory and we just want directories
  340.                 if(include_this && want_directory && !new_file->is_dir) include_this = 0;
  341.             }
  342.             else
  343.                 include_this = 0;
  344.             
  345.  
  346. // add to list
  347.             if(include_this)
  348.             {
  349.                 if(new_file->is_dir) directories.append(new_file);
  350.                  else files.append(new_file);
  351.             }
  352.             else
  353.                 delete new_file;
  354.         }
  355.     }
  356.  
  357.     closedir(dirstream);
  358. // combine the directories and files in the master list
  359.     combine(&directories, &files);
  360. // remove pointers
  361.     directories.remove_all();
  362.     files.remove_all();
  363.  
  364.     return 0;           // success
  365. }
  366.  
  367. int FileSystem::set_filter(char *new_filter)
  368. {
  369.     strcpy(filter, new_filter);
  370.     return 0;
  371. }
  372.  
  373. int FileSystem::set_show_all()
  374. {
  375.     show_all_files = 1;
  376.     return 0;
  377. }
  378.  
  379. int FileSystem::set_want_directory()
  380. {
  381.     want_directory = 1;
  382.     return 0;
  383. }
  384.  
  385. int FileSystem::is_dir(const char *path)      // return 0 if the text is a directory
  386. {
  387.     if(!strlen(path)) return 0;
  388.  
  389.     char new_dir[1024];
  390.     struct stat ostat;    // entire name is a directory
  391.  
  392.     strcpy(new_dir, path);
  393.     complete_path(new_dir);
  394.     if(!stat(new_dir, &ostat) && S_ISDIR(ostat.st_mode)) return 0;
  395.     return 1;
  396. }
  397.  
  398. int FileSystem::create_dir(char *new_dir_)
  399. {
  400.     char new_dir[1024];
  401.     strcpy(new_dir, new_dir_);
  402.     complete_path(new_dir);
  403.  
  404.     mkdir(new_dir, S_IREAD | S_IWRITE | S_IEXEC);
  405.     return 0;
  406. }
  407.  
  408. int FileSystem::parse_tildas(char *new_dir)
  409. {
  410.     if(new_dir[0] == 0) return 1;
  411.  
  412. // Our home directory
  413.     if(new_dir[0] == '~')
  414.     {
  415.  
  416.         if(new_dir[1] == '/' || new_dir[1] == 0)
  417.         {
  418. // user's home directory
  419.             char *home;
  420.             char string[1024];
  421.             home = getenv("HOME");
  422.  
  423. // print starting after tilda
  424.             if(home) sprintf(string, "%s%s", home, &new_dir[1]);
  425.             strcpy(new_dir, string);
  426.             return 0;
  427.         }
  428.         else
  429. // Another user's home directory
  430.         {                
  431.             char string[1024], new_user[1024];
  432.             struct passwd *pw;
  433.             int i, j;
  434.       
  435.             for(i = 1, j = 0; new_dir[i] != 0 && new_dir[i] != '/'; i++, j++)
  436.             {                // copy user name
  437.                 new_user[j] = new_dir[i];
  438.             }
  439.             new_user[j] = 0;
  440.       
  441.             setpwent();
  442.             while(pw = getpwent())
  443.             {
  444. // get info for user
  445.                 if(!strcmp(pw->pw_name, new_user))
  446.                 {
  447. // print starting after tilda
  448.                       sprintf(string, "%s%s", pw->pw_dir, &new_dir[i]);
  449.                       strcpy(new_dir, string);
  450.                       break;
  451.                   }
  452.             }
  453.             endpwent();
  454.             return 0;
  455.         }
  456.     }
  457.     return 0;
  458. }
  459.  
  460. int FileSystem::parse_directories(char *new_dir)
  461. {
  462.     if(new_dir[0] != '/')
  463.     {
  464. // extend path completely
  465.         char string[1024];
  466.         if(!strlen(current_dir))
  467.         {
  468. // no current directory
  469.             strcpy(string, new_dir);
  470.         }
  471.         else
  472.         if(!is_root_dir(current_dir))
  473.         {
  474. // current directory is not root
  475.             if(current_dir[strlen(current_dir) - 1] == '/')
  476. // current_dir already has ending /
  477.             sprintf(string, "%s%s", current_dir, new_dir);
  478.             else
  479. // need ending /
  480.             sprintf(string, "%s/%s", current_dir, new_dir);
  481.         }
  482.         else
  483.             sprintf(string, "%s%s", current_dir, new_dir);
  484.         
  485.         strcpy(new_dir, string);
  486.     }
  487.     return 0;
  488. }
  489.  
  490. int FileSystem::parse_dots(char *new_dir)
  491. {
  492. // recursively remove ..s
  493.     int changed = 1;
  494.     while(changed)
  495.     {
  496.         int i, j, len;
  497.         len = strlen(new_dir);
  498.         changed = 0;
  499.         for(i = 0, j = 1; !changed && j < len; i++, j++)
  500.         {
  501.             if(new_dir[i] == '.' && new_dir[j] == '.')
  502.             {
  503.                 changed = 1;
  504.                 while(new_dir[i] != '/' && i > 0)
  505.                 {
  506. // look for first / before ..
  507.                     i--;
  508.                 }
  509.  
  510. // find / before this /
  511.                 if(i > 0) i--;  
  512.                 while(new_dir[i] != '/' && i > 0)
  513.                 {
  514. // look for first / before first / before ..
  515.                     i--;
  516.                 }
  517.  
  518. // i now equals /first filename before ..
  519. // look for first / after ..
  520.                 while(new_dir[j] != '/' && j < len)
  521.                 {
  522.                     j++;
  523.                 }
  524.  
  525. // j now equals /first filename after ..
  526.                 while(j < len)
  527.                 {
  528.                     new_dir[i++] = new_dir[j++];
  529.                 }
  530.  
  531.                 new_dir[i] = 0;
  532. // default to root directory
  533.                 if((new_dir[0]) == 0) sprintf(new_dir, "/");
  534.                 break;
  535.             }
  536.         }
  537.     }
  538.     return 0;
  539. }
  540.  
  541. int FileSystem::complete_path(char *filename)
  542. {
  543.     if(!strlen(filename)) return 1;
  544.     parse_tildas(filename);
  545.     parse_directories(filename);
  546.     parse_dots(filename);
  547. // don't add end slash since this requires checking if dir
  548.     return 0;
  549. }
  550.  
  551. int FileSystem::extract_dir(char *out, const char *in)
  552. {
  553.     strcpy(out, in);
  554.     if(is_dir(in))
  555.     {
  556. // complete string is not directory
  557.         int i;
  558.  
  559.         complete_path(out);
  560.  
  561.         for(i = strlen(out); i > 0 && out[i] != '/'; i--)
  562.         {
  563.             ;
  564.         }
  565.         if(i >= 0) out[i] = 0;
  566.     }
  567.     return 0;
  568. }
  569.  
  570. int FileSystem::extract_name(char *out, const char *in)
  571. {
  572.     int i;
  573.     
  574.     if(!is_dir(in)) sprintf(out, "");    // complete string is directory
  575.     else
  576.     {
  577.         for(i = strlen(in)-1; i > 0 && in[i] != '/'; i--)
  578.         {
  579.             ;
  580.         }
  581.         if(in[i] == '/') i++;
  582.         strcpy(out, &in[i]);
  583.     }
  584.     return 0;
  585. }
  586.  
  587. int FileSystem::join_names(char *out, char *dir_in, char *name_in)
  588. {
  589.     strcpy(out, dir_in);
  590.     int len = strlen(out);
  591.     int result = 0;
  592.     
  593.     while(!result)
  594.         if(len == 0 || out[len] != 0) result = 1; else len--;
  595.     
  596.     if(len != 0)
  597.     {
  598.         if(out[len] != '/') strcat(out, "/");
  599.     }
  600.     
  601.     strcat(out, name_in);
  602.     return 0;
  603. }
  604.  
  605. long FileSystem::get_date(char *filename)
  606. {
  607.     struct stat file_status;
  608.     stat (filename, &file_status);
  609.     return file_status.st_mtime;
  610. }
  611.  
  612. long FileSystem::get_size(char *filename)
  613. {
  614.     struct stat file_status;
  615.     stat (filename, &file_status);
  616.     return file_status.st_size;
  617. }
  618.  
  619. int FileSystem::change_dir(char *new_dir)
  620. {
  621.     char new_dir_full[256];
  622.     
  623.     strcpy(new_dir_full, new_dir);
  624.  
  625.     complete_path(new_dir_full);
  626. // cut ending slash
  627.     if(strcmp(new_dir_full, "/") && 
  628.         new_dir_full[strlen(new_dir_full) - 1] == '/') 
  629.         new_dir_full[strlen(new_dir_full) - 1] = 0;
  630.     update(new_dir_full);
  631.     return 0;
  632. }
  633.  
  634. int FileSystem::set_current_dir(char *new_dir)
  635. {
  636.     strcpy(current_dir, new_dir);
  637.     return 0;
  638. }
  639.  
  640. int FileSystem::add_end_slash(char *new_dir)
  641. {
  642.     if(new_dir[strlen(new_dir) - 1] != '/') strcat(new_dir, "/");
  643.     return 0;
  644. }
  645.  
  646. char* FileSystem::get_current_dir()
  647. {
  648.     return current_dir;
  649. }
  650.  
  651. int FileSystem::total_files()
  652. {
  653.     return dir_list.total;
  654. }
  655.  
  656.  
  657. FileItem* FileSystem::get_entry(int entry)
  658. {
  659.     return dir_list.values[entry];
  660. }
  661.