source: mainline/kernel/generic/src/sysinfo/sysinfo.c@ 311bc25

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 311bc25 was 311bc25, checked in by Martin Decky <martin@…>, 14 years ago

avoid the possibility for infinite looping on fetching sysinfo values
still make the tests in statistical functions more robust
this fixes ticket #237

  • Property mode set to 100644
File size: 21.1 KB
Line 
1/*
2 * Copyright (c) 2006 Jakub Vana
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup generic
30 * @{
31 */
32/** @file
33 */
34
35#include <sysinfo/sysinfo.h>
36#include <mm/slab.h>
37#include <print.h>
38#include <syscall/copy.h>
39#include <synch/mutex.h>
40#include <arch/asm.h>
41#include <errno.h>
42#include <macros.h>
43
44/** Maximal sysinfo path length */
45#define SYSINFO_MAX_PATH 2048
46
47bool fb_exported = false;
48
49/** Global sysinfo tree root item */
50static sysinfo_item_t *global_root = NULL;
51
52/** Sysinfo SLAB cache */
53static slab_cache_t *sysinfo_item_slab;
54
55/** Sysinfo lock */
56static mutex_t sysinfo_lock;
57
58/** Sysinfo item constructor
59 *
60 */
61NO_TRACE static int sysinfo_item_constructor(void *obj, unsigned int kmflag)
62{
63 sysinfo_item_t *item = (sysinfo_item_t *) obj;
64
65 item->name = NULL;
66 item->val_type = SYSINFO_VAL_UNDEFINED;
67 item->subtree_type = SYSINFO_SUBTREE_NONE;
68 item->subtree.table = NULL;
69 item->next = NULL;
70
71 return 0;
72}
73
74/** Sysinfo item destructor
75 *
76 * Note that the return value is not perfectly correct
77 * since more space might get actually freed thanks
78 * to the disposal of item->name
79 *
80 */
81NO_TRACE static size_t sysinfo_item_destructor(void *obj)
82{
83 sysinfo_item_t *item = (sysinfo_item_t *) obj;
84
85 if (item->name != NULL)
86 free(item->name);
87
88 return 0;
89}
90
91/** Initialize sysinfo subsystem
92 *
93 * Create SLAB cache for sysinfo items.
94 *
95 */
96void sysinfo_init(void)
97{
98 sysinfo_item_slab = slab_cache_create("sysinfo_item_slab",
99 sizeof(sysinfo_item_t), 0, sysinfo_item_constructor,
100 sysinfo_item_destructor, SLAB_CACHE_MAGDEFERRED);
101
102 mutex_initialize(&sysinfo_lock, MUTEX_ACTIVE);
103}
104
105/** Recursively find an item in sysinfo tree
106 *
107 * Should be called with sysinfo_lock held.
108 *
109 * @param name Current sysinfo path suffix.
110 * @param subtree Current sysinfo (sub)tree root item.
111 * @param ret If the return value is NULL, this argument
112 * can be either also NULL (i.e. no item was
113 * found and no data was generated) or the
114 * original pointer is used to store the value
115 * generated by a generated subtree function.
116 * @param dry_run Do not actually get any generated
117 * binary data, just calculate the size.
118 *
119 * @return Found item or NULL if no item in the fixed tree
120 * was found (N.B. ret).
121 *
122 */
123NO_TRACE static sysinfo_item_t *sysinfo_find_item(const char *name,
124 sysinfo_item_t *subtree, sysinfo_return_t **ret, bool dry_run)
125{
126 ASSERT(subtree != NULL);
127 ASSERT(ret != NULL);
128
129 sysinfo_item_t *cur = subtree;
130
131 /* Walk all siblings */
132 while (cur != NULL) {
133 size_t i = 0;
134
135 /* Compare name with path */
136 while ((cur->name[i] != 0) && (name[i] == cur->name[i]))
137 i++;
138
139 /* Check for perfect name and path match */
140 if ((name[i] == 0) && (cur->name[i] == 0))
141 return cur;
142
143 /* Partial match up to the delimiter */
144 if ((name[i] == '.') && (cur->name[i] == 0)) {
145 /* Look into the subtree */
146 switch (cur->subtree_type) {
147 case SYSINFO_SUBTREE_TABLE:
148 /* Recursively find in subtree */
149 return sysinfo_find_item(name + i + 1,
150 cur->subtree.table, ret, dry_run);
151 case SYSINFO_SUBTREE_FUNCTION:
152 /* Get generated data */
153 **ret = cur->subtree.get_data(name + i + 1, dry_run);
154 return NULL;
155 default:
156 /* Not found, no data generated */
157 *ret = NULL;
158 return NULL;
159 }
160 }
161
162 cur = cur->next;
163 }
164
165 /* Not found, no data generated */
166 *ret = NULL;
167 return NULL;
168}
169
170/** Recursively create items in sysinfo tree
171 *
172 * Should be called with sysinfo_lock held.
173 *
174 * @param name Current sysinfo path suffix.
175 * @param psubtree Pointer to an already existing (sub)tree root
176 * item or where to store a new tree root item.
177 *
178 * @return Existing or newly allocated sysinfo item or NULL
179 * if the current tree configuration does not allow to
180 * create a new item.
181 *
182 */
183NO_TRACE static sysinfo_item_t *sysinfo_create_path(const char *name,
184 sysinfo_item_t **psubtree)
185{
186 ASSERT(psubtree != NULL);
187
188 if (*psubtree == NULL) {
189 /* No parent */
190
191 size_t i = 0;
192
193 /* Find the first delimiter in name */
194 while ((name[i] != 0) && (name[i] != '.'))
195 i++;
196
197 *psubtree =
198 (sysinfo_item_t *) slab_alloc(sysinfo_item_slab, 0);
199 ASSERT(*psubtree);
200
201 /* Fill in item name up to the delimiter */
202 (*psubtree)->name = str_ndup(name, i);
203 ASSERT((*psubtree)->name);
204
205 /* Create subtree items */
206 if (name[i] == '.') {
207 (*psubtree)->subtree_type = SYSINFO_SUBTREE_TABLE;
208 return sysinfo_create_path(name + i + 1,
209 &((*psubtree)->subtree.table));
210 }
211
212 /* No subtree needs to be created */
213 return *psubtree;
214 }
215
216 sysinfo_item_t *cur = *psubtree;
217
218 /* Walk all siblings */
219 while (cur != NULL) {
220 size_t i = 0;
221
222 /* Compare name with path */
223 while ((cur->name[i] != 0) && (name[i] == cur->name[i]))
224 i++;
225
226 /* Check for perfect name and path match
227 * -> item is already present.
228 */
229 if ((name[i] == 0) && (cur->name[i] == 0))
230 return cur;
231
232 /* Partial match up to the delimiter */
233 if ((name[i] == '.') && (cur->name[i] == 0)) {
234 switch (cur->subtree_type) {
235 case SYSINFO_SUBTREE_NONE:
236 /* No subtree yet, create one */
237 cur->subtree_type = SYSINFO_SUBTREE_TABLE;
238 return sysinfo_create_path(name + i + 1,
239 &(cur->subtree.table));
240 case SYSINFO_SUBTREE_TABLE:
241 /* Subtree already created, add new sibling */
242 return sysinfo_create_path(name + i + 1,
243 &(cur->subtree.table));
244 default:
245 /* Subtree items handled by a function, this
246 * cannot be overriden by a constant item.
247 */
248 return NULL;
249 }
250 }
251
252 /* No match and no more siblings to check
253 * -> create a new sibling item.
254 */
255 if (cur->next == NULL) {
256 /* Find the first delimiter in name */
257 i = 0;
258 while ((name[i] != 0) && (name[i] != '.'))
259 i++;
260
261 sysinfo_item_t *item =
262 (sysinfo_item_t *) slab_alloc(sysinfo_item_slab, 0);
263 ASSERT(item);
264
265 cur->next = item;
266
267 /* Fill in item name up to the delimiter */
268 item->name = str_ndup(name, i);
269 ASSERT(item->name);
270
271 /* Create subtree items */
272 if (name[i] == '.') {
273 item->subtree_type = SYSINFO_SUBTREE_TABLE;
274 return sysinfo_create_path(name + i + 1,
275 &(item->subtree.table));
276 }
277
278 /* No subtree needs to be created */
279 return item;
280 }
281
282 cur = cur->next;
283 }
284
285 /* Unreachable */
286 ASSERT(false);
287 return NULL;
288}
289
290/** Set sysinfo item with a constant numeric value
291 *
292 * @param name Sysinfo path.
293 * @param root Pointer to the root item or where to store
294 * a new root item (NULL for global sysinfo root).
295 * @param val Value to store in the item.
296 *
297 */
298void sysinfo_set_item_val(const char *name, sysinfo_item_t **root,
299 sysarg_t val)
300{
301 /* Protect sysinfo tree consistency */
302 mutex_lock(&sysinfo_lock);
303
304 if (root == NULL)
305 root = &global_root;
306
307 sysinfo_item_t *item = sysinfo_create_path(name, root);
308 if (item != NULL) {
309 item->val_type = SYSINFO_VAL_VAL;
310 item->val.val = val;
311 }
312
313 mutex_unlock(&sysinfo_lock);
314}
315
316/** Set sysinfo item with a constant binary data
317 *
318 * Note that sysinfo only stores the pointer to the
319 * binary data and does not touch it in any way. The
320 * data should be static and immortal.
321 *
322 * @param name Sysinfo path.
323 * @param root Pointer to the root item or where to store
324 * a new root item (NULL for global sysinfo root).
325 * @param data Binary data.
326 * @param size Size of the binary data.
327 *
328 */
329void sysinfo_set_item_data(const char *name, sysinfo_item_t **root,
330 void *data, size_t size)
331{
332 /* Protect sysinfo tree consistency */
333 mutex_lock(&sysinfo_lock);
334
335 if (root == NULL)
336 root = &global_root;
337
338 sysinfo_item_t *item = sysinfo_create_path(name, root);
339 if (item != NULL) {
340 item->val_type = SYSINFO_VAL_DATA;
341 item->val.data.data = data;
342 item->val.data.size = size;
343 }
344
345 mutex_unlock(&sysinfo_lock);
346}
347
348/** Set sysinfo item with a generated numeric value
349 *
350 * @param name Sysinfo path.
351 * @param root Pointer to the root item or where to store
352 * a new root item (NULL for global sysinfo root).
353 * @param fn Numeric value generator function.
354 *
355 */
356void sysinfo_set_item_fn_val(const char *name, sysinfo_item_t **root,
357 sysinfo_fn_val_t fn)
358{
359 /* Protect sysinfo tree consistency */
360 mutex_lock(&sysinfo_lock);
361
362 if (root == NULL)
363 root = &global_root;
364
365 sysinfo_item_t *item = sysinfo_create_path(name, root);
366 if (item != NULL) {
367 item->val_type = SYSINFO_VAL_FUNCTION_VAL;
368 item->val.fn_val = fn;
369 }
370
371 mutex_unlock(&sysinfo_lock);
372}
373
374/** Set sysinfo item with a generated binary data
375 *
376 * Note that each time the generator function is called
377 * it is supposed to return a new dynamically allocated
378 * data. This data is then freed by sysinfo in the context
379 * of the current sysinfo request.
380 *
381 * @param name Sysinfo path.
382 * @param root Pointer to the root item or where to store
383 * a new root item (NULL for global sysinfo root).
384 * @param fn Binary data generator function.
385 *
386 */
387void sysinfo_set_item_fn_data(const char *name, sysinfo_item_t **root,
388 sysinfo_fn_data_t fn)
389{
390 /* Protect sysinfo tree consistency */
391 mutex_lock(&sysinfo_lock);
392
393 if (root == NULL)
394 root = &global_root;
395
396 sysinfo_item_t *item = sysinfo_create_path(name, root);
397 if (item != NULL) {
398 item->val_type = SYSINFO_VAL_FUNCTION_DATA;
399 item->val.fn_data = fn;
400 }
401
402 mutex_unlock(&sysinfo_lock);
403}
404
405/** Set sysinfo item with an undefined value
406 *
407 * @param name Sysinfo path.
408 * @param root Pointer to the root item or where to store
409 * a new root item (NULL for global sysinfo root).
410 *
411 */
412void sysinfo_set_item_undefined(const char *name, sysinfo_item_t **root)
413{
414 /* Protect sysinfo tree consistency */
415 mutex_lock(&sysinfo_lock);
416
417 if (root == NULL)
418 root = &global_root;
419
420 sysinfo_item_t *item = sysinfo_create_path(name, root);
421 if (item != NULL)
422 item->val_type = SYSINFO_VAL_UNDEFINED;
423
424 mutex_unlock(&sysinfo_lock);
425}
426
427/** Set sysinfo item with a generated subtree
428 *
429 * @param name Sysinfo path.
430 * @param root Pointer to the root item or where to store
431 * a new root item (NULL for global sysinfo root).
432 * @param fn Subtree generator function.
433 *
434 */
435void sysinfo_set_subtree_fn(const char *name, sysinfo_item_t **root,
436 sysinfo_fn_subtree_t fn)
437{
438 /* Protect sysinfo tree consistency */
439 mutex_lock(&sysinfo_lock);
440
441 if (root == NULL)
442 root = &global_root;
443
444 sysinfo_item_t *item = sysinfo_create_path(name, root);
445
446 /* Change the type of the subtree only if it is not already
447 a fixed subtree */
448 if ((item != NULL) && (item->subtree_type != SYSINFO_SUBTREE_TABLE)) {
449 item->subtree_type = SYSINFO_SUBTREE_FUNCTION;
450 item->subtree.get_data = fn;
451 }
452
453 mutex_unlock(&sysinfo_lock);
454}
455
456/** Sysinfo dump indentation helper routine
457 *
458 * @param depth Number of indentation characters to print.
459 *
460 */
461NO_TRACE static void sysinfo_indent(unsigned int depth)
462{
463 unsigned int i;
464 for (i = 0; i < depth; i++)
465 printf(" ");
466}
467
468/** Dump the structure of sysinfo tree
469 *
470 * Should be called with sysinfo_lock held.
471 *
472 * @param root Root item of the current (sub)tree.
473 * @param depth Current depth in the sysinfo tree.
474 *
475 */
476NO_TRACE static void sysinfo_dump_internal(sysinfo_item_t *root, unsigned int depth)
477{
478 sysinfo_item_t *cur = root;
479
480 /* Walk all siblings */
481 while (cur != NULL) {
482 sysinfo_indent(depth);
483
484 sysarg_t val;
485 size_t size;
486
487 /* Display node value and type */
488 switch (cur->val_type) {
489 case SYSINFO_VAL_UNDEFINED:
490 printf("+ %s\n", cur->name);
491 break;
492 case SYSINFO_VAL_VAL:
493 printf("+ %s -> %" PRIun" (%#" PRIxn ")\n", cur->name,
494 cur->val.val, cur->val.val);
495 break;
496 case SYSINFO_VAL_DATA:
497 printf("+ %s (%zu bytes)\n", cur->name,
498 cur->val.data.size);
499 break;
500 case SYSINFO_VAL_FUNCTION_VAL:
501 val = cur->val.fn_val(cur);
502 printf("+ %s -> %" PRIun" (%#" PRIxn ") [generated]\n",
503 cur->name, val, val);
504 break;
505 case SYSINFO_VAL_FUNCTION_DATA:
506 /* N.B.: No data was actually returned (only a dry run) */
507 (void) cur->val.fn_data(cur, &size, true);
508 printf("+ %s (%zu bytes) [generated]\n", cur->name,
509 size);
510 break;
511 default:
512 printf("+ %s [unknown]\n", cur->name);
513 }
514
515 /* Recursivelly nest into the subtree */
516 switch (cur->subtree_type) {
517 case SYSINFO_SUBTREE_NONE:
518 break;
519 case SYSINFO_SUBTREE_TABLE:
520 sysinfo_dump_internal(cur->subtree.table, depth + 1);
521 break;
522 case SYSINFO_SUBTREE_FUNCTION:
523 sysinfo_indent(depth + 1);
524 printf("+ [generated subtree]\n");
525 break;
526 default:
527 sysinfo_indent(depth + 1);
528 printf("+ [unknown subtree]\n");
529 }
530
531 cur = cur->next;
532 }
533}
534
535/** Dump the structure of sysinfo tree
536 *
537 * @param root Root item of the sysinfo (sub)tree.
538 * If it is NULL then consider the global
539 * sysinfo tree.
540 *
541 */
542void sysinfo_dump(sysinfo_item_t *root)
543{
544 /* Avoid other functions to mess with sysinfo
545 while we are dumping it */
546 mutex_lock(&sysinfo_lock);
547
548 if (root == NULL)
549 sysinfo_dump_internal(global_root, 0);
550 else
551 sysinfo_dump_internal(root, 0);
552
553 mutex_unlock(&sysinfo_lock);
554}
555
556/** Return sysinfo item value determined by name
557 *
558 * Should be called with sysinfo_lock held.
559 *
560 * @param name Sysinfo path.
561 * @param root Root item of the sysinfo (sub)tree.
562 * If it is NULL then consider the global
563 * sysinfo tree.
564 * @param dry_run Do not actually get any generated
565 * binary data, just calculate the size.
566 *
567 * @return Item value (constant or generated).
568 *
569 */
570NO_TRACE static sysinfo_return_t sysinfo_get_item(const char *name,
571 sysinfo_item_t **root, bool dry_run)
572{
573 if (root == NULL)
574 root = &global_root;
575
576 /* Try to find the item or generate data */
577 sysinfo_return_t ret;
578 sysinfo_return_t *ret_ptr = &ret;
579 sysinfo_item_t *item = sysinfo_find_item(name, *root, &ret_ptr,
580 dry_run);
581
582 if (item != NULL) {
583 /* Item found in the fixed sysinfo tree */
584
585 ret.tag = item->val_type;
586 switch (item->val_type) {
587 case SYSINFO_VAL_UNDEFINED:
588 break;
589 case SYSINFO_VAL_VAL:
590 ret.val = item->val.val;
591 break;
592 case SYSINFO_VAL_DATA:
593 ret.data = item->val.data;
594 break;
595 case SYSINFO_VAL_FUNCTION_VAL:
596 ret.val = item->val.fn_val(item);
597 break;
598 case SYSINFO_VAL_FUNCTION_DATA:
599 ret.data.data = item->val.fn_data(item, &ret.data.size,
600 dry_run);
601 break;
602 }
603 } else {
604 /* No item in the fixed sysinfo tree */
605 if (ret_ptr == NULL) {
606 /* Even no data was generated */
607 ret.tag = SYSINFO_VAL_UNDEFINED;
608 }
609 }
610
611 return ret;
612}
613
614/** Return sysinfo item determined by name from user space
615 *
616 * The path string passed from the user space has to be properly null-terminated
617 * (the last passed character must be null).
618 *
619 * @param ptr Sysinfo path in the user address space.
620 * @param size Size of the path string.
621 * @param dry_run Do not actually get any generated
622 * binary data, just calculate the size.
623 *
624 */
625NO_TRACE static sysinfo_return_t sysinfo_get_item_uspace(void *ptr, size_t size,
626 bool dry_run)
627{
628 sysinfo_return_t ret;
629 ret.tag = SYSINFO_VAL_UNDEFINED;
630
631 if (size > SYSINFO_MAX_PATH)
632 return ret;
633
634 char *path = (char *) malloc(size + 1, 0);
635 ASSERT(path);
636
637 if ((copy_from_uspace(path, ptr, size + 1) == 0)
638 && (path[size] == 0)) {
639 /*
640 * Prevent other functions from messing with sysinfo while we
641 * are reading it.
642 */
643 mutex_lock(&sysinfo_lock);
644 ret = sysinfo_get_item(path, NULL, dry_run);
645 mutex_unlock(&sysinfo_lock);
646 }
647 free(path);
648 return ret;
649}
650
651/** Get the sysinfo value type (syscall)
652 *
653 * The path string passed from the user space has
654 * to be properly null-terminated (the last passed
655 * character must be null).
656 *
657 * @param path_ptr Sysinfo path in the user address space.
658 * @param path_size Size of the path string.
659 *
660 * @return Item value type.
661 *
662 */
663sysarg_t sys_sysinfo_get_tag(void *path_ptr, size_t path_size)
664{
665 /*
666 * Get the item.
667 *
668 * N.B.: There is no need to free any potential generated
669 * binary data since we request a dry run.
670 */
671 sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size, true);
672
673 /*
674 * Map generated value types to constant types (user space does not care
675 * whether the value is constant or generated).
676 */
677 if (ret.tag == SYSINFO_VAL_FUNCTION_VAL)
678 ret.tag = SYSINFO_VAL_VAL;
679 else if (ret.tag == SYSINFO_VAL_FUNCTION_DATA)
680 ret.tag = SYSINFO_VAL_DATA;
681
682 return (sysarg_t) ret.tag;
683}
684
685/** Get the sysinfo numerical value (syscall)
686 *
687 * The path string passed from the user space has
688 * to be properly null-terminated (the last passed
689 * character must be null).
690 *
691 * @param path_ptr Sysinfo path in the user address space.
692 * @param path_size Size of the path string.
693 * @param value_ptr User space pointer where to store the
694 * numberical value.
695 *
696 * @return Error code (EOK in case of no error).
697 *
698 */
699sysarg_t sys_sysinfo_get_value(void *path_ptr, size_t path_size,
700 void *value_ptr)
701{
702 int rc;
703
704 /*
705 * Get the item.
706 *
707 * N.B.: There is no need to free any potential generated binary data
708 * since we request a dry run.
709 */
710 sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size, true);
711
712 /* Only constant or generated numerical value is returned */
713 if ((ret.tag == SYSINFO_VAL_VAL) || (ret.tag == SYSINFO_VAL_FUNCTION_VAL))
714 rc = copy_to_uspace(value_ptr, &ret.val, sizeof(ret.val));
715 else
716 rc = EINVAL;
717
718 return (sysarg_t) rc;
719}
720
721/** Get the sysinfo binary data size (syscall)
722 *
723 * The path string passed from the user space has
724 * to be properly null-terminated (the last passed
725 * character must be null).
726 *
727 * @param path_ptr Sysinfo path in the user address space.
728 * @param path_size Size of the path string.
729 * @param size_ptr User space pointer where to store the
730 * binary data size.
731 *
732 * @return Error code (EOK in case of no error).
733 *
734 */
735sysarg_t sys_sysinfo_get_data_size(void *path_ptr, size_t path_size,
736 void *size_ptr)
737{
738 int rc;
739
740 /*
741 * Get the item.
742 *
743 * N.B.: There is no need to free any potential generated binary data
744 * since we request a dry run.
745 */
746 sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size, true);
747
748 /* Only the size of constant or generated binary data is considered */
749 if ((ret.tag == SYSINFO_VAL_DATA) || (ret.tag == SYSINFO_VAL_FUNCTION_DATA))
750 rc = copy_to_uspace(size_ptr, &ret.data.size,
751 sizeof(ret.data.size));
752 else
753 rc = EINVAL;
754
755 return (sysarg_t) rc;
756}
757
758/** Get the sysinfo binary data (syscall)
759 *
760 * The path string passed from the user space has
761 * to be properly null-terminated (the last passed
762 * character must be null).
763 *
764 * If the user space buffer size does not equal
765 * the actual size of the returned data, the data
766 * is truncated. Whether this is actually a fatal
767 * error or the data can be still interpreted as valid
768 * depends on the nature of the data and has to be
769 * decided by the user space.
770 *
771 * The actual size of data returned is stored to
772 * size_ptr.
773 *
774 * @param path_ptr Sysinfo path in the user address space.
775 * @param path_size Size of the path string.
776 * @param buffer_ptr User space pointer to the buffer where
777 * to store the binary data.
778 * @param buffer_size User space buffer size.
779 * @param size_ptr User space pointer where to store the
780 * binary data size.
781 *
782 * @return Error code (EOK in case of no error).
783 *
784 */
785sysarg_t sys_sysinfo_get_data(void *path_ptr, size_t path_size,
786 void *buffer_ptr, size_t buffer_size, size_t *size_ptr)
787{
788 int rc;
789
790 /* Get the item */
791 sysinfo_return_t ret = sysinfo_get_item_uspace(path_ptr, path_size,
792 false);
793
794 /* Only constant or generated binary data is considered */
795 if ((ret.tag == SYSINFO_VAL_DATA) ||
796 (ret.tag == SYSINFO_VAL_FUNCTION_DATA)) {
797 size_t size = min(ret.data.size, buffer_size);
798 rc = copy_to_uspace(buffer_ptr, ret.data.data, size);
799 if (rc == EOK)
800 rc = copy_to_uspace(size_ptr, &size, sizeof(size));
801 } else
802 rc = EINVAL;
803
804 /* N.B.: The generated binary data should be freed */
805 if ((ret.tag == SYSINFO_VAL_FUNCTION_DATA) && (ret.data.data != NULL))
806 free(ret.data.data);
807
808 return (sysarg_t) rc;
809}
810
811/** @}
812 */
Note: See TracBrowser for help on using the repository browser.