source: mainline/uspace/lib/posix/source/stdlib.c@ 5759642f

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

Libposix functions are without posix_ prefix

Prior this commit, libposix headers declared all functions as posix_*
and used macros to rename e.g. strncpy to posix_strncpy in all (ported)
sources.

After this change, libposix headers look as normal POSIX compliant headers
(well, almost) and no renaming is done in the source codei (of the ported
applications). Instead, the renaming is done at object files level to
bypass weird problems that are bound to happen if you use macros.

The scheme is following. libposix headers use special macro to declare
the names. When included from outside, the functions have their normal
(standard) names. When included from the libposix sources, posix_ prefix
is added. Thus, when libposix is compiled and linked, it contains the
posix_* naming while compiling of ported software uses the normal
non-prefixed versions. This way the posix_* can use HelenOS libc without
any problem. Before linking, the posix_* prefix is removed from all
symbols and special prefix helenos_libc_ is added to all functions
that exists in our (HelenOS) libc and its name clashes with the POSIX
one.

The following happens, for example, to the open() function that exists in
both libposix and in libc.

  • Headers and sources of libc are left intact.
  • Copy of libc.a is made and to all clashing functions is added the helenos_libc prefix. This library is called libc4posix.a.
  • POSIX_DEF(open)(const char *) is used in libposix headers. This macro expands to plain open when included from the "outside world". But it expands to posix_open when included from libposix sources.
  • Libposix is compiled and linked, containing posix_open() that internally calls open() [the original one from libc].
  • Libposix is transformed - all open() are replaced with prefix variant: helenos_libc_open() and all posix_open() are replaced with open(). The transformed library is stored as libposixaslibc.a

Binutils and PCC are then linked with libc4posix and libposixaslibc
libraries instead of libc and libposix as was done previously.

WARNING: it looks that binutils, PCC and MSIM still works but not all
architectures were tested.

  • 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();
