1*9292cfb2Schristos /* $NetBSD: clock_settime.c,v 1.12 2011/10/15 23:00:02 christos Exp $ */
254c0ce61Smanu
354c0ce61Smanu /*
454c0ce61Smanu * Copyright (c) 2001 The NetBSD Foundation, Inc.
554c0ce61Smanu * All rights reserved.
654c0ce61Smanu *
754c0ce61Smanu * This code is derived from software contributed to The NetBSD Foundation
854c0ce61Smanu * by Emmanuel Dreyfus.
954c0ce61Smanu *
1054c0ce61Smanu * Redistribution and use in source and binary forms, with or without
1154c0ce61Smanu * modification, are permitted provided that the following conditions
1254c0ce61Smanu * are met:
1354c0ce61Smanu * 1. Redistributions of source code must retain the above copyright
1454c0ce61Smanu * notice, this list of conditions and the following disclaimer.
1554c0ce61Smanu * 2. Redistributions in binary form must reproduce the above copyright
1654c0ce61Smanu * notice, this list of conditions and the following disclaimer in the
1754c0ce61Smanu * documentation and/or other materials provided with the distribution.
1854c0ce61Smanu * 3. The name of the author may not be used to endorse or promote products
1954c0ce61Smanu * derived from this software without specific prior written permission.
2054c0ce61Smanu *
2154c0ce61Smanu * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2254c0ce61Smanu * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2354c0ce61Smanu * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2454c0ce61Smanu * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2554c0ce61Smanu * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
2654c0ce61Smanu * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
2754c0ce61Smanu * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
2854c0ce61Smanu * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2954c0ce61Smanu * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3054c0ce61Smanu * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3154c0ce61Smanu * SUCH DAMAGE.
3254c0ce61Smanu */
3354c0ce61Smanu
3488c3eadbSlukem #include <sys/cdefs.h>
3588c3eadbSlukem #if defined(LIBC_SCCS) && !defined(lint)
36*9292cfb2Schristos __RCSID("$NetBSD: clock_settime.c,v 1.12 2011/10/15 23:00:02 christos Exp $");
3788c3eadbSlukem #endif /* LIBC_SCCS and not lint */
3888c3eadbSlukem
3954c0ce61Smanu #include "namespace.h"
40bb80a7f9Sthorpej
4154c0ce61Smanu #include <sys/types.h>
4254c0ce61Smanu #include <sys/ioctl.h>
4354c0ce61Smanu #include <sys/syscall.h>
4454c0ce61Smanu
458429e82fSmanu #include <errno.h>
46bb80a7f9Sthorpej #include <fcntl.h>
47bb80a7f9Sthorpej #include <paths.h>
48bb80a7f9Sthorpej #include <string.h>
49bb80a7f9Sthorpej #include <time.h>
50bb80a7f9Sthorpej #include <unistd.h>
51bb80a7f9Sthorpej
5254c0ce61Smanu #include <sys/clockctl.h>
5354c0ce61Smanu
548429e82fSmanu extern int __clockctl_fd;
558429e82fSmanu
56461a86f9Schristos int ____clock_settime50(clockid_t, const struct timespec *);
57b0b7248dSdsl
5854c0ce61Smanu int
clock_settime(clockid_t clock_id,const struct timespec * tp)59461a86f9Schristos clock_settime(clockid_t clock_id, const struct timespec *tp)
6054c0ce61Smanu {
61f7f0b661Schristos struct clockctl_clock_settime args;
6254c0ce61Smanu int rv;
6354c0ce61Smanu
6454c0ce61Smanu /*
65403d7591Skardel * always try the syscall first and attempt to switch to
66403d7591Skardel * clockctl if that fails.
6754c0ce61Smanu */
688429e82fSmanu if (__clockctl_fd == -1) {
69461a86f9Schristos rv = ____clock_settime50(clock_id, tp);
708429e82fSmanu
718429e82fSmanu /*
72403d7591Skardel * return unless we failed with EPERM
738429e82fSmanu */
748429e82fSmanu if (rv != -1 || errno != EPERM)
7554c0ce61Smanu return rv;
768429e82fSmanu
778429e82fSmanu /*
788429e82fSmanu * If this fails, it means that we are not root
798429e82fSmanu * and we cannot open clockctl. This is a failure.
808429e82fSmanu */
81*9292cfb2Schristos __clockctl_fd = open(_PATH_CLOCKCTL, O_WRONLY | O_CLOEXEC, 0);
82403d7591Skardel if (__clockctl_fd == -1) {
83403d7591Skardel /* original error was EPERM - don't leak open errors */
84403d7591Skardel errno = EPERM;
858429e82fSmanu return -1;
86403d7591Skardel }
878429e82fSmanu }
888429e82fSmanu
898429e82fSmanu /*
908429e82fSmanu * If __clockctl_fd >=0, clockctl has already been open
918429e82fSmanu * and used, so we carry on using it.
928429e82fSmanu */
93f7f0b661Schristos args.clock_id = clock_id;
94f7f0b661Schristos args.tp = tp;
95403d7591Skardel return ioctl(__clockctl_fd, CLOCKCTL_CLOCK_SETTIME, &args);
9654c0ce61Smanu }
97