static void test_set_A_unset_B_unset_A_cannot_find_A_can_find_B () { gdb_environ env; env.set ("GDB_SELFTEST_ENVIRON_1", "aaa"); SELF_CHECK (strcmp (env.get ("GDB_SELFTEST_ENVIRON_1"), "aaa") == 0); /* User-set environ var list must contain one element. */ SELF_CHECK (env.user_set_env ().size () == 1); SELF_CHECK (set_contains (env.user_set_env (), std::string ("GDB_SELFTEST_ENVIRON_1=aaa"))); env.set ("GDB_SELFTEST_ENVIRON_2", "bbb"); SELF_CHECK (strcmp (env.get ("GDB_SELFTEST_ENVIRON_2"), "bbb") == 0); env.unset ("GDB_SELFTEST_ENVIRON_1"); SELF_CHECK (env.get ("GDB_SELFTEST_ENVIRON_1") == NULL); SELF_CHECK (strcmp (env.get ("GDB_SELFTEST_ENVIRON_2"), "bbb") == 0); /* The user-set environ var list must contain only one element now. */ SELF_CHECK (set_contains (env.user_set_env (), std::string ("GDB_SELFTEST_ENVIRON_2=bbb"))); SELF_CHECK (env.user_set_env ().size () == 1); }
int main(int argc, char *argv[]) { void *a = new(String, "a"); void *b = new(String, "bbb"); void *s = new(Set); printf("LENGTH A: %lu\n", string_length(a)); printf("LENGTH B: %lu\n", string_length(b)); printf("Prev: %s\n", string_get(a)); string_set(a, "New String"); printf("New: %s\n", string_get(a)); set_add(s, a); set_add(s, b); printf("CONTAINS A: %u\n", set_contains(s, a)); printf("CONTAINS B: %u\n", set_contains(s, b)); printf("DROP B: %p\n", set_drop(s, b)); printf("DROP B: %p\n", set_drop(s, b)); printf("ADD B: %p\n", set_add(s, b)); delete(s); delete(a); delete(b); return 0; }
int set_contains(set_t* set, void* data) { if (set == NULL) return 0; else if (set->data == data) return 1; else if (set->data > data) return set_contains(set->left, data); else return set_contains(set->right, data); }
bool exit_status_set_test(ExitStatusSet *x, int code, int status) { if (exit_status_set_is_empty(x)) return false; if (code == CLD_EXITED && set_contains(x->status, INT_TO_PTR(status))) return true; if (IN_SET(code, CLD_KILLED, CLD_DUMPED) && set_contains(x->signal, INT_TO_PTR(status))) return true; return false; }
static void test_set_unset_reset () { gdb_environ env = gdb_environ::from_host_environ (); /* Our test variable should already be present in the host's environment. */ SELF_CHECK (env.get ("GDB_SELFTEST_ENVIRON") != NULL); /* Set our test variable to another value. */ env.set ("GDB_SELFTEST_ENVIRON", "test"); SELF_CHECK (strcmp (env.get ("GDB_SELFTEST_ENVIRON"), "test") == 0); SELF_CHECK (env.user_set_env ().size () == 1); SELF_CHECK (env.user_unset_env ().size () == 0); /* And unset our test variable. The variable still exists in the host's environment, but doesn't exist in our vector. */ env.unset ("GDB_SELFTEST_ENVIRON"); SELF_CHECK (env.get ("GDB_SELFTEST_ENVIRON") == NULL); SELF_CHECK (env.user_set_env ().size () == 0); SELF_CHECK (env.user_unset_env ().size () == 1); SELF_CHECK (set_contains (env.user_unset_env (), std::string ("GDB_SELFTEST_ENVIRON"))); /* Re-set the test variable. */ env.set ("GDB_SELFTEST_ENVIRON", "1"); SELF_CHECK (strcmp (env.get ("GDB_SELFTEST_ENVIRON"), "1") == 0); }
// Relative complement of set1 in set2. Returns a set of elements that exist in set2 but not in set1 struct set_t *set_difference(struct set_t *set1, struct set_t *set2) { struct set_t *temp_set_head = NULL; struct set_t *temp_set_it = NULL; struct set_t *set_it = set2; // Loop through every element in set2 while(set_it != NULL) { // Element must not exist in set1 if(!set_contains(set1, set_it->value)) { if(temp_set_head == NULL) { temp_set_head = new_set(set_it->value); temp_set_it = temp_set_head; } else { temp_set_it->next = set_add(temp_set_head, set_it->value); if(temp_set_it->next != NULL) temp_set_it = temp_set_it->next; } } set_it = set_it->next; } return temp_set_head; }
int main(int argc, char **argv) { struct set *set; const char *str1 = "test1"; const char *str2 = "test2"; const char *str3 = "test3"; set = set_create(badhash, string_key_equals); /* Unlike the hash table equivalent of this test, use an extra * string so that the rehash happens at the right time. */ set_add(set, str1); set_add(set, str2); set_add(set, str3); set_remove(set, str2); set_add(set, str3); set_remove(set, str3); assert(!set_contains(set, str3)); set_destroy(set, NULL); return 0; }
bool is_clean_exit(int code, int status, ExitClean clean, ExitStatusSet *success_status) { if (code == CLD_EXITED) return status == 0 || (success_status && set_contains(success_status->status, INT_TO_PTR(status))); /* If a daemon does not implement handlers for some of the signals that's not considered an unclean shutdown */ if (code == CLD_KILLED) return (clean == EXIT_CLEAN_DAEMON && IN_SET(status, SIGHUP, SIGINT, SIGTERM, SIGPIPE)) || (success_status && set_contains(success_status->signal, INT_TO_PTR(status))); return false; }
void *test(void *data) { unsigned int mySeed = seed + sched_getcpu(); long myOps = operations / nb_threads; long val = -1; int op; while (myOps > 0) { op = rand_r(&mySeed) % 100; if (op < update) { if (val == -1) { /* Add random value */ val = (rand_r(&mySeed) % range) + 1; if(set_add(val) == 0) { val = -1; } } else { /* Remove random value */ int res = set_remove( val); val = -1; } } else { /* Look for random value */ long tmp = (rand_r(&mySeed) % range) + 1; set_contains(tmp); } myOps--; } return NULL; }
// Performs an intersection of two sets struct set_t *set_intersection(struct set_t *set1, struct set_t *set2) { if(set1 == EMPTY || set2 == EMPTY) return EMPTY; struct set_t *temp_set_head = NULL; struct set_t *temp_set_it = NULL; struct set_t *set_it = set1; // Go through every element of set 1 set_it = set1; while(set_it != NULL) { // See if the elements value is also in set2 if(set_contains(set2, set_it->value)) { if(temp_set_head == NULL) { temp_set_head = new_set(set_it->value); temp_set_it = temp_set_head; } else { // set_add will resolve any attempts to add duplicate elements temp_set_it->next = set_add(temp_set_head, set_it->value); if(temp_set_it->next != NULL) temp_set_it = temp_set_it->next; } } set_it = set_it->next; } return temp_set_head; }
int block_parameter_set_contains( block_parameter_set * p_parameter_set, block_parameter * parameter ) { if ( p_parameter_set == NULL || parameter == NULL ) return 0; return set_contains( &p_parameter_set->parameter_set, (void*) parameter, &compare_parameters ); }
bool bfs_step_generic(const linear_hashing_t* hashing, queue_t* queue, set_t* visited, const struct bfs_node_struct *bfs_node_ptr) { assert(hashing != NULL && queue != NULL && visited != NULL && bfs_node_ptr != NULL); unsigned int i, adj_id; node_t* node; edge_t* edge; struct bfs_node_struct *adj_bfs_node_ptr = NULL; /* Get node from its id */ if(!linear_hashing_get(hashing, bfs_node_ptr->id, (void**)&node)) return false; /* Get the list of all edges starting from this node */ const list_t* edge_list = node_get_edge_list(node); /* Forall node neighbours... */ for(i=0; i < list_size(edge_list); i++) { /* Get the neighbour's id */ if(!list_get(edge_list, (void**)&edge, i)) return false; adj_id = edge_get_id(edge); /* Check if the neighbour node is already visited */ if(!set_contains(visited, adj_id)) { /* If not, allocate memory for the node in the queue */ if(!set_add(visited, adj_id)) return false; if((adj_bfs_node_ptr = malloc(sizeof(struct bfs_node_struct))) == NULL) return false; adj_bfs_node_ptr->id = adj_id; adj_bfs_node_ptr->distance = bfs_node_ptr->distance + 1; /* Add the neighbour node in the queue */ if(!queue_enqueue(queue, adj_bfs_node_ptr)) { free(adj_bfs_node_ptr); return false; } } } return true; }
static void test_unset_set_empty_vector () { gdb_environ env; env.set ("PWD", "test"); SELF_CHECK (strcmp (env.get ("PWD"), "test") == 0); SELF_CHECK (set_contains (env.user_set_env (), std::string ("PWD=test"))); SELF_CHECK (env.user_unset_env ().size () == 0); /* The second element must be NULL. */ SELF_CHECK (env.envp ()[1] == NULL); SELF_CHECK (env.user_set_env ().size () == 1); env.unset ("PWD"); SELF_CHECK (env.envp ()[0] == NULL); SELF_CHECK (env.user_set_env ().size () == 0); SELF_CHECK (env.user_unset_env ().size () == 1); SELF_CHECK (set_contains (env.user_unset_env (), std::string ("PWD"))); }
int main( int argc, char*argv[] ) { set * p_set = NULL; test_set_output( TEST_OUTPUT_BOTH ); p_set = set_create(); if ( test_assert_true ( p_set != NULL, "set creation" ) ) { /* create a set with 35 elements */ int i, *test_search; for( i=0; i<35; i++ ) { int * test_element = (int*) malloc( sizeof(int) ); *test_element = i; set_push_element( p_set, (void*) test_element ); if ( ! test_assert_true( p_set->size == (i + 1) , "set element pushing") ) break; } test_search = (int*) malloc( sizeof(int) ); /* search for an existing element */ *test_search = 10; test_assert_true( set_contains( p_set, test_search, &test_set_int_compare ), "set search existing" ); /* search for a non-existing element */ *test_search = 56; test_assert_true( !set_contains( p_set, test_search, &test_set_int_compare ), "set search non-existing" ); sn_free( (void**) &test_search ); set_free( &p_set ); } exit(0); }
bool is_clean_exit(int code, int status, ExitStatusSet *success_status) { if (code == CLD_EXITED) return status == 0 || (success_status && set_contains(success_status->status, INT_TO_PTR(status))); /* If a daemon does not implement handlers for some of the * signals that's not considered an unclean shutdown */ if (code == CLD_KILLED) return status == SIGHUP || status == SIGINT || status == SIGTERM || status == SIGPIPE || (success_status && set_contains(success_status->signal, INT_TO_PTR(status))); return false; }
/* Attempts to add C to SET. Returns 1 if successful, which will occur if and only if C was not already in SET. Otherwise, returns 0. */ static int set_add (struct set *set, int c) { if (set_contains (set, c)) return 0; set->which = xrealloc (set->which, sizeof *set->which * (set->n + 1)); set->which[set->n++] = c; return 1; }
/* the main program... */ int main(int UNUSED(argc),char UNUSED(*argv[])) { SET *set; const char **list; int i; /* initialize */ set=set_new(); /* store some entries */ set_add(set,"key1"); set_add(set,"key2"); set_add(set,"key3"); set_add(set,"key2"); /* check set contents */ assert(set_contains(set,"key1")); assert(set_contains(set,"key2")); assert(set_contains(set,"key3")); assert(!set_contains(set,"key4")); assert(!set_contains(set,"KEY1")); /* loop over set contents */ list=set_tolist(set); for (i=0;list[i]!=NULL;i++) { assert(isknownvalue(list[i])); } /* remove keys from the set */ assert(isknownvalue(set_pop(set))); assert(isknownvalue(set_pop(set))); assert(isknownvalue(set_pop(set))); assert(set_pop(set)==NULL); /* free set */ set_free(set); free(list); return 0; }
// Test if every element in set1 is contained within set2 bool set_subset(struct set_t *set1, struct set_t *set2) { struct set_t *set_it = set1; while(set_it != NULL) { if(!set_contains(set2, set_it->value)) return false; set_it = set_it->next; } return true; }
static void test_std_move () { gdb_environ env; gdb_environ env2; env.set ("A", "1"); SELF_CHECK (strcmp (env.get ("A"), "1") == 0); SELF_CHECK (set_contains (env.user_set_env (), std::string ("A=1"))); SELF_CHECK (env.user_set_env ().size () == 1); env2 = std::move (env); SELF_CHECK (env.envp ()[0] == NULL); SELF_CHECK (strcmp (env2.get ("A"), "1") == 0); SELF_CHECK (env2.envp ()[1] == NULL); SELF_CHECK (env.user_set_env ().size () == 0); SELF_CHECK (set_contains (env2.user_set_env (), std::string ("A=1"))); SELF_CHECK (env2.user_set_env ().size () == 1); env.set ("B", "2"); SELF_CHECK (strcmp (env.get ("B"), "2") == 0); SELF_CHECK (env.envp ()[1] == NULL); }
END_TEST /* -------------------------------------------------------------------------- */ // Set START_TEST (test_set) { set_t set; set_init(&set); uint16_t const values[] = { 0x0392, 0xAF78, 0x8923, 0xFEAA, 0x2939, 0xFFFF, 0 }; int i = 0; do { fail_unless(set_add(&set, values[i]), "Could not add 0x%X to set, value number %d", values[i], i+1); i++; } while (values[i] != 0); for (int j = 0; j < SET_MAX_VALUES - i; j++) { fail_unless(set_add(&set, j), "Could not add 0x%X to set, value number %d", j, j+i+1); } fail_unless(set.length == SET_MAX_VALUES, "Pl is not at max capacity"); fail_unless(set_add(&set, 0x0) == false, "Added entry after set was supposedly full"); i = 0; do { fail_unless(set_contains(&set, values[i]), "Pl failed to recognize added value 0x%X", values[i]); i++; } while (values[i] != 0); fail_unless(set_contains(&set, 0xDEAD) == false, "Pl recognized a value that was not added"); }
static void test_self_move () { gdb_environ env; /* Test self-move. */ env.set ("A", "1"); SELF_CHECK (strcmp (env.get ("A"), "1") == 0); SELF_CHECK (set_contains (env.user_set_env (), std::string ("A=1"))); SELF_CHECK (env.user_set_env ().size () == 1); /* Some compilers warn about moving to self, but that's precisely what we want to test here, so turn this warning off. */ DIAGNOSTIC_PUSH DIAGNOSTIC_IGNORE_SELF_MOVE env = std::move (env); DIAGNOSTIC_POP SELF_CHECK (strcmp (env.get ("A"), "1") == 0); SELF_CHECK (strcmp (env.envp ()[0], "A=1") == 0); SELF_CHECK (env.envp ()[1] == NULL); SELF_CHECK (set_contains (env.user_set_env (), std::string ("A=1"))); SELF_CHECK (env.user_set_env ().size () == 1); }
int routing_policy_rule_make_local(Manager *m, RoutingPolicyRule *rule) { int r; assert(m); if (set_contains(m->rules_foreign, rule)) { set_remove(m->rules_foreign, rule); r = set_ensure_allocated(&m->rules, &routing_policy_rule_hash_ops); if (r < 0) return r; return set_put(m->rules, rule); } return -ENOENT; }
/* Calculates the value of FIRST for the string of N grammar symbols at X. Sets the result into SET. */ static void calc_first (struct set *set, int *X, int n) { int i; set_init (set); for (i = 0; i < n; i++) { const struct set *f = &find_symbol (X[i])->first; set_merge (set, f, 0); if (!set_contains (f, 0)) return; } set_add (set, 0); }
int set_move(intset_t *set, val_t val1, val_t val2, int transactional) { int result; if(transactional != 0) { TX_START(NL); } result = 0; if(!set_contains(set, val2, transactional)) { if(set_remove(set, val1, transactional)) { set_add(set, val2, transactional); result = 1; } } if(transactional != 0) { TX_END; } return result; }
bool _solver_bfs_move(void *data, const maze *m, vec2 *pos) { bfs_data bfs = *((bfs_data *) data); list *neighbors; vec2 neigh; set_insert(bfs.visited, pos); neighbors = maze_get_neighbors(m, *pos); while (!list_is_empty(neighbors)) { list_pop_front(neighbors, &neigh); if (!map_contains_key(bfs.parent, &neigh) && !set_contains(bfs.visited, &neigh)) { map_put(bfs.parent, &neigh, pos); list_push_back(bfs.queue, &neigh); } } list_destroy(neighbors); if (list_is_empty(bfs.queue)) { return false; } list_pop_front(bfs.queue, pos); return true; }
static inline struct hamt_slot item_to_slot(void *item) { return (struct hamt_slot){(uint64_t)item | LEAF_MASK}; } static inline struct hamt_node *ston(struct hamt_slot slot) { return (struct hamt_node *)(uint64_t)slot.off; } static inline struct hamt_slot ntos(struct hamt_node *node) { return (struct hamt_slot){(uint64_t)node}; } /**************************************************************************/ static inline void *__hamt_search(struct hamt_root *root, uint128_t *hash, struct hamt_state *s) { if (!is_leaf(s->ptr[s->level])) { struct hamt_node *node = ston(*s->ptr[s->level]); int slice = slice_get(*hash, s->level); if (set_contains(node->mask, slice)) { s->hash = slice_set(s->hash, slice, s->level); int slot = set_slot_number(node->mask, slice); s->ptr[s->level + 1] = &node->slots[slot]; s->level += 1; return __hamt_search(root, hash, s); } return NULL; } else { void *item = to_leaf(s->ptr[s->level]); if (*root->hash(root->hash_ud, item) == *hash) { return item; } else { return NULL; } } } void *hamt_search(struct hamt_root *root, uint128_t *hash) { if (unlikely(ston(root->slot) == NULL)) { return NULL; } struct hamt_state s; s.level = 0; s.ptr[0] = &root->slot; return __hamt_search(root, hash, &s); } /**************************************************************************/ static struct hamt_node *__hamt_new_node(struct hamt_root *root, uint64_t mask, int len) { int size = sizeof(struct hamt_node) + len * sizeof(struct hamt_slot); struct hamt_node *node = \ (struct hamt_node *)root->mem_alloc(size); assert(((unsigned long)node & ITEM_MASK) == 0); node->mask = mask; return node; }
static void *test(void *data) { int op, val, last = -1; thread_data_t *d = (thread_data_t *)data; /* Create transaction */ TM_INIT_THREAD; /* Wait on barrier */ barrier_cross(d->barrier); while (stop == 0) { op = rand_range(100, d->seed); if (op < d->update) { if (d->alternate) { /* Alternate insertions and removals */ if (last < 0) { /* Add random value */ val = rand_range(d->range, d->seed) + 1; if (set_add(d->set, val, d)) { d->diff++; last = val; } d->nb_add++; } else { /* Remove last value */ if (set_remove(d->set, last, d)) d->diff--; d->nb_remove++; last = -1; } } else { /* Randomly perform insertions and removals */ val = rand_range(d->range, d->seed) + 1; if ((op & 0x01) == 0) { /* Add random value */ if (set_add(d->set, val, d)) d->diff++; d->nb_add++; } else { /* Remove random value */ if (set_remove(d->set, val, d)) d->diff--; d->nb_remove++; } } } else { /* Look for random value */ val = rand_range(d->range, d->seed) + 1; if (set_contains(d->set, val, d)) d->nb_found++; d->nb_contains++; } } #ifndef TM_COMPILER stm_get_stats("nb_aborts", &d->nb_aborts); stm_get_stats("nb_aborts_1", &d->nb_aborts_1); stm_get_stats("nb_aborts_2", &d->nb_aborts_2); stm_get_stats("nb_aborts_locked_read", &d->nb_aborts_locked_read); stm_get_stats("nb_aborts_locked_write", &d->nb_aborts_locked_write); stm_get_stats("nb_aborts_validate_read", &d->nb_aborts_validate_read); stm_get_stats("nb_aborts_validate_write", &d->nb_aborts_validate_write); stm_get_stats("nb_aborts_validate_commit", &d->nb_aborts_validate_commit); stm_get_stats("nb_aborts_invalid_memory", &d->nb_aborts_invalid_memory); stm_get_stats("nb_aborts_killed", &d->nb_aborts_killed); stm_get_stats("locked_reads_ok", &d->locked_reads_ok); stm_get_stats("locked_reads_failed", &d->locked_reads_failed); stm_get_stats("max_retries", &d->max_retries); #endif /* ! TM_COMPILER */ /* Free transaction */ TM_EXIT_THREAD; return NULL; }
sval_t ht_contains(ht_intset_t *set, skey_t key) { int addr = key & set->hash; return set_contains(&set->buckets[addr], key); }
void PreviewLayoutLinesTool::updateLineInformation() { m_lines.clear(); const HuginBase::Panorama & pano = *(helper->GetPanoramaPtr()); unsigned int numberOfImages = pano.getNrOfImages(); HuginBase::UIntSet active_images = pano.getActiveImages(); // make a line for every image pair, but set the unneeded ones as dud. // This is for constant look up times when we scan control points. m_lines.resize(numberOfImages * numberOfImages); unsigned int numberOfControlPoints = pano.getNrOfCtrlPoints(); // loop over all control points to count them and get error statistics. for (unsigned int cpi = 0 ; cpi < numberOfControlPoints ; cpi++) { const HuginBase::ControlPoint & cp = pano.getCtrlPoint(cpi); unsigned int low_index, high_index; if (cp.image1Nr < cp.image2Nr) { low_index = cp.image1Nr; high_index = cp.image2Nr; } else { low_index = cp.image2Nr; high_index = cp.image1Nr; } // find the line. // We use the formula in the line below to record image numbers to each // line later. LineDetails & line = m_lines[low_index * numberOfImages + high_index]; // update control point count. line.numberOfControlPoints++; // update error statistics line.totalError += cp.error; if (cp.error > line.worstError) { line.worstError = cp.error; } } /* Find some locations of the images. We will test if they overlap using * these locations. We don't need the last image as we can always take the * smallest numbered image as the source of points. */ /** @todo Check both ways around. * This only checks if points from the smallest numbered image are * within the largest numbered image. If the first image is huge compared to * the second, then it many points will miss and we might not reach the * target even if the second image is contained within the first. */ std::vector<PosMap> positions(pano.getNrOfImages() - 1); for (unsigned int i = 0; i < numberOfImages - 1; i++) { const HuginBase::SrcPanoImage & img = pano.getImage(i); for (unsigned int x = 0; x < SAMPLE_FREQUENCY; x++) { for (unsigned int y = 0; y < SAMPLE_FREQUENCY; y++) { // scale (x, y) so it is always within the cropped region of the // image. vigra::Rect2D c = img.getCropRect(); /** @todo Use only points inside the circle when circular crop * is used. */ double xc = double (x) / double (SAMPLE_FREQUENCY) * double(c.width()) + c.left(); double yc = double (y) / double (SAMPLE_FREQUENCY) * double(c.height()) + c.top(); // now look up (xc, yc) in the image, find where in the panorama // it ends up. m_transforms[i]->transformImgCoord ( positions[i][x][y].x, positions[i][x][y].y, xc, yc ); } } } // write other line data. for (unsigned int i = 0; i < numberOfImages; i++) { for (unsigned int j = 0; j < numberOfImages; j++) { LineDetails & line = m_lines[i * numberOfImages + j]; line.image1 = i; line.image2 = j; /// test if the line should be visible. if (!(set_contains(active_images, i) && set_contains(active_images, j))) { // At least one of the images is hidden, so don't show the line. line.dud = true; } else if (line.numberOfControlPoints > 0) { line.dud = false; } else if (i >= j) { // We only use lines where image1 is the lowest numbered image. // We don't bother with lines from one image to the same one. line.dud = true; } else { // test overlapping regions. HuginBase::PTools::Transform transform; ViewState & viewState = *helper->GetViewStatePtr(); HuginBase::SrcPanoImage & src = *viewState.GetSrcImage(j); transform.createTransform(src, *(viewState.GetOptions())); unsigned int overlapingSamples = 0; for (unsigned int x = 0; x < SAMPLE_FREQUENCY; x++) { for (unsigned int y = 0; y < SAMPLE_FREQUENCY; y++) { // check if mapping a point that was found earilier to // be inside an image in panorama space is inside the // other image when transformed from panorama to image. double dx, dy; transform.transformImgCoord ( dx, dy, positions[i][x][y].x, positions[i][x][y].y ); if (src.isInside(vigra::Point2D((int) dx, (int) dy))) { // they overlap overlapingSamples++; } } } // If the overlap isn't big enough, the line isn't used. line.dud = (overlapingSamples < MIN_SAMPLE_OVERLAPS); } if (!line.dud) { line.arc = GreatCircleArc(m_imageCentresSpherical[i].x, m_imageCentresSpherical[i].y, m_imageCentresSpherical[j].x, m_imageCentresSpherical[j].y, *(helper->GetVisualizationStatePtr())); } } } }
/* Use this function only if you do not have direct access to /proc/self/mountinfo but the caller can open it * for you. This is the case when /proc is masked or not mounted. Otherwise, use bind_remount_recursive. */ int bind_remount_recursive_with_mountinfo( const char *prefix, unsigned long new_flags, unsigned long flags_mask, char **blacklist, FILE *proc_self_mountinfo) { _cleanup_set_free_free_ Set *done = NULL; _cleanup_free_ char *cleaned = NULL; int r; assert(proc_self_mountinfo); /* Recursively remount a directory (and all its submounts) read-only or read-write. If the directory is already * mounted, we reuse the mount and simply mark it MS_BIND|MS_RDONLY (or remove the MS_RDONLY for read-write * operation). If it isn't we first make it one. Afterwards we apply MS_BIND|MS_RDONLY (or remove MS_RDONLY) to * all submounts we can access, too. When mounts are stacked on the same mount point we only care for each * individual "top-level" mount on each point, as we cannot influence/access the underlying mounts anyway. We * do not have any effect on future submounts that might get propagated, they migt be writable. This includes * future submounts that have been triggered via autofs. * * If the "blacklist" parameter is specified it may contain a list of subtrees to exclude from the * remount operation. Note that we'll ignore the blacklist for the top-level path. */ cleaned = strdup(prefix); if (!cleaned) return -ENOMEM; path_simplify(cleaned, false); done = set_new(&path_hash_ops); if (!done) return -ENOMEM; for (;;) { _cleanup_set_free_free_ Set *todo = NULL; bool top_autofs = false; char *x; unsigned long orig_flags; todo = set_new(&path_hash_ops); if (!todo) return -ENOMEM; rewind(proc_self_mountinfo); for (;;) { _cleanup_free_ char *path = NULL, *p = NULL, *type = NULL; int k; k = fscanf(proc_self_mountinfo, "%*s " /* (1) mount id */ "%*s " /* (2) parent id */ "%*s " /* (3) major:minor */ "%*s " /* (4) root */ "%ms " /* (5) mount point */ "%*s" /* (6) mount options (superblock) */ "%*[^-]" /* (7) optional fields */ "- " /* (8) separator */ "%ms " /* (9) file system type */ "%*s" /* (10) mount source */ "%*s" /* (11) mount options (bind mount) */ "%*[^\n]", /* some rubbish at the end */ &path, &type); if (k != 2) { if (k == EOF) break; continue; } r = cunescape(path, UNESCAPE_RELAX, &p); if (r < 0) return r; if (!path_startswith(p, cleaned)) continue; /* Ignore this mount if it is blacklisted, but only if it isn't the top-level mount we shall * operate on. */ if (!path_equal(cleaned, p)) { bool blacklisted = false; char **i; STRV_FOREACH(i, blacklist) { if (path_equal(*i, cleaned)) continue; if (!path_startswith(*i, cleaned)) continue; if (path_startswith(p, *i)) { blacklisted = true; log_debug("Not remounting %s blacklisted by %s, called for %s", p, *i, cleaned); break; } } if (blacklisted) continue; } /* Let's ignore autofs mounts. If they aren't * triggered yet, we want to avoid triggering * them, as we don't make any guarantees for * future submounts anyway. If they are * already triggered, then we will find * another entry for this. */ if (streq(type, "autofs")) { top_autofs = top_autofs || path_equal(cleaned, p); continue; } if (!set_contains(done, p)) { r = set_consume(todo, p); p = NULL; if (r == -EEXIST) continue; if (r < 0) return r; } } /* If we have no submounts to process anymore and if * the root is either already done, or an autofs, we * are done */ if (set_isempty(todo) && (top_autofs || set_contains(done, cleaned))) return 0; if (!set_contains(done, cleaned) && !set_contains(todo, cleaned)) { /* The prefix directory itself is not yet a mount, make it one. */ if (mount(cleaned, cleaned, NULL, MS_BIND|MS_REC, NULL) < 0) return -errno; orig_flags = 0; (void) get_mount_flags(cleaned, &orig_flags); orig_flags &= ~MS_RDONLY; if (mount(NULL, cleaned, NULL, (orig_flags & ~flags_mask)|MS_BIND|MS_REMOUNT|new_flags, NULL) < 0) return -errno; log_debug("Made top-level directory %s a mount point.", prefix); r = set_put_strdup(done, cleaned); if (r < 0) return r; } while ((x = set_steal_first(todo))) { r = set_consume(done, x); if (IN_SET(r, 0, -EEXIST)) continue; if (r < 0) return r; /* Deal with mount points that are obstructed by a later mount */ r = path_is_mount_point(x, NULL, 0); if (IN_SET(r, 0, -ENOENT)) continue; if (IN_SET(r, -EACCES, -EPERM)) { /* Even if root user invoke this, submounts under private FUSE or NFS mount points * may not be acceessed. E.g., * * $ bindfs --no-allow-other ~/mnt/mnt ~/mnt/mnt * $ bindfs --no-allow-other ~/mnt ~/mnt * * Then, root user cannot access the mount point ~/mnt/mnt. * In such cases, the submounts are ignored, as we have no way to manage them. */ log_debug_errno(r, "Failed to determine '%s' is mount point or not, ignoring: %m", x); continue; } if (r < 0) return r; /* Try to reuse the original flag set */ orig_flags = 0; (void) get_mount_flags(x, &orig_flags); orig_flags &= ~MS_RDONLY; if (mount(NULL, x, NULL, (orig_flags & ~flags_mask)|MS_BIND|MS_REMOUNT|new_flags, NULL) < 0) return -errno; log_debug("Remounted %s read-only.", x); } }