Exemplo n.º 1
0
void do_ethernet(int argc, char **argv)
{
	int sock, ret;
	uint8_t cmd = 0;
	struct sockaddr_nl src_addr, dest_addr;
	struct nlmsghdr *nlh;
	struct iovec iov;
	struct msghdr msg;
	struct vlinknlmsg *vmsg;

	if (unlikely(argc == 0))
		usage();
	if (!strncmp("add", argv[0], strlen("add")) && argc == 4)
		cmd = VLINKNLCMD_ADD_DEVICE;
	else if (!strncmp("rm", argv[0], strlen("rm")) && argc == 2)
		cmd = VLINKNLCMD_RM_DEVICE;
	else if (!strncmp("hook", argv[0], strlen("hook")) && argc == 2)
		cmd = VLINKNLCMD_START_HOOK_DEVICE;
	else if (!strncmp("unhook", argv[0], strlen("unhook")) && argc == 2)
		cmd = VLINKNLCMD_STOP_HOOK_DEVICE;
	else
		usage();

	sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_VLINK);
	if (unlikely(sock < 0))
		panic("Cannot get NETLINK_VLINK socket from kernel! "
		      "Modules not loaded?!\n");

	memset(&src_addr, 0, sizeof(src_addr));
	src_addr.nl_family = AF_NETLINK;
	src_addr.nl_pad = 0;
	src_addr.nl_pid = getpid();
	src_addr.nl_groups = 0;

	ret = bind(sock, (struct sockaddr *) &src_addr, sizeof(src_addr));
	if (unlikely(ret))
		panic("Cannot bind socket!\n");

	memset(&dest_addr, 0, sizeof(dest_addr));
	dest_addr.nl_family = AF_NETLINK;
	dest_addr.nl_pad = 0;
	dest_addr.nl_pid = 0;
	dest_addr.nl_groups = 0;

	nlh = xzmalloc(NLMSG_SPACE(sizeof(*vmsg)));
	nlh->nlmsg_len = NLMSG_SPACE(sizeof(*vmsg));
	nlh->nlmsg_pid = getpid();
	nlh->nlmsg_type = VLINKNLGRP_ETHERNET;
	nlh->nlmsg_flags = NLM_F_REQUEST;

	vmsg = (struct vlinknlmsg *) NLMSG_DATA(nlh);
	vmsg->cmd = cmd;
	if (cmd == VLINKNLCMD_ADD_DEVICE)
		vmsg->port = (uint16_t) (0xFFFF & atoi(argv[3]));
	vmsg->flags = 0;
	strlcpy((char *) vmsg->virt_name, argv[1], sizeof(vmsg->virt_name));
	if (cmd == VLINKNLCMD_ADD_DEVICE)
		strlcpy((char *) vmsg->real_name, argv[2],
			sizeof(vmsg->real_name));
	else if (cmd == VLINKNLCMD_START_HOOK_DEVICE ||
		 cmd == VLINKNLCMD_STOP_HOOK_DEVICE)
		strlcpy((char *) vmsg->real_name, argv[1],
			sizeof(vmsg->real_name));

	iov.iov_base = nlh;
	iov.iov_len = nlh->nlmsg_len;

	memset(&msg, 0, sizeof(msg));
	msg.msg_name = &dest_addr;
	msg.msg_namelen = sizeof(dest_addr);
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;

	ret = sendmsg(sock, &msg, 0);
	if (unlikely(ret < 0))
		panic("Cannot send NETLINK message to the kernel!\n");

	close(sock);
	xfree(nlh);
}
Exemplo n.º 2
0
int xapian_dbw_open(const char **paths, xapian_dbw_t **dbwp)
{
    xapian_dbw_t *dbw = (xapian_dbw_t *)xzmalloc(sizeof(xapian_dbw_t));
    int r = 0;

    const char *path = *paths++;
    try {
        /* Determine the sterm version of an existing database, or create a
         * new one with the latest one. Never implicitly upgrade. */
        try {
            dbw->database = new Xapian::WritableDatabase(path, Xapian::DB_OPEN);
            dbw->stem_version = stem_version_get(dbw->database);
            if (dbw->stem_version < 0) {
                syslog(LOG_ERR, "xapian_wrapper: Invalid stem version %d in %s",
                        dbw->stem_version, path);
                r = IMAP_IOERROR;
            }
        } catch (Xapian::DatabaseOpeningError &e) {
            /* It's OK not to atomically create or open, since we can assume
             * the xapianactive file items to be locked. */
            dbw->database = new Xapian::WritableDatabase(path, Xapian::DB_CREATE|Xapian::DB_BACKEND_GLASS);
            dbw->stem_version = XAPIAN_STEM_CURRENT_VERSION;
            stem_version_set(dbw->database, dbw->stem_version);
        }

        dbw->term_generator = new Xapian::TermGenerator();
        dbw->stemmer = new Xapian::Stem("en");
        dbw->stopper = get_stopper();
        dbw->term_generator->set_stemmer(*dbw->stemmer);
        /* Always enable CJK word tokenization */
        dbw->term_generator->set_flags(Xapian::TermGenerator::FLAG_CJK_WORDS,
                ~Xapian::TermGenerator::FLAG_CJK_WORDS);
        dbw->term_generator->set_stopper(dbw->stopper);
    }
    catch (const Xapian::DatabaseLockError &err) {
        /* somebody else is already indexing this user.  They may be doing a different
         * mailbox, so we need to re-insert this mailbox into the queue! */
        r = IMAP_MAILBOX_LOCKED;
    }
    catch (const Xapian::Error &err) {
        syslog(LOG_ERR, "IOERROR: Xapian: caught exception: %s: %s",
                    err.get_context().c_str(), err.get_description().c_str());
        r = IMAP_IOERROR;
    }

    if (r) {
        xapian_dbw_close(dbw);
        return r;
    }

    /* open the read-only databases */
    while (*paths) {
        try {
            Xapian::Database *database = new Xapian::Database(*paths++);
            ptrarray_append(&dbw->otherdbs, database);
        }
        catch (const Xapian::Error &err) {
            syslog(LOG_ERR, "IOERROR: Xapian: caught exception: %s: %s",
                        err.get_context().c_str(), err.get_description().c_str());
        }
    }

    *dbwp = dbw;

    return r;
}
Exemplo n.º 3
0
shutdown_t *shutdown_create (void)
{
    shutdown_t *s = xzmalloc (sizeof (*s));
    return s;
}
Exemplo n.º 4
0
int server_main(char *home, char *dev, char *port, int udp, int ipv4, int log)
{
	int lfd = -1, kdpfd, nfds, nfd, curfds, efd[2], refd[2], tunfd, i;
	unsigned int cpus = 0, threads, udp_cpu = 0;
	ssize_t ret;
	struct epoll_event *events;
	struct addrinfo hints, *ahead, *ai;

	auth_log = !!log;
	openlog("curvetun", LOG_PID | LOG_CONS | LOG_NDELAY, LOG_DAEMON);

	syslog(LOG_INFO, "curvetun server booting!\n");
	syslog_maybe(!auth_log, LOG_INFO, "curvetun user logging disabled!\n");

	parse_userfile_and_generate_user_store_or_die(home);

	memset(&hints, 0, sizeof(hints));
	hints.ai_family = PF_UNSPEC;
	hints.ai_socktype = udp ? SOCK_DGRAM : SOCK_STREAM;
	hints.ai_protocol = udp ? IPPROTO_UDP : IPPROTO_TCP;
	hints.ai_flags = AI_PASSIVE;

	ret = getaddrinfo(NULL, port, &hints, &ahead);
	if (ret < 0)
		syslog_panic("Cannot get address info!\n");

	for (ai = ahead; ai != NULL && lfd < 0; ai = ai->ai_next) {
		lfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
		if (lfd < 0)
			continue;
		if (ai->ai_family == AF_INET6) {
#ifdef IPV6_V6ONLY
			ret = set_ipv6_only(lfd);
			if (ret < 0) {
				close(lfd);
				lfd = -1;
				continue;
			}
#else
			close(lfd);
			lfd = -1;
			continue;
#endif /* IPV6_V6ONLY */
		}

		set_reuseaddr(lfd);
		set_mtu_disc_dont(lfd);

		ret = bind(lfd, ai->ai_addr, ai->ai_addrlen);
		if (ret < 0) {
			close(lfd);
			lfd = -1;
			continue;
		}

		if (!udp) {
			ret = listen(lfd, 5);
			if (ret < 0) {
				close(lfd);
				lfd = -1;
				continue;
			}
		}

		if (ipv4 == -1) {
			ipv4 = (ai->ai_family == AF_INET6 ? 0 :
				(ai->ai_family == AF_INET ? 1 : -1));
		}

		syslog_maybe(auth_log, LOG_INFO, "curvetun on IPv%d via %s "
			     "on port %s!\n", ai->ai_family == AF_INET ? 4 : 6,
			     udp ? "UDP" : "TCP", port);
		syslog_maybe(auth_log, LOG_INFO, "Allowed overlay proto is "
			     "IPv%d!\n", ipv4 ? 4 : 6);
	}

	freeaddrinfo(ahead);

	if (lfd < 0 || ipv4 < 0)
		syslog_panic("Cannot create socket!\n");

	tunfd = tun_open_or_die(dev ? dev : DEVNAME_SERVER, IFF_TUN | IFF_NO_PI);

	pipe_or_die(efd, O_NONBLOCK);
	pipe_or_die(refd, O_NONBLOCK);

	set_nonblocking(lfd);

	events = xzmalloc(MAX_EPOLL_SIZE * sizeof(*events));
	for (i = 0; i < MAX_EPOLL_SIZE; ++i)
		events[i].data.fd = -1;

	kdpfd = epoll_create(MAX_EPOLL_SIZE);
	if (kdpfd < 0)
		syslog_panic("Cannot create socket!\n");

	set_epoll_descriptor(kdpfd, EPOLL_CTL_ADD, lfd,
			     udp ? EPOLLIN | EPOLLET | EPOLLONESHOT : EPOLLIN);
	set_epoll_descriptor(kdpfd, EPOLL_CTL_ADD, efd[0], EPOLLIN);
	set_epoll_descriptor(kdpfd, EPOLL_CTL_ADD, refd[0], EPOLLIN);
	set_epoll_descriptor(kdpfd, EPOLL_CTL_ADD, tunfd,
			     EPOLLIN | EPOLLET | EPOLLONESHOT);
	curfds = 4;

	trie_init();

	cpus = get_number_cpus_online();
	threads = cpus * THREADS_PER_CPU;
	if (!ispow2(threads))
		syslog_panic("Thread number not power of two!\n");

	threadpool = xzmalloc(sizeof(*threadpool) * threads);
	thread_spawn_or_panic(cpus, efd[1], refd[1], tunfd, ipv4, udp);

	init_cpusched(threads);

	register_socket(tunfd);
	register_socket(lfd);

	syslog(LOG_INFO, "curvetun up and running!\n");

	while (likely(!sigint)) {
		nfds = epoll_wait(kdpfd, events, curfds, -1);
		if (nfds < 0) {
			syslog(LOG_ERR, "epoll_wait error: %s\n",
			       strerror(errno));
			break;
		}

		for (i = 0; i < nfds; ++i) {
			if (unlikely(events[i].data.fd < 0))
				continue;

			if (events[i].data.fd == lfd && !udp) {
				int ncpu;
				char hbuff[256], sbuff[256];
				struct sockaddr_storage taddr;
				socklen_t tlen;

				tlen = sizeof(taddr);
				nfd = accept(lfd, (struct sockaddr *) &taddr,
					     &tlen);
				if (nfd < 0) {
					syslog(LOG_ERR, "accept error: %s\n",
					       strerror(errno));
					continue;
				}

				if (curfds + 1 > MAX_EPOLL_SIZE) {
					close(nfd);
					continue;
				}

				curfds++;

				ncpu = register_socket(nfd);

				memset(hbuff, 0, sizeof(hbuff));
				memset(sbuff, 0, sizeof(sbuff));
				getnameinfo((struct sockaddr *) &taddr, tlen,
					    hbuff, sizeof(hbuff),
					    sbuff, sizeof(sbuff),
					    NI_NUMERICHOST | NI_NUMERICSERV);

				syslog_maybe(auth_log, LOG_INFO, "New connection "
					     "from %s:%s with id %d on CPU%d, %d "
					     "active!\n", hbuff, sbuff, nfd, ncpu,
					     curfds);

				set_nonblocking(nfd);
				set_socket_keepalive(nfd);
				set_tcp_nodelay(nfd);
				ret = set_epoll_descriptor2(kdpfd, EPOLL_CTL_ADD,
						nfd, EPOLLIN | EPOLLET | EPOLLONESHOT);
				if (ret < 0) {
					close(nfd);
					curfds--;
					continue;
				}
			} else if (events[i].data.fd == refd[0]) {
				int fd_one;

				ret = read_exact(refd[0], &fd_one,
						 sizeof(fd_one), 1);
				if (ret != sizeof(fd_one) || fd_one <= 0)
					continue;

				ret = set_epoll_descriptor2(kdpfd, EPOLL_CTL_MOD,
						fd_one, EPOLLIN | EPOLLET | EPOLLONESHOT);
				if (ret < 0) {
					close(fd_one);
					continue;
				}
			} else if (events[i].data.fd == efd[0]) {
				int fd_del, test;

				ret = read_exact(efd[0], &fd_del,
						 sizeof(fd_del), 1);
				if (ret != sizeof(fd_del) || fd_del <= 0)
					continue;

				ret = read(fd_del, &test, sizeof(test));
				if (ret < 0 && errno == EBADF)
					continue;

				ret = set_epoll_descriptor2(kdpfd, EPOLL_CTL_DEL,
						fd_del, 0);
				if (ret < 0) {
					close(fd_del);
					continue;
				}

				close(fd_del);
				curfds--;
				unregister_socket(fd_del);

				syslog_maybe(auth_log, LOG_INFO, "Closed connection "
					     "with id %d, %d active!\n", fd_del,
					     curfds);
			} else {
				int cpu, fd_work = events[i].data.fd;

				if (!udp)
					cpu = socket_to_cpu(fd_work);
				else
					udp_cpu = (udp_cpu + 1) & (threads - 1);

				write_exact(threadpool[udp ? udp_cpu : cpu].efd[1],
					    &fd_work, sizeof(fd_work), 1);
			}
		}
	}

	syslog(LOG_INFO, "curvetun prepare shut down!\n");

	close(lfd);
	close(efd[0]);
	close(efd[1]);
	close(refd[0]);
	close(refd[1]);
	close(tunfd);

	thread_finish(cpus);

	xfree(threadpool);
	xfree(events);

	unregister_socket(lfd);
	unregister_socket(tunfd);

	destroy_cpusched();

	trie_cleanup();

	destroy_user_store();

	syslog(LOG_INFO, "curvetun shut down!\n");
	closelog();

	return 0;
}
Exemplo n.º 5
0
void test_mt (int argc, char **argv)
{
    thd_t *thd;
    int i, rc;
    flux_t h;
    int errors = 0;

    if (argc != 3) {
        fprintf (stderr, "Usage: mt nthreads changes key\n");
        exit (1);
    }
    nthreads = strtoul (argv[0], NULL, 10);
    changes = strtoul (argv[1], NULL, 10);
    key = argv[2];

    thd = xzmalloc (sizeof (*thd) * nthreads);

    if (!(h = flux_open (NULL, 0)))
        err_exit ("flux_open");

    /* Set initial value of 'key' to -1 */
    if (kvs_put_int (h, key, -1) < 0)
        err_exit ("kvs_put_int %s", key);
    key_stable = xasprintf ("%s-stable", key);
    if (kvs_put_int (h, key_stable, 0) < 0)
        err_exit ("kvs_put_int %s", key);

    if (kvs_commit (h) < 0)
        err_exit ("kvs_commit");

    for (i = 0; i < nthreads; i++) {
        thd[i].n = i;
        thd[i].last_val = -42;
        if ((rc = pthread_attr_init (&thd[i].attr)))
            errn (rc, "pthread_attr_init");
        if ((rc = pthread_create (&thd[i].tid, &thd[i].attr, thread, &thd[i])))
            errn (rc, "pthread_create");
    }
    wait_ready ();

    for (i = 0; i < changes; i++) {
        if (kvs_put_int (h, key, i) < 0)
            err_exit ("kvs_put_int %s", key);
        if (kvs_commit (h) < 0)
            err_exit ("kvs_commit");
    }

    /* Verify that callbacks were called the correct number of times.
     * The nil and stable callbacks will be called exactly once before the
     * reactor is started, then should never be called again.
     * Due to commit merging on the master, the changing callback may
     * miss intervening values but it shouldn't be called extra times.
     */
    for (i = 0; i < nthreads; i++) {
        if ((rc = pthread_join (thd[i].tid, NULL)))
            errn (rc, "pthread_join");
        if (thd[i].nil_count != 1) {
            msg ("%d: nil callback called %d times (expected one)",
                 i, thd[i].nil_count);
            errors++;
        }
        if (thd[i].stable_count != 1) {
            msg ("%d: stable callback called %d times (expected one)",
                 i, thd[i].stable_count);
            errors++;
        }
        if (thd[i].change_count > changes + 1) {
            msg ("%d: changing callback called %d times (expected <= %d)",
                 i, thd[i].change_count, changes + 1);
            errors++;
        }
    }
    if (errors > 0)
        exit (1);

    free (thd);
    free (key_stable);

    flux_close (h);
}
Exemplo n.º 6
0
static sync_log_reader_t *sync_log_reader_alloc(void)
{
    sync_log_reader_t *slr = xzmalloc(sizeof(sync_log_reader_t));
    slr->fd = -1;
    return slr;
}
Exemplo n.º 7
0
struct alsa_dev *alsa_open(char *devname, unsigned int rate,
			   int channels, int period)
{
	int ret;
	struct alsa_dev *dev;

	if (!devname)
		devname = "plughw:0,0";

	dev = xzmalloc(sizeof(*dev));
	dev->name = xstrdup(devname);
	dev->channels = channels;
	dev->period = period;

	ret = snd_pcm_open(&dev->capture_handle, dev->name,
			   SND_PCM_STREAM_CAPTURE, 0);
	if (ret < 0)
		syslog_panic("Cannot open audio capture device %s: %s\n",
			     dev->name, snd_strerror(ret));
	alsa_set_hw_params(dev, dev->capture_handle, rate, channels, period);
	alsa_set_sw_params(dev, dev->capture_handle, period, 0);

	ret = snd_pcm_open(&dev->playback_handle, dev->name,
			   SND_PCM_STREAM_PLAYBACK, 0);
	if (ret < 0)
		syslog_panic("Cannot open audio playback device %s: %s\n",
			     dev->name, snd_strerror(ret));
	alsa_set_hw_params(dev, dev->playback_handle, rate, channels, period);
	alsa_set_sw_params(dev, dev->playback_handle, period, 1);

	snd_pcm_link(dev->capture_handle, dev->playback_handle);

	ret = snd_pcm_prepare(dev->capture_handle);
	if (ret < 0)
		syslog_panic("Cannot prepare audio interface: %s\n",
			     snd_strerror(ret));

	ret = snd_pcm_prepare(dev->playback_handle);
	if (ret < 0)
		syslog_panic("Cannot prepare audio interface: %s\n",
			     snd_strerror(ret));

	dev->read_fds = snd_pcm_poll_descriptors_count(dev->capture_handle);
	dev->write_fds = snd_pcm_poll_descriptors_count(dev->playback_handle);

	dev->read_fd = xzmalloc(dev->read_fds * sizeof(*dev->read_fd));
	ret = snd_pcm_poll_descriptors(dev->capture_handle, dev->read_fd,
				       dev->read_fds);
	if (ret != dev->read_fds)
		syslog_panic("Cannot obtain capture file descriptors: %s\n",
			     snd_strerror(ret));

	dev->write_fd = xzmalloc(dev->write_fds * sizeof(*dev->write_fd));
	ret = snd_pcm_poll_descriptors(dev->playback_handle, dev->write_fd,
				       dev->write_fds);
	if (ret != dev->write_fds)
		syslog_panic("Cannot obtain playback file descriptors: %s\n",
			     snd_strerror(ret));

	return dev;
}
Exemplo n.º 8
0
int main(int argc, char **argv)
{
    save_argv0(argv[0]);

    const char *alt_config = NULL;
    const char *input_file = NULL;
    const char *backup_name = NULL;
    const char *servername = NULL;
    enum restore_mode mode = RESTORE_MODE_UNSPECIFIED;
    int local_only = 0;
    int wait = 0;
    int do_nothing = 0;
    int do_all_mailboxes = 0;

    struct restore_options options = {0};
    options.expunged_mode = RESTORE_EXPUNGED_OKAY;
    options.trim_deletedprefix = 1;

    struct backup *backup = NULL;
    mbname_t *mbname = NULL;
    struct backup_mailbox_list *mailbox_list = NULL;
    struct sync_folder_list *reserve_folder_list = NULL;
    struct sync_reserve_list *reserve_list = NULL;
    struct buf tagbuf = BUF_INITIALIZER;
    struct backend *backend = NULL;
    struct dlist *upload = NULL;
    int opt, r;

    while ((opt = getopt(argc, argv, ":A:C:DF:LM:P:UXaf:m:nru:vw:xz")) != EOF) {
        switch (opt) {
        case 'A':
            if (options.keep_uidvalidity) usage();
            options.override_acl = optarg;
            break;
        case 'C':
            alt_config = optarg;
            break;
        case 'D':
            /* XXX does this clash with keep_uidvalidity? */
            options.trim_deletedprefix = 0;
            break;
        case 'F':
            if (do_all_mailboxes) usage();
            input_file = optarg;
            break;
        case 'L':
            local_only = 1;
            break;
        case 'M':
            if (options.keep_uidvalidity) usage();
            options.override_mboxname = optarg;
            break;
        case 'P':
            if (options.keep_uidvalidity) usage();
            options.override_partition = optarg;
            break;
        case 'U':
            if (options.override_acl || options.override_mboxname || options.override_partition)
                usage();
            options.keep_uidvalidity = 1;
            break;
        case 'X':
            if (options.expunged_mode != RESTORE_EXPUNGED_OKAY) usage();
            options.expunged_mode = RESTORE_EXPUNGED_EXCLUDE;
            break;
        case 'a':
            if (input_file) usage();
            do_all_mailboxes = 1;
            break;
        case 'f':
            if (mode != RESTORE_MODE_UNSPECIFIED) usage();
            mode = RESTORE_MODE_FILENAME;
            backup_name = optarg;
            break;
        case 'm':
            if (mode != RESTORE_MODE_UNSPECIFIED) usage();
            mode = RESTORE_MODE_MBOXNAME;
            backup_name = optarg;
            break;
        case 'n':
            do_nothing = 1;
            break;
        case 'r':
            options.do_submailboxes = 1;
            break;
        case 'u':
            if (mode != RESTORE_MODE_UNSPECIFIED) usage();
            mode = RESTORE_MODE_USERNAME;
            backup_name = optarg;
            break;
        case 'v':
            options.verbose++;
            break;
        case 'w':
            wait = atoi(optarg);
            if (wait < 0) usage();
            break;
        case 'x':
            if (options.expunged_mode != RESTORE_EXPUNGED_OKAY) usage();
            options.expunged_mode = RESTORE_EXPUNGED_ONLY;
            break;
        case 'z':
            options.require_compression = 1;
            break;
        case ':':
            if (optopt == 'A') options.override_acl = "";
            else usage();
            break;
        default:
            usage();
            break;
        }
    }

    /* we need a server name */
    if (optind == argc) usage();
    servername = argv[optind++];

    /* we need a source of backup data */
    if (mode == RESTORE_MODE_UNSPECIFIED) {
        if (optind == argc) usage();
        backup_name = argv[optind++];
        mode = RESTORE_MODE_USERNAME;
    }

    /* we need either an input file or some objects to restore */
    if (!do_all_mailboxes && !input_file && optind == argc) usage();
    /* and we can't have both because i said */
    if ((input_file || do_all_mailboxes) && optind < argc) usage();

    /* okay, arguments seem sane, we are go */
    cyrus_init(alt_config, "restore", 0, 0);

    /* load the SASL plugins */
    global_sasl_init(1, 0, mysasl_cb);

    /* wait here for gdb attach */
    if (wait) {
        fprintf(stderr, "Waiting for %d seconds for gdb attach...\n", wait);
        sleep(wait);
    }

    /* open backup */
    switch (mode) {
    case RESTORE_MODE_FILENAME:
        r = backup_open_paths(&backup, backup_name, NULL,
                              BACKUP_OPEN_NONBLOCK, BACKUP_OPEN_NOCREATE);
        break;
    case RESTORE_MODE_MBOXNAME:
        mbname = mbname_from_intname(backup_name);
        if (!mbname) usage();
        r = backup_open(&backup, mbname,
                        BACKUP_OPEN_NONBLOCK, BACKUP_OPEN_NOCREATE);
        mbname_free(&mbname);
        break;
    case RESTORE_MODE_USERNAME:
        mbname = mbname_from_userid(backup_name);
        if (!mbname) usage();
        r = backup_open(&backup, mbname,
                        BACKUP_OPEN_NONBLOCK, BACKUP_OPEN_NOCREATE);
        mbname_free(&mbname);
        break;
    default:
        usage();
        break;
    }

    if (r) goto done;

    /* scan for objects to restore:
     *   mailboxes will have all messages added, modulo expunged_mode
     *   messages will be added individually with appropriate folder
     */
    mailbox_list = xzmalloc(sizeof *mailbox_list);
    reserve_folder_list = restore_make_reserve_folder_list(backup);
    reserve_list = sync_reserve_list_create(SYNC_MSGID_LIST_HASH_SIZE);

    if (input_file) {
        char buf[MAX_MAILBOX_NAME + 2]; // \n\0
        size_t len;
        FILE *f;

        if (0 != strcmp(input_file, "-")) {
            f = fopen(input_file, "r");
            if (!f) {
                fprintf(stderr, "fopen %s: %s\n", input_file, strerror(errno));
                goto done;// FIXME shut_down?
            }
        }
        else {
            f = stdin;
        }

        while (fgets(buf, sizeof(buf), f)) {
            len = strlen(buf);

            if (len > 0 && buf[len - 1] == '\n')
                buf[--len] = '\0';

            if (len == 0 || buf[0] == '#')
                continue;

            r = restore_add_object(buf, &options, backup, mailbox_list,
                                   reserve_folder_list, reserve_list);

            // FIXME r
        }
        fclose(f);
    }
    else if (do_all_mailboxes) {
        struct backup_mailbox_list *all_mailboxes;
        struct backup_mailbox *mailbox;

        all_mailboxes = backup_get_mailboxes(backup, 0,
                                             BACKUP_MAILBOX_ALL_RECORDS);

        for (mailbox = all_mailboxes->head; mailbox; mailbox = mailbox->next) {
            restore_add_mailbox(mailbox, &options, mailbox_list,
                                reserve_folder_list, reserve_list);
        }

        backup_mailbox_list_empty(all_mailboxes);
        free(all_mailboxes);
    }
    else {
        int i;

        for (i = optind; i < argc; i++) {
            r = restore_add_object(argv[i], &options, backup, mailbox_list,
                                   reserve_folder_list, reserve_list);

            // FIXME r
        }
    }

    if (do_nothing) {
        if (options.verbose)
            fprintf(stderr, "do nothing (-n) specified, exiting now\n");
        goto done;
    }

    /* connect to destination */
    backend = restore_connect(servername, &tagbuf, &options);

    if (!backend) {
        // FIXME
        r = -1;
        goto done;
    }

    /* do the restore */
    struct sync_reserve *reserve;
    for (reserve = reserve_list->head; reserve; reserve = reserve->next) {
        /* send APPLY RESERVE and parse missing lists */
        r = sync_reserve_partition(reserve->part,
                                   reserve_folder_list,
                                   reserve->list,
                                   backend);
        if (r) goto done;

        /* send APPLY MESSAGEs */
        r = backup_prepare_message_upload(backup,
                                          reserve->part,
                                          reserve->list,
                                          &sync_msgid_lookup,
                                          &upload);
        if (r) goto done;
        /* upload in small(ish) blocks to avoid timeouts */
        while (upload->head) {
            struct dlist *block = dlist_splice(upload, 1024);
            sync_send_apply(block, backend->out);
            r = sync_parse_response("MESSAGE", backend->in, NULL);
            dlist_unlink_files(block);
            dlist_free(&block);
            if (r) goto done;
        }
    }

    /* sync_prepare_dlists needs to upload messages per-mailbox, because
     * it needs the mailbox to find the filename for the message.  but
     * we have no such limitation, so we can upload messages while
     * looping over the reserve_list instead, above.
     *
     * alternatively, if we do it on a per-mailbox basis then we can limit
     * the hit on the staging directory to only a mailbox worth of messages
     * at a time.  but we don't have a logical grouping that would make
     * this coherent
     */

    /* send RESTORE MAILBOXes */
    struct backup_mailbox *mailbox;
    for (mailbox = mailbox_list->head; mailbox; mailbox = mailbox->next) {
        /* XXX filter the mailbox records based on reserve/missing/upload */

        /* XXX does this sensibly handle mailbox objs with empty values? */
        struct dlist *dl = backup_mailbox_to_dlist(mailbox);
        if (!dl) continue;

        if (local_only) {
            free(dl->name);
            dl->name = xstrdup("LOCAL_MAILBOX");
        }

        sync_send_restore(dl, backend->out);
        r = sync_parse_response("MAILBOX", backend->in, NULL);
        dlist_free(&dl);
        if (r) goto done;
    }

done:
    if (r)
        fprintf(stderr, "%s: %s\n", backup_name, error_message(r));

    /* release lock asap */
    if (backup)
        backup_close(&backup);

    if (backend)
        backend_disconnect(backend);

    if (upload) {
        dlist_unlink_files(upload);
        dlist_free(&upload);
    }

    if (mailbox_list) {
        backup_mailbox_list_empty(mailbox_list);
        free(mailbox_list);
    }

    if (reserve_folder_list)
        sync_folder_list_free(&reserve_folder_list);

    if (reserve_list)
        sync_reserve_list_free(&reserve_list);

    buf_free(&tagbuf);

    backup_cleanup_staging_path();
    cyrus_done();

    exit(r ? EX_TEMPFAIL : EX_OK);
}
Exemplo n.º 9
0
int main (int argc, char *argv[])
{
    struct context ctx;
    struct pmi_simple_ops ops = {
        .kvs_put = s_kvs_put,
        .kvs_get = s_kvs_get,
        .barrier_enter = s_barrier_enter,
        .response_send = s_send_response,
    };
    struct pmi_simple_client *cli;
    int spawned = -1, initialized = -1;
    int rank = -1, size = -1;
    int universe_size = -1;
    int name_len = -1, key_len = -1, val_len = -1;
    char *name = NULL, *val = NULL, *val2 = NULL, *val3 = NULL;
    char *key = NULL;
    int rc;

    plan (NO_PLAN);

    if (!(ctx.kvs = zhash_new ()))
        oom ();
    ctx.size = 1;
    ok (socketpair (PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, ctx.fds) == 0,
        "socketpair returned client,server file descriptors");
    ctx.pmi = pmi_simple_server_create (&ops, 42, ctx.size, ctx.size,
                                        "bleepgorp", 0, &ctx);
    ok (ctx.pmi != NULL,
        "created simple pmi server context");
    ok (pthread_create (&ctx.t, NULL, server_thread, &ctx) == 0,
        "pthread_create successfully started server");

    setenvf ("PMI_FD", 1, "%d", ctx.fds[0]);
    setenvf ("PMI_RANK", 1, "%d", 0);
    setenvf ("PMI_SIZE", 1, "%d", ctx.size);

    ok ((cli = pmi_simple_client_create ()) != NULL,
        "pmi_simple_client_create OK");
    ok (pmi_simple_client_initialized (cli, &initialized) == PMI_SUCCESS
        && initialized == 0,
        "pmi_simple_client_initialized OK, initialized=0");
    ok (pmi_simple_client_init (cli, &spawned) == PMI_SUCCESS && spawned == 0,
        "pmi_simple_client_init OK, spawned=0");
    ok (pmi_simple_client_initialized (cli, &initialized) == PMI_SUCCESS
        && initialized == 1,
        "pmi_simple_client_initialized OK, initialized=1");

    /* retrieve basic params
     */
    ok (pmi_simple_client_get_size (cli, &size) == PMI_SUCCESS && size == 1,
        "pmi_simple_client_get_size OK, size=%d", size);
    ok (pmi_simple_client_get_rank (cli, &rank) == PMI_SUCCESS && rank == 0,
        "pmi_simple_client_get_rank OK, rank=%d", rank);
    ok (pmi_simple_client_get_universe_size (cli, &universe_size) == PMI_SUCCESS
        && universe_size == size,
        "pmi_simple_client_get_universe_size OK, universe_size=%d", universe_size);
    ok (pmi_simple_client_kvs_get_name_length_max (cli, &name_len) == PMI_SUCCESS
        && name_len > 0,
        "pmi_simple_client_kvs_get_name_length_max OK, name_len=%d", name_len);
    ok (pmi_simple_client_kvs_get_key_length_max (cli, &key_len) == PMI_SUCCESS
        && key_len > 0,
        "pmi_simple_client_kvs_get_key_length_max OK, key_len=%d", key_len);
    ok (pmi_simple_client_kvs_get_value_length_max (cli, &val_len) == PMI_SUCCESS
        && val_len > 0,
        "pmi_simple_client_kvs_get_value_length_max OK, val_len=%d", val_len);
    name = xzmalloc (name_len);
    ok (pmi_simple_client_kvs_get_my_name (cli, name, name_len) == PMI_SUCCESS
        && strlen (name) > 0,
        "pmi_simple_client_kvs_get_my_name OK, name=%s", name);

    /* put foo=bar / commit / barier / get foo
     */
    ok (pmi_simple_client_kvs_put (cli, name, "foo", "bar") == PMI_SUCCESS,
        "pmi_simple_client_kvs_put foo=bar OK");
    ok (pmi_simple_client_kvs_commit (cli, name) == PMI_SUCCESS,
        "pmi_simple_client_kvs_commit OK");
    ok (pmi_simple_client_barrier (cli) == PMI_SUCCESS,
        "pmi_simple_client_barrier OK");
    val = xzmalloc (val_len);
    ok (pmi_simple_client_kvs_get (cli, name, "foo", val, val_len) == PMI_SUCCESS
        && !strcmp (val, "bar"),
        "pmi_simple_client_kvs_get foo OK, val=%s", val);

    /* put long=... / get long
     */
    val2 = xzmalloc (val_len);
    memset (val2, 'x', val_len - 1);
    ok (pmi_simple_client_kvs_put (cli, name, "long", val2) == PMI_SUCCESS,
        "pmi_simple_client_kvs_put long=xxx... OK");
    memset (val, 'y', val_len); /* not null terminated */
    ok (pmi_simple_client_kvs_get (cli, name, "long", val, val_len) == PMI_SUCCESS
        && strnlen (val2, val_len) < val_len
        && strcmp (val, val2) == 0,
        "pmi_simple_client_kvs_get long OK, val=xxx...");

    /* put: value too long
     */
    val3 = xzmalloc (val_len + 1);
    memset (val3, 'y', val_len);
    rc = pmi_simple_client_kvs_put (cli, name, "toolong", val3);
    ok (rc == PMI_ERR_INVALID_VAL_LENGTH,
        "pmi_simple_client_kvs_put val too long fails");

    /* put: key too long
     */
    key = xzmalloc (key_len + 1);
    memset (key, 'z', key_len);
    rc = pmi_simple_client_kvs_put (cli, name, key, "abc");
    ok (rc == PMI_ERR_INVALID_KEY_LENGTH,
        "pmi_simple_client_kvs_put key too long fails");

    /* get: key too long
     */
    rc = pmi_simple_client_kvs_get (cli, name, key, val, val_len);
    ok (rc == PMI_ERR_INVALID_KEY_LENGTH,
        "pmi_simple_client_kvs_get key too long fails");

    /* get: no exist
     */
    rc = pmi_simple_client_kvs_get (cli, name, "noexist", val, val_len);
    ok (rc == PMI_ERR_INVALID_KEY,
        "pmi_simple_client_kvs_get unknown key fails");

    /* barrier: entry failure
     */
    rig_barrier_entry_failure = 1;
    ok (pmi_simple_client_barrier (cli) == PMI_FAIL,
        "pmi_simple_client_barrier with entry function failure fails");
    rig_barrier_entry_failure = 0;
    rig_barrier_exit_failure = 1;
    ok (pmi_simple_client_barrier (cli) == PMI_FAIL,
        "pmi_simple_client_barrier with exit function failure fails");
    rig_barrier_exit_failure = 0;
    ok (pmi_simple_client_barrier (cli) == PMI_SUCCESS,
        "pmi_simple_client_barrier OK (rigged errors cleared)");

    /* finalize
     */

    ok (pmi_simple_client_finalize (cli) == PMI_SUCCESS,
        "pmi_simple_client_finalize OK");

    ok (pthread_join (ctx.t, NULL) == 0,
        "pthread join successfully reaped server");

    free (name);
    free (val);
    free (val2);
    free (val3);
    free (key);
    pmi_simple_client_destroy (cli);
    if (ctx.pmi)
        pmi_simple_server_destroy (ctx.pmi);
    close (ctx.fds[0]);
    close (ctx.fds[1]);
    zhash_destroy (&ctx.kvs);

    done_testing ();
    return 0;
}
Exemplo n.º 10
0
HIDDEN int ws_start_channel(struct transaction_t *txn, const char *protocol,
                            int (*data_cb)(struct buf *inbuf, struct buf *outbuf,
                                           struct buf *logbuf, void **rock))
{
    int r;
    const char **hdr, *accept = NULL;
    wslay_event_context_ptr ev;
    struct ws_context *ctx;
    struct wslay_event_callbacks callbacks = {
        recv_cb,
        send_cb,
        NULL,
        NULL,
        NULL,
        NULL,
        on_msg_recv_cb
    };

