Пример #1
0
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;
}
Пример #2
0
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;
}
Пример #3
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;
}
Пример #4
0
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;
}
Пример #5
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);
}
Пример #6
0
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;
}
Пример #7
0
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;
}
Пример #8
0
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;
}
Пример #10
0
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);
}
Пример #11
0
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);
    }
}
Пример #12
0
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;
}