65}
66
67/**
[087c8798]68 * Integer absolute value.
[823a929]69 *
[2b83add]70 * @param i Input value.
71 * @return Absolute value of the parameter.
[823a929]72 */
73int posix_abs(int i)
74{
[2b83add]75 return i < 0 ? -i : i;
76}
77
78/**
[087c8798]79 * Long integer absolute value.
[2b83add]80 *
81 * @param i Input value.
82 * @return Absolute value of the parameter.
83 */
84long posix_labs(long i)
85{
86 return i < 0 ? -i : i;
87}
88
89/**
[087c8798]90 * Long long integer absolute value.
[2b83add]91 *
92 * @param i Input value.
93 * @return Absolute value of the parameter.
94 */
95long long posix_llabs(long long i)
96{
97 return i < 0 ? -i : i;
98}
99
[087c8798]100/**
101 * Compute the quotient and remainder of an integer division.
102 *
103 * @param numer Numerator.
104 * @param denom Denominator.
105 * @return Quotient and remainder packed into structure.
106 */
[cc3652db]107posix_div_t posix_div(int numer, int denom)
108{
109 return (posix_div_t) { .quot = numer / denom, .rem = numer % denom };
110}
111
[087c8798]112/**
113 * Compute the quotient and remainder of a long integer division.
114 *
115 * @param numer Numerator.
116 * @param denom Denominator.
117 * @return Quotient and remainder packed into structure.
118 */
[cc3652db]119posix_ldiv_t posix_ldiv(long numer, long denom)
120{
121 return (posix_ldiv_t) { .quot = numer / denom, .rem = numer % denom };
122}
123
[087c8798]124/**
125 * Compute the quotient and remainder of a long long integer division.
126 *
127 * @param numer Numerator.
128 * @param denom Denominator.
129 * @return Quotient and remainder packed into structure.
130 */
[cc3652db]131posix_lldiv_t posix_lldiv(long long numer, long long denom)
132{
133 return (posix_lldiv_t) { .quot = numer / denom, .rem = numer % denom };
134}
135
[2b83add]136/**
137 * Private helper function that serves as a compare function for qsort().
138 *
139 * @param elem1 First element to compare.
140 * @param elem2 Second element to compare.
141 * @param compare Comparison function without userdata parameter.
142 * @return Relative ordering of the elements.
143 */
144static int sort_compare_wrapper(void *elem1, void *elem2, void *userdata)
145{
146 int (*compare)(const void *, const void *) = userdata;
[102a729]147 int ret = compare(elem1, elem2);
148
149 /* Native qsort internals expect this. */
150 if (ret < 0) {
151 return -1;
152 } else if (ret > 0) {
153 return 1;
154 } else {
155 return 0;
156 }
[823a929]157}
158
[2fc5072]159/**
[2b83add]160 * Array sorting utilizing the quicksort algorithm.
[2fc5072]161 *
[087c8798]162 * @param array Array of elements to sort.
163 * @param count Number of elements in the array.
164 * @param size Width of each element.
165 * @param compare Decides relative ordering of two elements.
[2fc5072]166 */
[4f4b4e7]167void posix_qsort(void *array, size_t count, size_t size,
168 int (*compare)(const void *, const void *))
[2fc5072]169{
[2b83add]170 /* Implemented in libc with one extra argument. */
171 qsort(array, count, size, sort_compare_wrapper, compare);
[2fc5072]172}
173
[cc3652db]174/**
175 * Binary search in a sorted array.
176 *
177 * @param key Object to search for.
178 * @param base Pointer to the first element of the array.
179 * @param nmemb Number of elements in the array.
180 * @param size Size of each array element.
181 * @param compar Comparison function.
182 * @return Pointer to a matching element, or NULL if none can be found.
183 */
184void *posix_bsearch(const void *key, const void *base,
185 size_t nmemb, size_t size, int (*compar)(const void *, const void *))
186{
187 while (nmemb > 0) {
188 const void *middle = base + (nmemb / 2) * size;
189 int cmp = compar(key, middle);
190 if (cmp == 0) {
191 return (void *) middle;
192 }
193 if (middle == base) {
194 /* There is just one member left to check and it
195 * didn't match the key. Avoid infinite loop.
196 */
197 break;
198 }
199 if (cmp < 0) {
200 nmemb = nmemb / 2;
201 } else if (cmp > 0) {
202 nmemb = nmemb - (nmemb / 2);
203 base = middle;
204 }
205 }
206
207 return NULL;
208}
209
[2fc5072]210/**
[2b83add]211 * Retrieve a value of the given environment variable.
[087c8798]212 *
[2b83add]213 * Since HelenOS doesn't support env variables at the moment,
214 * this function always returns NULL.
[2fc5072]215 *
[087c8798]216 * @param name Name of the variable.
217 * @return Value of the variable or NULL if such variable does not exist.
[2fc5072]218 */
219char *posix_getenv(const char *name)
220{
[2b83add]221 return NULL;
[2fc5072]222}
223
[823a929]224/**
225 *
226 * @param name
227 * @param resolved
228 * @return
229 */
230int posix_putenv(char *string)
231{
232 // TODO: low priority, just a compile-time dependency of binutils
233 not_implemented();
234}
235
[cc3652db]236/**
[087c8798]237 * Issue a command.
[cc3652db]238 *
[087c8798]239 * @param string String to be passed to a command interpreter or NULL.
240 * @return Termination status of the command if the command is not NULL,
241 * otherwise indicate whether there is a command interpreter (non-zero)
242 * or not (zero).
[cc3652db]243 */
244int posix_system(const char *string) {
245 // TODO: does nothing at the moment
246 return 0;
247}
248
[2fc5072]249/**
[087c8798]250 * Resolve absolute pathname.
[2fc5072]251 *
[087c8798]252 * @param name Pathname to be resolved.
253 * @param resolved Either buffer for the resolved absolute pathname or NULL.
254 * @return On success, either resolved (if it was not NULL) or pointer to the
255 * newly allocated buffer containing the absolute pathname (if resolved was
256 * NULL). Otherwise NULL.
257 *
[2fc5072]258 */
[087c8798]259char *posix_realpath(const char *restrict name, char *restrict resolved)
[2fc5072]260{
[2b83add]261 #ifndef PATH_MAX
262 assert(resolved == NULL);
263 #endif
264
265 if (name == NULL) {
266 errno = EINVAL;
267 return NULL;
268 }
269
270 // TODO: symlink resolution
271
272 /* Function absolutize is implemented in libc and declared in vfs.h.
273 * No more processing is required as HelenOS doesn't have symlinks
274 * so far (as far as I can tell), although this function will need
275 * to be updated when that support is implemented.
276 */
277 char* absolute = absolutize(name, NULL);
278
279 if (absolute == NULL) {
280 /* POSIX requires some specific errnos to be set
281 * for some cases, but there is no way to find out from
282 * absolutize().
283 */
284 errno = EINVAL;
285 return NULL;
286 }
287
288 if (resolved == NULL) {
289 return absolute;
290 } else {
291 #ifdef PATH_MAX
292 str_cpy(resolved, PATH_MAX, absolute);
293 #endif
294 free(absolute);
295 return resolved;
296 }
[ceebf0a]297}
298
299/**
[63fc519]300 * Converts a string representation of a floating-point number to
301 * its native representation. See posix_strtold().
302 *
[087c8798]303 * @param nptr String representation of a floating-point number.
304 * @return Double-precision number resulting from the string conversion.
[ceebf0a]305 */
[2b83add]306double posix_atof(const char *nptr)
[ceebf0a]307{
[2b83add]308 return posix_strtod(nptr, NULL);
[ceebf0a]309}
310
311/**
[63fc519]312 * Converts a string representation of a floating-point number to
313 * its native representation. See posix_strtold().
314 *
[087c8798]315 * @param nptr String representation of a floating-point number.
316 * @param endptr Pointer to the final part of the string which
317 * was not used for conversion.
318 * @return Single-precision number resulting from the string conversion.
[ceebf0a]319 */
[2b83add]320float posix_strtof(const char *restrict nptr, char **restrict endptr)
[ceebf0a]321{
[2b83add]322 return (float) posix_strtold(nptr, endptr);
[2fc5072]323}
324
[09b0b1fb]325/**
[2b83add]326 * Converts a string representation of a floating-point number to
327 * its native representation. See posix_strtold().
328 *
[087c8798]329 * @param nptr String representation of a floating-point number.
330 * @param endptr Pointer to the final part of the string which
331 * was not used for conversion.
332 * @return Double-precision number resulting from the string conversion.
[09b0b1fb]333 */
[2b83add]334double posix_strtod(const char *restrict nptr, char **restrict endptr)
[09b0b1fb]335{
[2b83add]336 return (double) posix_strtold(nptr, endptr);
[09b0b1fb]337}
338
[823a929]339/**
[087c8798]340 * Allocate memory chunk.
[823a929]341 *
[087c8798]342 * @param size Size of the chunk to allocate.
343 * @return Either pointer to the allocated chunk or NULL if not possible.
[823a929]344 */
345void *posix_malloc(size_t size)
346{
347 return malloc(size);
348}
349
350/**
[087c8798]351 * Allocate memory for an array of elements.
[823a929]352 *
[087c8798]353 * @param nelem Number of elements in the array.
354 * @param elsize Size of each element.
355 * @return Either pointer to the allocated array or NULL if not possible.
[823a929]356 */
357void *posix_calloc(size_t nelem, size_t elsize)
358{
359 return calloc(nelem, elsize);
360}
361
362/**
[087c8798]363 * Reallocate memory chunk to a new size.
[823a929]364 *
[087c8798]365 * @param ptr Memory chunk to reallocate. Might be NULL.
366 * @param size Size of the reallocated chunk. Might be zero.
367 * @return Either NULL or the pointer to the newly reallocated chunk.
[823a929]368 */
369void *posix_realloc(void *ptr, size_t size)
370{
[102a729]371 if (ptr != NULL && size == 0) {
372 /* Native realloc does not handle this special case. */
373 free(ptr);
374 return NULL;
375 } else {
376 return realloc(ptr, size);
377 }
[823a929]378}
379
380/**
[087c8798]381 * Free allocated memory chunk.
[823a929]382 *
[087c8798]383 * @param ptr Memory chunk to be freed.
[823a929]384 */
385void posix_free(void *ptr)
386{
[ca1f1ec]387 if (ptr) {
388 free(ptr);
389 }
[823a929]390}
391
392/**
[11544f4]393 * Creates and opens an unique temporary file from template.
394 *
395 * @param tmpl Template. Last six characters must be XXXXXX.
396 * @return The opened file descriptor or -1 on error.
397 */
398int posix_mkstemp(char *tmpl)
399{
400 int fd = -1;
401
402 char *tptr = tmpl + posix_strlen(tmpl) - 6;
403
404 while (fd < 0) {
405 if (*posix_mktemp(tmpl) == '\0') {
406 /* Errno set by mktemp(). */
407 return -1;
408 }
409
410 fd = open(tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
411
412 if (fd == -1) {
413 /* Restore template to it's original state. */
414 snprintf(tptr, 7, "XXXXXX");
415 }
416 }
417
418 return fd;
419}
420
421/**
422 * Creates an unique temporary file name from template.
423 *
424 * @param tmpl Template. Last six characters must be XXXXXX.
425 * @return The value of tmpl. The template is modified in place.
426 * If no temporary file name can be created, template is
427 * reduced to an empty string.
[823a929]428 */
429char *posix_mktemp(char *tmpl)
430{
[11544f4]431 int tmpl_len = posix_strlen(tmpl);
432 if (tmpl_len < 6) {
433 errno = EINVAL;
434 *tmpl = '\0';
435 return tmpl;
436 }
437
438 char *tptr = tmpl + tmpl_len - 6;
439 if (posix_strcmp(tptr, "XXXXXX") != 0) {
440 errno = EINVAL;
441 *tmpl = '\0';
442 return tmpl;
443 }
444
445 static int seq = 0;
446
447 for (; seq < 1000000; ++seq) {
448 snprintf(tptr, 7, "%06d", seq);
449
450 int orig_errno = errno;
451 errno = 0;
452 /* Check if the file exists. */
453 if (posix_access(tmpl, F_OK) == -1) {
454 if (errno == ENOENT) {
455 errno = orig_errno;
456 break;
457 } else {
458 /* errno set by access() */
459 *tmpl = '\0';
460 return tmpl;
461 }
462 }
463 }
464
465 if (seq == 10000000) {
466 errno = EEXIST;
467 *tmpl = '\0';
468 return tmpl;
469 }
470
471 return tmpl;
[823a929]472}
473
[3acff69]474/**
[087c8798]475 * Get system load average statistics.
[3acff69]476 *
[087c8798]477 * @param loadavg Array where the load averages shall be placed.
478 * @param nelem Maximum number of elements to be placed into the array.
479 * @return Number of elements placed into the array on success, -1 otherwise.
[3acff69]480 */
481int bsd_getloadavg(double loadavg[], int nelem)
482{
[0d33863]483 assert(nelem > 0);
484
485 size_t count;
486 load_t *loads = stats_get_load(&count);
487
488 if (loads == NULL) {
489 return -1;
490 }
491
492 if (((size_t) nelem) < count) {
493 count = nelem;
494 }
495
496 for (size_t i = 0; i < count; ++i) {
497 loadavg[i] = (double) loads[i];
498 }
499
500 free(loads);
501 return count;
[3acff69]502}
503
[2fc5072]504/** @}
505 */
Note: See TracBrowser for help on using the repository browser.