12 #include "filesystem.h"
21 FileItem::FileItem(char *path,
28 int64_t calendar_time)
30 this->path = new char[strlen(path)];
31 this->name = new char[strlen(name)];
32 if(this->path) strcpy(this->path, path);
33 if(this->name) strcpy(this->name, name);
34 this->is_dir = is_dir;
39 this->calendar_time = calendar_time;
49 if(this->path) delete [] this->path;
50 if(this->name) delete [] this->name;
62 int FileItem::set_path(char *path)
64 if(this->path) delete [] this->path;
65 this->path = new char[strlen(path) + 1];
66 strcpy(this->path, path);
70 int FileItem::set_name(char *name)
72 if(this->name) delete [] this->name;
73 this->name = new char[strlen(name) + 1];
74 strcpy(this->name, name);
79 FileSystem::FileSystem()
82 getcwd(current_dir, BCTEXTLEN);
86 FileSystem::~FileSystem()
91 int FileSystem::reset_parameters()
96 strcpy(current_dir, "");
97 sort_order = SORT_ASCENDING;
98 sort_field = SORT_PATH;
102 int FileSystem::delete_directory()
104 for(int i = 0; i < dir_list.total; i++)
106 delete dir_list.values[i];
108 dir_list.remove_all();
112 int FileSystem::set_sort_order(int value)
114 this->sort_order = value;
117 int FileSystem::set_sort_field(int field)
119 this->sort_field = field;
122 int FileSystem::compare_items(ArrayList<FileItem*> *dir_list,
127 FileItem *ptr1 = dir_list->values[item1];
128 FileItem *ptr2 = dir_list->values[item2];
130 // Default to name in ascending order
134 result = (sort_order == SORT_ASCENDING) ?
135 strcasecmp(ptr1->name, ptr2->name) :
136 strcasecmp(ptr2->name, ptr1->name);
139 if(ptr1->size == ptr2->size || ptr1->is_dir)
140 result = strcasecmp(ptr1->name, ptr2->name);
142 result = (sort_order == SORT_ASCENDING) ?
143 (ptr1->size > ptr2->size) :
144 (ptr2->size > ptr1->size);
147 if(ptr1->calendar_time == ptr2->calendar_time)
148 result = strcasecmp(ptr1->name, ptr2->name);
150 result = (sort_order == SORT_ASCENDING) ?
151 (ptr1->calendar_time > ptr2->calendar_time) :
152 (ptr2->calendar_time > ptr1->calendar_time);
159 int FileSystem::sort_table(ArrayList<FileItem*> *dir_list)
169 for(i = 0; i < dir_list->total - 1; i++)
171 if(compare_items(dir_list, i, i + 1) > 0)
172 // if(strcasecmp(dir_list->values[i]->name, dir_list->values[i + 1]->name) > 0)
174 temp = dir_list->values[i];
175 dir_list->values[i] = dir_list->values[i+1];
176 dir_list->values[i+1] = temp;
184 int FileSystem::combine(ArrayList<FileItem*> *dir_list, ArrayList<FileItem*> *file_list)
187 FileItem *new_entry, *entry;
189 sort_table(dir_list);
190 for(i = 0; i < dir_list->total; i++)
192 this->dir_list.append(dir_list->values[i]);
195 sort_table(file_list);
196 for(i = 0; i < file_list->total; i++)
198 this->dir_list.append(file_list->values[i]);
203 int FileSystem::is_root_dir(char *path)
205 if(!strcmp(current_dir, "/")) return 1;
209 int FileSystem::test_filter(FileItem *file)
211 char *filter1 = 0, *filter2 = filter, *subfilter1, *subfilter2;
212 int total_filters = 0;
214 int done = 0, token_done;
215 int token_number = 0;
217 // Don't filter directories
218 if(file->is_dir) return 0;
219 // Empty filename string
220 if(!file->name) return 1;
225 filter1 = strchr(filter2, '[');
232 filter2 = strchr(filter1, ']');
237 for(i = 0; filter1 + i < filter2; i++)
238 string[i] = filter1[i];
243 strcpy(string, filter1);
250 strcpy(string, filter);
258 char *path = file->name;
266 subfilter2 = strchr(subfilter1, '*');
271 for(i = 0; subfilter1 + i < subfilter2; i++)
272 string2[i] = subfilter1[i];
278 strcpy(string2, subfilter1);
284 // Subfilter must exist at some later point in the string
285 if(subfilter1 > string)
287 if(!strstr(path, string2))
293 path = strstr(path, string2) + strlen(string2);
296 // Subfilter must exist at this point in the string
298 if(strncasecmp(path, string2, strlen(string2)))
304 path += strlen(string2);
307 // String must terminate after subfilter
317 subfilter1 = subfilter2 + 1;
318 // Let pass if no subfilter
319 }while(!token_done && !result);
322 }while(!done && result);
328 int FileSystem::update(char *new_dir)
331 struct dirent64 *new_filename;
334 int i, j, k, include_this;
336 char full_path[BCTEXTLEN], name_only[BCTEXTLEN];
337 ArrayList<FileItem*>directories;
338 ArrayList<FileItem*>files;
341 if(new_dir != 0) strcpy(current_dir, new_dir);
342 dirstream = opendir(current_dir);
343 if(!dirstream) return 1; // failed to open directory
345 while(new_filename = readdir64(dirstream))
349 // File is directory heirarchy
350 if(!strcmp(new_filename->d_name, ".") ||
351 !strcmp(new_filename->d_name, "..")) include_this = 0;
353 // File is hidden and we don't want all files
354 if(include_this && !show_all_files && new_filename->d_name[0] == '.') include_this = 0;
359 new_file = new FileItem;
360 sprintf(full_path, "%s", current_dir);
361 if(!is_root_dir(current_dir)) strcat(full_path, "/");
362 strcat(full_path, new_filename->d_name);
363 strcpy(name_only, new_filename->d_name);
364 new_file->set_path(full_path);
365 new_file->set_name(name_only);
367 // Get information about the file.
368 if(!stat(full_path, &ostat))
370 new_file->size = ostat.st_size;
371 mod_time = localtime(&(ostat.st_mtime));
372 new_file->month = mod_time->tm_mon + 1;
373 new_file->day = mod_time->tm_mday;
374 new_file->year = mod_time->tm_year + 1900;
375 new_file->calendar_time = ostat.st_mtime;
377 if(S_ISDIR(ostat.st_mode))
379 strcat(name_only, "/"); // is a directory
380 new_file->is_dir = 1;
383 // File is excluded from filter
384 if(include_this && test_filter(new_file)) include_this = 0;
385 //printf("FileSystem::update 3 %d %d\n", include_this, test_filter(new_file));
387 // File is not a directory and we just want directories
388 if(include_this && want_directory && !new_file->is_dir) include_this = 0;
392 //printf("FileSystem::update 3 %s\n", full_path);
399 if(new_file->is_dir) directories.append(new_file);
400 else files.append(new_file);
408 // combine the directories and files in the master list
409 combine(&directories, &files);
411 directories.remove_all();
417 int FileSystem::set_filter(char *new_filter)
419 strcpy(filter, new_filter);
423 int FileSystem::set_show_all()
429 int FileSystem::set_want_directory()
435 int FileSystem::is_dir(const char *path) // return 0 if the text is a directory
437 if(!strlen(path)) return 0;
439 char new_dir[BCTEXTLEN];
440 struct stat ostat; // entire name is a directory
442 strcpy(new_dir, path);
443 complete_path(new_dir);
444 if(!stat(new_dir, &ostat) && S_ISDIR(ostat.st_mode)) return 0;
448 int FileSystem::create_dir(char *new_dir_)
450 char new_dir[BCTEXTLEN];
451 strcpy(new_dir, new_dir_);
452 complete_path(new_dir);
454 mkdir(new_dir, S_IREAD | S_IWRITE | S_IEXEC);
458 int FileSystem::parse_tildas(char *new_dir)
460 if(new_dir[0] == 0) return 1;
462 // Our home directory
463 if(new_dir[0] == '~')
466 if(new_dir[1] == '/' || new_dir[1] == 0)
468 // user's home directory
470 char string[BCTEXTLEN];
471 home = getenv("HOME");
473 // print starting after tilda
474 if(home) sprintf(string, "%s%s", home, &new_dir[1]);
475 strcpy(new_dir, string);
479 // Another user's home directory
481 char string[BCTEXTLEN], new_user[BCTEXTLEN];
485 for(i = 1, j = 0; new_dir[i] != 0 && new_dir[i] != '/'; i++, j++)
487 new_user[j] = new_dir[i];
492 while(pw = getpwent())
495 if(!strcmp(pw->pw_name, new_user))
497 // print starting after tilda
498 sprintf(string, "%s%s", pw->pw_dir, &new_dir[i]);
499 strcpy(new_dir, string);
510 int FileSystem::parse_directories(char *new_dir)
512 //printf("FileSystem::parse_directories 1 %s\n", new_dir);
513 if(new_dir[0] != '/')
515 // extend path completely
516 char string[BCTEXTLEN];
517 //printf("FileSystem::parse_directories 2 %s\n", current_dir);
518 if(!strlen(current_dir))
520 // no current directory
521 strcpy(string, new_dir);
524 if(!is_root_dir(current_dir))
526 // current directory is not root
527 if(current_dir[strlen(current_dir) - 1] == '/')
528 // current_dir already has ending /
529 sprintf(string, "%s%s", current_dir, new_dir);
532 sprintf(string, "%s/%s", current_dir, new_dir);
535 sprintf(string, "%s%s", current_dir, new_dir);
537 //printf("FileSystem::parse_directories 3 %s %s\n", new_dir, string);
538 strcpy(new_dir, string);
539 //printf("FileSystem::parse_directories 4\n");
544 int FileSystem::parse_dots(char *new_dir)
546 // recursively remove ..s
551 len = strlen(new_dir);
553 for(i = 0, j = 1; !changed && j < len; i++, j++)
555 if(new_dir[i] == '.' && new_dir[j] == '.')
558 while(new_dir[i] != '/' && i > 0)
560 // look for first / before ..
564 // find / before this /
566 while(new_dir[i] != '/' && i > 0)
568 // look for first / before first / before ..
572 // i now equals /first filename before ..
573 // look for first / after ..
574 while(new_dir[j] != '/' && j < len)
579 // j now equals /first filename after ..
582 new_dir[i++] = new_dir[j++];
586 // default to root directory
587 if((new_dir[0]) == 0) sprintf(new_dir, "/");
595 int FileSystem::complete_path(char *filename)
597 //printf("FileSystem::complete_path 1\n");
598 if(!strlen(filename)) return 1;
599 //printf("FileSystem::complete_path 1\n");
600 parse_tildas(filename);
601 //printf("FileSystem::complete_path 1\n");
602 parse_directories(filename);
603 //printf("FileSystem::complete_path 1\n");
604 parse_dots(filename);
605 // don't add end slash since this requires checking if dir
606 //printf("FileSystem::complete_path 2\n");
610 int FileSystem::extract_dir(char *out, const char *in)
615 // complete string is not directory
620 for(i = strlen(out); i > 0 && out[i] != '/'; i--)
624 if(i >= 0) out[i] = 0;
629 int FileSystem::extract_name(char *out, const char *in, int test_dir)
633 if(test_dir && !is_dir(in))
634 sprintf(out, ""); // complete string is directory
637 for(i = strlen(in)-1; i > 0 && in[i] != '/'; i--)
641 if(in[i] == '/') i++;
647 int FileSystem::join_names(char *out, char *dir_in, char *name_in)
650 int len = strlen(out);
654 if(len == 0 || out[len] != 0) result = 1; else len--;
658 if(out[len] != '/') strcat(out, "/");
661 strcat(out, name_in);
665 long FileSystem::get_date(char *filename)
667 struct stat file_status;
668 bzero(&file_status, sizeof(struct stat));
669 stat (filename, &file_status);
670 return file_status.st_mtime;
673 int64_t FileSystem::get_size(char *filename)
675 struct stat file_status;
676 bzero(&file_status, sizeof(struct stat));
677 stat(filename, &file_status);
678 return file_status.st_size;
681 int FileSystem::change_dir(char *new_dir)
683 char new_dir_full[BCTEXTLEN];
685 strcpy(new_dir_full, new_dir);
687 complete_path(new_dir_full);
689 if(strcmp(new_dir_full, "/") &&
690 new_dir_full[strlen(new_dir_full) - 1] == '/')
691 new_dir_full[strlen(new_dir_full) - 1] = 0;
692 update(new_dir_full);
696 int FileSystem::set_current_dir(char *new_dir)
698 strcpy(current_dir, new_dir);
702 int FileSystem::add_end_slash(char *new_dir)
704 if(new_dir[strlen(new_dir) - 1] != '/') strcat(new_dir, "/");
708 char* FileSystem::get_current_dir()
713 int FileSystem::total_files()
715 return dir_list.total;
719 FileItem* FileSystem::get_entry(int entry)
721 return dir_list.values[entry];