    /* Check for supported WebSocket version */
    hdr = spool_getheader(txn->req_hdrs, "Sec-WebSocket-Version");
    if (!hdr) {
        txn->error.desc = "Missing WebSocket version";
        return HTTP_BAD_REQUEST;
    }
    else if (hdr[1]) {
        txn->error.desc = "Multiple WebSocket versions";
        return HTTP_BAD_REQUEST;
    }
    else if (strcmp(hdr[0], WS_VERSION)) {
        txn->error.desc = "Unsupported WebSocket version";
        return HTTP_UPGRADE;
    }

    if (protocol) {
        /* Check for supported WebSocket subprotocol */
        int i, found = 0;

        hdr = spool_getheader(txn->req_hdrs, "Sec-WebSocket-Protocol");
        if (!hdr) {
            txn->error.desc = "Missing WebSocket protocol";
            return HTTP_BAD_REQUEST;
        }

        for (i = 0; !found && hdr[i]; i++) {
            tok_t tok = TOK_INITIALIZER(hdr[i], ",", TOK_TRIMLEFT|TOK_TRIMRIGHT);
            char *token;

            while ((token = tok_next(&tok))) {
                if (!strcmp(token, protocol)) {
                    found = 1;
                    break;
                }
            }
            tok_fini(&tok);
        }
        if (!found) {
            txn->error.desc = "Unsupported WebSocket protocol";
            return HTTP_BAD_REQUEST;
        }
    }

