source: mainline/uspace/lib/posix/src/stdlib.c@ 34e1206

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 34e1206 was a35b458, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 7 years ago

style: Remove trailing whitespace on _all_ lines, including empty ones, for particular file types.

Command used: tools/srepl '\s\+$' '' -- *.c *.h *.py *.sh *.s *.S *.ag

Currently, whitespace on empty lines is very inconsistent.
There are two basic choices: Either remove the whitespace, or keep empty lines
indented to the level of surrounding code. The former is AFAICT more common,
and also much easier to do automatically.

Alternatively, we could write script for automatic indentation, and use that
instead. However, if such a script exists, it's possible to use the indented
style locally, by having the editor apply relevant conversions on load/save,
without affecting remote repository. IMO, it makes more sense to adopt
the simpler rule.

  • Property mode set to 100644
File size: 9.7 KB
Line 
1/*
2 * Copyright (c) 2011 Petr Koupy
3 * Copyright (c) 2011 Jiri Zarevucky
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 */
33/** @file Standard library definitions.
34 */
35
36#include "internal/common.h"
37#include "posix/stdlib.h"
38
39#include <errno.h>
40
41#include "posix/fcntl.h"
42#include "posix/limits.h"
43#include "posix/string.h"
44#include "posix/sys/stat.h"
45#include "posix/unistd.h"
46
47#include "libc/qsort.h"
48#include "libc/str.h"
49#include "libc/vfs/vfs.h"
50#include "libc/stats.h"
51
52/**
53 *
54 * @param array
55 * @param count
56 * @param size
57 * @param compare
58 */
59int atexit(void (*func)(void))
60{
61 // TODO: low priority, just a compile-time dependency of binutils
62 not_implemented();
63 return 0;
64}
65
66/**
67 * Integer absolute value.
68 *
69 * @param i Input value.
70 * @return Absolute value of the parameter.
71 */
72int abs(int i)
73{
74 return i < 0 ? -i : i;
75}
76
77/**
78 * Long integer absolute value.
79 *
80 * @param i Input value.
81 * @return Absolute value of the parameter.
82 */
83long labs(long i)
84{
85 return i < 0 ? -i : i;
86}
87
88/**
89 * Long long integer absolute value.
90 *
91 * @param i Input value.
92 * @return Absolute value of the parameter.
93 */
94long long llabs(long long i)
95{
96 return i < 0 ? -i : i;
97}
98
99/**
100 * Compute the quotient and remainder of an integer division.
101 *
102 * @param numer Numerator.
103 * @param denom Denominator.
104 * @return Quotient and remainder packed into structure.
105 */
106div_t div(int numer, int denom)
107{
108 return (div_t) { .quot = numer / denom, .rem = numer % denom };
109}
110
111/**
112 * Compute the quotient and remainder of a long integer division.
113 *
114 * @param numer Numerator.
115 * @param denom Denominator.
116 * @return Quotient and remainder packed into structure.
117 */
118ldiv_t ldiv(long numer, long denom)
119{
120 return (ldiv_t) { .quot = numer / denom, .rem = numer % denom };
121}
122
123/**
124 * Compute the quotient and remainder of a long long integer division.
125 *
126 * @param numer Numerator.
127 * @param denom Denominator.
128 * @return Quotient and remainder packed into structure.
129 */
130lldiv_t lldiv(long long numer, long long denom)
131{
132 return (lldiv_t) { .quot = numer / denom, .rem = numer % denom };
133}
134
135/**
136 * Binary search in a sorted array.
137 *
138 * @param key Object to search for.
139 * @param base Pointer to the first element of the array.
140 * @param nmemb Number of elements in the array.
141 * @param size Size of each array element.
142 * @param compar Comparison function.
143 * @return Pointer to a matching element, or NULL if none can be found.
144 */
145void *bsearch(const void *key, const void *base,
146 size_t nmemb, size_t size, int (*compar)(const void *, const void *))
147{
148 while (nmemb > 0) {
149 const void *middle = base + (nmemb / 2) * size;
150 int cmp = compar(key, middle);
151 if (cmp == 0) {
152 return (void *) middle;
153 }
154 if (middle == base) {
155 /* There is just one member left to check and it
156 * didn't match the key. Avoid infinite loop.
157 */
158 break;
159 }
160 if (cmp < 0) {
161 nmemb = nmemb / 2;
162 } else if (cmp > 0) {
163 nmemb = nmemb - (nmemb / 2);
164 base = middle;
165 }
166 }
167
168 return NULL;
169}
170
171/**
172 * Retrieve a value of the given environment variable.
173 *
174 * Since HelenOS doesn't support env variables at the moment,
175 * this function always returns NULL.
176 *
177 * @param name Name of the variable.
178 * @return Value of the variable or NULL if such variable does not exist.
179 */
180char *getenv(const char *name)
181{
182 return NULL;
183}
184
185/**
186 *
187 * @param name
188 * @param resolved
189 * @return
190 */
191int putenv(char *string)
192{
193 // TODO: low priority, just a compile-time dependency of binutils
194 not_implemented();
195 return 0;
196}
197
198/**
199 * Issue a command.
200 *
201 * @param string String to be passed to a command interpreter or NULL.
202 * @return Termination status of the command if the command is not NULL,
203 * otherwise indicate whether there is a command interpreter (non-zero)
204 * or not (zero).
205 */
206int system(const char *string) {
207 // TODO: does nothing at the moment
208 not_implemented();
209 return 0;
210}
211
212/**
213 * Resolve absolute pathname.
214 *
215 * @param name Pathname to be resolved.
216 * @param resolved Either buffer for the resolved absolute pathname or NULL.
217 * @return On success, either resolved (if it was not NULL) or pointer to the
218 * newly allocated buffer containing the absolute pathname (if resolved was
219 * NULL). Otherwise NULL.
220 *
221 */
222char *realpath(const char *restrict name, char *restrict resolved)
223{
224 #ifndef PATH_MAX
225 assert(resolved == NULL);
226 #endif
227
228 if (name == NULL) {
229 errno = EINVAL;
230 return NULL;
231 }
232
233 // TODO: symlink resolution
234
235 /* Function absolutize is implemented in libc and declared in vfs.h.
236 * No more processing is required as HelenOS doesn't have symlinks
237 * so far (as far as I can tell), although this function will need
238 * to be updated when that support is implemented.
239 */
240 char* absolute = vfs_absolutize(name, NULL);
241
242 if (absolute == NULL) {
243 /* POSIX requires some specific errnos to be set
244 * for some cases, but there is no way to find out from
245 * absolutize().
246 */
247 errno = EINVAL;
248 return NULL;
249 }
250
251 if (resolved == NULL) {
252 return absolute;
253 } else {
254 #ifdef PATH_MAX
255 str_cpy(resolved, PATH_MAX, absolute);
256 #endif
257 free(absolute);
258 return resolved;
259 }
260}
261
262/**
263 * Converts a string representation of a floating-point number to
264 * its native representation. See strtold().
265 *
266 * @param nptr String representation of a floating-point number.
267 * @return Double-precision number resulting from the string conversion.
268 */
269double atof(const char *nptr)
270{
271 return strtod(nptr, NULL);
272}
273
274/**
275 * Converts a string representation of a floating-point number to
276 * its native representation. See strtold().
277 *
278 * @param nptr String representation of a floating-point number.
279 * @param endptr Pointer to the final part of the string which
280 * was not used for conversion.
281 * @return Single-precision number resulting from the string conversion.
282 */
283float strtof(const char *restrict nptr, char **restrict endptr)
284{
285 return (float) strtold(nptr, endptr);
286}
287
288/**
289 * Converts a string representation of a floating-point number to
290 * its native representation. See strtold().
291 *
292 * @param nptr String representation of a floating-point number.
293 * @param endptr Pointer to the final part of the string which
294 * was not used for conversion.
295 * @return Double-precision number resulting from the string conversion.
296 */
297double strtod(const char *restrict nptr, char **restrict endptr)
298{
299 return (double) strtold(nptr, endptr);
300}
301
302/**
303 * Creates and opens an unique temporary file from template.
304 *
305 * @param tmpl Template. Last six characters must be XXXXXX.
306 * @return The opened file descriptor or -1 on error.
307 */
308int mkstemp(char *tmpl)
309{
310 int fd = -1;
311
312 char *tptr = tmpl + strlen(tmpl) - 6;
313
314 while (fd < 0) {
315 if (*mktemp(tmpl) == '\0') {
316 /* Errno set by mktemp(). */
317 return -1;
318 }
319
320 fd = open(tmpl, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
321
322 if (fd == -1) {
323 /* Restore template to it's original state. */
324 snprintf(tptr, 7, "XXXXXX");
325 }
326 }
327
328 return fd;
329}
330
331/**
332 * Creates an unique temporary file name from template.
333 *
334 * @param tmpl Template. Last six characters must be XXXXXX.
335 * @return The value of tmpl. The template is modified in place.
336 * If no temporary file name can be created, template is
337 * reduced to an empty string.
338 */
339char *mktemp(char *tmpl)
340{
341 int tmpl_len = strlen(tmpl);
342 if (tmpl_len < 6) {
343 errno = EINVAL;
344 *tmpl = '\0';
345 return tmpl;
346 }
347
348 char *tptr = tmpl + tmpl_len - 6;
349 if (strcmp(tptr, "XXXXXX") != 0) {
350 errno = EINVAL;
351 *tmpl = '\0';
352 return tmpl;
353 }
354
355 static int seq = 0;
356
357 for (; seq < 1000000; ++seq) {
358 snprintf(tptr, 7, "%06d", seq);
359
360 int orig_errno = errno;
361 errno = 0;
362 /* Check if the file exists. */
363 if (access(tmpl, F_OK) == -1) {
364 if (errno == ENOENT) {
365 errno = orig_errno;
366 break;
367 } else {
368 /* errno set by access() */
369 *tmpl = '\0';
370 return tmpl;
371 }
372 }
373 }
374
375 if (seq == 10000000) {
376 errno = EEXIST;
377 *tmpl = '\0';
378 return tmpl;
379 }
380
381 return tmpl;
382}
383
384/**
385 * Get system load average statistics.
386 *
387 * @param loadavg Array where the load averages shall be placed.
388 * @param nelem Maximum number of elements to be placed into the array.
389 * @return Number of elements placed into the array on success, -1 otherwise.
390 */
391int bsd_getloadavg(double loadavg[], int nelem)
392{
393 assert(nelem > 0);
394
395 size_t count;
396 load_t *loads = stats_get_load(&count);
397
398 if (loads == NULL) {
399 return -1;
400 }
401
402 if (((size_t) nelem) < count) {
403 count = nelem;
404 }
405
406 for (size_t i = 0; i < count; ++i) {
407 loadavg[i] = (double) loads[i];
408 }
409
410 free(loads);
411 return count;
412}
413
414/** @}
415 */
Note: See TracBrowser for help on using the repository browser.