Beispiel #1
0
void test_set_operations(){
	set_t *even1 = new_set(10);
	set_t *even2 = new_set(10);
	set_t *odd  = new_set(10);
	
	int i;
	for (i=0; i < 10; i++){
		set_put(even1, 2*i);
		set_put(even2, 2*i);
		set_put(odd, 2*i+1);
	}
	
	set_union(even1, odd);
	assert(set_size(even1) == 20);
	
	set_difference(even2, odd);
	assert(set_size(even2) == 10);
	
	set_intersection(even2, odd);
	assert(set_size(even2) == 0);
	
	set_print(even1); printf("\n");
	set_optimize(even1);
	set_print(even1); printf("\n");
	
	set_print(even2); printf("\n");
	set_print(odd); printf("\n");
	
	delete_set(even1);
	delete_set(even2);
	delete_set(odd);
}
Beispiel #2
0
//设置优惠活动 
struct sales_promotion *get_promotion() 
{
	static struct sales_promotion *promotions;
        struct promotion_one_info *p; //临时变量  
    	struct set_t *pset; //临时变量
    	int i;  
    	static struct sales_products discount_promotion[] = { //折扣商品信息
		{"ITEM00002", 1},
		{"ITEM00001", 1}
		//{"ITEM00003", 0},
		//{"ITEM00004", 0}
	};
	static struct sales_products one_free_promotion[] = { //买二送一商品信息
		{"ITEM00001", 1},
		{"ITEM00003", 1}
		//{"ITEM00003", 0}
	};
	 
    	PNEW(promotions, 1, struct sales_promotion *);
	promotions->promotion_all_info = NULL;
	
        /*假设当前有以下两种活动*
         *  1. 买二送一活动
         *  2. 9.5折优惠 */
    	promotions->priority = FREE_ONE;  //当某种商品满足两种优惠时,优先选则活动一
     
        /*首先设置优惠活动1信息*/
     	PNEW(p, 1, struct promotion_one_info *);
     	p->next_promotion = promotions->promotion_all_info;
     	promotions->promotion_all_info = p;
     	p->type = FREE_ONE;
     	strcpy(p->statement, "买二送一活动");
     	pset = set_new(100, compare_product, hashcode);
     	p->sales_set = pset; 

     	for(i = 0; i < array_len(one_free_promotion); i++) {
     		set_put(pset, &one_free_promotion[i]);		 		 
     	}
 
     	/*其次设置优惠活动2信息*/ 
	 PNEW(p, 1, struct promotion_one_info *); //分配活动2商品所需的内存
	 //链表头插法
	 p->next_promotion = promotions->promotion_all_info;
	 promotions->promotion_all_info = p;
	 p->type = DISCOUNT;
	 strcpy(p->statement, "9.5折优惠");
	 pset = set_new(100, compare_product, hashcode);
	 p->sales_set = pset;

	 for(i = 0; i < array_len(discount_promotion); i++) {
		 set_put(pset, &discount_promotion[i]);
	 }
	 
