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; }
static nodeid get_or_create_leaf(fs_ptree *pt, fs_rid pk) { nodeid pos = FS_PTREE_ROOT_NODE; for (int i=0; i < 64/FS_PTREE_BRANCH_BITS; i++) { int kbranch = PK_BRANCH(pk, i); again:; node *nr = node_ref(pt, pos); if (!nr) { fs_error(LOG_CRIT, "failed to get node ref"); break; } nodeid newpos = nr->branch[kbranch]; if (newpos == FS_PTREE_NULL_NODE) { int done = 0; if (i > 1) { newpos = fs_ptree_new_leaf(pt); LEAF_REF(pt, newpos)->pk = pk; done = 1; } else { newpos = fs_ptree_new_node(pt); } node_ref(pt, pos)->branch[kbranch] = newpos; if (done) { return newpos; } } else if (IS_LEAF(newpos)) { const fs_rid existpk = LEAF_REF(pt, newpos)->pk; if (pk == existpk) { /* PKs are the same, we can reuse the block */ return newpos; } /* split and insert node */ int oldkbr = PK_BRANCH(existpk, i-1); nodeid split = fs_ptree_new_node(pt); node_ref(pt, pos)->branch[kbranch] = split; node_ref(pt, split)->branch[oldkbr] = newpos; goto again; } pos = newpos; } fs_error(LOG_ERR, "fell through get_or_create_leaf(%016llx)", pk); char tmp[256]; tmp[0] = '\0'; for (int i=0; i < 64/FS_PTREE_BRANCH_BITS; i++) { int kbranch = PK_BRANCH(pk, i); char tmp2[16]; sprintf(tmp2, "%d.", kbranch); strcat(tmp, tmp2); } fs_error(LOG_ERR, "path was %s", tmp); return 0; }
status_t BDaemonClient::GetInstallationLocationInfo( BPackageInstallationLocation location, BInstallationLocationInfo& _info) { status_t error = _InitMessenger(); if (error != B_OK) return error; // send the request BMessage request(B_MESSAGE_GET_INSTALLATION_LOCATION_INFO); error = request.AddInt32("location", location); if (error != B_OK) return error; BMessage reply; fDaemonMessenger.SendMessage(&request, &reply); if (reply.what != B_MESSAGE_GET_INSTALLATION_LOCATION_INFO_REPLY) return B_ERROR; // extract the location info int32 baseDirectoryDevice; int64 baseDirectoryNode; int32 packagesDirectoryDevice; int64 packagesDirectoryNode; int64 changeCount; BPackageInfoSet activePackages; BPackageInfoSet inactivePackages; if ((error = reply.FindInt32("base directory device", &baseDirectoryDevice)) != B_OK || (error = reply.FindInt64("base directory node", &baseDirectoryNode)) != B_OK || (error = reply.FindInt32("packages directory device", &packagesDirectoryDevice)) != B_OK || (error = reply.FindInt64("packages directory node", &packagesDirectoryNode)) != B_OK || (error = _ExtractPackageInfoSet(reply, "active packages", activePackages)) != B_OK || (error = _ExtractPackageInfoSet(reply, "inactive packages", inactivePackages)) != B_OK || (error = reply.FindInt64("change count", &changeCount)) != B_OK) { return error; } _info.Unset(); _info.SetLocation(location); _info.SetBaseDirectoryRef(node_ref(baseDirectoryDevice, baseDirectoryNode)); _info.SetPackagesDirectoryRef( node_ref(packagesDirectoryDevice, packagesDirectoryNode)); _info.SetActivePackageInfos(activePackages); _info.SetInactivePackageInfos(inactivePackages); _info.SetChangeCount(changeCount); return B_OK; }
static nodeid get_leaf_and_parent(fs_ptree *pt, fs_rid pk, nodeid *parent) { nodeid pos = FS_PTREE_ROOT_NODE; for (int i=0; i < 64/FS_PTREE_BRANCH_BITS; i++) { int kbranch = PK_BRANCH(pk, i); nodeid newpos = node_ref(pt, pos)->branch[kbranch]; if (newpos == FS_PTREE_NULL_NODE) { return 0; } else if (IS_LEAF(newpos)) { if (pk == LEAF_REF(pt, newpos)->pk) { /* PKs are the same, we can use the block */ if (parent) *parent = pos; return newpos; } return 0; } pos = newpos; } fs_error(LOG_ERR, "fell through get_leaf(%016llx)", pk); char tmp[256]; tmp[0] = '\0'; for (int i=0; i < 64/FS_PTREE_BRANCH_BITS; i++) { int kbranch = PK_BRANCH(pk, i); char tmp2[16]; sprintf(tmp2, "%d.", kbranch); strcat(tmp, tmp2); } fs_error(LOG_ERR, "path was %s", tmp); return 0; }
struct Node * node_eval(struct Node *node) { if(node_classes[node->type].eval_func) { return (* node_classes[node->type].eval_func)(node); } return node_ref(node); }
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; }
int fs_ptree_traverse_next(fs_ptree_it *it, fs_rid quad[4]) { top:; while (it->block) { int matched = 0; fs_rid row[2]; fs_ptable_get_row(it->pt->table, it->block, row); if ((it->pair[0] == FS_RID_NULL || it->pair[0] == row[0])) { quad[0] = row[0]; quad[1] = it->pk; /* don't fill out the predicate */ quad[3] = row[1]; matched = 1; } it->block = fs_ptable_get_next(it->pt->table, it->block); if (matched) return 1; } if (!it->stack) return 0; it->block = 0; tree_pos *pos = it->stack; node *no = node_ref(it->pt, pos->node); for (int b=pos->branch; b<FS_PTREE_BRANCHES; b++) { if (no->branch[b] == FS_PTREE_NULL_NODE) { /* dead end, do nothing */ } else if (IS_LEAF(no->branch[b])) { leaf *l = LEAF_REF(it->pt, no->branch[b]); it->block = l->block; it->pk = l->pk; pos->branch = b+1; goto top; } else { tree_pos *newpos = malloc(sizeof(tree_pos)); newpos->node = no->branch[b]; newpos->branch = 0; newpos->next = pos->next; pos->next = newpos; } } it->stack = pos->next; free(pos); goto top; }
static enum recurse_action collapse_by_pk_recurse(fs_ptree *pt, fs_rid pk, fs_index_node n, int level) { node *no = node_ref(pt, n); int b = PK_BRANCH(pk, level); if (no->branch[b] == FS_PTREE_NULL_NODE) { /* dead end, do nothing */ return NONE; } else if (IS_LEAF(no->branch[b])) { leaf *lref = LEAF_REF(pt, no->branch[b]); if (lref->length == 0 && lref->block == 0) { fs_ptree_free_leaf(pt, no->branch[b]); no->branch[b] = FS_PTREE_NULL_NODE; } else { fs_error(LOG_ERR, "hit an unexpected non-empty leaf recursing pk %016llx in %s", pk, pt->filename); } } else { enum recurse_action action = collapse_by_pk_recurse(pt, pk, no->branch[b], level+1); if (action == CULL) { fs_ptree_free_node(pt, no->branch[b]); no->branch[b] = FS_PTREE_NULL_NODE; } else if (action == MERGE) { /* MERGE not currently implemented, harmless, but less efficient * than it could be */ } } int branches = 0; for (int c=0; c<FS_PTREE_BRANCHES; c++) { if (no->branch[c] != FS_PTREE_NULL_NODE) branches++; } if (branches == 0) { return CULL; } return NONE; }
bool VirtualDirectoryPoseView::_EntryRemoved(const BMessage* message) { NotOwningEntryRef entryRef; node_ref nodeRef; if (message->FindInt32("device", &nodeRef.device) != B_OK || message->FindInt64("node", &nodeRef.node) != B_OK || message->FindInt64("directory", &entryRef.directory) != B_OK || message->FindString("name", (const char**)&entryRef.name) != B_OK) { return true; } entryRef.device = nodeRef.device; // It might be our definition file. if (nodeRef == *TargetModel()->NodeRef()) return _inherited::FSNotification(message); // It might be one of our directories. BString path; if (message->FindString("path", &path) == B_OK && fDirectoryPaths.HasString(path)) { // Find all poses that stem from that directory and generate an // entry-removed message for each. PoseList poses; for (int32 i = 0; BPose* pose = fPoseList->ItemAt(i); i++) { NotOwningEntryRef poseEntryRef = *pose->TargetModel()->EntryRef(); if (poseEntryRef.DirectoryNodeRef() == nodeRef) poses.AddItem(pose); } for (int32 i = 0; BPose* pose = poses.ItemAt(i); i++) { _DispatchEntryCreatedOrRemovedMessage(B_ENTRY_REMOVED, *pose->TargetModel()->NodeRef(), *pose->TargetModel()->EntryRef(), NULL, false); } return true; } // If it is a directory, translate it. entry_ref* actualEntryRef = &entryRef; node_ref* actualNodeRef = &nodeRef; entry_ref definitionEntryRef; node_ref definitionNodeRef; VirtualDirectoryManager* manager = VirtualDirectoryManager::Instance(); AutoLocker<VirtualDirectoryManager> managerLocker(manager); if (manager != NULL && manager->GetSubDirectoryDefinitionFile(*TargetModel()->NodeRef(), entryRef.name, definitionEntryRef, definitionNodeRef)) { actualEntryRef = &definitionEntryRef; actualNodeRef = &definitionNodeRef; } // Check the pose. It might have been an entry that wasn't visible anyway. // In that case we can just ignore the notification. BPose* pose = fPoseList->FindPoseByFileName(actualEntryRef->name); if (pose == NULL || *actualNodeRef != *pose->TargetModel()->NodeRef()) return true; // See, if another entry becomes visible, now. struct stat st; entry_ref visibleEntryRef; node_ref visibleNodeRef; if (_GetEntry(actualEntryRef->name, visibleEntryRef, &st)) { // If the new entry is a directory, translate it. visibleNodeRef = node_ref(st.st_dev, st.st_ino); if (S_ISDIR(st.st_mode)) { if (manager == NULL || manager->TranslateDirectoryEntry( *TargetModel()->NodeRef(), visibleEntryRef, visibleNodeRef) != B_OK) { return true; } // Effectively nothing changes, when the removed entry was a // directory as well. if (visibleNodeRef == *actualNodeRef) return true; } } if (actualEntryRef == &entryRef) { managerLocker.Unlock(); if (_inherited::FSNotification(message)) pendingNodeMonitorCache.Add(message); } else { // tell the manager that the directory has been removed manager->DirectoryRemoved(*actualNodeRef); managerLocker.Unlock(); _DispatchEntryCreatedOrRemovedMessage(B_ENTRY_REMOVED, *actualNodeRef, *actualEntryRef); } _DispatchEntryCreatedOrRemovedMessage(B_ENTRY_CREATED, visibleNodeRef, visibleEntryRef); return true; }
bool VirtualDirectoryPoseView::_EntryCreated(const BMessage* message) { NotOwningEntryRef entryRef; node_ref nodeRef; if (message->FindInt32("device", &nodeRef.device) != B_OK || message->FindInt64("node", &nodeRef.node) != B_OK || message->FindInt64("directory", &entryRef.directory) != B_OK || message->FindString("name", (const char**)&entryRef.name) != B_OK) { return true; } entryRef.device = nodeRef.device; // It might be one of our directories. BString path; if (message->FindString("path", &path) == B_OK && fDirectoryPaths.HasString(path)) { // Iterate through the directory and generate an entry-created message // for each entry. BDirectory directory; if (directory.SetTo(&nodeRef) != B_OK) return true; BPrivate::Storage::LongDirEntry entry; while (directory.GetNextDirents(&entry, sizeof(entry), 1) == 1) { if (strcmp(entry.d_name, ".") != 0 && strcmp(entry.d_name, "..") != 0) { _DispatchEntryCreatedOrRemovedMessage(B_ENTRY_CREATED, node_ref(entry.d_dev, entry.d_ino), NotOwningEntryRef(entry.d_pdev, entry.d_pino, entry.d_name), NULL, false); } } return true; } // See, if this entry actually becomes visible. If not, we can simply ignore // it. struct stat st; entry_ref visibleEntryRef; if (!_GetEntry(entryRef.name, visibleEntryRef, &st) || visibleEntryRef != entryRef) { return true; } // If it is a directory, translate it. VirtualDirectoryManager* manager = VirtualDirectoryManager::Instance(); AutoLocker<VirtualDirectoryManager> managerLocker(manager); bool entryTranslated = S_ISDIR(st.st_mode); if (entryTranslated) { if (manager == NULL) return true; if (manager->TranslateDirectoryEntry(*TargetModel()->NodeRef(), entryRef, nodeRef) != B_OK) { return true; } } // The entry might replace another entry. If it does, we'll fake a removed // message for the old one first. BPose* pose = fPoseList->FindPoseByFileName(entryRef.name); if (pose != NULL) { if (nodeRef == *pose->TargetModel()->NodeRef()) { // apparently not really a new entry -- can happen for // subdirectories return true; } // It may be a directory, so tell the manager. if (manager != NULL) manager->DirectoryRemoved(*pose->TargetModel()->NodeRef()); managerLocker.Unlock(); BMessage removedMessage(B_NODE_MONITOR); _DispatchEntryCreatedOrRemovedMessage(B_ENTRY_REMOVED, *pose->TargetModel()->NodeRef(), *pose->TargetModel()->EntryRef()); } else managerLocker.Unlock(); return entryTranslated ? (_DispatchEntryCreatedOrRemovedMessage(B_ENTRY_CREATED, nodeRef, entryRef), true) : _inherited::FSNotification(message); }
static void recurse_print(fs_ptree *pt, nodeid n, char *buffer, int pos, struct ptree_stats *stats, FILE *out, int verbosity) { unsigned int len = 0; node *no = node_ref(pt, n); int branches = 0; int leaves = 0; for (int b=0; b<FS_PTREE_BRANCHES; b++) { sprintf(buffer+pos, "%x", b); if (no->branch[b] == FS_PTREE_NULL_NODE) { (stats->deadends)++; } else if (IS_LEAF(no->branch[b])) { branches++; leaves++; (stats->leaves)++; buffer[pos+1] ='\0'; fprintf(out, "%-32s [B%08x, %016llx x %d]\n", buffer, LEAF_REF(pt, no->branch[b])->block, LEAF_REF(pt, no->branch[b])->pk, LEAF_REF(pt, no->branch[b])->length); if (pt->table) { int check_len = 0; fs_ptable_check_consistency(pt->table, out, no->branch[b], LEAF_REF(pt, no->branch[b])->block, &check_len); if (LEAF_REF(pt, no->branch[b])->length != check_len) { fprintf(out, "ERROR: tree leaf has length %d, but consistency check says %d\n", LEAF_REF(pt, no->branch[b])->length, check_len); } if (LEAF_REF(pt, no->branch[b])->length == 0) { if (LEAF_REF(pt, no->branch[b])->block != 0) { fprintf(out, "ERROR: tree leaf has 0 length, but block is non-zero\n"); } else { fprintf(out, "ERROR: tree leaf has 0 length, should have been colected\n"); } } else if (LEAF_REF(pt, no->branch[b])->length < 0) { fprintf(out, "ERROR: tree node length is %d\n", LEAF_REF(pt, no->branch[b])->length < 0); } else if (LEAF_REF(pt, no->branch[b])->block == 0) { fprintf(out, "ERROR: tree node references block zero, but has non-zero length\n"); } else if ((len = fs_ptable_chain_length(pt->table, LEAF_REF(pt, no->branch[b])->block, LEAF_REF(pt, no->branch[b])->length + 100)) != LEAF_REF(pt, no->branch[b])->length) { if (LEAF_REF(pt, no->branch[b])->length + 101 == len) { fprintf(out, "ERROR: probable loop in table, tree node length %d, table length > %d\n", LEAF_REF(pt, no->branch[b])->length, len); } else { fprintf(out, "ERROR: tree node length %d != table length %d\n", LEAF_REF(pt, no->branch[b])->length, len); } } } stats->count += LEAF_REF(pt, no->branch[b])->length; for (int c=0; c<pos; c++) { buffer[c] = '.'; } } else { (stats->nodes)++; branches++; recurse_print(pt, no->branch[b], buffer, pos+1, stats, out, verbosity); } } if (branches == 1 && leaves == 1 && pos > 2 && n != FS_PTREE_ROOT_NODE) { fprintf(out, "ERROR: node %08x has 1 leaf at depth %d, should have " "been merged up\n", n, pos); } else if (branches == 0 && n != FS_PTREE_ROOT_NODE) { fprintf(out, "ERROR: node %08x has 0 branches at depth %d, should " "have been culled\n", n, pos); } }
static enum recurse_action remove_all_recurse(fs_ptree *pt, fs_rid pair[2], nodeid n, int *removed) { node *no = node_ref(pt, n); int branches = 0; int leaves = 0; for (int b=0; b<FS_PTREE_BRANCHES; b++) { if (no->branch[b] == FS_PTREE_NULL_NODE) { /* dead end, do nothing */ } else if (IS_LEAF(no->branch[b])) { leaf *lref = LEAF_REF(pt, no->branch[b]); int sub_removed = 0; if (lref->block) { fs_row_id newblock = fs_ptable_remove_pair(pt->table, lref->block, pair, &sub_removed, NULL); if (lref->block != newblock) { lref->block = newblock; } if (sub_removed) { lref->length -= sub_removed; } if (removed) { (*removed) += sub_removed; } } if (sub_removed && lref->length == 0) { fs_ptree_free_leaf(pt, no->branch[b]); no->branch[b] = FS_PTREE_NULL_NODE; } else { branches++; leaves++; } } else { enum recurse_action action = remove_all_recurse(pt, pair, no->branch[b], removed); if (action == CULL) { fs_ptree_free_node(pt, no->branch[b]); no->branch[b] = FS_PTREE_NULL_NODE; } else if (action == MERGE) { node *sub = NODE_REF(pt, no->branch[b]); nodeid subn = FS_PTREE_NULL_NODE; for (int subb=0; subb<FS_PTREE_BRANCHES; subb++) { if (sub->branch[subb] != FS_PTREE_NULL_NODE) { subn = sub->branch[subb]; break; } } if (subn != FS_PTREE_NULL_NODE) { fs_ptree_free_node(pt, no->branch[b]); no->branch[b] = subn; } else { fs_error(LOG_CRIT, "tried to merge nodes, but no children were available"); } branches++; } else { branches++; } } } if (branches == 0) { return CULL; } else if (branches == 1 && leaves == 1) { return MERGE; } return NONE; }