/* * Given a directory, subscribe to Node Monitor * messages on it and all it's descendents. * For all directories, use B_WATCH_DIRECTORY. * For all file, use B_WATCH_STAT. * It also watches the directory itself * with B_WATCH_DIRECOTRY. */ void App::recursive_watch(BDirectory *dir) { status_t err; BEntry entry; err = dir->GetNextEntry(&entry); //for each file in the current directory while(err == B_OK) { //put this file in global list this->track_file(&entry); BFile file = BFile(&entry,B_READ_ONLY); if(file.IsDirectory()) { watch_entry(&entry,B_WATCH_DIRECTORY); BDirectory *ndir = new BDirectory(&entry); this->recursive_watch(ndir); delete ndir; } else { watch_entry(&entry,B_WATCH_STAT); } err = dir->GetNextEntry(&entry); } }
int outside_watch_entry(struct kdebug_entry *entry, unsigned vaddr) { return watch_entry(entry, vaddr); }
/* * Message Handling Function * If it's a node monitor message, * then figure out what to do based on it. * Otherwise, let BApplication handle it. */ void App::MessageReceived(BMessage *msg) { printf("message received:\n"); msg->PrintToStream(); switch(msg->what) { case MY_DELTA_CONST: { printf("Pulling changes from Dropbox\n"); pull_and_apply_deltas(); break; } case B_NODE_MONITOR: { printf("Received Node Monitor Alert\n"); status_t err; int32 opcode; err = msg->FindInt32("opcode",&opcode); if(err == B_OK) { switch(opcode) { case B_ENTRY_CREATED: { printf("CREATED NEW FILE\n"); entry_ref ref; BPath path; const char * name; // unpack the message msg->FindInt32("device",&ref.device); msg->FindInt64("directory",&ref.directory); msg->FindString("name",&name); ref.set_name(name); BEntry new_file = BEntry(&ref); new_file.GetPath(&path); //if we said to ignore a `NEW` msg from the path, then ignore it if(this->ignore_created(&path)) return; this->track_file(&new_file); if(new_file.IsDirectory()) { add_folder_to_dropbox(path.Path()); BDirectory new_dir = BDirectory(&new_file); this->recursive_watch(&new_dir); } else { BString *result = add_file_to_dropbox(path.Path()); BString *real_path = parse_path(result); BString *parent_rev = parse_parent_rev(result); delete result; printf("path:|%s|\nparent_rev:|%s|\n",real_path->String(),parent_rev->String()); BNode node = BNode(&new_file); set_parent_rev(&node,parent_rev); delete parent_rev; BPath new_path = BPath(db_to_local_filepath(real_path->String()).String()); if(strcmp(new_path.Leaf(),path.Leaf()) != 0) { printf("moving %s to %s\n", path.Leaf(), new_path.Leaf()); BEntry entry = BEntry(path.Path()); //entry for local path status_t err = entry.Rename(new_path.Leaf(),true); if(err != B_OK) printf("error moving: %s\n",strerror(err)); } delete real_path; watch_entry(&new_file,B_WATCH_STAT); } break; } case B_ENTRY_MOVED: { printf("MOVED FILE\n"); entry_ref eref; BDirectory from_dir, to_dir; node_ref from_ref,to_ref,nref; BPath path; const char* name; msg->FindInt32("device",&from_ref.device); msg->FindInt32("device",&to_ref.device); msg->FindInt32("device",&eref.device); msg->FindInt32("device",&nref.device); msg->FindInt64("from directory",&from_ref.node); msg->FindInt64("to directory",&to_ref.node); msg->FindInt64("to directory",&eref.directory); msg->FindInt64("node",&nref.node); msg->FindString("name",&name); eref.set_name(name); err = from_dir.SetTo(&from_ref); err = to_dir.SetTo(&to_ref); BEntry dest_entry = BEntry(&eref); BEntry test = BEntry("/boot/home/Dropbox/hi"); BDirectory dropbox_local = BDirectory(local_path_string); bool into_dropbox = dropbox_local.Contains(&dest_entry); int32 index = this->find_nref_in_tracked_files(nref); if((index >= 0) && into_dropbox) { printf("moving within dropbox\n"); BPath *old_path = (BPath*)this->tracked_filepaths.ItemAt(index); BPath new_path; dest_entry.GetPath(&new_path); char *argv[3]; argv[0] = "db_mv.py"; BString opath = local_to_db_filepath(old_path->Path()); BString npath = local_to_db_filepath(new_path.Path()); char not_const_o[opath.CountChars()]; char not_const_n[npath.CountChars()]; strcpy(not_const_o,opath.String()); strcpy(not_const_n,npath.String()); argv[1] = not_const_o; argv[2] = not_const_n; run_python_script(argv,3); old_path->SetTo(&dest_entry); } else if(index >= 0) { printf("moving the file out of dropbox\n"); BPath *old_path = (BPath*)this->tracked_filepaths.ItemAt(index); delete_file_on_dropbox(old_path->Path()); this->tracked_files.RemoveItem(index); this->tracked_filepaths.RemoveItem(index); } else if(into_dropbox) { printf("moving file into dropbox\n"); BPath new_path; dest_entry.GetPath(&new_path); this->track_file(&dest_entry); if(dest_entry.IsDirectory()) { add_folder_to_dropbox(new_path.Path()); BDirectory new_dir = BDirectory(&dest_entry); this->recursive_watch(&new_dir); } else { add_file_to_dropbox(new_path.Path()); watch_entry(&dest_entry,B_WATCH_STAT); } } else { printf("moving unrelated file...?\n"); } break; } case B_ENTRY_REMOVED: { printf("DELETED FILE\n"); node_ref nref; msg->FindInt32("device", &nref.device); msg->FindInt64("node", &nref.node); int32 index = this->find_nref_in_tracked_files(nref); if(index >= 0) { BPath *path = (BPath*)this->tracked_filepaths.ItemAt(index); printf("local file %s deleted\n",path->Path()); if(ignore_removed(path)) return; delete_file_on_dropbox(path->Path()); this->tracked_files.RemoveItem(index); this->tracked_filepaths.RemoveItem(index); } else { printf("could not find deleted file\n"); } break; } case B_STAT_CHANGED: { printf("EDITED FILE\n"); node_ref nref; msg->FindInt32("device", &nref.device); msg->FindInt64("node", &nref.node); int32 index = this->find_nref_in_tracked_files(nref); if(index >= 0) { BPath *path = (BPath*)this->tracked_filepaths.ItemAt(index); if(ignore_edited(path)) return; BNode node = BNode(path->Path()); BString * rev = get_parent_rev(&node); printf("parent_rev:|%s|\n",rev->String()); update_file_in_dropbox(path->Path(),rev->String()); } else { printf("Could not find edited file\n"); } break; } default: { printf("default case opcode...\n"); } } } break; } default: { BApplication::MessageReceived(msg); break; } } }