/*
* 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);
  }
}
Example #2
0
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;
    }
  }
}