d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano * CDDL HEADER START
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano * The contents of this file are subject to the terms of the
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano * Common Development and Distribution License (the "License").
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano * You may not use this file except in compliance with the License.
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano * or http://www.opensolaris.org/os/licensing.
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano * See the License for the specific language governing permissions
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano * and limitations under the License.
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano * When distributing Covered Code, include this CDDL HEADER in each
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano * If applicable, add the following below this CDDL HEADER, with the
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano * fields enclosed by brackets "[]" replaced with your own identifying
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano * information: Portions Copyright [yyyy] [name of copyright owner]
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano * CDDL HEADER END
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano * Use is subject to license terms.
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano/* All Rights Reserved */
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakanostatic void init_file(void);
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakanostatic void doit(const char *zname, const char *zroot, int get);
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakanostatic void counter_get(const char *zname, int fd);
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakanostatic void send_cron_msg(const char *zname, const char *zroot);
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano * There are undocumeted command line options:
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano * -l list the value of semaphore.
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano * -I initialize the semaphore file (ie /var/run/tzsync)
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano while ((arg = getopt(argc, argv, "alI")) != EOF) {
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano * Create /var/run/tzsync atomically.
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano * While creating the /var/run/tzsync initially, there is a timing window
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano * that the file is created but no disk block is allocated (empty file).
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano * If apps mmap'ed the file at the very moment, it succeeds but accessing
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano * the memory page causes a segfault since disk block isn't yet allocated.
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano * To avoid this situation, we create a temp file which has pagesize block
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano * assigned, and then rename it to tzsync.
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano /* We don't allow to re-create the file */
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano (void) fprintf(stderr, gettext("%s already exists.\n"),
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano gettext("failed to create a temporary file.\n"));
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano (void) fprintf(stderr, gettext("Insufficient memory.\n"));
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano gettext("failed to create tzsync file, %s\n"),
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano /* link it */
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano (void) fprintf(stderr, gettext("%s already exists.\n"),
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano (void) fprintf(stderr, gettext("failed to create %s\n"),
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano * Unplivileged apps may fail to open the file until the chmod
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano * below succeeds. However, it's okay as long as open() fails;
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano * ctime() won't cache zoneinfo until file is opened and mmap'd.
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano /* /var/run/tzsync has been made. Adjust permission */
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano gettext("failed to change permission of %s\n"),
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano * Open the /var/run/tzsync, then set or get the semaphore.
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano * zname name of zone (NULL if no need to consider zones)
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano * zroot zone's root path
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano * get get/set semaphore
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakanodoit(const char *zname, const char *zroot, int get)
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano if (strlcpy(file, zroot, sizeof (file)) >= sizeof (file) ||
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano strlcat(file, TZSYNC_FILE, sizeof (file)) >= sizeof (file)) {
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano (void) fprintf(stderr, gettext("zonepath too long\n"));
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano if ((fd = open(file, get ? O_RDONLY : O_RDWR)) < 0) {
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano /* let cron reschedule events */
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano * Get semaphore value and print.
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano addr = mmap(NULL, sizeof (uint32_t), PROT_READ, MAP_SHARED, fd, 0);
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano (void) printf("%-20s %u\n", zname, counter);
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano * Increment semaphore value.
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano addr = mmap(NULL, sizeof (uint32_t), PROT_READ|PROT_WRITE,
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano * Walk through running zones and call doit() for each zones.
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano * Note: we call zone_get_rootpath() indirectly using dlopen().
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano * This is because tzreload resides under /sbin and needs to run
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano * without /usr (ie /usr/lib/libzonecfg.so.1). The reason tzreload
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano * being in /sbin is that tzreload -I may be called to create
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano * /var/run/tzsync before /usr is mounted. To do that zone_get_rootpath()
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano * isn't necessary. Therefore, libzonecfg is dlopen'd when required
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano * rather than having static linkage to it which would make tzreload
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano * unable to run without /usr.
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano static int (*get_zroot)(char *, char *, size_t);
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano (void) fprintf(stderr, gettext("not in the global zone.\n"));
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano if ((hdl = dlopen("libzonecfg.so.1", RTLD_NOW)) == NULL) {
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano gettext("unable to get zone configuration.\n"));
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano get_zroot = (int (*)(char *, char *, size_t))
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano gettext("unable to get zone configuration.\n"));
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano if ((zids = malloc(nzents * sizeof (zoneid_t))) == NULL) {
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano (void) fprintf(stderr, gettext("Insufficient memory.\n"));
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano /* zone increased while doing zone_list() */
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano if (zone_getattr(zids[ui], ZONE_ATTR_BRAND, zbrand,
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano sizeof (zbrand)) < 0) {
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano /* We only take care of native zones */
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano if (getzonenamebyid(zids[ui], zname, sizeof (zname)) < 0) {
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano * Send REFRESH event to cron.
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakanosend_cron_msg(const char *zname, const char *zroot)
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano if (strlcpy(fifo, zroot, sizeof (fifo)) >= sizeof (fifo) ||
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano strlcat(fifo, FIFO, sizeof (fifo)) >= sizeof (fifo)) {
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano (void) fprintf(stderr, gettext("zonepath too long\n"));
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano if ((msgfd = open(fifo, O_WRONLY|O_NDELAY)) < 0) {
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano "cron isn't running in %s zone.\n"), zname);
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano "failed to send message to cron "
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano "failed to send message to cron.\n"));
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano if (write(msgfd, &msg, sizeof (msg)) != sizeof (msg)) {
d1419d5a02eaedd520f925cd465fd62f3950ae43Nobutomo Nakano (void) fprintf(stderr, gettext("failed to send message.\n"));