xref: /netbsd-src/lib/libc/sys/adjtime.c (revision 9292cfb210c8727c49ec3d6350ccc84533ba1f68)
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