	 return promotions;
}
Beispiel #3
0
static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, void *userdata) {
        union autofs_v5_packet_union packet;
        Automount *a = AUTOMOUNT(userdata);
        ssize_t l;
        int r;

        assert(a);
        assert(fd == a->pipe_fd);

        if (events != EPOLLIN) {
                log_error_unit(UNIT(a)->id, "Got invalid poll event on pipe.");
                goto fail;
        }

        l = loop_read(a->pipe_fd, &packet, sizeof(packet), true);
        if (l != sizeof(packet)) {
                log_error_unit(UNIT(a)->id, "Invalid read from pipe: %s", l < 0 ? strerror(-l) : "short read");
                goto fail;
        }

        switch (packet.hdr.type) {

        case autofs_ptype_missing_direct:

                if (packet.v5_packet.pid > 0) {
                        _cleanup_free_ char *p = NULL;

                        get_process_comm(packet.v5_packet.pid, &p);
                        log_info_unit(UNIT(a)->id,
                                       "Got automount request for %s, triggered by "PID_FMT" (%s)",
                                       a->where, packet.v5_packet.pid, strna(p));
                } else
                        log_debug_unit(UNIT(a)->id, "Got direct mount request on %s", a->where);

                r = set_ensure_allocated(&a->tokens, trivial_hash_func, trivial_compare_func);
                if (r < 0) {
                        log_error_unit(UNIT(a)->id, "Failed to allocate token set.");
                        goto fail;
                }

                r = set_put(a->tokens, UINT_TO_PTR(packet.v5_packet.wait_queue_token));
                if (r < 0) {
                        log_error_unit(UNIT(a)->id, "Failed to remember token: %s", strerror(-r));
                        goto fail;
                }

                automount_enter_runnning(a);
                break;

        default:
                log_error_unit(UNIT(a)->id, "Received unknown automount request %i", packet.hdr.type);
                break;
        }

        return 0;

fail:
        automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES);
        return 0;
}
Beispiel #4
0
static Set *new_matches(void) {
        Set *set;
        char *tmp;
        int r;

        set = set_new(trivial_hash_func, trivial_compare_func);
        if (!set) {
                log_oom();
                return NULL;
        }

        tmp = strdup("MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1");
        if (!tmp) {
                log_oom();
                set_free(set);
                return NULL;
        }

        r = set_put(set, tmp);
        if (r < 0) {
                log_error("failed to add to set: %s", strerror(-r));
                free(tmp);
                set_free(set);
                return NULL;
        }

        return set;
}
Beispiel #5
0
void test_removing(){
	set_t *set = new_set(0);
	
	int i;
	for (i=0; i < 1000; i++){ set_put(set, i); }
	assert(set_size(set) == 1000);
	
	set_optimize(set);
	
	for (i=0; i < 1000; i += 2){ set_remove(set, i); }
	assert(set_size(set) == 500);
	
	for (i=0; i < 1000; i += 2){ set_put(set, i); }
	assert(set_size(set) == 1000);
	
	delete_set(set);
}
Beispiel #6
0
static int killall(int sig, Set *pids, bool send_sighup) {
        _cleanup_closedir_ DIR *dir = NULL;
        struct dirent *d;

        dir = opendir("/proc");
        if (!dir)
                return -errno;

        while ((d = readdir(dir))) {
                pid_t pid;
                int r;

                if (d->d_type != DT_DIR &&
                    d->d_type != DT_UNKNOWN)
                        continue;

                if (parse_pid(d->d_name, &pid) < 0)
                        continue;

                if (ignore_proc(pid, sig == SIGKILL && !in_initrd()))
                        continue;

                if (sig == SIGKILL) {
                        _cleanup_free_ char *s = NULL;

                        get_process_comm(pid, &s);
                        log_notice("Sending SIGKILL to PID "PID_FMT" (%s).", pid, strna(s));
                }

                if (kill(pid, sig) >= 0) {
                        if (pids) {
                                r = set_put(pids, PID_TO_PTR(pid));
                                if (r < 0)
                                        log_oom();
                        }
                } else if (errno != ENOENT)
                        log_warning_errno(errno, "Could not kill %d: %m", pid);

                if (send_sighup) {
                        /* Optionally, also send a SIGHUP signal, but
                        only if the process has a controlling
                        tty. This is useful to allow handling of
                        shells which ignore SIGTERM but react to
                        SIGHUP. We do not send this to processes that
                        have no controlling TTY since we don't want to
                        trigger reloads of daemon processes. Also we
                        make sure to only send this after SIGTERM so
                        that SIGTERM is always first in the queue. */


                        if (get_ctty_devnr(pid, NULL) >= 0)
                                kill(pid, SIGHUP);
                }
        }

        return set_size(pids);
}
Beispiel #7
0
/*将购物车中的商品加入到集合中*/
void pack_cart(int sum, char *bar_code, void *shoping_set)
{
	struct sales_products *one_product; //购物车商品
    	
	PNEW(one_product, 1, struct sales_products *);
	strcpy(one_product->bar_code, bar_code);
	one_product->sum = sum;
	set_put((struct set_t *)shoping_set, one_product);
}
Beispiel #8
0
int set_consume(Set *s, void *value) {
        int r;

        r = set_put(s, value);
        if (r < 0)
                free(value);

        return r;
}
Beispiel #9
0
void test_basic(){
	set_t *set = new_set(10);
	
	int i, j;
	for (i=0; i < 10; i++){
		for (j=0; j < 10; j++){
			set_put(set, i);
		}
	}
	assert(set_size(set) == 10);
	delete_set(set);
}
static int routing_policy_rule_add_internal(Manager *m,
                                            Set **rules,
                                            int family,
                                            const union in_addr_union *from,
                                            uint8_t from_prefixlen,
                                            const union in_addr_union *to,
                                            uint8_t to_prefixlen,
                                            uint8_t tos,
                                            uint32_t fwmark,
                                            uint32_t table,
                                            char *iif,
                                            char *oif,
                                            RoutingPolicyRule **ret) {

        _cleanup_routing_policy_rule_free_ RoutingPolicyRule *rule = NULL;
        int r;

        assert_return(rules, -EINVAL);

        r = routing_policy_rule_new(&rule);
        if (r < 0)
                return r;

        rule->manager = m;
        rule->family = family;
        rule->from = *from;
        rule->from_prefixlen = from_prefixlen;
        rule->to = *to;
        rule->to_prefixlen = to_prefixlen;
        rule->tos = tos;
        rule->fwmark = fwmark;
        rule->table = table;
        rule->iif = iif;
        rule->oif = oif;

        r = set_ensure_allocated(rules, &routing_policy_rule_hash_ops);
        if (r < 0)
                return r;

        r = set_put(*rules, rule);
        if (r < 0)
                return r;

        if (ret)
                *ret = rule;

        rule = NULL;

        return 0;
}
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;
}
Beispiel #12
0
static int route_add_internal(
                Link *link,
                Set **routes,
                int family,
                const union in_addr_union *dst,
                unsigned char dst_prefixlen,
                unsigned char tos,
                uint32_t priority,
                unsigned char table,
                Route **ret) {

        _cleanup_route_free_ Route *route = NULL;
        int r;

        assert(link);
        assert(routes);
        assert(dst);

        r = route_new(&route);
        if (r < 0)
                return r;

        route->family = family;
        route->dst = *dst;
        route->dst_prefixlen = dst_prefixlen;
        route->tos = tos;
        route->priority = priority;
        route->table = table;

        r = set_ensure_allocated(routes, &route_hash_ops);
        if (r < 0)
                return r;

        r = set_put(*routes, route);
        if (r < 0)
                return r;

        route->link = link;

        if (ret)
                *ret = route;

        route = NULL;

        return 0;
}
Beispiel #13
0
static int add_listen_socket(Context *context, int fd) {
        sd_event_source *source;
        int r;

        assert(context);
        assert(fd >= 0);

        r = set_ensure_allocated(&context->listen, NULL);
        if (r < 0) {
                log_oom();
                return r;
        }

        r = sd_is_socket(fd, 0, SOCK_STREAM, 1);
        if (r < 0)
                return log_error_errno(r, "Failed to determine socket type: %m");
        if (r == 0) {
                log_error("Passed in socket is not a stream socket.");
                return -EINVAL;
        }

        r = fd_nonblock(fd, true);
        if (r < 0)
                return log_error_errno(r, "Failed to mark file descriptor non-blocking: %m");

        r = sd_event_add_io(context->event, &source, fd, EPOLLIN, accept_cb, context);
        if (r < 0)
                return log_error_errno(r, "Failed to add event source: %m");

        r = set_put(context->listen, source);
        if (r < 0) {
                log_error_errno(r, "Failed to add source to set: %m");
                sd_event_source_unref(source);
                return r;
        }

        /* Set the watcher to oneshot in case other processes are also
         * watching to accept(). */
        r = sd_event_source_set_enabled(source, SD_EVENT_ONESHOT);
        if (r < 0)
                return log_error_errno(r, "Failed to enable oneshot mode: %m");

        return 0;
}
Beispiel #14
0
int route_add(
              Link *link,
              int family,
              const union in_addr_union *dst,
              unsigned char dst_prefixlen,
              unsigned char tos,
              uint32_t priority,
              uint32_t table,
              Route **ret) {

        Route *route;
        int r;

        r = route_get(link, family, dst, dst_prefixlen, tos, priority, table, &route);
        if (r == -ENOENT) {
                /* Route does not exist, create a new one */
                r = route_add_internal(link, &link->routes, family, dst, dst_prefixlen, tos, priority, table, &route);
                if (r < 0)
                        return r;
        } else if (r == 0) {
                /* Take over a foreign route */
                r = set_ensure_allocated(&link->routes, &route_hash_ops);
                if (r < 0)
                        return r;

                r = set_put(link->routes, route);
                if (r < 0)
                        return r;

                set_remove(link->routes_foreign, route);
        } else if (r == 1) {
                /* Route exists, do nothing */
                ;
        } else
                return r;

        if (ret)
                *ret = route;

        return 0;
}
Beispiel #15
0
static int add_connection_socket(Context *context, int fd) {
        Connection *c;
        int r;

        assert(context);
        assert(fd >= 0);

        if (set_size(context->connections) > arg_connections_max) {
                log_warning("Hit connection limit, refusing connection.");
                safe_close(fd);
                return 0;
        }

        r = set_ensure_allocated(&context->connections, NULL);
        if (r < 0) {
                log_oom();
                return 0;
        }

        c = new0(Connection, 1);
        if (!c) {
                log_oom();
                return 0;
        }

        c->context = context;
        c->server_fd = fd;
        c->client_fd = -1;
        c->server_to_client_buffer[0] = c->server_to_client_buffer[1] = -1;
        c->client_to_server_buffer[0] = c->client_to_server_buffer[1] = -1;

        r = set_put(context->connections, c);
        if (r < 0) {
                free(c);
                log_oom();
                return 0;
        }

        return resolve_remote(c);
}
Beispiel #16
0
static int add_match(Set *set, const char *match) {
        int r = -ENOMEM;
        unsigned pid;
        const char* prefix;
        char *pattern = NULL;
        _cleanup_free_ char *p = NULL;

        if (strchr(match, '='))
                prefix = "";
        else if (strchr(match, '/')) {
                p = path_make_absolute_cwd(match);
                if (!p)
                        goto fail;

                match = p;
                prefix = "COREDUMP_EXE=";
        }
        else if (safe_atou(match, &pid) == 0)
                prefix = "COREDUMP_PID=";
        else
                prefix = "COREDUMP_COMM=";

        pattern = strjoin(prefix, match, NULL);
        if (!pattern)
                goto fail;

        log_debug("Adding pattern: %s", pattern);
        r = set_put(set, pattern);
        if (r < 0) {
                log_error("Failed to add pattern '%s': %s",
                          pattern, strerror(-r));
                free(pattern);
                goto fail;
        }

        return 0;
fail:
        log_error("Failed to add match: %s", strerror(-r));
        return r;
}
Beispiel #17
0
void test_picking(){
	int n = 10000;
	set_t *set = new_set(0);
	int i;
	for (i=0; i < n; i++){
		set_put(set, i);
	}
	assert(set_size(set) == n);
	
	set_entry_t *p = set_head(set);
	for (i=0; i < n; i++){
		assert(p->key == i);
		p = p->next;
	}
	
	for (i=0; i < 3*n; i++){
		int v = set_get_random(set);
		assert(v < n);
	}
	
	delete_set(set);
}
Beispiel #18
0
/*从收银系统取得商品信息*/ 
static struct set_t *get_products()
{
	static struct set_t *product_set;
	int i;
	static struct product_detail products[] = {
		{"ITEM00001", "可口可乐", 3, "瓶", "饮料"},
		{"ITEM00002", "苹果", 5.5, "斤", "水果"},
		{"ITEM00003", "羽毛球", 1, "个", "体育用品"},
		{"ITEM00004", "柚子", 10.5, "斤", "水果"},
		{"ITEM00005", "瓜子", 99, "斤", "干果"},
		{"ITEM00006", "麻子", 19.5, "斤", "干果"},
		{"ITEM00007", "开心果", 10.5, "斤", "干果"},
		{"ITEM00008", "花生", 10.5, "斤", "干果"}
	};
	
