LCOV - code coverage report
Current view: top level - libsystemd/sd-device - device-private.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 19 581 3.3 %
Date: 2019-08-22 15:41:25 Functions: 6 46 13.0 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: LGPL-2.1+ */
       2             : 
       3             : #include <ctype.h>
       4             : #include <net/if.h>
       5             : #include <sys/types.h>
       6             : 
       7             : #include "sd-device.h"
       8             : 
       9             : #include "alloc-util.h"
      10             : #include "device-internal.h"
      11             : #include "device-private.h"
      12             : #include "device-util.h"
      13             : #include "fd-util.h"
      14             : #include "fileio.h"
      15             : #include "fs-util.h"
      16             : #include "hashmap.h"
      17             : #include "macro.h"
      18             : #include "mkdir.h"
      19             : #include "nulstr-util.h"
      20             : #include "parse-util.h"
      21             : #include "path-util.h"
      22             : #include "set.h"
      23             : #include "string-table.h"
      24             : #include "string-util.h"
      25             : #include "strv.h"
      26             : #include "strxcpyx.h"
      27             : #include "tmpfile-util.h"
      28             : #include "user-util.h"
      29             : 
      30           0 : int device_add_property(sd_device *device, const char *key, const char *value) {
      31             :         int r;
      32             : 
      33           0 :         assert(device);
      34           0 :         assert(key);
      35             : 
      36           0 :         r = device_add_property_aux(device, key, value, false);
      37           0 :         if (r < 0)
      38           0 :                 return r;
      39             : 
      40           0 :         if (key[0] != '.') {
      41           0 :                 r = device_add_property_aux(device, key, value, true);
      42           0 :                 if (r < 0)
      43           0 :                         return r;
      44             :         }
      45             : 
      46           0 :         return 0;
      47             : }
      48             : 
      49           0 : void device_set_devlink_priority(sd_device *device, int priority) {
      50           0 :         assert(device);
      51             : 
      52           0 :         device->devlink_priority = priority;
      53           0 : }
      54             : 
      55           0 : void device_set_is_initialized(sd_device *device) {
      56           0 :         assert(device);
      57             : 
      58           0 :         device->is_initialized = true;
      59           0 : }
      60             : 
      61           0 : int device_ensure_usec_initialized(sd_device *device, sd_device *device_old) {
      62             :         usec_t when;
      63             : 
      64           0 :         assert(device);
      65             : 
      66           0 :         if (device_old && device_old->usec_initialized > 0)
      67           0 :                 when = device_old->usec_initialized;
      68             :         else
      69           0 :                 when = now(CLOCK_MONOTONIC);
      70             : 
      71           0 :         return device_set_usec_initialized(device, when);
      72             : }
      73             : 
      74          17 : uint64_t device_get_properties_generation(sd_device *device) {
      75          17 :         assert(device);
      76             : 
      77          17 :         return device->properties_generation;
      78             : }
      79             : 
      80           0 : uint64_t device_get_tags_generation(sd_device *device) {
      81           0 :         assert(device);
      82             : 
      83           0 :         return device->tags_generation;
      84             : }
      85             : 
      86          15 : uint64_t device_get_devlinks_generation(sd_device *device) {
      87          15 :         assert(device);
      88             : 
      89          15 :         return device->devlinks_generation;
      90             : }
      91             : 
      92           0 : int device_get_devnode_mode(sd_device *device, mode_t *mode) {
      93             :         int r;
      94             : 
      95           0 :         assert(device);
      96             : 
      97           0 :         r = device_read_db(device);
      98           0 :         if (r < 0)
      99           0 :                 return r;
     100             : 
     101           0 :         if (device->devmode == (mode_t) -1)
     102           0 :                 return -ENOENT;
     103             : 
     104           0 :         if (mode)
     105           0 :                 *mode = device->devmode;
     106             : 
     107           0 :         return 0;
     108             : }
     109             : 
     110           0 : int device_get_devnode_uid(sd_device *device, uid_t *uid) {
     111             :         int r;
     112             : 
     113           0 :         assert(device);
     114             : 
     115           0 :         r = device_read_db(device);
     116           0 :         if (r < 0)
     117           0 :                 return r;
     118             : 
     119           0 :         if (device->devuid == (uid_t) -1)
     120           0 :                 return -ENOENT;
     121             : 
     122           0 :         if (uid)
     123           0 :                 *uid = device->devuid;
     124             : 
     125           0 :         return 0;
     126             : }
     127             : 
     128           0 : static int device_set_devuid(sd_device *device, const char *uid) {
     129             :         unsigned u;
     130             :         int r;
     131             : 
     132           0 :         assert(device);
     133           0 :         assert(uid);
     134             : 
     135           0 :         r = safe_atou(uid, &u);
     136           0 :         if (r < 0)
     137           0 :                 return r;
     138             : 
     139           0 :         r = device_add_property_internal(device, "DEVUID", uid);
     140           0 :         if (r < 0)
     141           0 :                 return r;
     142             : 
     143           0 :         device->devuid = u;
     144             : 
     145           0 :         return 0;
     146             : }
     147             : 
     148           0 : int device_get_devnode_gid(sd_device *device, gid_t *gid) {
     149             :         int r;
     150             : 
     151           0 :         assert(device);
     152             : 
     153           0 :         r = device_read_db(device);
     154           0 :         if (r < 0)
     155           0 :                 return r;
     156             : 
     157           0 :         if (device->devgid == (gid_t) -1)
     158           0 :                 return -ENOENT;
     159             : 
     160           0 :         if (gid)
     161           0 :                 *gid = device->devgid;
     162             : 
     163           0 :         return 0;
     164             : }
     165             : 
     166           0 : static int device_set_devgid(sd_device *device, const char *gid) {
     167             :         unsigned g;
     168             :         int r;
     169             : 
     170           0 :         assert(device);
     171           0 :         assert(gid);
     172             : 
     173           0 :         r = safe_atou(gid, &g);
     174           0 :         if (r < 0)
     175           0 :                 return r;
     176             : 
     177           0 :         r = device_add_property_internal(device, "DEVGID", gid);
     178           0 :         if (r < 0)
     179           0 :                 return r;
     180             : 
     181           0 :         device->devgid = g;
     182             : 
     183           0 :         return 0;
     184             : }
     185             : 
     186           8 : int device_get_action(sd_device *device, DeviceAction *action) {
     187           8 :         assert(device);
     188             : 
     189           8 :         if (device->action < 0)
     190           8 :                 return -ENOENT;
     191             : 
     192           0 :         if (action)
     193           0 :                 *action = device->action;
     194             : 
     195           0 :         return 0;
     196             : }
     197             : 
     198           0 : static int device_set_action(sd_device *device, const char *action) {
     199             :         DeviceAction a;
     200             :         int r;
     201             : 
     202           0 :         assert(device);
     203           0 :         assert(action);
     204             : 
     205           0 :         a = device_action_from_string(action);
     206           0 :         if (a < 0)
     207           0 :                 return -EINVAL;
     208             : 
     209           0 :         r = device_add_property_internal(device, "ACTION", action);
     210           0 :         if (r < 0)
     211           0 :                 return r;
     212             : 
     213           0 :         device->action = a;
     214             : 
     215           0 :         return 0;
     216             : }
     217             : 
     218           0 : int device_get_seqnum(sd_device *device, uint64_t *seqnum) {
     219           0 :         assert(device);
     220             : 
     221           0 :         if (device->seqnum == 0)
     222           0 :                 return -ENOENT;
     223             : 
     224           0 :         if (seqnum)
     225           0 :                 *seqnum = device->seqnum;
     226             : 
     227           0 :         return 0;
     228             : }
     229             : 
     230           0 : static int device_set_seqnum(sd_device *device, const char *str) {
     231             :         uint64_t seqnum;
     232             :         int r;
     233             : 
     234           0 :         assert(device);
     235           0 :         assert(str);
     236             : 
     237           0 :         r = safe_atou64(str, &seqnum);
     238           0 :         if (r < 0)
     239           0 :                 return r;
     240           0 :         if (seqnum == 0)
     241           0 :                 return -EINVAL;
     242             : 
     243           0 :         r = device_add_property_internal(device, "SEQNUM", str);
     244           0 :         if (r < 0)
     245           0 :                 return r;
     246             : 
     247           0 :         device->seqnum = seqnum;
     248             : 
     249           0 :         return 0;
     250             : }
     251             : 
     252           0 : static int device_amend(sd_device *device, const char *key, const char *value) {
     253             :         int r;
     254             : 
     255           0 :         assert(device);
     256           0 :         assert(key);
     257           0 :         assert(value);
     258             : 
     259           0 :         if (streq(key, "DEVPATH")) {
     260             :                 char *path;
     261             : 
     262           0 :                 path = strjoina("/sys", value);
     263             : 
     264             :                 /* the caller must verify or trust this data (e.g., if it comes from the kernel) */
     265           0 :                 r = device_set_syspath(device, path, false);
     266           0 :                 if (r < 0)
     267           0 :                         return log_device_debug_errno(device, r, "sd-device: Failed to set syspath to '%s': %m", path);
     268           0 :         } else if (streq(key, "SUBSYSTEM")) {
     269           0 :                 r = device_set_subsystem(device, value);
     270           0 :                 if (r < 0)
     271           0 :                         return log_device_debug_errno(device, r, "sd-device: Failed to set subsystem to '%s': %m", value);
     272           0 :         } else if (streq(key, "DEVTYPE")) {
     273           0 :                 r = device_set_devtype(device, value);
     274           0 :                 if (r < 0)
     275           0 :                         return log_device_debug_errno(device, r, "sd-device: Failed to set devtype to '%s': %m", value);
     276           0 :         } else if (streq(key, "DEVNAME")) {
     277           0 :                 r = device_set_devname(device, value);
     278           0 :                 if (r < 0)
     279           0 :                         return log_device_debug_errno(device, r, "sd-device: Failed to set devname to '%s': %m", value);
     280           0 :         } else if (streq(key, "USEC_INITIALIZED")) {
     281             :                 usec_t t;
     282             : 
     283           0 :                 r = safe_atou64(value, &t);
     284           0 :                 if (r < 0)
     285           0 :                         return log_device_debug_errno(device, r, "sd-device: Failed to parse timestamp '%s': %m", value);
     286             : 
     287           0 :                 r = device_set_usec_initialized(device, t);
     288           0 :                 if (r < 0)
     289           0 :                         return log_device_debug_errno(device, r, "sd-device: Failed to set usec-initialized to '%s': %m", value);
     290           0 :         } else if (streq(key, "DRIVER")) {
     291           0 :                 r = device_set_driver(device, value);
     292           0 :                 if (r < 0)
     293           0 :                         return log_device_debug_errno(device, r, "sd-device: Failed to set driver to '%s': %m", value);
     294           0 :         } else if (streq(key, "IFINDEX")) {
     295           0 :                 r = device_set_ifindex(device, value);
     296           0 :                 if (r < 0)
     297           0 :                         return log_device_debug_errno(device, r, "sd-device: Failed to set ifindex to '%s': %m", value);
     298           0 :         } else if (streq(key, "DEVMODE")) {
     299           0 :                 r = device_set_devmode(device, value);
     300           0 :                 if (r < 0)
     301           0 :                         return log_device_debug_errno(device, r, "sd-device: Failed to set devmode to '%s': %m", value);
     302           0 :         } else if (streq(key, "DEVUID")) {
     303           0 :                 r = device_set_devuid(device, value);
     304           0 :                 if (r < 0)
     305           0 :                         return log_device_debug_errno(device, r, "sd-device: Failed to set devuid to '%s': %m", value);
     306           0 :         } else if (streq(key, "DEVGID")) {
     307           0 :                 r = device_set_devgid(device, value);
     308           0 :                 if (r < 0)
     309           0 :                         return log_device_debug_errno(device, r, "sd-device: Failed to set devgid to '%s': %m", value);
     310           0 :         } else if (streq(key, "ACTION")) {
     311           0 :                 r = device_set_action(device, value);
     312           0 :                 if (r < 0)
     313           0 :                         return log_device_debug_errno(device, r, "sd-device: Failed to set action to '%s': %m", value);
     314           0 :         } else if (streq(key, "SEQNUM")) {
     315           0 :                 r = device_set_seqnum(device, value);
     316           0 :                 if (r < 0)
     317           0 :                         return log_device_debug_errno(device, r, "sd-device: Failed to set SEQNUM to '%s': %m", value);
     318           0 :         } else if (streq(key, "DEVLINKS")) {
     319             :                 const char *word, *state;
     320             :                 size_t l;
     321             : 
     322           0 :                 FOREACH_WORD(word, l, value, state) {
     323           0 :                         char devlink[l + 1];
     324             : 
     325           0 :                         strncpy(devlink, word, l);
     326           0 :                         devlink[l] = '\0';
     327             : 
     328           0 :                         r = device_add_devlink(device, devlink);
     329           0 :                         if (r < 0)
     330           0 :                                 return log_device_debug_errno(device, r, "sd-device: Failed to add devlink '%s': %m", devlink);
     331             :                 }
     332           0 :         } else if (streq(key, "TAGS")) {
     333             :                 const char *word, *state;
     334             :                 size_t l;
     335             : 
     336           0 :                 FOREACH_WORD_SEPARATOR(word, l, value, ":", state) {
     337           0 :                         char tag[l + 1];
     338             : 
     339           0 :                         (void) strncpy(tag, word, l);
     340           0 :                         tag[l] = '\0';
     341             : 
     342           0 :                         r = device_add_tag(device, tag);
     343           0 :                         if (r < 0)
     344           0 :                                 return log_device_debug_errno(device, r, "sd-device: Failed to add tag '%s': %m", tag);
     345             :                 }
     346             :         } else {
     347           0 :                 r = device_add_property_internal(device, key, value);
     348           0 :                 if (r < 0)
     349           0 :                         return log_device_debug_errno(device, r, "sd-device: Failed to add property '%s=%s': %m", key, value);
     350             :         }
     351             : 
     352           0 :         return 0;
     353             : }
     354             : 
     355           0 : static int device_append(sd_device *device, char *key, const char **_major, const char **_minor) {
     356           0 :         const char *major = NULL, *minor = NULL;
     357             :         char *value;
     358             :         int r;
     359             : 
     360           0 :         assert(device);
     361           0 :         assert(key);
     362           0 :         assert(_major);
     363           0 :         assert(_minor);
     364             : 
     365           0 :         value = strchr(key, '=');
     366           0 :         if (!value) {
     367           0 :                 log_device_debug(device, "sd-device: Not a key-value pair: '%s'", key);
     368           0 :                 return -EINVAL;
     369             :         }
     370             : 
     371           0 :         *value = '\0';
     372             : 
     373           0 :         value++;
     374             : 
     375           0 :         if (streq(key, "MAJOR"))
     376           0 :                 major = value;
     377           0 :         else if (streq(key, "MINOR"))
     378           0 :                 minor = value;
     379             :         else {
     380           0 :                 r = device_amend(device, key, value);
     381           0 :                 if (r < 0)
     382           0 :                         return r;
     383             :         }
     384             : 
     385           0 :         if (major != 0)
     386           0 :                 *_major = major;
     387             : 
     388           0 :         if (minor != 0)
     389           0 :                 *_minor = minor;
     390             : 
     391           0 :         return 0;
     392             : }
     393             : 
     394           0 : void device_seal(sd_device *device) {
     395           0 :         assert(device);
     396             : 
     397           0 :         device->sealed = true;
     398           0 : }
     399             : 
     400           0 : static int device_verify(sd_device *device) {
     401           0 :         assert(device);
     402             : 
     403           0 :         if (!device->devpath || !device->subsystem || device->action < 0 || device->seqnum == 0) {
     404           0 :                 log_device_debug(device, "sd-device: Device created from strv or nulstr lacks devpath, subsystem, action or seqnum.");
     405           0 :                 return -EINVAL;
     406             :         }
     407             : 
     408           0 :         device->sealed = true;
     409             : 
     410           0 :         return 0;
     411             : }
     412             : 
     413           0 : int device_new_from_strv(sd_device **ret, char **strv) {
     414           0 :         _cleanup_(sd_device_unrefp) sd_device *device = NULL;
     415             :         char **key;
     416           0 :         const char *major = NULL, *minor = NULL;
     417             :         int r;
     418             : 
     419           0 :         assert(ret);
     420           0 :         assert(strv);
     421             : 
     422           0 :         r = device_new_aux(&device);
     423           0 :         if (r < 0)
     424           0 :                 return r;
     425             : 
     426           0 :         STRV_FOREACH(key, strv) {
     427           0 :                 r = device_append(device, *key, &major, &minor);
     428           0 :                 if (r < 0)
     429           0 :                         return r;
     430             :         }
     431             : 
     432           0 :         if (major) {
     433           0 :                 r = device_set_devnum(device, major, minor);
     434           0 :                 if (r < 0)
     435           0 :                         return log_device_debug_errno(device, r, "sd-device: Failed to set devnum %s:%s: %m", major, minor);
     436             :         }
     437             : 
     438           0 :         r = device_verify(device);
     439           0 :         if (r < 0)
     440           0 :                 return r;
     441             : 
     442           0 :         *ret = TAKE_PTR(device);
     443             : 
     444           0 :         return 0;
     445             : }
     446             : 
     447           0 : int device_new_from_nulstr(sd_device **ret, uint8_t *nulstr, size_t len) {
     448           0 :         _cleanup_(sd_device_unrefp) sd_device *device = NULL;
     449           0 :         const char *major = NULL, *minor = NULL;
     450           0 :         unsigned i = 0;
     451             :         int r;
     452             : 
     453           0 :         assert(ret);
     454           0 :         assert(nulstr);
     455           0 :         assert(len);
     456             : 
     457           0 :         r = device_new_aux(&device);
     458           0 :         if (r < 0)
     459           0 :                 return r;
     460             : 
     461           0 :         while (i < len) {
     462             :                 char *key;
     463             :                 const char *end;
     464             : 
     465           0 :                 key = (char*)&nulstr[i];
     466           0 :                 end = memchr(key, '\0', len - i);
     467           0 :                 if (!end) {
     468           0 :                         log_device_debug(device, "sd-device: Failed to parse nulstr");
     469           0 :                         return -EINVAL;
     470             :                 }
     471           0 :                 i += end - key + 1;
     472             : 
     473           0 :                 r = device_append(device, key, &major, &minor);
     474           0 :                 if (r < 0)
     475           0 :                         return r;
     476             :         }
     477             : 
     478           0 :         if (major) {
     479           0 :                 r = device_set_devnum(device, major, minor);
     480           0 :                 if (r < 0)
     481           0 :                         return log_device_debug_errno(device, r, "sd-device: Failed to set devnum %s:%s: %m", major, minor);
     482             :         }
     483             : 
     484           0 :         r = device_verify(device);
     485           0 :         if (r < 0)
     486           0 :                 return r;
     487             : 
     488           0 :         *ret = TAKE_PTR(device);
     489             : 
     490           0 :         return 0;
     491             : }
     492             : 
     493           0 : static int device_update_properties_bufs(sd_device *device) {
     494             :         const char *val, *prop;
     495           0 :         _cleanup_free_ char **buf_strv = NULL;
     496           0 :         _cleanup_free_ uint8_t *buf_nulstr = NULL;
     497           0 :         size_t allocated_nulstr = 0;
     498           0 :         size_t nulstr_len = 0, num = 0, i = 0;
     499             : 
     500           0 :         assert(device);
     501             : 
     502           0 :         if (!device->properties_buf_outdated)
     503           0 :                 return 0;
     504             : 
     505           0 :         FOREACH_DEVICE_PROPERTY(device, prop, val) {
     506           0 :                 size_t len = 0;
     507             : 
     508           0 :                 len = strlen(prop) + 1 + strlen(val);
     509             : 
     510           0 :                 buf_nulstr = GREEDY_REALLOC0(buf_nulstr, allocated_nulstr, nulstr_len + len + 2);
     511           0 :                 if (!buf_nulstr)
     512           0 :                         return -ENOMEM;
     513             : 
     514           0 :                 strscpyl((char *)buf_nulstr + nulstr_len, len + 1, prop, "=", val, NULL);
     515           0 :                 nulstr_len += len + 1;
     516           0 :                 ++num;
     517             :         }
     518             : 
     519             :         /* build buf_strv from buf_nulstr */
     520           0 :         buf_strv = new0(char *, num + 1);
     521           0 :         if (!buf_strv)
     522           0 :                 return -ENOMEM;
     523             : 
     524           0 :         NULSTR_FOREACH(val, (char*) buf_nulstr) {
     525           0 :                 buf_strv[i] = (char *) val;
     526           0 :                 assert(i < num);
     527           0 :                 i++;
     528             :         }
     529             : 
     530           0 :         free_and_replace(device->properties_nulstr, buf_nulstr);
     531           0 :         device->properties_nulstr_len = nulstr_len;
     532           0 :         free_and_replace(device->properties_strv, buf_strv);
     533             : 
     534           0 :         device->properties_buf_outdated = false;
     535             : 
     536           0 :         return 0;
     537             : }
     538             : 
     539           0 : int device_get_properties_nulstr(sd_device *device, const uint8_t **nulstr, size_t *len) {
     540             :         int r;
     541             : 
     542           0 :         assert(device);
     543           0 :         assert(nulstr);
     544           0 :         assert(len);
     545             : 
     546           0 :         r = device_update_properties_bufs(device);
     547           0 :         if (r < 0)
     548           0 :                 return r;
     549             : 
     550           0 :         *nulstr = device->properties_nulstr;
     551           0 :         *len = device->properties_nulstr_len;
     552             : 
     553           0 :         return 0;
     554             : }
     555             : 
     556           0 : int device_get_properties_strv(sd_device *device, char ***strv) {
     557             :         int r;
     558             : 
     559           0 :         assert(device);
     560           0 :         assert(strv);
     561             : 
     562           0 :         r = device_update_properties_bufs(device);
     563           0 :         if (r < 0)
     564           0 :                 return r;
     565             : 
     566           0 :         *strv = device->properties_strv;
     567             : 
     568           0 :         return 0;
     569             : }
     570             : 
     571           0 : int device_get_devlink_priority(sd_device *device, int *priority) {
     572             :         int r;
     573             : 
     574           0 :         assert(device);
     575           0 :         assert(priority);
     576             : 
     577           0 :         r = device_read_db(device);
     578           0 :         if (r < 0)
     579           0 :                 return r;
     580             : 
     581           0 :         *priority = device->devlink_priority;
     582             : 
     583           0 :         return 0;
     584             : }
     585             : 
     586           0 : int device_get_watch_handle(sd_device *device, int *handle) {
     587             :         int r;
     588             : 
     589           0 :         assert(device);
     590             : 
     591           0 :         r = device_read_db(device);
     592           0 :         if (r < 0)
     593           0 :                 return r;
     594             : 
     595           0 :         if (device->watch_handle < 0)
     596           0 :                 return -ENOENT;
     597             : 
     598           0 :         if (handle)
     599           0 :                 *handle = device->watch_handle;
     600             : 
     601           0 :         return 0;
     602             : }
     603             : 
     604           0 : void device_set_watch_handle(sd_device *device, int handle) {
     605           0 :         assert(device);
     606             : 
     607           0 :         device->watch_handle = handle;
     608           0 : }
     609             : 
     610           0 : int device_rename(sd_device *device, const char *name) {
     611           0 :         _cleanup_free_ char *dirname = NULL;
     612             :         const char *new_syspath, *interface;
     613             :         int r;
     614             : 
     615           0 :         assert(device);
     616           0 :         assert(name);
     617             : 
     618           0 :         dirname = dirname_malloc(device->syspath);
     619           0 :         if (!dirname)
     620           0 :                 return -ENOMEM;
     621             : 
     622           0 :         new_syspath = prefix_roota(dirname, name);
     623             : 
     624             :         /* the user must trust that the new name is correct */
     625           0 :         r = device_set_syspath(device, new_syspath, false);
     626           0 :         if (r < 0)
     627           0 :                 return r;
     628             : 
     629           0 :         r = sd_device_get_property_value(device, "INTERFACE", &interface);
     630           0 :         if (r >= 0) {
     631             :                 /* like DEVPATH_OLD, INTERFACE_OLD is not saved to the db, but only stays around for the current event */
     632           0 :                 r = device_add_property_internal(device, "INTERFACE_OLD", interface);
     633           0 :                 if (r < 0)
     634           0 :                         return r;
     635             : 
     636           0 :                 r = device_add_property_internal(device, "INTERFACE", name);
     637           0 :                 if (r < 0)
     638           0 :                         return r;
     639           0 :         } else if (r != -ENOENT)
     640           0 :                 return r;
     641             : 
     642           0 :         return 0;
     643             : }
     644             : 
     645           0 : int device_shallow_clone(sd_device *old_device, sd_device **new_device) {
     646           0 :         _cleanup_(sd_device_unrefp) sd_device *ret = NULL;
     647             :         int r;
     648             : 
     649           0 :         assert(old_device);
     650           0 :         assert(new_device);
     651             : 
     652           0 :         r = device_new_aux(&ret);
     653           0 :         if (r < 0)
     654           0 :                 return r;
     655             : 
     656           0 :         r = device_set_syspath(ret, old_device->syspath, false);
     657           0 :         if (r < 0)
     658           0 :                 return r;
     659             : 
     660           0 :         r = device_set_subsystem(ret, old_device->subsystem);
     661           0 :         if (r < 0)
     662           0 :                 return r;
     663             : 
     664           0 :         ret->devnum = old_device->devnum;
     665             : 
     666           0 :         *new_device = TAKE_PTR(ret);
     667             : 
     668           0 :         return 0;
     669             : }
     670             : 
     671           0 : int device_clone_with_db(sd_device *old_device, sd_device **new_device) {
     672           0 :         _cleanup_(sd_device_unrefp) sd_device *ret = NULL;
     673             :         int r;
     674             : 
     675           0 :         assert(old_device);
     676           0 :         assert(new_device);
     677             : 
     678           0 :         r = device_shallow_clone(old_device, &ret);
     679           0 :         if (r < 0)
     680           0 :                 return r;
     681             : 
     682           0 :         r = device_read_db(ret);
     683           0 :         if (r < 0)
     684           0 :                 return r;
     685             : 
     686           0 :         ret->sealed = true;
     687             : 
     688           0 :         *new_device = TAKE_PTR(ret);
     689             : 
     690           0 :         return 0;
     691             : }
     692             : 
     693           0 : int device_new_from_synthetic_event(sd_device **new_device, const char *syspath, const char *action) {
     694           0 :         _cleanup_(sd_device_unrefp) sd_device *ret = NULL;
     695             :         int r;
     696             : 
     697           0 :         assert(new_device);
     698           0 :         assert(syspath);
     699           0 :         assert(action);
     700             : 
     701           0 :         r = sd_device_new_from_syspath(&ret, syspath);
     702           0 :         if (r < 0)
     703           0 :                 return r;
     704             : 
     705           0 :         r = device_read_uevent_file(ret);
     706           0 :         if (r < 0)
     707           0 :                 return r;
     708             : 
     709           0 :         r = device_set_action(ret, action);
     710           0 :         if (r < 0)
     711           0 :                 return r;
     712             : 
     713           0 :         *new_device = TAKE_PTR(ret);
     714             : 
     715           0 :         return 0;
     716             : }
     717             : 
     718         132 : int device_new_from_stat_rdev(sd_device **ret, const struct stat *st) {
     719             :         char type;
     720             : 
     721         132 :         assert(ret);
     722         132 :         assert(st);
     723             : 
     724         132 :         if (S_ISBLK(st->st_mode))
     725         121 :                 type = 'b';
     726          11 :         else if (S_ISCHR(st->st_mode))
     727          11 :                 type = 'c';
     728             :         else
     729           0 :                 return -ENOTTY;
     730             : 
     731         132 :         return sd_device_new_from_devnum(ret, type, st->st_rdev);
     732             : }
     733             : 
     734           0 : int device_copy_properties(sd_device *device_dst, sd_device *device_src) {
     735             :         const char *property, *value;
     736             :         Iterator i;
     737             :         int r;
     738             : 
     739           0 :         assert(device_dst);
     740           0 :         assert(device_src);
     741             : 
     742           0 :         r = device_properties_prepare(device_src);
     743           0 :         if (r < 0)
     744           0 :                 return r;
     745             : 
     746           0 :         ORDERED_HASHMAP_FOREACH_KEY(value, property, device_src->properties_db, i) {
     747           0 :                 r = device_add_property_aux(device_dst, property, value, true);
     748           0 :                 if (r < 0)
     749           0 :                         return r;
     750             :         }
     751             : 
     752           0 :         ORDERED_HASHMAP_FOREACH_KEY(value, property, device_src->properties, i) {
     753           0 :                 r = device_add_property_aux(device_dst, property, value, false);
     754           0 :                 if (r < 0)
     755           0 :                         return r;
     756             :         }
     757             : 
     758           0 :         return 0;
     759             : }
     760             : 
     761           0 : void device_cleanup_tags(sd_device *device) {
     762           0 :         assert(device);
     763             : 
     764           0 :         set_free_free(device->tags);
     765           0 :         device->tags = NULL;
     766           0 :         device->property_tags_outdated = true;
     767           0 :         device->tags_generation++;
     768           0 : }
     769             : 
     770           0 : void device_cleanup_devlinks(sd_device *device) {
     771           0 :         assert(device);
     772             : 
     773           0 :         set_free_free(device->devlinks);
     774           0 :         device->devlinks = NULL;
     775           0 :         device->property_devlinks_outdated = true;
     776           0 :         device->devlinks_generation++;
     777           0 : }
     778             : 
     779           0 : void device_remove_tag(sd_device *device, const char *tag) {
     780           0 :         assert(device);
     781           0 :         assert(tag);
     782             : 
     783           0 :         free(set_remove(device->tags, tag));
     784           0 :         device->property_tags_outdated = true;
     785           0 :         device->tags_generation++;
     786           0 : }
     787             : 
     788           0 : static int device_tag(sd_device *device, const char *tag, bool add) {
     789             :         const char *id;
     790             :         char *path;
     791             :         int r;
     792             : 
     793           0 :         assert(device);
     794           0 :         assert(tag);
     795             : 
     796           0 :         r = device_get_id_filename(device, &id);
     797           0 :         if (r < 0)
     798           0 :                 return r;
     799             : 
     800           0 :         path = strjoina("/run/udev/tags/", tag, "/", id);
     801             : 
     802           0 :         if (add) {
     803           0 :                 r = touch_file(path, true, USEC_INFINITY, UID_INVALID, GID_INVALID, 0444);
     804           0 :                 if (r < 0)
     805           0 :                         return r;
     806             :         } else {
     807           0 :                 r = unlink(path);
     808           0 :                 if (r < 0 && errno != ENOENT)
     809           0 :                         return -errno;
     810             :         }
     811             : 
     812           0 :         return 0;
     813             : }
     814             : 
     815           0 : int device_tag_index(sd_device *device, sd_device *device_old, bool add) {
     816             :         const char *tag;
     817           0 :         int r = 0, k;
     818             : 
     819           0 :         if (add && device_old) {
     820             :                 /* delete possible left-over tags */
     821           0 :                 FOREACH_DEVICE_TAG(device_old, tag) {
     822           0 :                         if (!sd_device_has_tag(device, tag)) {
     823           0 :                                 k = device_tag(device_old, tag, false);
     824           0 :                                 if (r >= 0 && k < 0)
     825           0 :                                         r = k;
     826             :                         }
     827             :                 }
     828             :         }
     829             : 
     830           0 :         FOREACH_DEVICE_TAG(device, tag) {
     831           0 :                 k = device_tag(device, tag, add);
     832           0 :                 if (r >= 0 && k < 0)
     833           0 :                         r = k;
     834             :         }
     835             : 
     836           0 :         return r;
     837             : }
     838             : 
     839           0 : static bool device_has_info(sd_device *device) {
     840           0 :         assert(device);
     841             : 
     842           0 :         if (!set_isempty(device->devlinks))
     843           0 :                 return true;
     844             : 
     845           0 :         if (device->devlink_priority != 0)
     846           0 :                 return true;
     847             : 
     848           0 :         if (!ordered_hashmap_isempty(device->properties_db))
     849           0 :                 return true;
     850             : 
     851           0 :         if (!set_isempty(device->tags))
     852           0 :                 return true;
     853             : 
     854           0 :         if (device->watch_handle >= 0)
     855           0 :                 return true;
     856             : 
     857           0 :         return false;
     858             : }
     859             : 
     860           0 : void device_set_db_persist(sd_device *device) {
     861           0 :         assert(device);
     862             : 
     863           0 :         device->db_persist = true;
     864           0 : }
     865             : 
     866           0 : int device_update_db(sd_device *device) {
     867             :         const char *id;
     868             :         char *path;
     869           0 :         _cleanup_fclose_ FILE *f = NULL;
     870           0 :         _cleanup_free_ char *path_tmp = NULL;
     871             :         bool has_info;
     872             :         int r;
     873             : 
     874           0 :         assert(device);
     875             : 
     876           0 :         has_info = device_has_info(device);
     877             : 
     878           0 :         r = device_get_id_filename(device, &id);
     879           0 :         if (r < 0)
     880           0 :                 return r;
     881             : 
     882           0 :         path = strjoina("/run/udev/data/", id);
     883             : 
     884             :         /* do not store anything for otherwise empty devices */
     885           0 :         if (!has_info && major(device->devnum) == 0 && device->ifindex == 0) {
     886           0 :                 r = unlink(path);
     887           0 :                 if (r < 0 && errno != ENOENT)
     888           0 :                         return -errno;
     889             : 
     890           0 :                 return 0;
     891             :         }
     892             : 
     893             :         /* write a database file */
     894           0 :         r = mkdir_parents(path, 0755);
     895           0 :         if (r < 0)
     896           0 :                 return r;
     897             : 
     898           0 :         r = fopen_temporary(path, &f, &path_tmp);
     899           0 :         if (r < 0)
     900           0 :                 return r;
     901             : 
     902             :         /*
     903             :          * set 'sticky' bit to indicate that we should not clean the
     904             :          * database when we transition from initramfs to the real root
     905             :          */
     906           0 :         if (device->db_persist) {
     907           0 :                 r = fchmod(fileno(f), 01644);
     908           0 :                 if (r < 0) {
     909           0 :                         r = -errno;
     910           0 :                         goto fail;
     911             :                 }
     912             :         } else {
     913           0 :                 r = fchmod(fileno(f), 0644);
     914           0 :                 if (r < 0) {
     915           0 :                         r = -errno;
     916           0 :                         goto fail;
     917             :                 }
     918             :         }
     919             : 
     920           0 :         if (has_info) {
     921             :                 const char *property, *value, *tag;
     922             :                 Iterator i;
     923             : 
     924           0 :                 if (major(device->devnum) > 0) {
     925             :                         const char *devlink;
     926             : 
     927           0 :                         FOREACH_DEVICE_DEVLINK(device, devlink)
     928           0 :                                 fprintf(f, "S:%s\n", devlink + STRLEN("/dev/"));
     929             : 
     930           0 :                         if (device->devlink_priority != 0)
     931           0 :                                 fprintf(f, "L:%i\n", device->devlink_priority);
     932             : 
     933           0 :                         if (device->watch_handle >= 0)
     934           0 :                                 fprintf(f, "W:%i\n", device->watch_handle);
     935             :                 }
     936             : 
     937           0 :                 if (device->usec_initialized > 0)
     938           0 :                         fprintf(f, "I:"USEC_FMT"\n", device->usec_initialized);
     939             : 
     940           0 :                 ORDERED_HASHMAP_FOREACH_KEY(value, property, device->properties_db, i)
     941           0 :                         fprintf(f, "E:%s=%s\n", property, value);
     942             : 
     943           0 :                 FOREACH_DEVICE_TAG(device, tag)
     944           0 :                         fprintf(f, "G:%s\n", tag);
     945             :         }
     946             : 
     947           0 :         r = fflush_and_check(f);
     948           0 :         if (r < 0)
     949           0 :                 goto fail;
     950             : 
     951           0 :         r = rename(path_tmp, path);
     952           0 :         if (r < 0) {
     953           0 :                 r = -errno;
     954           0 :                 goto fail;
     955             :         }
     956             : 
     957           0 :         log_device_debug(device, "sd-device: Created %s file '%s' for '%s'", has_info ? "db" : "empty",
     958             :                          path, device->devpath);
     959             : 
     960           0 :         return 0;
     961             : 
     962           0 : fail:
     963           0 :         (void) unlink(path);
     964           0 :         (void) unlink(path_tmp);
     965             : 
     966           0 :         return log_device_debug_errno(device, r, "sd-device: Failed to create %s file '%s' for '%s'", has_info ? "db" : "empty", path, device->devpath);
     967             : }
     968             : 
     969           0 : int device_delete_db(sd_device *device) {
     970             :         const char *id;
     971             :         char *path;
     972             :         int r;
     973             : 
     974           0 :         assert(device);
     975             : 
     976           0 :         r = device_get_id_filename(device, &id);
     977           0 :         if (r < 0)
     978           0 :                 return r;
     979             : 
     980           0 :         path = strjoina("/run/udev/data/", id);
     981             : 
     982           0 :         r = unlink(path);
     983           0 :         if (r < 0 && errno != ENOENT)
     984           0 :                 return -errno;
     985             : 
     986           0 :         return 0;
     987             : }
     988             : 
     989             : static const char* const device_action_table[_DEVICE_ACTION_MAX] = {
     990             :         [DEVICE_ACTION_ADD]     = "add",
     991             :         [DEVICE_ACTION_REMOVE]  = "remove",
     992             :         [DEVICE_ACTION_CHANGE]  = "change",
     993             :         [DEVICE_ACTION_MOVE]    = "move",
     994             :         [DEVICE_ACTION_ONLINE]  = "online",
     995             :         [DEVICE_ACTION_OFFLINE] = "offline",
     996             :         [DEVICE_ACTION_BIND]    = "bind",
     997             :         [DEVICE_ACTION_UNBIND]  = "unbind",
     998             : };
     999             : 
    1000          20 : DEFINE_STRING_TABLE_LOOKUP(device_action, DeviceAction);
    1001             : 
    1002           0 : void dump_device_action_table(void) {
    1003           0 :         DUMP_STRING_TABLE(device_action, DeviceAction, _DEVICE_ACTION_MAX);
    1004           0 : }

Generated by: LCOV version 1.14