1 /*
2  * Copyright (c) 2023 Nordic Semiconductor ASA
3  *
4  * This software may be distributed under the terms of the BSD license.
5  * See README for more details.
6  */
7 
8 #include <zephyr/posix/time.h>
9 #include <zephyr/posix/sys/time.h>
10 
11 /* The clock_gettime() would be found in <zephyr/posix/time.h> but
12  * that will cause conflict with picolib definition.
13  */
14 int clock_gettime(clockid_t clock_id, struct timespec *ts);
15 
16 #include <zephyr/random/random.h>
17 
18 #include "includes.h"
19 #include "os.h"
20 
os_sleep(os_time_t sec,os_time_t usec)21 void os_sleep(os_time_t sec, os_time_t usec)
22 {
23 	k_sleep(K_USEC(usec + USEC_PER_SEC * sec));
24 }
25 
os_get_time(struct os_time * t)26 int os_get_time(struct os_time *t)
27 {
28 	int res;
29 	struct timeval tv;
30 
31 	res = gettimeofday(&tv, NULL);
32 	t->sec = (os_time_t)tv.tv_sec;
33 	t->usec = (os_time_t)tv.tv_usec;
34 	return res;
35 }
36 
os_get_reltime(struct os_reltime * t)37 int os_get_reltime(struct os_reltime *t)
38 {
39 #if defined(CLOCK_BOOTTIME)
40 	static clockid_t clock_id = CLOCK_BOOTTIME;
41 #elif defined(CLOCK_MONOTONIC)
42 	static clockid_t clock_id = CLOCK_MONOTONIC;
43 #else
44 	static clockid_t clock_id = CLOCK_REALTIME;
45 #endif
46 	struct timespec ts;
47 	int res;
48 
49 	if (TEST_FAIL()) {
50 		return -1;
51 	}
52 
53 	while (1) {
54 		res = clock_gettime(clock_id, &ts);
55 		if (res == 0) {
56 			t->sec = ts.tv_sec;
57 			t->usec = ts.tv_nsec / 1000;
58 			return 0;
59 		}
60 		switch (clock_id) {
61 #ifdef CLOCK_BOOTTIME
62 		case CLOCK_BOOTTIME:
63 			clock_id = CLOCK_MONOTONIC;
64 			break;
65 #endif
66 #ifdef CLOCK_MONOTONIC
67 		case CLOCK_MONOTONIC:
68 			clock_id = CLOCK_REALTIME;
69 			break;
70 #endif
71 		case CLOCK_REALTIME:
72 			return -1;
73 		}
74 	}
75 }
76 
os_mktime(int year,int month,int day,int hour,int min,int sec,os_time_t * t)77 int os_mktime(int year, int month, int day, int hour, int min, int sec,
78 	      os_time_t *t)
79 {
80 	struct tm tm, *tm1;
81 	time_t t_local, t1, t2;
82 	os_time_t tz_offset;
83 
84 	if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 ||
85 	    hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 ||
86 	    sec > 60) {
87 		return -1;
88 	}
89 
90 	memset(&tm, 0, sizeof(tm));
91 	tm.tm_year = year - 1900;
92 	tm.tm_mon = month - 1;
93 	tm.tm_mday = day;
94 	tm.tm_hour = hour;
95 	tm.tm_min = min;
96 	tm.tm_sec = sec;
97 
98 	t_local = mktime(&tm);
99 
100 	/* figure out offset to UTC */
101 	tm1 = localtime(&t_local);
102 	if (tm1) {
103 		t1 = mktime(tm1);
104 		tm1 = gmtime(&t_local);
105 		if (tm1) {
106 			t2 = mktime(tm1);
107 			tz_offset = t2 - t1;
108 		} else {
109 			tz_offset = 0;
110 		}
111 	} else {
112 		tz_offset = 0;
113 	}
114 
115 	*t = (os_time_t)t_local - tz_offset;
116 	return 0;
117 }
118 
os_gmtime(os_time_t t,struct os_tm * tm)119 int os_gmtime(os_time_t t, struct os_tm *tm)
120 {
121 	struct tm *tm2;
122 	time_t t2 = t;
123 
124 	tm2 = gmtime(&t2);
125 	if (tm2 == NULL) {
126 		return -1;
127 	}
128 	tm->sec = tm2->tm_sec;
129 	tm->min = tm2->tm_min;
130 	tm->hour = tm2->tm_hour;
131 	tm->day = tm2->tm_mday;
132 	tm->month = tm2->tm_mon + 1;
133 	tm->year = tm2->tm_year + 1900;
134 	return 0;
135 }
136 
os_daemonize(const char * pid_file)137 int os_daemonize(const char *pid_file)
138 {
139 	return -1;
140 }
141 
os_daemonize_terminate(const char * pid_file)142 void os_daemonize_terminate(const char *pid_file)
143 {
144 }
145 
os_get_random(unsigned char * buf,size_t len)146 int os_get_random(unsigned char *buf, size_t len)
147 {
148 #if defined(CONFIG_ENTROPY_HAS_DRIVER)
149 	return sys_csrand_get(buf, len);
150 #else
151 	sys_rand_get(buf, len);
152 
153 	return 0;
154 #endif
155 }
156 
os_random(void)157 unsigned long os_random(void)
158 {
159 	return sys_rand32_get();
160 }
161 
os_rel2abs_path(const char * rel_path)162 char *os_rel2abs_path(const char *rel_path)
163 {
164 	return NULL; /* strdup(rel_path) can be used here */
165 }
166 
os_program_init(void)167 int os_program_init(void)
168 {
169 	return 0;
170 }
171 
os_program_deinit(void)172 void os_program_deinit(void)
173 {
174 }
175 
os_setenv(const char * name,const char * value,int overwrite)176 int os_setenv(const char *name, const char *value, int overwrite)
177 {
178 	return -1;
179 }
180 
os_unsetenv(const char * name)181 int os_unsetenv(const char *name)
182 {
183 	return -1;
184 }
185 
os_readfile(const char * name,size_t * len)186 char *os_readfile(const char *name, size_t *len)
187 {
188 	return NULL;
189 }
190 
os_fdatasync(FILE * stream)191 int os_fdatasync(FILE *stream)
192 {
193 	return 0;
194 }
195 
os_strdup(const char * s)196 char *os_strdup(const char *s)
197 {
198 	size_t len;
199 	char *d;
200 
201 	len = os_strlen(s);
202 	d   = os_malloc(len + 1);
203 	if (d == NULL) {
204 		return NULL;
205 	}
206 	os_memcpy(d, s, len);
207 	d[len] = '\0';
208 	return d;
209 }
210 
os_memdup(const void * src,size_t len)211 void *os_memdup(const void *src, size_t len)
212 {
213 	void *r = os_malloc(len);
214 
215 	if (r && src) {
216 		os_memcpy(r, src, len);
217 	}
218 	return r;
219 }
220 
os_malloc(size_t size)221 void *os_malloc(size_t size)
222 {
223 	return k_malloc(size);
224 }
225 
os_free(void * ptr)226 void os_free(void *ptr)
227 {
228 	k_free(ptr);
229 }
230 
os_realloc(void * ptr,size_t newsize)231 void *os_realloc(void *ptr, size_t newsize)
232 {
233 	void *p;
234 
235 	if (newsize == 0) {
236 		os_free(ptr);
237 		return NULL;
238 	}
239 
240 	if (ptr == NULL) {
241 		return os_malloc(newsize);
242 	}
243 
244 	p = os_zalloc(newsize);
245 
246 	if (p) {
247 		if (ptr != NULL) {
248 			memcpy(p, ptr, newsize);
249 			os_free(ptr);
250 		}
251 	}
252 
253 	return p;
254 }
255 
os_zalloc(size_t size)256 void *os_zalloc(size_t size)
257 {
258 	void *p = k_malloc(size);
259 
260 	if (p != NULL) {
261 		(void)memset(p, 0, size);
262 	}
263 	return p;
264 }
265 
os_strlcpy(char * dest,const char * src,size_t siz)266 size_t os_strlcpy(char *dest, const char *src, size_t siz)
267 {
268 	const char *s = src;
269 	size_t left = siz;
270 
271 	if (left) {
272 		/* Copy string up to the maximum size of the dest buffer */
273 		while (--left != 0) {
274 			if ((*dest++ = *s++) == '\0') {
275 				break;
276 			}
277 		}
278 	}
279 
280 	if (left == 0) {
281 		/* Not enough room for the string; force NUL-termination */
282 		if (siz != 0) {
283 			*dest = '\0';
284 		}
285 		while (*s++) {
286 			; /* determine total src string length */
287 		}
288 	}
289 
290 	return s - src - 1;
291 }
292 
os_exec(const char * program,const char * arg,int wait_completion)293 int os_exec(const char *program, const char *arg, int wait_completion)
294 {
295 	return -1;
296 }
297 
os_memcmp_const(const void * a,const void * b,size_t len)298 int os_memcmp_const(const void *a, const void *b, size_t len)
299 {
300 	return memcmp(a, b, len);
301 }
302 
os_strcasecmp(const char * s1,const char * s2)303 int os_strcasecmp(const char *s1, const char *s2)
304 {
305 	/*
306 	 * Ignoring case is not required for main functionality, so just use
307 	 * the case sensitive version of the function.
308 	 */
309 	return os_strcmp(s1, s2);
310 }
311 
os_strncasecmp(const char * s1,const char * s2,size_t n)312 int os_strncasecmp(const char *s1, const char *s2, size_t n)
313 {
314 	/*
315 	 * Ignoring case is not required for main functionality, so just use
316 	 * the case sensitive version of the function.
317 	 */
318 	return os_strncmp(s1, s2, n);
319 }
320