status_t WatchNode (BEntry *entry, uint32 flags, const BHandler *handler, const BLooper *looper) { codeLocker.Lock(); /* Derive a node_ref from the entry received */ node_ref node; entry->GetNodeRef (&node); /* Allocate a node monitor normally */ status_t result = watch_node (&node, flags, handler, looper); if (result == B_OK || result != B_NO_MEMORY) { codeLocker.Unlock(); return result; } /* Failed to start monitor, try to allocate more monitors */ result = NeedMoreNodeMonitors(); /* Failed to allocate more monitors */ if (result != B_OK) { codeLocker.Unlock(); return result; } codeLocker.Unlock(); /* Try again, this time with more node monitors */ return watch_node (&node, flags, handler, looper); }
/*! Starts watching the settings file, or if that doesn't exist, the directory the settings file will be placed into. */ void ScreenSaverFilter::_WatchSettings() { BEntry entry(fSettings.Path().Path()); if (entry.Exists()) { if (fWatchingFile) return; if (fWatchingDirectory) { watch_node(&fNodeRef, B_STOP_WATCHING, fController); fWatchingDirectory = false; } if (entry.GetNodeRef(&fNodeRef) == B_OK && watch_node(&fNodeRef, B_WATCH_ALL, fController) == B_OK) fWatchingFile = true; } else { if (fWatchingDirectory) return; if (fWatchingFile) { watch_node(&fNodeRef, B_STOP_WATCHING, fController); fWatchingFile = false; } BEntry dir; if (entry.GetParent(&dir) == B_OK && dir.GetNodeRef(&fNodeRef) == B_OK && watch_node(&fNodeRef, B_WATCH_DIRECTORY, fController) == B_OK) fWatchingDirectory = true; } }
status_t WatchNode (node_ref node, uint32 flags, const BHandler *handler, const BLooper *looper) { /* Allocate a node monitor normally */ codeLocker.Lock(); status_t result = watch_node (&node, flags, handler, looper); if (result == B_OK || result != B_NO_MEMORY) { codeLocker.Unlock(); return result; } /* Failed to start monitor, try to allocate more monitors */ result = NeedMoreNodeMonitors(); /* Failed to allocate more monitors */ if (result != B_OK) { codeLocker.Unlock(); return result; } /* Try again, this time with more node monitors */ codeLocker.Unlock(); return watch_node (&node, flags, handler, looper); }
/* * Store the parent_rev as an attribute on a local file * Takes the BNode representing the file * and a BString containing the parent_rev */ void set_parent_rev(BNode *node, const BString *rev) { printf("setting parent_rev |%s| of len %d\n" , rev->String() , rev->CountChars() + 1); node_ref nref; node->GetNodeRef(&nref); watch_node(&nref, B_STOP_WATCHING, be_app_messenger); int32 len = rev->CountChars() + 1; const char * str = rev->String(); node->WriteAttr("parent_rev_len" , B_INT32_TYPE , 0 , (void*)&len , 4); node->WriteAttr("parent_rev" , B_STRING_TYPE , 0 , (void*)str , len); watch_node(&nref, B_WATCH_STAT, be_app_messenger); }
status_t TTracker::WatchNode(const node_ref *node, uint32 flags, BMessenger target) { status_t result = watch_node(node, flags, target); if (result == B_OK || result != ENOMEM) // need to make sure this uses the same error value as // the node monitor code return result; PRINT(("failed to start monitoring, trying to allocate more " "node monitors\n")); TTracker *tracker = dynamic_cast<TTracker *>(be_app); if (!tracker) // we are the file panel only, just fail return result; result = tracker->NeedMoreNodeMonitors(); if (result != B_OK) { PRINT(("failed to allocate more node monitors, %s\n", strerror(result))); return result; } // try again, this time with more node monitors return watch_node(node, flags, target); }
void UninstallView::AttachedToWindow() { fAppList->SetTarget(this); fButton->SetTarget(this); _ReloadAppList(); // We loaded the list, but now let's set up a node watcher for the packages // directory, so that we can update the list of installed packages in real // time _CachePathToPackages(); node_ref ref; fWatcherRunning = false; BDirectory dir(fToPackages.Path()); if (dir.InitCheck() != B_OK) { // The packages/ directory obviously does not exist. // Since this is the case, we need to watch for it to appear first BPath path; fToPackages.GetParent(&path); if (dir.SetTo(path.Path()) != B_OK) return; } else fWatcherRunning = true; dir.GetNodeRef(&ref); if (watch_node(&ref, B_WATCH_DIRECTORY, this) != B_OK) { fWatcherRunning = false; return; } }
void NotificationWindow::_LoadSettings(bool startMonitor) { BPath path; BMessage settings; if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK) return; path.Append(kSettingsFile); BFile file(path.Path(), B_READ_ONLY | B_CREATE_FILE); settings.Unflatten(&file); _LoadGeneralSettings(settings); _LoadDisplaySettings(settings); _LoadAppFilters(settings); if (startMonitor) { node_ref nref; BEntry entry(path.Path()); entry.GetNodeRef(&nref); if (watch_node(&nref, B_WATCH_ALL, BMessenger(this)) != B_OK) { BAlert* alert = new BAlert(B_TRANSLATE("Warning"), B_TRANSLATE("Couldn't start general settings monitor.\n" "Live filter changes disabled."), B_TRANSLATE("OK")); alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE); alert->Go(NULL); } } }
status_t ArpConfigureFile::StartWatcher(void) { StopWatcher(); ArpD(cdb << ADH << "Starting watcher..." << endl); if( mFile != entry_ref() && mWatcher.IsValid() ) { ArpD(cdb << ADH << "On file: " << Path().Path() << endl); BEntry entry(&mFile); if( entry.InitCheck() != B_OK ) return entry.InitCheck(); status_t err = entry.GetNodeRef(&mNode); if( err != B_OK ) return err; BLooper* looper=0; mWatcher.Target(&looper); ArpD(cdb << ADH << "Target is: " << looper << endl); if( looper == 0 ) { mNode = node_ref(); return B_ERROR; } looper->AddHandler(this); err = watch_node(&mNode, B_WATCH_ALL, this); ArpD(cdb << ADH << "Result from watch_node(): " << err << endl); if( err != B_OK ) { looper->RemoveHandler(this); mNode = node_ref(); return err; } } return B_OK; }
// StopWatching status_t NodeMonitor::StopWatching(const node_ref& ref) { PRINT("NodeMonitor: stopped watching node: (%ld, %lld)\n", ref.device, ref.node); return watch_node(&ref, B_STOP_WATCHING, this); }
status_t PathHandler::_RemoveDirectory(const node_ref& nodeRef, ino_t directoryNode) { TRACE(" REMOVE DIRECTORY %ld:%Ld\n", nodeRef.device, nodeRef.node); WatchedDirectory directory; directory.node = nodeRef; DirectorySet::iterator iterator = fDirectories.find(directory); if (iterator == fDirectories.end()) return B_ENTRY_NOT_FOUND; watch_node(&directory.node, B_STOP_WATCHING, this); node_ref directoryRef; directoryRef.device = nodeRef.device; directoryRef.node = directoryNode; if (!_HasDirectory(directoryRef)) { // we don't have the parent directory now, but we'll need it in order // to find this directory again in case it's added again if (_AddDirectory(directoryRef) != B_OK && _GetClosest(fPath.Path(), false, directoryRef) == B_OK) _AddDirectory(directoryRef); } fDirectories.erase(iterator); // TODO: stop watching subdirectories and their files when in recursive // mode! return B_OK; }
/* * Sets up the Node Monitoring for Dropbox folder and contents * and creates data structure for determining which files are deleted or edited */ App::App(void) : BApplication("application/x-vnd.lh-MyDropboxClient") { pull_and_apply_deltas(); printf("Done pulling changes, now to start tracking\n"); //start watching ~/Dropbox folder contents (create, delete, move) BDirectory dir(local_path_string_noslash); //don't use ~ here node_ref nref; status_t err; if(dir.InitCheck() == B_OK){ dir.GetNodeRef(&nref); err = watch_node(&nref, B_WATCH_DIRECTORY, be_app_messenger); if(err != B_OK) printf("Watch Node: Not OK\n"); } printf("Done watching root directory\n"); //watch all the child files for edits and the folders for create/delete/move this->recursive_watch(&dir); printf("Done watching and tracking all children of ~/Dropbox.\n"); BMessage msg = BMessage(MY_DELTA_CONST); bigtime_t microseconds = HOW_OFTEN_TO_POLL; this->msg_runner = new BMessageRunner(be_app_messenger, msg, microseconds, -1); }
void PersonWindow::_WatchChanges(bool enable) { if (fRef == NULL) return; node_ref nodeRef; BNode node(fRef); node.GetNodeRef(&nodeRef); uint32 flags; BString action; if (enable) { // Start watching. flags = B_WATCH_ALL; action = "starting"; } else { // Stop watching. flags = B_STOP_WATCHING; action = "stoping"; } if (watch_node(&nodeRef, flags, this) != B_OK) { printf("Error %s node monitor.\n", action.String()); } }
void BClipboardRefsWatcher::RemoveNodesByDevice(dev_t device) { if (!be_clipboard->Lock()) return; BMessage *clip = be_clipboard->Data(); if (clip != NULL) { char deviceName[6]; sprintf(deviceName, "r%ld_", device); int32 index = 0; char *refName; type_code type; int32 count; while (clip->GetInfo(B_REF_TYPE, index, #ifdef B_BEOS_VERSION_DANO (const char **) #endif &refName, &type, &count) == B_OK) { if (!strncmp(deviceName, refName, strlen(deviceName))) { clip->RemoveName(refName); MakeModeName(refName); clip->RemoveName(refName); node_ref node; MakeNodeFromName(&node, refName); watch_node(&node, B_STOP_WATCHING, this); } index++; } be_clipboard->Commit(); } be_clipboard->Unlock(); }
void DownloadProgressView::_StartNodeMonitor(const BEntry& entry) { node_ref nref; if (entry.GetNodeRef(&nref) == B_OK) watch_node(&nref, B_WATCH_ALL, this); }
void ActivityView::_LoadBackgroundInfo(bool watch) { fCachedOutline = false; fCachedWorkspace = -1; BPath path; if (find_directory(B_DESKTOP_DIRECTORY, &path) == B_OK) { BNode desktopNode = BNode(path.Path()); attr_info info; if (desktopNode.GetAttrInfo(kDesktopAttrName, &info) != B_OK) return; char* buffer = new char[info.size]; if (desktopNode.ReadAttr(kDesktopAttrName, B_MESSAGE_TYPE, 0, buffer, (size_t)info.size) == info.size) { BMessage message; if (message.Unflatten(buffer) == B_OK) fBackgroundInfo = message; } delete[] buffer; if (watch) { node_ref nref; desktopNode.GetNodeRef(&nref); watch_node(&nref, B_WATCH_ATTR, this); } } }
status_t DirectoryView::OpenDirectory(const Entry* dir) { if (! dir->IsDirectory()) { return B_ERROR; } // stop node watcher stop_watching(this); // clear entry data and listview mListView->DeleteAllItems(); entryList_.DeleteAllItems(); if (entry_) { delete entry_; entry_ = NULL; } if (parent_) { delete parent_; parent_ = NULL; } UpdateStatus(); // set current directory entry_ = new Directory(*(Directory*)dir); // get parent directory BEntry bentry; if (entry_->GetBEntry(&bentry) == B_OK) { BEntry parent; if (bentry.GetParent(&parent) == B_OK) { parent_ = new Directory(parent); } } // get directory entry ListVisitor* lv1 = new ListVisitor(*entry_, &entryList_); lv1->Go(); delete lv1; // show directory entry if (parent_ != NULL) { mListView->AddItem(new EntryListItem(parent_, EntryListItem::ENTRY_IS_PARENT)); } mListView->AddEntryList((BList*) &entryList_); mListView->DoSort(); if (mListView->CountItems() > 0) mListView->Select(0); UpdateStatus(); // start node watcher if (bentry.InitCheck() == B_OK) { node_ref nref; bentry.GetNodeRef(&nref); watch_node(&nref, B_WATCH_ALL, this); } return B_OK; }
BClipboardRefsWatcher::BClipboardRefsWatcher() : BLooper("ClipboardRefsWatcher", B_LOW_PRIORITY, 4096), fNotifyList(10, false) { watch_node(NULL, B_WATCH_MOUNT, this); fRefsInClipboard = FSClipboardHasRefs(); be_clipboard->StartWatching(this); }
// StartWatching status_t NodeMonitor::StartWatching(const node_ref& ref) { uint32 flags = B_WATCH_ALL; status_t error = watch_node(&ref, flags, this); // If starting to watch the node fail, we allocate more node // monitoring slots and try again. if (error != B_OK) { error = _IncreaseLimit(); if (error == B_OK) error = watch_node(&ref, flags, this); } if (error == B_OK) { PRINT("NodeMonitor: started watching node: (%ld, %lld)\n", ref.device, ref.node); } return error; }
/*! Adds a new directory to the roster. Note, the order in which these directories are added to actually matters, see AddPaths(). */ status_t BTranslatorRoster::Private::AddPath(const char* path, int32* _added) { BDirectory directory(path); status_t status = directory.InitCheck(); if (status != B_OK) return status; // if a subdirectory for our ABI exists, use that instead if (fABISubDirectory != NULL) { BEntry entry(&directory, fABISubDirectory); if (entry.IsDirectory()) { status = directory.SetTo(&entry); if (status != B_OK) return status; } } node_ref nodeRef; status = directory.GetNodeRef(&nodeRef); if (status < B_OK) return status; // do we know this directory already? if (_IsKnownDirectory(nodeRef)) return B_OK; if (Looper() != NULL) { // watch that directory watch_node(&nodeRef, B_WATCH_DIRECTORY, this); fDirectories.push_back(nodeRef); } int32 count = 0; int32 files = 0; entry_ref ref; while (directory.GetNextRef(&ref) == B_OK) { BEntry entry(&ref); if (entry.IsDirectory()) continue; if (CreateTranslators(ref, count) == B_OK) count++; files++; } if (_added) *_added = count; if (files != 0 && count == 0) return B_BAD_VALUE; return B_OK; }
status_t FontManager::_AddPath(BEntry& entry, font_directory** _newDirectory) { node_ref nodeRef; status_t status = entry.GetNodeRef(&nodeRef); if (status != B_OK) return status; // check if we are already know this directory font_directory* directory = _FindDirectory(nodeRef); if (directory != NULL) { if (_newDirectory) *_newDirectory = directory; return B_OK; } // it's a new one, so let's add it directory = new (std::nothrow) font_directory; if (directory == NULL) return B_NO_MEMORY; struct stat stat; status = entry.GetStat(&stat); if (status != B_OK) { delete directory; return status; } directory->directory = nodeRef; directory->user = stat.st_uid; directory->group = stat.st_gid; directory->revision = 0; status = watch_node(&nodeRef, B_WATCH_DIRECTORY, this); if (status != B_OK) { // we cannot watch this directory - while this is unfortunate, // it's not a critical error printf("could not watch directory %ld:%Ld\n", nodeRef.device, nodeRef.node); // TODO: should go into syslog() } else { BPath path(&entry); FTRACE(("FontManager: now watching: %s\n", path.Path())); } fDirectories.AddItem(directory); if (_newDirectory) *_newDirectory = directory; fScanned = false; return B_OK; }
/*! \brief Subscribes a target to node and/or mount watching, or unsubscribes it from node watching. Depending of \a flags the action performed by this function varies: - \a flags is \c 0: The target is unsubscribed from watching the node. \a node must not be \c NULL in this case. - \a flags contains \c B_WATCH_MOUNT: The target is subscribed to mount watching. - \a flags contains at least one of \c B_WATCH_NAME, \c B_WATCH_STAT, \c B_WATCH_ATTR, or \c B_WATCH_DIRECTORY: The target is subscribed to watching the specified aspects of the node. \a node must not be \c NULL in this case. Note, that the latter two cases are not mutual exlusive, i.e. mount and node watching can be requested with a single call. \param node node_ref referring to the node to be watched. May be \c NULL, if only mount watching is requested. \param flags Flags indicating the actions to be performed. \param target Messenger referring to the target. Must be valid. \return \c B_OK, if everything went fine, another error code otherwise. */ status_t watch_node(const node_ref *node, uint32 flags, BMessenger target) { status_t error = (target.IsValid() ? B_OK : B_BAD_VALUE); if (error == B_OK) { BLooper *looper = NULL; BHandler *handler = target.Target(&looper); error = watch_node(node, flags, handler, looper); } return error; }
status_t ArpConfigureFile::StopWatcher(void) { ArpD(cdb << ADH << "Stopping watcher..." << endl); status_t err = B_NO_ERROR; if( mNode != node_ref() ) { err = watch_node(&mNode, B_STOP_WATCHING, this); } if( Looper() ) Looper()->RemoveHandler(this); return err; }
VolumeWatcher::VolumeWatcher() : BHandler("volume watcher") { if (be_app->Lock()) { be_app->AddHandler(this); watch_node(NULL, B_WATCH_MOUNT, this); be_app->Unlock(); } }
status_t PathHandler::_AddFile(BEntry& entry, bool notify) { if ((fFlags & (WATCH_NODE_FLAG_MASK & ~B_WATCH_DIRECTORY)) == 0) return B_OK; #ifdef TRACE_PATH_MONITOR { BPath path(&entry); TRACE(" ADD FILE %s\n", path.Path()); } #endif node_ref nodeRef; status_t status = entry.GetNodeRef(&nodeRef); if (status != B_OK) return status; // check if we already know this file // TODO: It should be possible to omit this check if we know it // can't be the case (for example when adding subfolders recursively, // although in that case, the API user may still have added this file // independently, so for now, it should be the safest to perform this // check in all cases.) if (_HasFile(nodeRef)) return B_OK; status = watch_node(&nodeRef, (fFlags & WATCH_NODE_FLAG_MASK), this); if (status != B_OK) return status; FileEntry setEntry; entry.GetRef(&setEntry.ref); setEntry.node = nodeRef.node; fFiles.insert(setEntry); if (notify && _WatchFilesOnly()) { // We also notify our target about new files if it's only interested // in files; it won't be notified about new directories, so it cannot // know when to search for them. BMessage update; update.AddInt32("opcode", B_ENTRY_CREATED); update.AddInt32("device", nodeRef.device); update.AddInt64("directory", setEntry.ref.directory); update.AddString("name", setEntry.ref.name); update.AddBool("added", true); _NotifyTarget(&update, nodeRef); } return B_OK; }
TEnclosuresView::~TEnclosuresView() { for (int32 index = fList->CountItems();index-- > 0;) { TListItem *item = static_cast<TListItem *>(fList->ItemAt(index)); fList->RemoveItem(index); if (item->Component() == NULL) watch_node(item->NodeRef(), B_STOP_WATCHING, this); delete item; } }
void FontManager::_RemoveDirectory(font_directory* directory) { FTRACE(("FontManager: Remove directory (%Ld)!\n", directory->directory.node)); fDirectories.RemoveItem(directory, false); // TODO: remove styles from this directory! watch_node(&directory->directory, B_STOP_WATCHING, this); delete directory; }
void MailingList::Go() { if (fApp->GetMaxMsgBytes() < fMaxContentBytes) { fMaxContentBytes=fApp->GetMaxMsgBytes(); } if (fApp->GetPlainTextOnly()=='Y') { if ( (fPlainTextOnly=='N') ) { LogError("INFO: List is set to allow HTML text messages and attachments but server isn't. List setting is being overridden by server setting"); } else if (fPlainTextOnly=='H') { LogError("INFO: List is set to allow HTML text messages but server isn't. List setting is being overridden by server setting"); } fPlainTextOnly='Y'; } else if (fApp->GetPlainTextOnly()=='H') { if ( (fPlainTextOnly=='N') ) { LogError("INFO: List is set to allow HTML text messages but server isn't. List setting is being overridden by server setting"); fPlainTextOnly='H'; } } //setup Node Monitor to send messages to app if a new file appears BDirectory indir(fListInDirectoryPath.c_str()); node_ref indir_node_ref; status_t err; if (indir.InitCheck() == B_OK) { indir.GetNodeRef(&indir_node_ref); err=watch_node(&indir_node_ref,B_WATCH_DIRECTORY,be_app); if (err!=B_OK) { //could not set watch on BDirectory exit; } } else { //could not init BDirectory exit; } //now process any files which were already in the dir when we launched BMessage msg(B_PULSE); fApp->PostMessage(&msg,NULL); }
void App::StartWatching() { gRefLock.Lock(); for (int32 i = 0; i < gRefStructList.CountItems(); i++) { RefStorage* refholder = (RefStorage*)gRefStructList.ItemAt(i); watch_node(&refholder->nref, B_WATCH_ALL, this); } gRefLock.Unlock(); }
// constructor NodeMonitor::NodeMonitor(NodeMonitorListener* listener) : BLooper("node monitor", B_DISPLAY_PRIORITY, 1000), fListener(listener), fCurrentNodeMonitorLimit(kDefaultNodeMonitorLimit) { // set the initial limit -- just to be sure struct rlimit rl; rl.rlim_cur = fCurrentNodeMonitorLimit; rl.rlim_max = RLIM_SAVED_MAX; setrlimit(RLIMIT_NOVMON, &rl); // start volume watching watch_node(NULL, B_WATCH_MOUNT, this); }
/* * Subscribe to Node Monitor alerts * Just wraps the watch_node function of the Node Monitor * (with the BMessenger being be_app_messenger) */ void watch_entry(const BEntry *entry, int flag) { node_ref nref; status_t err; err = entry->GetNodeRef(&nref); if(err == B_OK) { err = watch_node(&nref, flag, be_app_messenger); if(err != B_OK) printf("watch_entry: Not Ok.\n"); } }