LCOV - code coverage report
Current view: top level - libudev - libudev-util.c (source / functions) Hit Total Coverage
Test: systemd test coverage Lines: 10 147 6.8 %
Date: 2015-07-29 18:47:03 Functions: 2 11 18.2 %

          Line data    Source code
       1             : /***
       2             :   This file is part of systemd.
       3             : 
       4             :   Copyright 2008-2012 Kay Sievers <kay@vrfy.org>
       5             : 
       6             :   systemd is free software; you can redistribute it and/or modify it
       7             :   under the terms of the GNU Lesser General Public License as published by
       8             :   the Free Software Foundation; either version 2.1 of the License, or
       9             :   (at your option) any later version.
      10             : 
      11             :   systemd is distributed in the hope that it will be useful, but
      12             :   WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
      14             :   Lesser General Public License for more details.
      15             : 
      16             :   You should have received a copy of the GNU Lesser General Public License
      17             :   along with systemd; If not, see <http://www.gnu.org/licenses/>.
      18             : ***/
      19             : 
      20             : #include <stdlib.h>
      21             : #include <stddef.h>
      22             : #include <unistd.h>
      23             : #include <errno.h>
      24             : #include <string.h>
      25             : #include <ctype.h>
      26             : 
      27             : #include "device-nodes.h"
      28             : #include "libudev.h"
      29             : #include "libudev-private.h"
      30             : #include "utf8.h"
      31             : #include "MurmurHash2.h"
      32             : 
      33             : /**
      34             :  * SECTION:libudev-util
      35             :  * @short_description: utils
      36             :  *
      37             :  * Utilities useful when dealing with devices and device node names.
      38             :  */
      39             : 
      40             : /* handle "[<SUBSYSTEM>/<KERNEL>]<attribute>" format */
      41           0 : int util_resolve_subsys_kernel(struct udev *udev, const char *string,
      42             :                                char *result, size_t maxsize, int read_value)
      43             : {
      44             :         char temp[UTIL_PATH_SIZE];
      45             :         char *subsys;
      46             :         char *sysname;
      47             :         struct udev_device *dev;
      48             :         char *attr;
      49             : 
      50           0 :         if (string[0] != '[')
      51           0 :                 return -1;
      52             : 
      53           0 :         strscpy(temp, sizeof(temp), string);
      54             : 
      55           0 :         subsys = &temp[1];
      56             : 
      57           0 :         sysname = strchr(subsys, '/');
      58           0 :         if (sysname == NULL)
      59           0 :                 return -1;
      60           0 :         sysname[0] = '\0';
      61           0 :         sysname = &sysname[1];
      62             : 
      63           0 :         attr = strchr(sysname, ']');
      64           0 :         if (attr == NULL)
      65           0 :                 return -1;
      66           0 :         attr[0] = '\0';
      67           0 :         attr = &attr[1];
      68           0 :         if (attr[0] == '/')
      69           0 :                 attr = &attr[1];
      70           0 :         if (attr[0] == '\0')
      71           0 :                 attr = NULL;
      72             : 
      73           0 :         if (read_value && attr == NULL)
      74           0 :                 return -1;
      75             : 
      76           0 :         dev = udev_device_new_from_subsystem_sysname(udev, subsys, sysname);
      77           0 :         if (dev == NULL)
      78           0 :                 return -1;
      79             : 
      80           0 :         if (read_value) {
      81             :                 const char *val;
      82             : 
      83           0 :                 val = udev_device_get_sysattr_value(dev, attr);
      84           0 :                 if (val != NULL)
      85           0 :                         strscpy(result, maxsize, val);
      86             :                 else
      87           0 :                         result[0] = '\0';
      88           0 :                 log_debug("value '[%s/%s]%s' is '%s'", subsys, sysname, attr, result);
      89             :         } else {
      90             :                 size_t l;
      91             :                 char *s;
      92             : 
      93           0 :                 s = result;
      94           0 :                 l = strpcpyl(&s, maxsize, udev_device_get_syspath(dev), NULL);
      95           0 :                 if (attr != NULL)
      96           0 :                         strpcpyl(&s, l, "/", attr, NULL);
      97           0 :                 log_debug("path '[%s/%s]%s' is '%s'", subsys, sysname, attr, result);
      98             :         }
      99           0 :         udev_device_unref(dev);
     100           0 :         return 0;
     101             : }
     102             : 
     103           0 : ssize_t util_get_sys_core_link_value(struct udev *udev, const char *slink, const char *syspath, char *value, size_t size)
     104             : {
     105             :         char path[UTIL_PATH_SIZE];
     106             :         char target[UTIL_PATH_SIZE];
     107             :         ssize_t len;
     108             :         const char *pos;
     109             : 
     110           0 :         strscpyl(path, sizeof(path), syspath, "/", slink, NULL);
     111           0 :         len = readlink(path, target, sizeof(target));
     112           0 :         if (len <= 0 || len == (ssize_t)sizeof(target))
     113           0 :                 return -1;
     114           0 :         target[len] = '\0';
     115           0 :         pos = strrchr(target, '/');
     116           0 :         if (pos == NULL)
     117           0 :                 return -1;
     118           0 :         pos = &pos[1];
     119           0 :         return strscpy(value, size, pos);
     120             : }
     121             : 
     122           0 : int util_resolve_sys_link(struct udev *udev, char *syspath, size_t size)
     123             : {
     124             :         char link_target[UTIL_PATH_SIZE];
     125             : 
     126             :         ssize_t len;
     127             :         int i;
     128             :         int back;
     129           0 :         char *base = NULL;
     130             : 
     131           0 :         len = readlink(syspath, link_target, sizeof(link_target));
     132           0 :         if (len <= 0 || len == (ssize_t)sizeof(link_target))
     133           0 :                 return -1;
     134           0 :         link_target[len] = '\0';
     135             : 
     136           0 :         for (back = 0; startswith(&link_target[back * 3], "../"); back++)
     137             :                 ;
     138           0 :         for (i = 0; i <= back; i++) {
     139           0 :                 base = strrchr(syspath, '/');
     140           0 :                 if (base == NULL)
     141           0 :                         return -EINVAL;
     142           0 :                 base[0] = '\0';
     143             :         }
     144             : 
     145           0 :         strscpyl(base, size - (base - syspath), "/", &link_target[back * 3], NULL);
     146           0 :         return 0;
     147             : }
     148             : 
     149           0 : int util_log_priority(const char *priority)
     150             : {
     151             :         char *endptr;
     152             :         int prio;
     153             : 
     154           0 :         prio = strtoul(priority, &endptr, 10);
     155           0 :         if (endptr[0] == '\0' || isspace(endptr[0])) {
     156           0 :                 if (prio >= 0 && prio <= 7)
     157           0 :                         return prio;
     158             :                 else
     159           0 :                         return -ERANGE;
     160             :         }
     161             : 
     162           0 :         return log_level_from_string(priority);
     163             : }
     164             : 
     165           0 : size_t util_path_encode(const char *src, char *dest, size_t size)
     166             : {
     167             :         size_t i, j;
     168             : 
     169           0 :         for (i = 0, j = 0; src[i] != '\0'; i++) {
     170           0 :                 if (src[i] == '/') {
     171           0 :                         if (j+4 >= size) {
     172           0 :                                 j = 0;
     173           0 :                                 break;
     174             :                         }
     175           0 :                         memcpy(&dest[j], "\\x2f", 4);
     176           0 :                         j += 4;
     177           0 :                 } else if (src[i] == '\\') {
     178           0 :                         if (j+4 >= size) {
     179           0 :                                 j = 0;
     180           0 :                                 break;
     181             :                         }
     182           0 :                         memcpy(&dest[j], "\\x5c", 4);
     183           0 :                         j += 4;
     184             :                 } else {
     185           0 :                         if (j+1 >= size) {
     186           0 :                                 j = 0;
     187           0 :                                 break;
     188             :                         }
     189           0 :                         dest[j] = src[i];
     190           0 :                         j++;
     191             :                 }
     192             :         }
     193           0 :         dest[j] = '\0';
     194           0 :         return j;
     195             : }
     196             : 
     197           0 : void util_remove_trailing_chars(char *path, char c)
     198             : {
     199             :         size_t len;
     200             : 
     201           0 :         if (path == NULL)
     202           0 :                 return;
     203           0 :         len = strlen(path);
     204           0 :         while (len > 0 && path[len-1] == c)
     205           0 :                 path[--len] = '\0';
     206             : }
     207             : 
     208           0 : int util_replace_whitespace(const char *str, char *to, size_t len)
     209             : {
     210             :         size_t i, j;
     211             : 
     212             :         /* strip trailing whitespace */
     213           0 :         len = strnlen(str, len);
     214           0 :         while (len && isspace(str[len-1]))
     215           0 :                 len--;
     216             : 
     217             :         /* strip leading whitespace */
     218           0 :         i = 0;
     219           0 :         while ((i < len) && isspace(str[i]))
     220           0 :                 i++;
     221             : 
     222           0 :         j = 0;
     223           0 :         while (i < len) {
     224             :                 /* substitute multiple whitespace with a single '_' */
     225           0 :                 if (isspace(str[i])) {
     226           0 :                         while (isspace(str[i]))
     227           0 :                                 i++;
     228           0 :                         to[j++] = '_';
     229             :                 }
     230           0 :                 to[j++] = str[i++];
     231             :         }
     232           0 :         to[j] = '\0';
     233           0 :         return 0;
     234             : }
     235             : 
     236             : /* allow chars in whitelist, plain ascii, hex-escaping and valid utf8 */
     237           0 : int util_replace_chars(char *str, const char *white)
     238             : {
     239           0 :         size_t i = 0;
     240           0 :         int replaced = 0;
     241             : 
     242           0 :         while (str[i] != '\0') {
     243             :                 int len;
     244             : 
     245           0 :                 if (whitelisted_char_for_devnode(str[i], white)) {
     246           0 :                         i++;
     247           0 :                         continue;
     248             :                 }
     249             : 
     250             :                 /* accept hex encoding */
     251           0 :                 if (str[i] == '\\' && str[i+1] == 'x') {
     252           0 :                         i += 2;
     253           0 :                         continue;
     254             :                 }
     255             : 
     256             :                 /* accept valid utf8 */
     257           0 :                 len = utf8_encoded_valid_unichar(&str[i]);
     258           0 :                 if (len > 1) {
     259           0 :                         i += len;
     260           0 :                         continue;
     261             :                 }
     262             : 
     263             :                 /* if space is allowed, replace whitespace with ordinary space */
     264           0 :                 if (isspace(str[i]) && white != NULL && strchr(white, ' ') != NULL) {
     265           0 :                         str[i] = ' ';
     266           0 :                         i++;
     267           0 :                         replaced++;
     268           0 :                         continue;
     269             :                 }
     270             : 
     271             :                 /* everything else is replaced with '_' */
     272           0 :                 str[i] = '_';
     273           0 :                 i++;
     274           0 :                 replaced++;
     275             :         }
     276           0 :         return replaced;
     277             : }
     278             : 
     279             : /**
     280             :  * udev_util_encode_string:
     281             :  * @str: input string to be encoded
     282             :  * @str_enc: output string to store the encoded input string
     283             :  * @len: maximum size of the output string, which may be
     284             :  *       four times as long as the input string
     285             :  *
     286             :  * Encode all potentially unsafe characters of a string to the
     287             :  * corresponding 2 char hex value prefixed by '\x'.
     288             :  *
     289             :  * Returns: 0 if the entire string was copied, non-zero otherwise.
     290             :  **/
     291           0 : _public_ int udev_util_encode_string(const char *str, char *str_enc, size_t len)
     292             : {
     293           0 :         return encode_devnode_name(str, str_enc, len);
     294             : }
     295             : 
     296          11 : unsigned int util_string_hash32(const char *str)
     297             : {
     298          11 :         return MurmurHash2(str, strlen(str), 0);
     299             : }
     300             : 
     301             : /* get a bunch of bit numbers out of the hash, and set the bits in our bit field */
     302          10 : uint64_t util_string_bloom64(const char *str)
     303             : {
     304          10 :         uint64_t bits = 0;
     305          10 :         unsigned int hash = util_string_hash32(str);
     306             : 
     307          10 :         bits |= 1LLU << (hash & 63);
     308          10 :         bits |= 1LLU << ((hash >> 6) & 63);
     309          10 :         bits |= 1LLU << ((hash >> 12) & 63);
     310          10 :         bits |= 1LLU << ((hash >> 18) & 63);
     311          10 :         return bits;
     312             : }

Generated by: LCOV version 1.11