    if (txn->flags.ver == VER_1_1) {
        unsigned char sha1buf[SHA1_DIGEST_LENGTH];

        /* Check for WebSocket client key */
        hdr = spool_getheader(txn->req_hdrs, "Sec-WebSocket-Key");
        if (!hdr) {
            txn->error.desc = "Missing WebSocket client key";
            return HTTP_BAD_REQUEST;
        }
        else if (hdr[1]) {
            txn->error.desc = "Multiple WebSocket client keys";
            return HTTP_BAD_REQUEST;
        }
        else if (strlen(hdr[0]) != WS_CKEY_LEN) {
            txn->error.desc = "Invalid WebSocket client key";
            return HTTP_BAD_REQUEST;
        }

        /* Create WebSocket accept key */
        buf_setcstr(&txn->buf, hdr[0]);
        buf_appendcstr(&txn->buf, WS_GUID);
        xsha1((u_char *) buf_base(&txn->buf), buf_len(&txn->buf), sha1buf);

        buf_ensure(&txn->buf, WS_AKEY_LEN+1);
        accept = buf_base(&txn->buf);

        r = sasl_encode64((char *) sha1buf, SHA1_DIGEST_LENGTH,
                          (char *) accept, WS_AKEY_LEN+1, NULL);
        if (r != SASL_OK) syslog(LOG_WARNING, "sasl_encode64: %d", r);
    }