	/*初始化商品信息集合*/
	product_set = set_new(1024, compare_product, hashcode);
	for(i = 0; i < array_len(products); i++) {
        	set_put(product_set, &products[i]);
    	}
	return product_set;
}
Beispiel #19
0
static int nftw_cb(
                const char *fpath,
                const struct stat *sb,
                int tflag,
                struct FTW *ftwbuf) {

        char *p, *e;
        int r;

        if (tflag != FTW_F)
                return 0;

        if (!endswith(fpath, ".map") &&
            !endswith(fpath, ".map.gz"))
                return 0;

        p = strdup(path_get_file_name(fpath));
        if (!p)
                return log_oom();

        e = endswith(p, ".map");
        if (e)
                *e = 0;

        e = endswith(p, ".map.gz");
        if (e)
                *e = 0;

        r = set_put(keymaps, p);
        if (r == -EEXIST)
                free(p);
        else if (r < 0) {
                log_error("Can't add keymap: %s", strerror(-r));
                free(p);
                return r;
        }

        return 0;
}
Beispiel #20
0
static int killall(int sig, Set *pids) {
        _cleanup_closedir_ DIR *dir = NULL;
        struct dirent *d;

        dir = opendir("/proc");
        if (!dir)
                return -errno;

        while ((d = readdir(dir))) {
                pid_t pid;

                if (d->d_type != DT_DIR &&
                    d->d_type != DT_UNKNOWN)
                        continue;

                if (parse_pid(d->d_name, &pid) < 0)
                        continue;

                if (ignore_proc(pid))
                        continue;

                if (sig == SIGKILL) {
                        _cleanup_free_ char *s;

                        get_process_comm(pid, &s);
                        log_notice("Sending SIGKILL to PID %lu (%s).", (unsigned long) pid, strna(s));
                }

                if (kill(pid, sig) >= 0) {
                        if (pids)
                                set_put(pids, ULONG_TO_PTR((unsigned long) pid));
                } else if (errno != ENOENT)
                        log_warning("Could not kill %d: %m", pid);
        }

        return set_size(pids);
}
Beispiel #21
0
int config_parse_dns(const char *unit,
                const char *filename,
                unsigned line,
                const char *section,
                unsigned section_line,
                const char *lvalue,
                int ltype,
                const char *rvalue,
                void *data,
                void *userdata) {
        Set **dns = data;
        _cleanup_address_free_ Address *n = NULL;
        int r;

        assert(filename);
        assert(section);
        assert(lvalue);
        assert(rvalue);
        assert(data);

        r = address_new_dynamic(&n);
        if (r < 0)
                return r;

        r = net_parse_inaddr(rvalue, &n->family, &n->in_addr);
        if (r < 0) {
                log_syntax(unit, LOG_ERR, filename, line, EINVAL,
                           "DNS address is invalid, ignoring assignment: %s", rvalue);
                return 0;
        }

        set_put(*dns, n);
        n = NULL;

        return 0;
}
Beispiel #22
0
int fdset_put(FDSet *s, int fd) {
        assert(s);
        assert(fd >= 0);

        return set_put(MAKE_SET(s), FD_TO_PTR(fd));
}
Beispiel #23
0
int mount_cgroup_controllers(char ***join_controllers) {
        int r;
        FILE *f;
        char buf[LINE_MAX];
        Set *controllers;

        /* Mount all available cgroup controllers that are built into the kernel. */

        f = fopen("/proc/cgroups", "re");
        if (!f) {
                log_error("Failed to enumerate cgroup controllers: %m");
                return 0;
        }

        controllers = set_new(string_hash_func, string_compare_func);
        if (!controllers) {
                r = log_oom();
                goto finish;
        }

        /* Ignore the header line */
        (void) fgets(buf, sizeof(buf), f);

        for (;;) {
                char *controller;
                int enabled = 0;

                if (fscanf(f, "%ms %*i %*i %i", &controller, &enabled) != 2) {

                        if (feof(f))
                                break;

                        log_error("Failed to parse /proc/cgroups.");
                        r = -EIO;
                        goto finish;
                }

                if (!enabled) {
                        free(controller);
                        continue;
                }

                r = set_put(controllers, controller);
                if (r < 0) {
                        log_error("Failed to add controller to set.");
                        free(controller);
                        goto finish;
                }
        }

        for (;;) {
                MountPoint p;
                char *controller, *where, *options;
                char ***k = NULL;

                controller = set_steal_first(controllers);
                if (!controller)
                        break;

                if (join_controllers)
                        for (k = join_controllers; *k; k++)
                                if (strv_find(*k, controller))
                                        break;

                if (k && *k) {
                        char **i, **j;

                        for (i = *k, j = *k; *i; i++) {

                                if (!streq(*i, controller)) {
                                        char *t;

                                        t = set_remove(controllers, *i);
                                        if (!t) {
                                                free(*i);
                                                continue;
                                        }
                                        free(t);
                                }

                                *(j++) = *i;
                        }

                        *j = NULL;

                        options = strv_join(*k, ",");
                        if (!options) {
                                free(controller);
                                r = log_oom();
                                goto finish;
                        }

                } else {
                        options = controller;
                        controller = NULL;
                }

                where = strappend("/sys/fs/cgroup/", options);
                if (!where) {
                        free(options);
                        r = log_oom();
                        goto finish;
                }

                zero(p);
                p.what = "cgroup";
                p.where = where;
                p.type = "cgroup";
                p.options = options;
                p.flags = MS_NOSUID|MS_NOEXEC|MS_NODEV;
                p.mode = MNT_IN_CONTAINER;

                r = mount_one(&p, true);
                free(controller);
                free(where);

                if (r < 0) {
                        free(options);
                        goto finish;
                }

                if (r > 0 && k && *k) {
                        char **i;

                        for (i = *k; *i; i++) {
                                char *t;

                                t = strappend("/sys/fs/cgroup/", *i);
                                if (!t) {
                                        r = log_oom();
                                        free(options);
                                        goto finish;
                                }

                                r = symlink(options, t);
                                free(t);

                                if (r < 0 && errno != EEXIST) {
                                        log_error("Failed to create symlink: %m");
                                        r = -errno;
                                        free(options);
                                        goto finish;
                                }
                        }
                }

                free(options);
        }

        r = 0;

finish:
        set_free_free(controllers);

        fclose(f);

        return r;
}
Beispiel #24
0
int cg_migrate(const char *controller, const char *from, const char *to, bool ignore_self) {
        bool done = false;
        Set *s;
        int r, ret = 0;
        pid_t my_pid;
        FILE *f = NULL;

        assert(controller);
        assert(from);
        assert(to);

        if (!(s = set_new(trivial_hash_func, trivial_compare_func)))
                return -ENOMEM;

        my_pid = getpid();

        do {
                pid_t pid = 0;
                done = true;

                if ((r = cg_enumerate_tasks(controller, from, &f)) < 0) {
                        if (ret >= 0 && r != -ENOENT)
                                ret = r;

                        goto finish;
                }

                while ((r = cg_read_pid(f, &pid)) > 0) {

                        /* This might do weird stuff if we aren't a
                         * single-threaded program. However, we
                         * luckily know we are not */
                        if (pid == my_pid && ignore_self)
                                continue;

                        if (set_get(s, LONG_TO_PTR(pid)) == LONG_TO_PTR(pid))
                                continue;

                        if ((r = cg_attach(controller, to, pid)) < 0) {
                                if (ret >= 0 && r != -ESRCH)
                                        ret = r;
                        } else if (ret == 0)
                                ret = 1;

                        done = false;

                        if ((r = set_put(s, LONG_TO_PTR(pid))) < 0) {
                                if (ret >= 0)
                                        ret = r;

                                goto finish;
                        }
                }

                if (r < 0) {
                        if (ret >= 0)
                                ret = r;

                        goto finish;
                }

                fclose(f);
                f = NULL;

        } while (!done);

finish:
        set_free(s);

        if (f)
                fclose(f);

        return ret;
}
Beispiel #25
0
int cg_kill(const char *controller, const char *path, int sig, bool sigcont, bool ignore_self, Set *s) {
        bool done = false;
        int r, ret = 0;
        pid_t my_pid;
        FILE *f = NULL;
        Set *allocated_set = NULL;

        assert(controller);
        assert(path);
        assert(sig >= 0);

        /* This goes through the tasks list and kills them all. This
         * is repeated until no further processes are added to the
         * tasks list, to properly handle forking processes */

        if (!s)
                if (!(s = allocated_set = set_new(trivial_hash_func, trivial_compare_func)))
                        return -ENOMEM;

        my_pid = getpid();

        do {
                pid_t pid = 0;
                done = true;

                if ((r = cg_enumerate_processes(controller, path, &f)) < 0) {
                        if (ret >= 0 && r != -ENOENT)
                                ret = r;

                        goto finish;
                }

                while ((r = cg_read_pid(f, &pid)) > 0) {

                        if (pid == my_pid && ignore_self)
                                continue;

                        if (set_get(s, LONG_TO_PTR(pid)) == LONG_TO_PTR(pid))
                                continue;

                        /* If we haven't killed this process yet, kill
                         * it */
                        if (kill(pid, sig) < 0) {
                                if (ret >= 0 && errno != ESRCH)
                                        ret = -errno;
                        } else if (ret == 0) {

                                if (sigcont)
                                        kill(pid, SIGCONT);

                                ret = 1;
                        }

                        done = false;

                        if ((r = set_put(s, LONG_TO_PTR(pid))) < 0) {
                                if (ret >= 0)
                                        ret = r;

                                goto finish;
                        }
                }

                if (r < 0) {
                        if (ret >= 0)
                                ret = r;

                        goto finish;
                }

                fclose(f);
                f = NULL;

                /* To avoid racing against processes which fork
                 * quicker than we can kill them we repeat this until
                 * no new pids need to be killed. */

        } while (!done);

finish:
        if (allocated_set)
                set_free(allocated_set);

        if (f)
                fclose(f);

        return ret;
}
Beispiel #26
0
static int list_locales(DBusConnection *bus, char **args, unsigned n) {
        /* Stolen from glibc... */

        struct locarhead {
                uint32_t magic;
                /* Serial number.  */
                uint32_t serial;
                /* Name hash table.  */
                uint32_t namehash_offset;
                uint32_t namehash_used;
                uint32_t namehash_size;
                /* String table.  */
                uint32_t string_offset;
                uint32_t string_used;
                uint32_t string_size;
                /* Table with locale records.  */
                uint32_t locrectab_offset;
                uint32_t locrectab_used;
                uint32_t locrectab_size;
                /* MD5 sum hash table.  */
                uint32_t sumhash_offset;
                uint32_t sumhash_used;
                uint32_t sumhash_size;
        };

        struct namehashent {
                /* Hash value of the name.  */
                uint32_t hashval;
                /* Offset of the name in the string table.  */
                uint32_t name_offset;
                /* Offset of the locale record.  */
                uint32_t locrec_offset;
        };

        const struct locarhead *h;
        const struct namehashent *e;
        const void *p = MAP_FAILED;
        _cleanup_close_ int fd = -1;
        _cleanup_strv_free_ char **l = NULL;
        char **j;
        Set *locales;
        size_t sz = 0;
        struct stat st;
        unsigned i;
        int r;

        locales = set_new(string_hash_func, string_compare_func);
        if (!locales)
                return log_oom();

        fd = open("/usr/lib/locale/locale-archive", O_RDONLY|O_NOCTTY|O_CLOEXEC);
        if (fd < 0) {
                log_error("Failed to open locale archive: %m");
                r = -errno;
                goto finish;
        }

        if (fstat(fd, &st) < 0) {
                log_error("fstat() failed: %m");
                r = -errno;
                goto finish;
        }

        if (!S_ISREG(st.st_mode)) {
                log_error("Archive file is not regular");
                r = -EBADMSG;
                goto finish;
        }

        if (st.st_size < (off_t) sizeof(struct locarhead)) {
                log_error("Archive has invalid size");
                r = -EBADMSG;
                goto finish;
        }

        p = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
        if (p == MAP_FAILED) {
                log_error("Failed to map archive: %m");
                r = -errno;
                goto finish;
        }

        h = (const struct locarhead *) p;
        if (h->magic != 0xde020109 ||
            h->namehash_offset + h->namehash_size > st.st_size ||
            h->string_offset + h->string_size > st.st_size ||
            h->locrectab_offset + h->locrectab_size > st.st_size ||
            h->sumhash_offset + h->sumhash_size > st.st_size) {
                log_error("Invalid archive file.");
                r = -EBADMSG;
                goto finish;
        }

        e = (const struct namehashent*) ((const uint8_t*) p + h->namehash_offset);
        for (i = 0; i < h->namehash_size; i++) {
                char *z;

                if (e[i].locrec_offset == 0)
                        continue;

                z = strdup((char*) p + e[i].name_offset);
                if (!z) {
                        r = log_oom();
                        goto finish;
                }

                r = set_put(locales, z);
                if (r < 0) {
                        free(z);
                        log_error("Failed to add locale: %s", strerror(-r));
                        goto finish;
                }
        }

        l = set_get_strv(locales);
        if (!l) {
                r = log_oom();
                goto finish;
        }

        set_free(locales);
        locales = NULL;

        strv_sort(l);

        pager_open_if_enabled();

        STRV_FOREACH(j, l)
                puts(*j);

        r = 0;

finish:
        if (p != MAP_FAILED)
                munmap((void*) p, sz);

        set_free_free(locales);

        return r;
}
Beispiel #27
0
int cg_migrate(const char *cfrom, const char *pfrom, const char *cto, const char *pto, bool ignore_self) {
        bool done = false;
        _cleanup_set_free_ Set *s = NULL;
        int r, ret = 0;
        pid_t my_pid;
        _cleanup_fclose_ FILE *f = NULL;

        assert(cfrom);
        assert(pfrom);
        assert(cto);
        assert(pto);

        s = set_new(trivial_hash_func, trivial_compare_func);
        if (!s)
                return -ENOMEM;

        my_pid = getpid();

        do {
                pid_t pid = 0;
                done = true;

                r = cg_enumerate_tasks(cfrom, pfrom, &f);
                if (r < 0) {
                        if (ret >= 0 && r != -ENOENT)
                                ret = r;

                        return ret;
                }

                while ((r = cg_read_pid(f, &pid)) > 0) {

                        /* This might do weird stuff if we aren't a
                         * single-threaded program. However, we
                         * luckily know we are not */
                        if (pid == my_pid && ignore_self)
                                continue;

                        if (set_get(s, LONG_TO_PTR(pid)) == LONG_TO_PTR(pid))
                                continue;

                        r = cg_attach(cto, pto, pid);
                        if (r < 0) {
                                if (ret >= 0 && r != -ESRCH)
                                        ret = r;
                        } else if (ret == 0)
                                ret = 1;

                        done = false;

                        r = set_put(s, LONG_TO_PTR(pid));
                        if (r < 0) {
                                if (ret >= 0)
                                        ret = r;

                                return ret;
                        }
                }

                if (r < 0) {
                        if (ret >= 0)
                                ret = r;

                        return ret;
                }

                fclose(f);
                f = NULL;
        } while (!done);

        return ret;
}
Beispiel #28
0
static int bus_scope_set_transient_property(
                Scope *s,
                const char *name,
                sd_bus_message *message,
                UnitSetPropertiesMode mode,
                sd_bus_error *error) {

        int r;

        assert(s);
        assert(name);
        assert(message);

        if (streq(name, "PIDs")) {
                unsigned n = 0;
                uint32_t pid;

                r = set_ensure_allocated(&s->pids, trivial_hash_func, trivial_compare_func);
                if (r < 0)
                        return r;

                r = sd_bus_message_enter_container(message, 'a', "u");
                if (r < 0)
                        return r;

                while ((r = sd_bus_message_read(message, "u", &pid)) > 0) {

                        if (pid <= 1)
                                return -EINVAL;

                        if (mode != UNIT_CHECK) {
                                r = set_put(s->pids, LONG_TO_PTR(pid));
                                if (r < 0 && r != -EEXIST)
                                        return r;
                        }

                        n++;
                }
                if (r < 0)
                        return r;

                r = sd_bus_message_exit_container(message);
                if (r < 0)
                        return r;

                if (n <= 0)
                        return -EINVAL;

                return 1;

        } else if (streq(name, "TimeoutStopUSec")) {

                if (mode != UNIT_CHECK) {
                        r = sd_bus_message_read(message, "t", &s->timeout_stop_usec);
                        if (r < 0)
                                return r;

                        unit_write_drop_in_format(UNIT(s), mode, name, "[Scope]\nTimeoutStopSec=%lluus\n", (unsigned long long) s->timeout_stop_usec);
                } else {
                        r = sd_bus_message_skip(message, "t");
                        if (r < 0)
                                return r;
                }

                return 1;
        }

        return 0;
}
Beispiel #29
0
static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, void *userdata) {
        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
        union autofs_v5_packet_union packet;
        Automount *a = AUTOMOUNT(userdata);
        struct stat st;
        Unit *trigger;
        int r;

        assert(a);
        assert(fd == a->pipe_fd);

        if (events != EPOLLIN) {
                log_unit_error(UNIT(a), "Got invalid poll event %"PRIu32" on pipe (fd=%d)", events, fd);
                goto fail;
        }

        r = loop_read_exact(a->pipe_fd, &packet, sizeof(packet), true);
        if (r < 0) {
                log_unit_error_errno(UNIT(a), r, "Invalid read from pipe: %m");
                goto fail;
        }

        switch (packet.hdr.type) {

        case autofs_ptype_missing_direct:

                if (packet.v5_packet.pid > 0) {
                        _cleanup_free_ char *p = NULL;

                        get_process_comm(packet.v5_packet.pid, &p);
                        log_unit_info(UNIT(a), "Got automount request for %s, triggered by %"PRIu32" (%s)", a->where, packet.v5_packet.pid, strna(p));
                } else
                        log_unit_debug(UNIT(a), "Got direct mount request on %s", a->where);

                r = set_ensure_allocated(&a->tokens, NULL);
                if (r < 0) {
                        log_unit_error(UNIT(a), "Failed to allocate token set.");
                        goto fail;
                }

                r = set_put(a->tokens, UINT_TO_PTR(packet.v5_packet.wait_queue_token));
                if (r < 0) {
                        log_unit_error_errno(UNIT(a), r, "Failed to remember token: %m");
                        goto fail;
                }

                automount_enter_runnning(a);
                break;

        case autofs_ptype_expire_direct:
                log_unit_debug(UNIT(a), "Got direct umount request on %s", a->where);

                automount_stop_expire(a);

                r = set_ensure_allocated(&a->expire_tokens, NULL);
                if (r < 0) {
                        log_unit_error(UNIT(a), "Failed to allocate token set.");
                        goto fail;
                }

                r = set_put(a->expire_tokens, UINT_TO_PTR(packet.v5_packet.wait_queue_token));
                if (r < 0) {
                        log_unit_error_errno(UNIT(a), r, "Failed to remember token: %m");
                        goto fail;
                }

                /* Before we do anything, let's see if somebody is playing games with us? */
                if (lstat(a->where, &st) < 0) {
                        log_unit_warning_errno(UNIT(a), errno, "Failed to stat automount point: %m");
                        goto fail;
                }

                if (!S_ISDIR(st.st_mode) || st.st_dev == a->dev_id) {
                        log_unit_info(UNIT(a), "Automount point already unmounted?");
                        automount_send_ready(a, a->expire_tokens, 0);
                        break;
                }

                trigger = UNIT_TRIGGER(UNIT(a));
                if (!trigger) {
                        log_unit_error(UNIT(a), "Unit to trigger vanished.");
                        goto fail;
                }

                r = manager_add_job(UNIT(a)->manager, JOB_STOP, trigger, JOB_REPLACE, &error, NULL);
                if (r < 0) {
                        log_unit_warning(UNIT(a), "Failed to queue umount startup job: %s", bus_error_message(&error, r));
                        goto fail;
                }
                break;

        default:
                log_unit_error(UNIT(a), "Received unknown automount request %i", packet.hdr.type);
                break;
        }

        return 0;

fail:
        automount_enter_dead(a, AUTOMOUNT_FAILURE_RESOURCES);
        return 0;
}
Beispiel #30
0
static int automount_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
        Automount *a = AUTOMOUNT(u);
        int r;

        assert(a);
        assert(fds);

        if (streq(key, "state")) {
                AutomountState state;

                state = automount_state_from_string(value);
                if (state < 0)
                        log_unit_debug(u, "Failed to parse state value: %s", value);
                else
                        a->deserialized_state = state;
        } else if (streq(key, "result")) {
                AutomountResult f;

                f = automount_result_from_string(value);
                if (f < 0)
                        log_unit_debug(u, "Failed to parse result value: %s", value);
                else if (f != AUTOMOUNT_SUCCESS)
                        a->result = f;

        } else if (streq(key, "dev-id")) {
                unsigned d;

                if (safe_atou(value, &d) < 0)
                        log_unit_debug(u, "Failed to parse dev-id value: %s", value);
                else
                        a->dev_id = (unsigned) d;
        } else if (streq(key, "token")) {
                unsigned token;

                if (safe_atou(value, &token) < 0)
                        log_unit_debug(u, "Failed to parse token value: %s", value);
                else {
                        r = set_ensure_allocated(&a->tokens, NULL);
                        if (r < 0) {
                                log_oom();
                                return 0;
                        }

                        r = set_put(a->tokens, UINT_TO_PTR(token));
                        if (r < 0)
                                log_unit_error_errno(u, r, "Failed to add token to set: %m");
                }
        } else if (streq(key, "expire-token")) {
                unsigned token;

                if (safe_atou(value, &token) < 0)
                        log_unit_debug(u, "Failed to parse token value: %s", value);
                else {
                        r = set_ensure_allocated(&a->expire_tokens, NULL);
                        if (r < 0) {
                                log_oom();
                                return 0;
                        }

                        r = set_put(a->expire_tokens, UINT_TO_PTR(token));
                        if (r < 0)
                                log_unit_error_errno(u, r, "Failed to add expire token to set: %m");
                }
        } else if (streq(key, "pipe-fd")) {
                int fd;

                if (safe_atoi(value, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
                        log_unit_debug(u, "Failed to parse pipe-fd value: %s", value);
                else {
                        safe_close(a->pipe_fd);
                        a->pipe_fd = fdset_remove(fds, fd);
                }
        } else
                log_unit_debug(u, "Unknown serialization key: %s", key);

        return 0;
}