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