    /* Create server context */
    r = wslay_event_context_server_init(&ev, &callbacks, txn);
    if (r) {
        syslog(LOG_WARNING,
               "wslay_event_context_init: %s", wslay_strerror(r));
        return HTTP_SERVER_ERROR;
    }

    /* Create channel context */
    ctx = xzmalloc(sizeof(struct ws_context));
    ctx->event = ev;
    ctx->accept = accept;
    ctx->protocol = protocol;
    ctx->data_cb = data_cb;
    txn->ws_ctx = ctx;

    /* Check for supported WebSocket extensions */
    parse_extensions(txn);

    /* Prepare log buffer */

    /* Add client data */
    buf_printf(&ctx->log, "%s", txn->conn->clienthost);
    if (httpd_userid) buf_printf(&ctx->log, " as \"%s\"", httpd_userid);
    if ((hdr = spool_getheader(txn->req_hdrs, "User-Agent"))) {
        buf_printf(&ctx->log, " with \"%s\"", hdr[0]);
        if ((hdr = spool_getheader(txn->req_hdrs, "X-Client")))
            buf_printf(&ctx->log, " by \"%s\"", hdr[0]);
        else if ((hdr = spool_getheader(txn->req_hdrs, "X-Requested-With")))
            buf_printf(&ctx->log, " by \"%s\"", hdr[0]);
    }

