13 #include "filesystem.h"
22 FileItem::FileItem(char *path,
29 int64_t calendar_time)
31 this->path = new char[strlen(path)];
32 this->name = new char[strlen(name)];
33 if(this->path) strcpy(this->path, path);
34 if(this->name) strcpy(this->name, name);
35 this->is_dir = is_dir;
40 this->calendar_time = calendar_time;
50 if(this->path) delete [] this->path;
51 if(this->name) delete [] this->name;
63 int FileItem::set_path(char *path)
65 if(this->path) delete [] this->path;
66 this->path = new char[strlen(path) + 1];
67 strcpy(this->path, path);
71 int FileItem::set_name(char *name)
73 if(this->name) delete [] this->name;
74 this->name = new char[strlen(name) + 1];
75 strcpy(this->name, name);
80 FileSystem::FileSystem()
83 getcwd(current_dir, BCTEXTLEN);
87 FileSystem::~FileSystem()
92 int FileSystem::reset_parameters()
97 strcpy(current_dir, "");
98 sort_order = SORT_ASCENDING;
99 sort_field = SORT_PATH;
103 int FileSystem::delete_directory()
105 for(int i = 0; i < dir_list.total; i++)
107 delete dir_list.values[i];
109 dir_list.remove_all();
113 int FileSystem::set_sort_order(int value)
115 this->sort_order = value;
118 int FileSystem::set_sort_field(int field)
120 this->sort_field = field;
123 // filename.with.dots.extension
125 // extension.dots.with.filename
127 int FileSystem::dot_reverse_filename(char *out, const char *in)
129 int i, i2, j=0, lastdot;
130 lastdot = strlen(in);
131 for (i = strlen(in); i >= 0; i--){
143 while (i < lastdot) out[j++] = in[i++];
149 int FileSystem::compare_items(ArrayList<FileItem*> *dir_list,
154 FileItem *ptr1 = dir_list->values[item1];
155 FileItem *ptr2 = dir_list->values[item2];
157 // Default to name in ascending order
160 char dotreversedname1[BCTEXTLEN], dotreversedname2[BCTEXTLEN];
163 result = (sort_order == SORT_ASCENDING) ?
164 strcasecmp(ptr1->name, ptr2->name) :
165 strcasecmp(ptr2->name, ptr1->name);
168 if(ptr1->size == ptr2->size || ptr1->is_dir)
169 result = strcasecmp(ptr1->name, ptr2->name);
171 result = (sort_order == SORT_ASCENDING) ?
172 (ptr1->size > ptr2->size) :
173 (ptr2->size > ptr1->size);
176 if(ptr1->calendar_time == ptr2->calendar_time)
177 result = strcasecmp(ptr1->name, ptr2->name);
179 result = (sort_order == SORT_ASCENDING) ?
180 (ptr1->calendar_time > ptr2->calendar_time) :
181 (ptr2->calendar_time > ptr1->calendar_time);
184 dot_reverse_filename(dotreversedname1,ptr1->name);
185 dot_reverse_filename(dotreversedname2,ptr2->name);
187 result = (sort_order == SORT_ASCENDING) ?
188 strcasecmp(dotreversedname1, dotreversedname2) :
189 strcasecmp(dotreversedname2, dotreversedname1);
196 int FileSystem::sort_table(ArrayList<FileItem*> *dir_list)
206 for(i = 0; i < dir_list->total - 1; i++)
208 if(compare_items(dir_list, i, i + 1) > 0)
209 // if(strcasecmp(dir_list->values[i]->name, dir_list->values[i + 1]->name) > 0)
211 temp = dir_list->values[i];
212 dir_list->values[i] = dir_list->values[i+1];
213 dir_list->values[i+1] = temp;
221 int FileSystem::combine(ArrayList<FileItem*> *dir_list, ArrayList<FileItem*> *file_list)
224 FileItem *new_entry, *entry;
226 sort_table(dir_list);
227 for(i = 0; i < dir_list->total; i++)
229 this->dir_list.append(dir_list->values[i]);
232 sort_table(file_list);
233 for(i = 0; i < file_list->total; i++)
235 this->dir_list.append(file_list->values[i]);
240 void FileSystem::alphabetize()
242 sort_table(&dir_list);
245 int FileSystem::is_root_dir(char *path)
247 if(!strcmp(current_dir, "/")) return 1;
251 int FileSystem::test_filter(FileItem *file)
253 char *filter1 = 0, *filter2 = filter, *subfilter1, *subfilter2;
254 int total_filters = 0;
256 int done = 0, token_done;
257 int token_number = 0;
259 // Don't filter directories
260 if(file->is_dir) return 0;
262 // Empty filename string
263 if(!file->name) return 1;
268 filter1 = strchr(filter2, '[');
275 filter2 = strchr(filter1, ']');
280 for(i = 0; filter1 + i < filter2; i++)
281 string[i] = filter1[i];
286 strcpy(string, filter1);
293 strcpy(string, filter);
301 char *path = file->name;
309 subfilter2 = strchr(subfilter1, '*');
314 for(i = 0; subfilter1 + i < subfilter2; i++)
315 string2[i] = subfilter1[i];
321 strcpy(string2, subfilter1);
327 // Subfilter must exist at some later point in the string
328 if(subfilter1 > string)
330 if(!strstr(path, string2))
336 path = strstr(path, string2) + strlen(string2);
339 // Subfilter must exist at this point in the string
341 if(strncmp(path, string2, strlen(string2)))
342 // if(strncasecmp(path, string2, strlen(string2)))
348 path += strlen(string2);
351 // String must terminate after subfilter
361 subfilter1 = subfilter2 + 1;
362 // Let pass if no subfilter
363 }while(!token_done && !result);
366 }while(!done && result);
372 int FileSystem::update(char *new_dir)
375 struct dirent64 *new_filename;
378 int i, j, k, include_this;
380 char full_path[BCTEXTLEN], name_only[BCTEXTLEN];
381 ArrayList<FileItem*>directories;
382 ArrayList<FileItem*>files;
386 if(new_dir != 0) strcpy(current_dir, new_dir);
387 dirstream = opendir(current_dir);
388 if(!dirstream) return 1; // failed to open directory
390 while(new_filename = readdir64(dirstream))
394 // File is directory heirarchy
395 if(!strcmp(new_filename->d_name, ".") ||
396 !strcmp(new_filename->d_name, "..")) include_this = 0;
398 // File is hidden and we don't want all files
399 if(include_this && !show_all_files && new_filename->d_name[0] == '.') include_this = 0;
404 new_file = new FileItem;
405 sprintf(full_path, "%s", current_dir);
406 if(!is_root_dir(current_dir)) strcat(full_path, "/");
407 strcat(full_path, new_filename->d_name);
408 strcpy(name_only, new_filename->d_name);
409 new_file->set_path(full_path);
410 new_file->set_name(name_only);
412 // Get information about the file.
413 if(!stat(full_path, &ostat))
415 new_file->size = ostat.st_size;
416 mod_time = localtime(&(ostat.st_mtime));
417 new_file->month = mod_time->tm_mon + 1;
418 new_file->day = mod_time->tm_mday;
419 new_file->year = mod_time->tm_year + 1900;
420 new_file->calendar_time = ostat.st_mtime;
422 if(S_ISDIR(ostat.st_mode))
424 strcat(name_only, "/"); // is a directory
425 new_file->is_dir = 1;
428 // File is excluded from filter
429 if(include_this && test_filter(new_file)) include_this = 0;
430 //printf("FileSystem::update 3 %d %d\n", include_this, test_filter(new_file));
432 // File is not a directory and we just want directories
433 if(include_this && want_directory && !new_file->is_dir) include_this = 0;
437 //printf("FileSystem::update 3 %s\n", full_path);
438 printf("FileSystem::update %s: %s\n",
448 if(new_file->is_dir) directories.append(new_file);
449 else files.append(new_file);
457 // combine the directories and files in the master list
458 combine(&directories, &files);
460 directories.remove_all();
467 int FileSystem::set_filter(char *new_filter)
469 strcpy(filter, new_filter);
473 int FileSystem::set_show_all()
479 int FileSystem::set_want_directory()
485 int FileSystem::is_dir(const char *path) // return 0 if the text is a directory
487 if(!strlen(path)) return 0;
489 char new_dir[BCTEXTLEN];
490 struct stat ostat; // entire name is a directory
492 strcpy(new_dir, path);
493 complete_path(new_dir);
494 if(!stat(new_dir, &ostat) && S_ISDIR(ostat.st_mode))
500 int FileSystem::create_dir(char *new_dir_)
502 char new_dir[BCTEXTLEN];
503 strcpy(new_dir, new_dir_);
504 complete_path(new_dir);
506 mkdir(new_dir, S_IREAD | S_IWRITE | S_IEXEC);
510 int FileSystem::parse_tildas(char *new_dir)
512 if(new_dir[0] == 0) return 1;
514 // Our home directory
515 if(new_dir[0] == '~')
518 if(new_dir[1] == '/' || new_dir[1] == 0)
520 // user's home directory
522 char string[BCTEXTLEN];
523 home = getenv("HOME");
525 // print starting after tilda
526 if(home) sprintf(string, "%s%s", home, &new_dir[1]);
527 strcpy(new_dir, string);
531 // Another user's home directory
533 char string[BCTEXTLEN], new_user[BCTEXTLEN];
537 for(i = 1, j = 0; new_dir[i] != 0 && new_dir[i] != '/'; i++, j++)
539 new_user[j] = new_dir[i];
544 while(pw = getpwent())
547 if(!strcmp(pw->pw_name, new_user))
549 // print starting after tilda
550 sprintf(string, "%s%s", pw->pw_dir, &new_dir[i]);
551 strcpy(new_dir, string);
562 int FileSystem::parse_directories(char *new_dir)
564 //printf("FileSystem::parse_directories 1 %s\n", new_dir);
565 if(new_dir[0] != '/')
567 // extend path completely
568 char string[BCTEXTLEN];
569 //printf("FileSystem::parse_directories 2 %s\n", current_dir);
570 if(!strlen(current_dir))
572 // no current directory
573 strcpy(string, new_dir);
576 if(!is_root_dir(current_dir))
578 // current directory is not root
579 if(current_dir[strlen(current_dir) - 1] == '/')
580 // current_dir already has ending /
581 sprintf(string, "%s%s", current_dir, new_dir);
584 sprintf(string, "%s/%s", current_dir, new_dir);
587 sprintf(string, "%s%s", current_dir, new_dir);
589 //printf("FileSystem::parse_directories 3 %s %s\n", new_dir, string);
590 strcpy(new_dir, string);
591 //printf("FileSystem::parse_directories 4\n");
596 int FileSystem::parse_dots(char *new_dir)
598 // recursively remove ..s
603 len = strlen(new_dir);
605 for(i = 0, j = 1; !changed && j < len; i++, j++)
607 if(new_dir[i] == '.' && new_dir[j] == '.')
610 while(new_dir[i] != '/' && i > 0)
612 // look for first / before ..
616 // find / before this /
618 while(new_dir[i] != '/' && i > 0)
620 // look for first / before first / before ..
624 // i now equals /first filename before ..
625 // look for first / after ..
626 while(new_dir[j] != '/' && j < len)
631 // j now equals /first filename after ..
634 new_dir[i++] = new_dir[j++];
638 // default to root directory
639 if((new_dir[0]) == 0) sprintf(new_dir, "/");
647 int FileSystem::complete_path(char *filename)
649 //printf("FileSystem::complete_path 1\n");
650 if(!strlen(filename)) return 1;
651 //printf("FileSystem::complete_path 1\n");
652 parse_tildas(filename);
653 //printf("FileSystem::complete_path 1\n");
654 parse_directories(filename);
655 //printf("FileSystem::complete_path 1\n");
656 parse_dots(filename);
657 // don't add end slash since this requires checking if dir
658 //printf("FileSystem::complete_path 2\n");
662 int FileSystem::extract_dir(char *out, const char *in)
667 // complete string is not directory
672 for(i = strlen(out); i > 0 && out[i - 1] != '/'; i--)
676 if(i >= 0) out[i] = 0;
681 int FileSystem::extract_name(char *out, const char *in, int test_dir)
685 if(test_dir && is_dir(in))
686 sprintf(out, ""); // complete string is directory
689 for(i = strlen(in)-1; i > 0 && in[i] != '/'; i--)
693 if(in[i] == '/') i++;
699 int FileSystem::join_names(char *out, char *dir_in, char *name_in)
702 int len = strlen(out);
706 if(len == 0 || out[len] != 0) result = 1; else len--;
710 if(out[len] != '/') strcat(out, "/");
713 strcat(out, name_in);
717 int64_t FileSystem::get_date(char *filename)
719 struct stat file_status;
720 bzero(&file_status, sizeof(struct stat));
721 stat(filename, &file_status);
722 return file_status.st_mtime;
725 int64_t FileSystem::get_size(char *filename)
727 struct stat file_status;
728 bzero(&file_status, sizeof(struct stat));
729 stat(filename, &file_status);
730 return file_status.st_size;
733 int FileSystem::change_dir(char *new_dir)
735 char new_dir_full[BCTEXTLEN];
737 strcpy(new_dir_full, new_dir);
739 complete_path(new_dir_full);
741 if(strcmp(new_dir_full, "/") &&
742 new_dir_full[strlen(new_dir_full) - 1] == '/')
743 new_dir_full[strlen(new_dir_full) - 1] = 0;
744 update(new_dir_full);
748 int FileSystem::set_current_dir(char *new_dir)
750 strcpy(current_dir, new_dir);
754 int FileSystem::add_end_slash(char *new_dir)
756 if(new_dir[strlen(new_dir) - 1] != '/') strcat(new_dir, "/");
760 char* FileSystem::get_current_dir()
765 int FileSystem::total_files()
767 return dir_list.total;
771 FileItem* FileSystem::get_entry(int entry)
773 return dir_list.values[entry];