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); }
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; }
shutdown_t *shutdown_create (void) { shutdown_t *s = xzmalloc (sizeof (*s)); return s; }
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; }
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); }
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; }
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; }
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); }
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; }
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; }
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; }
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; }
/* 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); }