1*9292cfb2Schristos /* $NetBSD: adjtime.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: adjtime.c,v 1.12 2011/10/15 23:00:02 christos Exp $");
3788c3eadbSlukem #endif /* LIBC_SCCS and not lint */
3888c3eadbSlukem
3954c0ce61Smanu #include "namespace.h"
408429e82fSmanu #include <errno.h>
4154c0ce61Smanu #include <fcntl.h>
4254c0ce61Smanu #include <paths.h>
4354c0ce61Smanu #include <unistd.h>
4454c0ce61Smanu #include <time.h>
45a50a963cStsutsui #include <string.h>
4654c0ce61Smanu #include <sys/types.h>
4754c0ce61Smanu #include <sys/ioctl.h>
4854c0ce61Smanu #include <sys/syscall.h>
498429e82fSmanu
5054c0ce61Smanu #include <sys/clockctl.h>
5154c0ce61Smanu
528429e82fSmanu extern int __clockctl_fd;
538429e82fSmanu
54461a86f9Schristos int ____adjtime50(const struct timeval *, struct timeval *);
55b0b7248dSdsl
5654c0ce61Smanu int
adjtime(const struct timeval * delta,struct timeval * olddelta)57461a86f9Schristos adjtime(const struct timeval *delta, struct timeval *olddelta)
5854c0ce61Smanu {
59f7f0b661Schristos struct clockctl_adjtime args;
6054c0ce61Smanu int rv;
6154c0ce61Smanu
6254c0ce61Smanu /*
63403d7591Skardel * we always attempt the syscall first and switch to
64403d7591Skardel * clockctl if that fails with EPERM
6554c0ce61Smanu */
668429e82fSmanu if (__clockctl_fd == -1) {
67461a86f9Schristos rv = ____adjtime50(delta, olddelta);
688429e82fSmanu
698429e82fSmanu /*
70403d7591Skardel * try via clockctl if the call fails with EPERM
718429e82fSmanu */
728429e82fSmanu if (rv != -1 || errno != EPERM)
7354c0ce61Smanu return rv;
748429e82fSmanu
758429e82fSmanu /*
768429e82fSmanu * If this fails, it means that we are not root
778429e82fSmanu * and we cannot open clockctl. This is a failure.
788429e82fSmanu */
79*9292cfb2Schristos __clockctl_fd = open(_PATH_CLOCKCTL, O_WRONLY | O_CLOEXEC, 0);
80403d7591Skardel if (__clockctl_fd == -1) {
81403d7591Skardel /* original error was EPERM - don't leak open errors */
82403d7591Skardel errno = EPERM;
838429e82fSmanu return -1;
84403d7591Skardel }
858429e82fSmanu }
868429e82fSmanu
878429e82fSmanu /*
888429e82fSmanu * If __clockctl_fd >=0, clockctl has already been open
898429e82fSmanu * and used, so we carry on using it.
908429e82fSmanu */
91f7f0b661Schristos args.delta = delta;
92f7f0b661Schristos args.olddelta = olddelta;
93403d7591Skardel return ioctl(__clockctl_fd, CLOCKCTL_ADJTIME, &args);
9454c0ce61Smanu }
95