source: mainline/uspace/lib/posix/source/stdlib.c@ e6edc8d1

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since e6edc8d1 was e965dec, checked in by Vojtech Horky <vojtechhorky@…>, 12 years ago

Add missing returns

  • Property mode set to 100644
File size: 12.1 KB
RevLine 
[2fc5072]1/*
2 * Copyright (c) 2011 Petr Koupy
[ceebf0a]3 * Copyright (c) 2011 Jiri Zarevucky
[2fc5072]4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * - The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30/** @addtogroup libposix
31 * @{
32 */
[087c8798]33/** @file Standard library definitions.
[2fc5072]34 */
35
[4d10fc8]36#define LIBPOSIX_INTERNAL
[fdf97f6]37#define __POSIX_DEF__(x) posix_##x
[2fc5072]38
[a6d908c1]39#include "internal/common.h"
[a3da2b2]40#include "posix/stdlib.h"
[a6d908c1]41
[a3da2b2]42#include "posix/errno.h"
43#include "posix/fcntl.h"
44#include "posix/limits.h"
45#include "posix/string.h"
46#include "posix/sys/stat.h"
47#include "posix/unistd.h"
[ec18957a]48
[2b83add]49#include "libc/sort.h"
50#include "libc/str.h"
51#include "libc/vfs/vfs.h"
[0d33863]52#include "libc/stats.h"
[2fc5072]53
[823a929]54/**
55 *
56 * @param array
57 * @param count
58 * @param size
59 * @param compare
60 */
61int posix_atexit(void (*func)(void))
62{
63 // TODO: low priority, just a compile-time dependency of binutils
64 not_implemented();
[e965dec]65 return 1;
[823a929]66}
67
68/**
[087c8798]69 * Integer absolute value.
[823a929]70 *
[2b83add]71 * @param i Input value.
72 * @return Absolute value of the parameter.
[823a929]73 */
74int posix_abs(int i)
75{
[2b83add]76 return i < 0 ? -i : i;
77}
78
79/**
[087c8798]80 * Long integer absolute value.
[2b83add]81 *
82 * @param i Input value.
83 * @return Absolute value of the parameter.
84 */
85long posix_labs(long i)
86{
87 return i < 0 ? -i : i;
88}
89
90/**
[087c8798]91 * Long long integer absolute value.
[2b83add]92 *
93 * @param i Input value.
94 * @return Absolute value of the parameter.
95 */
96long long posix_llabs(long long i)
97{
98 return i < 0 ? -i : i;
99}
100
[087c8798]101/**
102 * Compute the quotient and remainder of an integer division.
103 *
104 * @param numer Numerator.
105 * @param denom Denominator.
106 * @return Quotient and remainder packed into structure.
107 */
[cc3652db]108posix_div_t posix_div(int numer, int denom)
109{
110 return (posix_div_t) { .quot = numer / denom, .rem = numer % denom };
111}
112
[087c8798]113/**
114 * Compute the quotient and remainder of a long integer division.
115 *
116 * @param numer Numerator.
117 * @param denom Denominator.
118 * @return Quotient and remainder packed into structure.
119 */
[cc3652db]120posix_ldiv_t posix_ldiv(long numer, long denom)
121{
122 return (posix_ldiv_t) { .quot = numer / denom, .rem = numer % denom };
123}
124
[087c8798]125/**
126 * Compute the quotient and remainder of a long long integer division.
127 *
128 * @param numer Numerator.
129 * @param denom Denominator.
130 * @return Quotient and remainder packed into structure.
131 */
[cc3652db]132posix_lldiv_t posix_lldiv(long long numer, long long denom)
133{
134 return (posix_lldiv_t) { .quot = numer / denom, .rem = numer % denom };
135}
136
[2b83add]137/**
138 * Private helper function that serves as a compare function for qsort().
139 *
140 * @param elem1 First element to compare.
141 * @param elem2 Second element to compare.
142 * @param compare Comparison function without userdata parameter.
143 * @return Relative ordering of the elements.
144 */
145static int sort_compare_wrapper(void *elem1, void *elem2, void *userdata)
146{
147 int (*compare)(const void *, const void *) = userdata;
[102a729]148 int ret = compare(elem1, elem2);
149
150 /* Native qsort internals expect this. */
151 if (ret < 0) {
152 return -1;
153 } else if (ret > 0) {
154 return 1;
155 } else {
156 return 0;
157 }
[823a929]158}
159
[2fc5072]160/**
[2b83add]161 * Array sorting utilizing the quicksort algorithm.
[2fc5072]162 *
[087c8798]163 * @param array Array of elements to sort.
164 * @param count Number of elements in the array.
165 * @param size Width of each element.
166 * @param compare Decides relative ordering of two elements.
[2fc5072]167 */
[4f4b4e7]168void posix_qsort(void *array, size_t count, size_t size,
169 int (*compare)(const void *, const void *))
[2fc5072]170{
[2b83add]171 /* Implemented in libc with one extra argument. */
172 qsort(array, count, size, sort_compare_wrapper, compare);
[2fc5072]173}
174
[cc3652db]175/**
176 * Binary search in a sorted array.
177 *
178 * @param key Object to search for.
179 * @param base Pointer to the first element of the array.
180 * @param nmemb Number of elements in the array.
181 * @param size Size of each array element.
182 * @param compar Comparison function.
183 * @return Pointer to a matching element, or NULL if none can be found.
184 */
185void *posix_bsearch(const void *key, const void *base,
186 size_t nmemb, size_t size, int (*compar)(const void *, const void *))
187{
188 while (nmemb > 0) {
189 const void *middle = base + (nmemb / 2) * size;
190 int cmp = compar(key, middle);
191 if (cmp == 0) {
192 return (void *) middle;
193 }
194 if (middle == base) {
195 /* There is just one member left to check and it
196 * didn't match the key. Avoid infinite loop.
197 */
198 break;
199 }
200 if (cmp < 0) {
201 nmemb = nmemb / 2;
202 } else if (cmp > 0) {
203 nmemb = nmemb - (nmemb / 2);
204 base = middle;
205 }
206 }
207
208 return NULL;
209}
210
[2fc5072]211/**
[2b83add]212 * Retrieve a value of the given environment variable.
[087c8798]213 *
[2b83add]214 * Since HelenOS doesn't support env variables at the moment,
215 * this function always returns NULL.
[2fc5072]216 *
[087c8798]217 * @param name Name of the variable.
218 * @return Value of the variable or NULL if such variable does not exist.
[2fc5072]219 */
220char *posix_getenv(const char *name)
221{
[2b83add]222 return NULL;
[2fc5072]223}
224
[823a929]225/**
226 *
227 * @param name
228 * @param resolved
229 * @return
230 */
231int posix_putenv(char *string)
232{
233 // TODO: low priority, just a compile-time dependency of binutils
234 not_implemented();
[e965dec]235 return 0;
[823a929]236}
237
[cc3652db]238/**
[087c8798]239 * Issue a command.
[cc3652db]240 *
[087c8798]241 * @param string String to be passed to a command interpreter or NULL.
242 * @return Termination status of the command if the command is not NULL,
243 * otherwise indicate whether there is a command interpreter (non-zero)
244 * or not (zero).
[cc3652db]245 */
246int posix_system(const char *string) {
247 // TODO: does nothing at the moment
[e965dec]248 not_implemented();
[cc3652db]249 return 0;
250}
251
[2fc5072]252/**
[087c8798]253 * Resolve absolute pathname.
[2fc5072]254 *
[087c8798]255 * @param name Pathname to be resolved.
256 * @param resolved Either buffer for the resolved absolute pathname or NULL.
257 * @return On success, either resolved (if it was not NULL) or pointer to the
258 * newly allocated buffer containing the absolute pathname (if resolved was
259 * NULL). Otherwise NULL.
260 *
[2fc5072]261 */
[087c8798]262char *posix_realpath(const char *restrict name, char *restrict resolved)
[2fc5072]263{
[2b83add]264 #ifndef PATH_MAX
265 assert(resolved == NULL);
266 #endif
267
268 if (name == NULL) {
269 errno = EINVAL;
270 return NULL;
271 }
272
273 // TODO: symlink resolution
274
275 /* Function absolutize is implemented in libc and declared in vfs.h.
276 * No more processing is required as HelenOS doesn't have symlinks
277 * so far (as far as I can tell), although this function will need
278 * to be updated when that support is implemented.
279 */
280 char* absolute = absolutize(name, NULL);
281
282 if (absolute == NULL) {
283 /* POSIX requires some specific errnos to be set
284 * for some cases, but there is no way to find out from
285 * absolutize().
286 */
287 errno = EINVAL;
288 return NULL;
289 }
290
291 if (resolved == NULL) {
292 return absolute;
293 } else {
294 #ifdef PATH_MAX
295 str_cpy(resolved, PATH_MAX, absolute);
296 #endif
297 free(absolute);
298 return resolved;
299 }
[ceebf0a]300}
301
302/**
[63fc519]303 * Converts a string representation of a floating-point number to
304 * its native representation. See posix_strtold().
305 *
[087c8798]306 * @param nptr String representation of a floating-point number.
307 * @return Double-precision number resulting from the string conversion.
[ceebf0a]308 */
[2b83add]309double posix_atof(const char *nptr)
[ceebf0a]310{
[2b83add]311 return posix_strtod(nptr, NULL);
[ceebf0a]312}
313
314/**
[63fc519]315 * Converts a string representation of a floating-point number to
316 * its native representation. See posix_strtold().
317 *
[087c8798]318 * @param nptr String representation of a floating-point number.
319 * @param endptr Pointer to the final part of the string which
320 * was not used for conversion.
321 * @return Single-precision number resulting from the string conversion.
[ceebf0a]322 */
[2b83add]323float posix_strtof(const char *restrict nptr, char **restrict endptr)
[ceebf0a]324{
[2b83add]325 return (float) posix_strtold(nptr, endptr);
[2fc5072]326}
327
[09b0b1fb]328/**
[2b83add]329 * Converts a string representation of a floating-point number to
330 * its native representation. See posix_strtold().
331 *
[087c8798]332 * @param nptr String representation of a floating-point number.
333 * @param endptr Pointer to the final part of the string which
334 * was not used for conversion.
335 * @return Double-precision number resulting from the string conversion.
[09b0b1fb]336 */
[2b83add]337double posix_strtod(const char *restrict nptr, char **restrict endptr)
[09b0b1fb]338{
[2b83add]339 return (double) posix_strtold(nptr, endptr);
[09b0b1fb]340}
341
[823a929]342/**
[087c8798]343 * Allocate memory chunk.
[823a929]344 *
[087c8798]345 * @param size Size of the chunk to allocate.
346 * @return Either pointer to the allocated chunk or NULL if not possible.
[823a929]347 */
348void *posix_malloc(size_t size)
349{
350 return malloc(size);
351}
352
353/**
[087c8798]354 * Allocate memory for an array of elements.
[823a929]355 *
[087c8798]356 * @param nelem Number of elements in the array.
357 * @param elsize Size of each element.
358 * @return Either pointer to the allocated array or NULL if not possible.
[823a929]359 */
360void *posix_calloc(size_t nelem, size_t elsize)
361{
362 return calloc(nelem, elsize);
363}
364
365/**
[087c8798]366 * Reallocate memory chunk to a new size.
[823a929]367 *
[087c8798]368 * @param ptr Memory chunk to reallocate. Might be NULL.
369 * @param size Size of the reallocated chunk. Might be zero.
370 * @return Either NULL or the pointer to the newly reallocated chunk.
[823a929]371 */
372void *posix_realloc(void *ptr, size_t size)
373{
[102a729]374 if (ptr != NULL && size == 0) {
375 /* Native realloc does not handle this special case. */
376 free(ptr);
377 return NULL;
378 } else {
379 return realloc(ptr, size);
380 }
[823a929]381}
382
383/**
[087c8798]384 * Free allocated memory chunk.
[823a929]385 *
[087c8798]386 * @param ptr Memory chunk to be freed.
[823a929]387 */
388void posix_free(void *ptr)
389{
[ca1f1ec]390 if (ptr) {
391 free(ptr);
392 }
[823a929]393}
394
395/**
[11544f4]396 * Creates and opens an unique temporary file from template.
397 *
398 * @param tmpl Template. Last six characters must be XXXXXX.
399 * @return The opened file descriptor or -1 on error.
400 */
401int posix_mkstemp(char *tmpl)
402{
403 int fd = -1;
404
405 char *tptr = tmpl + posix_strlen(tmpl) - 6;
406
407 while (fd < 0) {
408 if (*posix_mktemp(tmpl) == '\0') {
409 /* Errno set by mktemp(). */
410 return -1;
411 }
412
413 fd = open(tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
414
415 if (fd == -1) {
416 /* Restore template to it's original state. */
417 snprintf(tptr, 7, "XXXXXX");
418 }
419 }
420
421 return fd;
422}
423
424/**
425 * Creates an unique temporary file name from template.
426 *
427 * @param tmpl Template. Last six characters must be XXXXXX.
428 * @return The value of tmpl. The template is modified in place.
429 * If no temporary file name can be created, template is
430 * reduced to an empty string.
[823a929]431 */
432char *posix_mktemp(char *tmpl)
433{
[11544f4]434 int tmpl_len = posix_strlen(tmpl);
435 if (tmpl_len < 6) {
436 errno = EINVAL;
437 *tmpl = '\0';
438 return tmpl;
439 }
440
441 char *tptr = tmpl + tmpl_len - 6;
442 if (posix_strcmp(tptr, "XXXXXX") != 0) {
443 errno = EINVAL;
444 *tmpl = '\0';
445 return tmpl;
446 }
447
448 static int seq = 0;
449
450 for (; seq < 1000000; ++seq) {
451 snprintf(tptr, 7, "%06d", seq);
452
453 int orig_errno = errno;
454 errno = 0;
455 /* Check if the file exists. */
456 if (posix_access(tmpl, F_OK) == -1) {
457 if (errno == ENOENT) {
458 errno = orig_errno;
459 break;
460 } else {
461 /* errno set by access() */
462 *tmpl = '\0';
463 return tmpl;
464 }
465 }
466 }
467
468 if (seq == 10000000) {
469 errno = EEXIST;
470 *tmpl = '\0';
471 return tmpl;
472 }
473
474 return tmpl;
[823a929]475}
476
[3acff69]477/**
[087c8798]478 * Get system load average statistics.
[3acff69]479 *
[087c8798]480 * @param loadavg Array where the load averages shall be placed.
481 * @param nelem Maximum number of elements to be placed into the array.
482 * @return Number of elements placed into the array on success, -1 otherwise.
[3acff69]483 */
484int bsd_getloadavg(double loadavg[], int nelem)
485{
[0d33863]486 assert(nelem > 0);
487
488 size_t count;
489 load_t *loads = stats_get_load(&count);
490
491 if (loads == NULL) {
492 return -1;
493 }
494
495 if (((size_t) nelem) < count) {
496 count = nelem;
497 }
498
499 for (size_t i = 0; i < count; ++i) {
500 loadavg[i] = (double) loads[i];
501 }
502
503 free(loads);
504 return count;
[3acff69]505}
506
[2fc5072]507/** @}
508 */
Note: See TracBrowser for help on using the repository browser.