    /* Add request-line */
    buf_printf(&ctx->log, "; \"WebSocket/%s via %s\"",
               protocol ? protocol : "echo" , txn->req_line.ver);
    ctx->log_tail = buf_len(&ctx->log);

    /* Tell client that WebSocket negotiation has succeeded */
    if (txn->conn->sess_ctx) {
        /* Treat WS data as chunked response */
        txn->flags.te = TE_CHUNKED;

        response_header(HTTP_OK, txn);

        /* Force the response to the client immediately */
        prot_flush(httpd_out);
    }
    else response_header(HTTP_SWITCH_PROT, txn);

    /* Set connection as non-blocking */
    prot_NONBLOCK(txn->conn->pin);

    /* Don't do telemetry logging in prot layer */
    prot_setlog(txn->conn->pin, PROT_NO_FD);
    prot_setlog(txn->conn->pout, PROT_NO_FD);

    return 0;
}
Exemplo n.º 11
0
EXPORTED int cyrusdb_open(const char *backend, const char *fname,
		 int flags, struct db **ret)
{
    const char *realname;
    struct db *db = xzmalloc(sizeof(struct db));
    int r;

    if (!backend) backend = DEFAULT_BACKEND; /* not used yet, later */
    db->backend = cyrusdb_fromname(backend);

    /* This whole thing is a fricking critical section.  We don't have the API
     * in place for a safe rename of a locked database, so the choices are
     * basically:
     * a) convert each DB layer to support locked database renames while still
     *    in the transaction.  Best, but lots of work.
     * b) rename and hope... unreliable
     * c) global lock around this block of code.  Safest and least efficient.
     */

    /* check if it opens normally.  Horray */
    r = db->backend->open(fname, flags, &db->engine);
    if (r == CYRUSDB_NOTFOUND) goto done; /* no open flags */
    if (!r) goto done;

    /* magic time - we need to work out if the file was created by a different
     * backend and convert if possible */

    realname = cyrusdb_detect(fname);
    if (!realname) {
	syslog(LOG_ERR, "DBERROR: failed to detect DB type for %s (backend %s) (r was %d)",
	       fname, backend, r);
	/* r is still set */
	goto done;
    }

    /* different type */
    if (strcmp(realname, backend)) {
	if (flags & CYRUSDB_CONVERT) {
	    r = cyrusdb_convert(fname, fname, realname, backend);
	    if (r) {
		syslog(LOG_ERR, "DBERROR: failed to convert %s from %s to %s, maybe someone beat us",
		       fname, realname, backend);
	    }
	    else {
		syslog(LOG_NOTICE, "cyrusdb: converted %s from %s to %s",
		       fname, realname, backend);
	    }
	}
	else {
	    syslog(LOG_NOTICE, "cyrusdb: opening %s with backend %s (requested %s)",
		   fname, realname, backend);
	    db->backend = cyrusdb_fromname(realname);
	}
    }
    
    r = db->backend->open(fname, flags, &db->engine);

done:

    if (r) free(db);
    else *ret = db;

    return r;
}
Exemplo n.º 12
0
int main(int argc, char **argv)
{
    int opt, r = 0;
    char *alt_config = NULL, *pub = NULL, *ver = NULL, *winfile = NULL;
    char prefix[2048];
    enum { REBUILD, WINZONES, NONE } op = NONE;

    if ((geteuid()) == 0 && (become_cyrus(/*ismaster*/0) != 0)) {
        fatal("must run as the Cyrus user", EC_USAGE);
    }

    while ((opt = getopt(argc, argv, "C:r:vw:")) != EOF) {
        switch (opt) {
        case 'C': /* alt config file */
            alt_config = optarg;
            break;

        case 'r':
            if (op == NONE) {
                op = REBUILD;
                pub = optarg;
                ver = strchr(optarg, ':');
                if (ver) *ver++ = '\0';
                else usage();
            }
            else usage();
            break;

        case 'v':
            verbose = 1;
            break;

        case 'w':
            if (op == NONE) {
                op = WINZONES;
                winfile = optarg;
            }
            else usage();
            break;

        default:
            usage();
        }
    }

    cyrus_init(alt_config, "ctl_zoneinfo", 0, 0);

    signals_set_shutdown(&shut_down);
    signals_add_handlers(0);

    snprintf(prefix, sizeof(prefix), "%s%s", config_dir, FNAME_ZONEINFODIR);

    switch (op) {
    case REBUILD: {
        struct hash_table tzentries;
        struct zoneinfo *info;
        struct txn *tid = NULL;
        char buf[1024];
        FILE *fp;

        construct_hash_table(&tzentries, 500, 1);

        /* Add INFO record (overall lastmod and TZ DB source version) */
        info = xzmalloc(sizeof(struct zoneinfo));
        info->type = ZI_INFO;
        appendstrlist(&info->data, pub);
        appendstrlist(&info->data, ver);
        hash_insert(INFO_TZID, info, &tzentries);

        /* Add LEAP record (last updated and hash) */
        snprintf(buf, sizeof(buf), "%s%s", prefix, FNAME_LEAPSECFILE);
        if (verbose) printf("Processing leap seconds file %s\n", buf);
        if (!(fp = fopen(buf, "r"))) {
            fprintf(stderr, "Could not open leap seconds file %s\n", buf);
        }
        else {
            struct zoneinfo *leap = xzmalloc(sizeof(struct zoneinfo));
            leap->type = ZI_INFO;

            while(fgets(buf, sizeof(buf), fp)) {
                if (buf[0] == '#') {
                    /* comment line */

                    if (buf[1] == '$') {
                        /* last updated */
                        unsigned long last;

                        sscanf(buf+2, "\t%lu", &last);
                        leap->dtstamp = last - NIST_EPOCH_OFFSET;
                    }
                    else if (buf[1] == 'h') {
                        /* hash */
                        char *p, *hash = buf+3 /* skip "#h\t" */;

                        /* trim trailing whitespace */
                        for (p = hash + strlen(hash); isspace(*--p); *p = '\0');
                        appendstrlist(&leap->data, hash);
                    }
                }
            }
            fclose(fp);

            hash_insert(LEAP_TZID, leap, &tzentries);
            info->dtstamp = leap->dtstamp;
        }

        /* Add ZONE/LINK records */
        do_zonedir(prefix, &tzentries, info);

        zoneinfo_open(NULL);

        /* Store records */
        hash_enumerate(&tzentries, &store_zoneinfo, &tid);

        zoneinfo_close(tid);

        free_hash_table(&tzentries, &free_zoneinfo);
        break;
    }

    case WINZONES: {
        xmlParserCtxtPtr ctxt;
        xmlDocPtr doc;
        xmlNodePtr node;
        struct buf tzidbuf = BUF_INITIALIZER;
        struct buf aliasbuf = BUF_INITIALIZER;

        if (verbose) printf("Processing Windows Zone file %s\n", winfile);

        /* Parse the XML file */
        ctxt = xmlNewParserCtxt();
        if (!ctxt) {
            fprintf(stderr, "Failed to create XML parser context\n");
            break;
        }

        doc = xmlCtxtReadFile(ctxt, winfile, NULL, 0);
        xmlFreeParserCtxt(ctxt);
        if (!doc) {
            fprintf(stderr, "Failed to parse XML document\n");
            break;
        }

        node = xmlDocGetRootElement(doc);
        if (!node || xmlStrcmp(node->name, BAD_CAST "supplementalData")) {
            fprintf(stderr, "Incorrect root node\n");
            goto done;
        }

        for (node = xmlFirstElementChild(node);
             node && xmlStrcmp(node->name, BAD_CAST "windowsZones");
             node = xmlNextElementSibling(node));
        if (!node) {
            fprintf(stderr, "Missing windowsZones node\n");
            goto done;
        }

        node = xmlFirstElementChild(node);
        if (!node || xmlStrcmp(node->name, BAD_CAST "mapTimezones")) {
            fprintf(stderr, "Missing mapTimezones node\n");
            goto done;
        }

        if (chdir(prefix)) {
            fprintf(stderr, "chdir(%s) failed\n", prefix);
            goto done;
        }

        for (node = xmlFirstElementChild(node);
             node;
             node = xmlNextElementSibling(node)) {
            if (!xmlStrcmp(node->name, BAD_CAST "mapZone") &&
                !xmlStrcmp(xmlGetProp(node, BAD_CAST "territory"),
                           BAD_CAST "001")) {
                const char *tzid, *alias;

                buf_setcstr(&tzidbuf,
                            (const char *) xmlGetProp(node, BAD_CAST "type"));
                buf_appendcstr(&tzidbuf, ".ics");
                tzid = buf_cstring(&tzidbuf);
                buf_setcstr(&aliasbuf,
                            (const char *) xmlGetProp(node, BAD_CAST "other"));
                buf_appendcstr(&aliasbuf, ".ics");
                alias = buf_cstring(&aliasbuf);

                if (verbose) printf("\tLINK: %s -> %s\n", alias, tzid);

                if (symlink(tzid, alias)) {
                    if (errno == EEXIST) {
                        struct stat sbuf;

                        if (stat(alias, &sbuf)) {
                            fprintf(stderr, "stat(%s) failed: %s\n",
                                    alias, strerror(errno));
                            errno = EEXIST;
                        }
                        else if (sbuf.st_mode & S_IFLNK) {
                            char link[MAX_MAILBOX_PATH+1];
                            int n = readlink(alias, link, MAX_MAILBOX_PATH);

                            if (n == -1) {
                                fprintf(stderr, "readlink(%s) failed: %s\n",
                                        alias, strerror(errno));
                                errno = EEXIST;
                            }
                            else if (n == (int) strlen(tzid) &&
                                     !strncmp(tzid, link, n)) {
                                errno = 0;
                            }
                        }
                    }

                    if (errno) {
                        fprintf(stderr, "symlink(%s, %s) failed: %s\n",
                                tzid, alias, strerror(errno));
                    }
                }
            }
        }

  done:
        buf_free(&aliasbuf);
        buf_free(&tzidbuf);
        xmlFreeDoc(doc);
        break;
    }

    case NONE:
        r = 2;
        usage();
        break;
    }

    cyrus_done();

    return r;
}
Exemplo n.º 13
0
/* Add all ZONEs and LINKs in the given directory to the hash table */
void do_zonedir(const char *dir, struct hash_table *tzentries,
                struct zoneinfo *info)
{
    DIR *dirp;
    struct dirent *dirent;

