open-src/util/build-tools/sun-src/time.c
changeset 1193 81e7bcbed056
equal deleted inserted replaced
1192:60e4ec16e28d 1193:81e7bcbed056
       
     1 /*
       
     2  * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved.
       
     3  *
       
     4  * Permission is hereby granted, free of charge, to any person obtaining a
       
     5  * copy of this software and associated documentation files (the "Software"),
       
     6  * to deal in the Software without restriction, including without limitation
       
     7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
       
     8  * and/or sell copies of the Software, and to permit persons to whom the
       
     9  * Software is furnished to do so, subject to the following conditions:
       
    10  *
       
    11  * The above copyright notice and this permission notice (including the next
       
    12  * paragraph) shall be included in all copies or substantial portions of the
       
    13  * Software.
       
    14  *
       
    15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
       
    16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
       
    17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
       
    18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
       
    19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
       
    20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
       
    21  * DEALINGS IN THE SOFTWARE.
       
    22  */
       
    23 
       
    24 /*
       
    25  * This compiles to a module that can be preloaded during a build.  If this
       
    26  * is preloaded, it interposes on time(2), gettimeofday(3C), and
       
    27  * clock_gethrtime(3C) and returns a constant number of seconds since epoch
       
    28  * when the execname matches one of the desired "programs" and TIME_CONSTANT
       
    29  * contains an integer value to be returned.
       
    30  */
       
    31 
       
    32 #include <stdlib.h>
       
    33 #include <ucontext.h>
       
    34 #include <dlfcn.h>
       
    35 #include <strings.h>
       
    36 #include <time.h>
       
    37 
       
    38 /* The list of programs that we want to use a constant time. */
       
    39 static char *programs[] = { "autogen", "bash", "cpp", "cc1", "date", "doxygen",
       
    40 	"erl", "javadoc", "ksh", "ksh93", "ld", "perl", "perl5.8.4", "perl5.10",
       
    41 	"ruby", "sh", "uil", NULL };
       
    42 
       
    43 static int
       
    44 stack_info(uintptr_t pc, int signo, void *arg)
       
    45 {
       
    46 	Dl_info info;
       
    47 	void *sym;
       
    48 
       
    49 	if (dladdr1((void *)pc, &info, &sym, RTLD_DL_SYMENT) != NULL) {
       
    50 		if (strstr(info.dli_fname, ".so") == NULL)
       
    51 			*(char **)arg = (char *)info.dli_fname;
       
    52 	}
       
    53 
       
    54 	return (0);
       
    55 }
       
    56 
       
    57 static char *
       
    58 my_execname()
       
    59 {
       
    60 	static char *execname;
       
    61 
       
    62 	if (execname == NULL) {
       
    63 		ucontext_t ctx;
       
    64 
       
    65 		if (getcontext(&ctx) == 0)
       
    66 			walkcontext(&ctx, stack_info, &execname);
       
    67 
       
    68 		if (execname != NULL) {
       
    69 			char *s = strrchr(execname, '/');
       
    70 
       
    71 			if (s != NULL)
       
    72 				execname = ++s;
       
    73 		}
       
    74 	}
       
    75 
       
    76 	return (execname);
       
    77 }
       
    78 
       
    79 static time_t
       
    80 time_constant()
       
    81 {
       
    82 	char *execname = my_execname();
       
    83 	time_t result = -1;
       
    84 
       
    85 	if (execname != NULL) {
       
    86 		int i;
       
    87 
       
    88 		for (i = 0; programs[i] != NULL; i++)
       
    89 			if (strcmp(execname, programs[i]) == 0) {
       
    90 				static char *time_string;
       
    91 
       
    92 				if (time_string == NULL)
       
    93 					time_string = getenv("TIME_CONSTANT");
       
    94 
       
    95 				if (time_string != NULL)
       
    96 					result = atoll(time_string);
       
    97 
       
    98 				break;
       
    99 			}
       
   100 	}
       
   101 
       
   102 	return (result);
       
   103 }
       
   104 
       
   105 time_t
       
   106 time(time_t *ptr)
       
   107 {
       
   108 	time_t result = time_constant();
       
   109 
       
   110 	if (result == (time_t)-1) {
       
   111 		static time_t (*fptr)(time_t *);
       
   112 
       
   113 		if (fptr == NULL)
       
   114 			fptr = (time_t (*)(time_t *))dlsym(RTLD_NEXT, "time");
       
   115 
       
   116 		result = (fptr)(ptr);
       
   117 	} else if (ptr != NULL)
       
   118 			*ptr = result;
       
   119 
       
   120 	return (result);
       
   121 }
       
   122 
       
   123 int
       
   124 gettimeofday(struct timeval *tp, void *tzp)
       
   125 {
       
   126 	static int (*fptr)(struct timeval *, void *);
       
   127 	int result = -1;
       
   128 
       
   129 	if (fptr == NULL)
       
   130 		fptr = (int (*)(struct timeval *, void *))dlsym(RTLD_NEXT,
       
   131 				"gettimeofday");
       
   132 
       
   133 	if ((result = (fptr)(tp, tzp)) == 0) {
       
   134 		time_t curtime = time_constant();
       
   135 
       
   136 		if (curtime != (time_t)-1)
       
   137 			tp->tv_sec = curtime;
       
   138 	}
       
   139 
       
   140 	return (result);
       
   141 }
       
   142 
       
   143 int
       
   144 clock_gettime(clockid_t clock_id, struct timespec *tp)
       
   145 {
       
   146 	static int (*fptr)(clockid_t, struct timespec *);
       
   147 	int result = -1;
       
   148 
       
   149 	if (fptr == NULL)
       
   150 		fptr = (int (*)(clockid_t, struct timespec *))dlsym(RTLD_NEXT,
       
   151 				"clock_gettime");
       
   152 
       
   153 	if ((result = (fptr)(clock_id, tp)) == 0) {
       
   154 		time_t curtime = time_constant();
       
   155 
       
   156 		if (curtime != (time_t)-1)
       
   157 			tp->tv_sec = curtime;
       
   158 	}
       
   159 
       
   160 	return (result);
       
   161 }