Changeset 0030eef in mainline for kernel/generic/src/sysinfo/sysinfo.c


Ignore:
Timestamp:
2012-03-02T13:55:54Z (12 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
560d79f
Parents:
5869ce0
Message:

add kernel support for listing sysinfo keys from uspace

File:
1 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/sysinfo/sysinfo.c

    r5869ce0 r0030eef  
    110110 * @param subtree Current sysinfo (sub)tree root item.
    111111 * @param ret     If the return value is NULL, this argument
    112  *                can be either also NULL (i.e. no item was
     112 *                can be set either to NULL (i.e. no item was
    113113 *                found and no data was generated) or the
    114114 *                original pointer is used to store the value
     
    125125{
    126126        ASSERT(subtree != NULL);
    127         ASSERT(ret != NULL);
    128127       
    129128        sysinfo_item_t *cur = subtree;
     
    151150                        case SYSINFO_SUBTREE_FUNCTION:
    152151                                /* Get generated data */
    153                                 **ret = cur->subtree.generator.fn(name + i + 1, dry_run,
    154                                     cur->subtree.generator.data);
     152                                if (ret != NULL)
     153                                        **ret = cur->subtree.generator.fn(name + i + 1,
     154                                            dry_run, cur->subtree.generator.data);
     155                               
    155156                                return NULL;
    156157                        default:
    157158                                /* Not found, no data generated */
    158                                 *ret = NULL;
     159                                if (ret != NULL)
     160                                        *ret = NULL;
     161                               
    159162                                return NULL;
    160163                        }
     
    165168       
    166169        /* Not found, no data generated */
    167         *ret = NULL;
     170        if (ret != NULL)
     171                *ret = NULL;
     172       
    168173        return NULL;
    169174}
     
    653658}
    654659
     660/** Return sysinfo keys determined by name
     661 *
     662 * Should be called with sysinfo_lock held.
     663 *
     664 * @param name    Sysinfo path.
     665 * @param root    Root item of the sysinfo (sub)tree.
     666 *                If it is NULL then consider the global
     667 *                sysinfo tree.
     668 * @param dry_run Do not actually get any generated
     669 *                binary data, just calculate the size.
     670 *
     671 * @return Item value (constant or generated).
     672 *
     673 */
     674NO_TRACE static sysinfo_return_t sysinfo_get_keys(const char *name,
     675    sysinfo_item_t **root, bool dry_run)
     676{
     677        if (root == NULL)
     678                root = &global_root;
     679       
     680        /* Try to find the item */
     681        sysinfo_item_t *item = sysinfo_find_item(name, *root, NULL,
     682            dry_run);
     683       
     684        sysinfo_return_t ret;
     685       
     686        if ((item != NULL) && (item->subtree_type == SYSINFO_SUBTREE_TABLE)) {
     687                /*
     688                 * Subtree found in the fixed sysinfo tree.
     689                 * Calculate the size of subkeys.
     690                 */
     691                size_t size = 0;
     692                for (sysinfo_item_t *cur = item->subtree.table; cur;
     693                    cur = cur->next)
     694                        size += str_size(cur->name) + 1;
     695               
     696                if (dry_run) {
     697                        ret.tag = SYSINFO_VAL_FUNCTION_DATA;
     698                        ret.data.data = NULL;
     699                        ret.data.size = size;
     700                } else {
     701                        /* Allocate buffer for subkeys */
     702                        char *names = (char *) malloc(size, FRAME_ATOMIC);
     703                        if (names == NULL)
     704                                return ret;
     705                       
     706                        size_t pos = 0;
     707                        for (sysinfo_item_t *cur = item->subtree.table; cur;
     708                            cur = cur->next) {
     709                                str_cpy(names + pos, size - pos, cur->name);
     710                                pos += str_size(cur->name) + 1;
     711                        }
     712                       
     713                        /* Correct return value */
     714                        ret.tag = SYSINFO_VAL_FUNCTION_DATA;
     715                        ret.data.data = (void *) names;
     716                        ret.data.size = size;
     717                }
     718        } else {
     719                /* No item in the fixed sysinfo tree */
     720                ret.tag = SYSINFO_VAL_UNDEFINED;
     721        }
     722       
     723        return ret;
     724}
     725
     726/** Return sysinfo keys determined by name from user space
     727 *
     728 * The path string passed from the user space has to be properly
     729 * null-terminated (the last passed character must be null).
     730 *
     731 * @param ptr     Sysinfo path in the user address space.
     732 * @param size    Size of the path string.
     733 * @param dry_run Do not actually get any generated
     734 *                binary data, just calculate the size.
     735 *
     736 */
     737NO_TRACE static sysinfo_return_t sysinfo_get_keys_uspace(void *ptr, size_t size,
     738    bool dry_run)
     739{
     740        sysinfo_return_t ret;
     741        ret.tag = SYSINFO_VAL_UNDEFINED;
     742       
     743        if (size > SYSINFO_MAX_PATH)
     744                return ret;
     745       
     746        char *path = (char *) malloc(size + 1, 0);
     747        ASSERT(path);
     748       
     749        if ((copy_from_uspace(path, ptr, size + 1) == 0) &&
     750            (path[size] == 0)) {
     751                /*
     752                 * Prevent other functions from messing with sysinfo while we
     753                 * are reading it.
     754                 */
     755                mutex_lock(&sysinfo_lock);
     756                ret = sysinfo_get_keys(path, NULL, dry_run);
     757                mutex_unlock(&sysinfo_lock);
     758        }
     759       
     760        free(path);
     761        return ret;
     762}
     763
     764/** Get the sysinfo keys size (syscall)
     765 *
     766 * The path string passed from the user space has
     767 * to be properly null-terminated (the last passed
     768 * character must be null).
     769 *
     770 * @param path_ptr  Sysinfo path in the user address space.
     771 * @param path_size Size of the path string.
     772 * @param size_ptr  User space pointer where to store the
     773 *                  keys size.
     774 *
     775 * @return Error code (EOK in case of no error).
     776 *
     777 */
     778sysarg_t sys_sysinfo_get_keys_size(void *path_ptr, size_t path_size,
     779    void *size_ptr)
     780{
     781        int rc;
     782       
     783        /*
     784         * Get the keys.
     785         *
     786         * N.B.: There is no need to free any potential keys
     787         * since we request a dry run.
     788         */
     789        sysinfo_return_t ret =
     790            sysinfo_get_keys_uspace(path_ptr, path_size, true);
     791       
     792        /* Check return data tag */
     793        if (ret.tag == SYSINFO_VAL_DATA)
     794                rc = copy_to_uspace(size_ptr, &ret.data.size,
     795                    sizeof(ret.data.size));
     796        else
     797                rc = EINVAL;
     798       
     799        return (sysarg_t) rc;
     800}
     801
     802/** Get the sysinfo keys (syscall)
     803 *
     804 * The path string passed from the user space has
     805 * to be properly null-terminated (the last passed
     806 * character must be null).
     807 *
     808 * If the user space buffer size does not equal
     809 * the actual size of the returned data, the data
     810 * is truncated.
     811 *
     812 * The actual size of data returned is stored to
     813 * size_ptr.
     814 *
     815 * @param path_ptr    Sysinfo path in the user address space.
     816 * @param path_size   Size of the path string.
     817 * @param buffer_ptr  User space pointer to the buffer where
     818 *                    to store the binary data.
     819 * @param buffer_size User space buffer size.
     820 * @param size_ptr    User space pointer where to store the
     821 *                    binary data size.
     822 *
     823 * @return Error code (EOK in case of no error).
     824 *
     825 */
     826sysarg_t sys_sysinfo_get_keys(void *path_ptr, size_t path_size,
     827    void *buffer_ptr, size_t buffer_size, size_t *size_ptr)
     828{
     829        int rc;
     830       
     831        /* Get the keys */
     832        sysinfo_return_t ret = sysinfo_get_keys_uspace(path_ptr, path_size,
     833            false);
     834       
     835        /* Check return data tag */
     836        if (ret.tag == SYSINFO_VAL_DATA) {
     837                size_t size = min(ret.data.size, buffer_size);
     838                rc = copy_to_uspace(buffer_ptr, ret.data.data, size);
     839                if (rc == EOK)
     840                        rc = copy_to_uspace(size_ptr, &size, sizeof(size));
     841               
     842                free(ret.data.data);
     843        } else
     844                rc = EINVAL;
     845       
     846        return (sysarg_t) rc;
     847}
     848
    655849/** Get the sysinfo value type (syscall)
    656850 *
Note: See TracChangeset for help on using the changeset viewer.