    signals_poll();

    if (verbose) printf("Rebuilding %s\n", dir);

    dirp = opendir(dir);
    if (!dirp) {
        fprintf(stderr, "can't open zoneinfo directory %s\n", dir);
    }

    while ((dirent = readdir(dirp))) {
        char path[2048], *tzid;
        int plen;
        struct stat sbuf;
        struct zoneinfo *zi;

        if (*dirent->d_name == '.') continue;

        plen = snprintf(path, sizeof(path), "%s/%s", dir, dirent->d_name);
        lstat(path, &sbuf);

        if (S_ISDIR(sbuf.st_mode)) {
            /* Path is a directory (region) */
          do_zonedir(path, tzentries, info);
        }
        else if (S_ISLNK(sbuf.st_mode)) {
            /* Path is a symlink (alias) */
            char link[1024], *alias;
            ssize_t llen;

            /* Isolate tzid in path */
            if ((llen = readlink(path, link, sizeof(link))) < 0) continue;
            link[llen-4] = '\0';  /* Trim ".ics" */
            for (tzid = link; !strncmp(tzid, "../", 3); tzid += 3);

            /* Isolate alias in path */
            path[plen-4] = '\0';  /* Trim ".ics" */
            alias = path + strlen(config_dir) + strlen("zoneinfo") + 2;

            if (verbose) printf("\tLINK: %s -> %s\n", alias, tzid);

            /* Create hash entry for alias */
            if (!(zi = hash_lookup(alias, tzentries))) {
                zi = xzmalloc(sizeof(struct zoneinfo));
                hash_insert(alias, zi, tzentries);
            }
            zi->type = ZI_LINK;
            appendstrlist(&zi->data, tzid);

            /* Create/update hash entry for tzid */
            if (!(zi = hash_lookup(tzid, tzentries))) {
                zi = xzmalloc(sizeof(struct zoneinfo));
                hash_insert(tzid, zi, tzentries);
            }
            zi->type = ZI_ZONE;
            appendstrlist(&zi->data, alias);
        }
        else if (S_ISREG(sbuf.st_mode)) {
            /* Path is a regular file (zone) */
            int fd;
            const char *base = NULL;
            size_t len = 0;
            icalcomponent *ical, *comp;
            icalproperty *prop;

            /* Parse the iCalendar file for important properties */
            if ((fd = open(path, O_RDONLY)) == -1) continue;
            map_refresh(fd, 1, &base, &len, MAP_UNKNOWN_LEN, path, NULL);
            close(fd);

            ical = icalparser_parse_string(base);
            map_free(&base, &len);

            if (!ical) continue;  /* skip non-iCalendar files */

            comp = icalcomponent_get_first_component(ical,
                                                     ICAL_VTIMEZONE_COMPONENT);
            prop = icalcomponent_get_first_property(comp, ICAL_TZID_PROPERTY);
            tzid = (char *) icalproperty_get_value_as_string(prop);

            if (verbose) printf("\tZONE: %s\n", tzid);

            /* Create/update hash entry for tzid */
            if (!(zi = hash_lookup(tzid, tzentries))) {
                zi = xzmalloc(sizeof(struct zoneinfo));
                hash_insert(tzid, zi, tzentries);
            }
            zi->type = ZI_ZONE;
            prop = icalcomponent_get_first_property(comp,
                                                    ICAL_LASTMODIFIED_PROPERTY);
            zi->dtstamp = icaltime_as_timet(icalproperty_get_lastmodified(prop));

            icalcomponent_free(ical);

            /* Check overall lastmod */
            if (zi->dtstamp > info->dtstamp) info->dtstamp = zi->dtstamp;
        }
        else {
            fprintf(stderr, "unknown path type %s\n", path);
        }
    }

    closedir(dirp);
}