chiark / gitweb /
359ae443dab2ec6059c66110a22e63b69dd7f60c
[elogind.git] / udev / lib / libudev-device.c
1 /*
2  * libudev - interface to udev device information
3  *
4  * Copyright (C) 2008 Kay Sievers <kay.sievers@vrfy.org>
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <stddef.h>
23 #include <unistd.h>
24 #include <errno.h>
25 #include <string.h>
26 #include <dirent.h>
27 #include <fcntl.h>
28 #include <sys/stat.h>
29
30 #include "libudev.h"
31 #include "libudev-private.h"
32
33 struct udev_device {
34         int refcount;
35         struct udev *udev;
36         struct udev_device *parent_device;
37         char *syspath;
38         const char *devpath;
39         const char *sysname;
40         char *devname;
41         char *subsystem;
42         struct list_head link_list;
43         struct list_head properties_list;
44         char *action;
45         char *driver;
46         char *devpath_old;
47         char *physdevpath;
48         int timeout;
49         dev_t devnum;
50         unsigned long long int seqnum;
51         int num_fake_partitions;
52         int devlink_priority;
53         int ignore_remove;
54         struct list_head attr_list;
55 };
56
57 static size_t syspath_to_db_path(struct udev_device *udev_device, char *filename, size_t len)
58 {
59         size_t start;
60
61         /* translate to location of db file */
62         util_strlcpy(filename, udev_get_dev_path(udev_device->udev), len);
63         start = util_strlcat(filename, "/.udev/db/", len);
64         util_strlcat(filename, udev_device->devpath, len);
65         return util_path_encode(&filename[start], len - start);
66 }
67
68 static int device_read_uevent_file(struct udev_device *udev_device)
69 {
70         char filename[UTIL_PATH_SIZE];
71         FILE *f;
72         char line[UTIL_LINE_SIZE];
73         int maj = 0;
74         int min = 0;
75
76         util_strlcpy(filename, udev_device->syspath, sizeof(filename));
77         util_strlcat(filename, "/uevent", sizeof(filename));
78         f = fopen(filename, "r");
79         if (f == NULL)
80                 return -1;
81
82         while (fgets(line, sizeof(line), f)) {
83                 char *pos;
84
85                 pos = strchr(line, '\n');
86                 if (pos == NULL)
87                         continue;
88                 pos[0] = '\0';
89
90                 if (strncmp(line, "MAJOR=", 6) == 0)
91                         maj = strtoull(&line[6], NULL, 10);
92                 else if (strncmp(line, "MINOR=", 6) == 0)
93                         min = strtoull(&line[6], NULL, 10);
94
95                 device_add_property_from_string(udev_device, line);
96         }
97
98         udev_device->devnum = makedev(maj, min);
99
100         fclose(f);
101         return 0;
102 }
103
104 static int device_read_db(struct udev_device *udev_device)
105 {
106         struct stat stats;
107         char filename[UTIL_PATH_SIZE];
108         char line[UTIL_LINE_SIZE];
109         FILE *f;
110
111         syspath_to_db_path(udev_device, filename, sizeof(filename));
112
113         if (lstat(filename, &stats) != 0) {
114                 info(udev_device->udev, "no db file to read %s: %s\n", filename, strerror(errno));
115                 return -1;
116         }
117         if ((stats.st_mode & S_IFMT) == S_IFLNK) {
118                 char target[UTIL_PATH_SIZE];
119                 int target_len;
120
121                 info(udev_device->udev, "found a symlink as db file\n");
122                 target_len = readlink(filename, target, sizeof(target));
123                 if (target_len > 0)
124                         target[target_len] = '\0';
125                 else {
126                         info(udev_device->udev, "error reading db link %s: %s\n", filename, strerror(errno));
127                         return -1;
128                 }
129                 dbg(udev_device->udev, "db link points to '%s'\n", target);
130                 if (asprintf(&udev_device->devname, "%s/%s", udev_get_dev_path(udev_device->udev), target) < 0)
131                         return -ENOMEM;
132                 return 0;
133         }
134
135         f = fopen(filename, "r");
136         if (f == NULL) {
137                 info(udev_device->udev, "error reading db file %s: %s\n", filename, strerror(errno));
138                 return -1;
139         }
140         while (fgets(line, sizeof(line), f)) {
141                 ssize_t len;
142                 const char *val;
143
144                 len = strlen(line);
145                 if (len < 4)
146                         break;
147                 line[len-1] = '\0';
148                 val = &line[2];
149
150                 switch(line[0]) {
151                 case 'N':
152                         asprintf(&udev_device->devname, "%s/%s", udev_get_dev_path(udev_device->udev), val);
153                         break;
154                 case 'S':
155                         util_strlcpy(filename, udev_get_dev_path(udev_device->udev), sizeof(filename));
156                         util_strlcat(filename, "/", sizeof(filename));
157                         util_strlcat(filename, val, sizeof(filename));
158                         device_add_devlink(udev_device, filename);
159                         break;
160                 case 'L':
161                         device_set_devlink_priority(udev_device, atoi(val));
162                         break;
163                 case 'T':
164                         device_set_timeout(udev_device, atoi(val));
165                         break;
166                 case 'A':
167                         device_set_num_fake_partitions(udev_device, atoi(val));
168                         break;
169                 case 'R':
170                         device_set_ignore_remove(udev_device, atoi(val));
171                         break;
172                 case 'E':
173                         device_add_property_from_string(udev_device, val);
174                         break;
175                 }
176         }
177         fclose(f);
178
179         info(udev_device->udev, "device %p filled with udev database data\n", udev_device);
180         return 0;
181 }
182
183 struct udev_device *device_init(struct udev *udev)
184 {
185         struct udev_device *udev_device;
186
187         if (udev == NULL)
188                 return NULL;
189
190         udev_device = malloc(sizeof(struct udev_device));
191         if (udev_device == NULL)
192                 return NULL;
193         memset(udev_device, 0x00, sizeof(struct udev_device));
194         udev_device->refcount = 1;
195         udev_device->udev = udev;
196         INIT_LIST_HEAD(&udev_device->link_list);
197         INIT_LIST_HEAD(&udev_device->properties_list);
198         INIT_LIST_HEAD(&udev_device->attr_list);
199         info(udev_device->udev, "udev_device: %p created\n", udev_device);
200         return udev_device;
201 }
202
203 /**
204  * udev_device_new_from_syspath:
205  * @udev: udev library context
206  * @syspath: sys device path including sys directory
207  *
208  * Create new udev device, and fill in information from the sys
209  * device and the udev database entry. The sypath is the absolute
210  * path to the device, including the sys mount point.
211  *
212  * The initial refcount is 1, and needs to be decremented to
213  * release the ressources of the udev device.
214  *
215  * Returns: a new udev device, or #NULL, if it does not exist
216  **/
217 struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char *syspath)
218 {
219         char path[UTIL_PATH_SIZE];
220         struct stat statbuf;
221         struct udev_device *udev_device;
222
223         if (udev == NULL)
224                 return NULL;
225         if (syspath == NULL)
226                 return NULL;
227
228         util_strlcpy(path, syspath, sizeof(path));
229         util_strlcat(path, "/uevent", sizeof(path));
230         if (stat(path, &statbuf) != 0) {
231                 info(udev, "not a device :%s\n", syspath);
232                 return NULL;
233         }
234
235         udev_device = device_init(udev);
236         if (udev_device == NULL)
237                 return NULL;
238
239         /* resolve possible symlink to real path */
240         util_strlcpy(path, syspath, sizeof(path));
241         util_resolve_sys_link(udev, path, sizeof(path));
242         device_set_syspath(udev_device, path);
243         info(udev, "device %p has devpath '%s'\n", udev_device, udev_device_get_devpath(udev_device));
244
245         device_read_uevent_file(udev_device);
246         device_read_db(udev_device);
247         return udev_device;
248 }
249
250 struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, dev_t devnum)
251 {
252         char path[UTIL_PATH_SIZE];
253         const char *type_str;
254         struct udev_enumerate *enumerate;
255         struct udev_list *list;
256         struct udev_device *device = NULL;
257
258         if (type == 'b')
259                 type_str = "block";
260         else if (type == 'c')
261                 type_str = "char";
262         else
263                 return NULL;
264
265         /* /sys/dev/{block,char}/<maj>:<min> links */
266         snprintf(path, sizeof(path), "%s/dev/%s/%u:%u", udev_get_sys_path(udev),
267                  type_str, major(devnum), minor(devnum));
268         if (util_resolve_sys_link(udev, path, sizeof(path)) == 0)
269                 return udev_device_new_from_syspath(udev, path);
270
271         /* fallback to search all sys devices for the major/minor */
272         enumerate = udev_enumerate_new_from_subsystems(udev, NULL);
273         if (enumerate == NULL)
274                 return NULL;
275         list = udev_enumerate_get_devices_list(enumerate);
276         while (list != NULL) {
277                 struct udev_device *device_loop;
278
279                 device_loop = udev_device_new_from_syspath(udev, udev_list_get_name(list));
280                 if (device_loop != NULL) {
281                         if (udev_device_get_devnum(device_loop) == devnum) {
282                                 device = device_loop;
283                                 break;
284                         }
285                         udev_device_unref(device_loop);
286                 }
287                 list = udev_list_get_next(list);
288         }
289         udev_enumerate_unref(enumerate);
290         return device;
291 }
292
293 static struct udev_device *device_new_from_parent(struct udev_device *udev_device)
294 {
295         struct udev_device *udev_device_parent = NULL;
296         char path[UTIL_PATH_SIZE];
297         char *pos;
298
299         if (udev_device == NULL)
300                 return NULL;
301
302         util_strlcpy(path, udev_device->syspath, sizeof(path));
303         while (1) {
304                 pos = strrchr(path, '/');
305                 if (pos == path || pos == NULL)
306                         break;
307                 pos[0] = '\0';
308                 udev_device_parent = udev_device_new_from_syspath(udev_device->udev, path);
309                 if (udev_device_parent != NULL)
310                         return udev_device_parent;
311         }
312
313         /* follow "device" link in deprecated sys /sys/class/ layout */
314         if (strncmp(udev_device->devpath, "/class/", 7) == 0) {
315                 util_strlcpy(path, udev_device->syspath, sizeof(path));
316                 util_strlcat(path, "/device", sizeof(path));
317                 if (util_resolve_sys_link(udev_device->udev, path, sizeof(path)) == 0) {
318                         udev_device_parent = udev_device_new_from_syspath(udev_device->udev, path);
319                         if (udev_device_parent != NULL)
320                                 return udev_device_parent;
321                 }
322         }
323         return NULL;
324 }
325
326 struct udev_device *udev_device_get_parent(struct udev_device *udev_device)
327 {
328         if (udev_device->parent_device != NULL) {
329                 info(udev_device->udev, "returning existing parent %p\n", udev_device->parent_device);
330                 return udev_device->parent_device;
331         }
332         udev_device->parent_device = device_new_from_parent(udev_device);
333         return udev_device->parent_device;
334 }
335
336 /**
337  * udev_device_get_udev:
338  * @udev_device: udev device
339  *
340  * Retrieve the udev library context the device was created with.
341  *
342  * Returns: the udev library context
343  **/
344 struct udev *udev_device_get_udev(struct udev_device *udev_device)
345 {
346         if (udev_device == NULL)
347                 return NULL;
348         return udev_device->udev;
349 }
350
351 /**
352  * udev_device_ref:
353  * @udev_device: udev device
354  *
355  * Take a reference of a udev device.
356  *
357  * Returns: the passed udev device
358  **/
359 struct udev_device *udev_device_ref(struct udev_device *udev_device)
360 {
361         if (udev_device == NULL)
362                 return NULL;
363         udev_device->refcount++;
364         return udev_device;
365 }
366
367 /**
368  * udev_device_unref:
369  * @udev_device: udev device
370  *
371  * Drop a reference of a udev device. If the refcount reaches zero,
372  * the ressources of the device will be released.
373  *
374  **/
375 void udev_device_unref(struct udev_device *udev_device)
376 {
377         if (udev_device == NULL)
378                 return;
379         udev_device->refcount--;
380         if (udev_device->refcount > 0)
381                 return;
382         if (udev_device->parent_device != NULL)
383                 udev_device_unref(udev_device->parent_device);
384         free(udev_device->syspath);
385         free(udev_device->devname);
386         free(udev_device->subsystem);
387         list_cleanup(udev_device->udev, &udev_device->link_list);
388         list_cleanup(udev_device->udev, &udev_device->properties_list);
389         free(udev_device->action);
390         free(udev_device->driver);
391         free(udev_device->devpath_old);
392         free(udev_device->physdevpath);
393         list_cleanup(udev_device->udev, &udev_device->attr_list);
394         info(udev_device->udev, "udev_device: %p released\n", udev_device);
395         free(udev_device);
396 }
397
398 /**
399  * udev_device_get_devpath:
400  * @udev_device: udev device
401  *
402  * Retrieve the kernel devpath value of the udev device. The path
403  * does not contain the sys mount point, and starts with a '/'.
404  *
405  * Returns: the devpath of the udev device
406  **/
407 const char *udev_device_get_devpath(struct udev_device *udev_device)
408 {
409         if (udev_device == NULL)
410                 return NULL;
411         return udev_device->devpath;
412 }
413
414 /**
415  * udev_device_get_syspath:
416  * @udev_device: udev device
417  *
418  * Retrieve the sys path of the udev device. The path is an
419  * absolute path and starts with the sys mount point.
420  *
421  * Returns: the sys path of the udev device
422  **/
423 const char *udev_device_get_syspath(struct udev_device *udev_device)
424 {
425         if (udev_device == NULL)
426                 return NULL;
427         return udev_device->syspath;
428 }
429
430 const char *udev_device_get_sysname(struct udev_device *udev_device)
431 {
432         if (udev_device == NULL)
433                 return NULL;
434         return udev_device->sysname;
435 }
436
437 /**
438  * udev_device_get_devnode:
439  * @udev_device: udev device
440  *
441  * Retrieve the device node file name belonging to the udev device.
442  * The path is an absolute path, and starts with the device directory.
443  *
444  * Returns: the device node file name of the udev device, or #NULL if no device node exists
445  **/
446 const char *udev_device_get_devnode(struct udev_device *udev_device)
447 {
448         if (udev_device == NULL)
449                 return NULL;
450         return udev_device->devname;
451 }
452
453 /**
454  * udev_device_get_subsystem:
455  * @udev_device: udev device
456  *
457  * Retrieve the subsystem string of the udev device. The string does not
458  * contain any "/".
459  *
460  * Returns: the subsystem name of the udev device, or #NULL if it can not be determined
461  **/
462 const char *udev_device_get_subsystem(struct udev_device *udev_device)
463 {
464         char subsystem[UTIL_NAME_SIZE];
465
466         if (udev_device == NULL)
467                 return NULL;
468         if (udev_device->subsystem != NULL)
469                 return udev_device->subsystem;
470
471         /* read "subsytem" link */
472         if (util_get_sys_subsystem(udev_device->udev, udev_device->syspath, subsystem, sizeof(subsystem)) > 0) {
473                 udev_device->subsystem = strdup(subsystem);
474                 return udev_device->subsystem;
475         }
476
477         /* implicit names */
478         if (strncmp(udev_device->devpath, "/module/", 8) == 0) {
479                 udev_device->subsystem = strdup("module");
480                 return udev_device->subsystem;
481         }
482         if (strstr(udev_device->devpath, "/drivers/") != NULL) {
483                 udev_device->subsystem = strdup("drivers");
484                 return udev_device->subsystem;
485         }
486         if (strncmp(udev_device->devpath, "/subsystem/", 11) == 0 ||
487             strncmp(udev_device->devpath, "/class/", 7) == 0 ||
488             strncmp(udev_device->devpath, "/bus/", 5) == 0) {
489                 udev_device->subsystem = strdup("subsystem");
490                 return udev_device->subsystem;
491         }
492         return NULL;
493 }
494
495 /**
496  * udev_device_get_devlinks_list:
497  * @udev_device: udev device
498  *
499  * Retrieve the list of device links pointing to the device file of
500  * the udev device. The next list entry can be retrieved with
501  * udev_list_next(), which returns #NULL if no more entries exist.
502  * The devlink path can be retrieved from the list entry by
503  * udev_list_get_name(). The path is an absolute path, and starts with
504  * the device directory.
505  *
506  * Returns: the first entry of the device node link list
507  **/
508 struct udev_list *udev_device_get_devlinks_list(struct udev_device *udev_device)
509 {
510         return list_get_entry(&udev_device->link_list);
511 }
512
513 /**
514  * udev_device_get_properties_list:
515  * @udev_device: udev device
516  *
517  * Retrieve the list of key/value device properties of the udev
518  * device. The next list entry can be retrieved with udev_list_next(),
519  * which returns #NULL if no more entries exist. The property name
520  * can be retrieved from the list entry by udev_list_get_name(),
521  * the property value by udev_list_get_value().
522  *
523  * Returns: the first entry of the property list
524  **/
525 struct udev_list *udev_device_get_properties_list(struct udev_device *udev_device)
526 {
527         return list_get_entry(&udev_device->properties_list);
528 }
529
530 const char *udev_device_get_driver(struct udev_device *udev_device)
531 {
532         char driver[UTIL_NAME_SIZE];
533
534         if (udev_device == NULL)
535                 return NULL;
536         if (udev_device->driver != NULL)
537                 return udev_device->driver;
538         if (util_get_sys_driver(udev_device->udev, udev_device->syspath, driver, sizeof(driver)) < 2)
539                 return NULL;
540         udev_device->driver = strdup(driver);
541         return udev_device->driver;
542 }
543
544 dev_t udev_device_get_devnum(struct udev_device *udev_device)
545 {
546         if (udev_device == NULL)
547                 return makedev(0, 0);
548         return udev_device->devnum;
549 }
550
551 const char *udev_device_get_action(struct udev_device *udev_device)
552 {
553         if (udev_device == NULL)
554                 return NULL;
555         return udev_device->action;
556 }
557
558 unsigned long long int udev_device_get_seqnum(struct udev_device *udev_device)
559 {
560         if (udev_device == NULL)
561                 return 0;
562         return udev_device->seqnum;
563 }
564
565 const char *udev_device_get_attr_value(struct udev_device *udev_device, const char *attr)
566 {
567         struct udev_list *list;
568         char path[UTIL_PATH_SIZE];
569         char value[UTIL_NAME_SIZE];
570         struct stat statbuf;
571         int fd;
572         ssize_t size;
573         const char *val = NULL;
574
575         /* look for possibly already cached result */
576         list = list_get_entry(&udev_device->attr_list);
577         while (list != NULL) {
578                 if (strcmp(udev_list_get_name(list), attr) == 0) {
579                         info(udev_device->udev, "got '%s' (%s) from cache\n", attr, udev_list_get_value(list));
580                         return udev_list_get_name(list);
581                 }
582                 list = udev_list_get_next(list);
583         }
584
585         util_strlcpy(path, udev_device_get_syspath(udev_device), sizeof(path));
586         util_strlcat(path, "/", sizeof(path));
587         util_strlcat(path, attr, sizeof(path));
588
589         if (lstat(path, &statbuf) != 0) {
590                 info(udev_device->udev, "stat '%s' failed: %s\n", path, strerror(errno));
591                 goto out;
592         }
593
594         if (S_ISLNK(statbuf.st_mode)) {
595                 /* links return the last element of the target path */
596                 char target[UTIL_NAME_SIZE];
597                 int len;
598                 char *pos;
599
600                 len = readlink(path, target, sizeof(target));
601                 if (len > 0) {
602                         target[len] = '\0';
603                         pos = strrchr(target, '/');
604                         if (pos != NULL) {
605                                 pos = &pos[1];
606                                 info(udev_device->udev, "cache '%s' with link value '%s'\n", attr, pos);
607                                 list = list_insert(udev_device->udev, &udev_device->attr_list, attr, pos, 0);
608                                 val = udev_list_get_value(list);
609                         }
610                 }
611                 goto out;
612         }
613
614         /* skip directories */
615         if (S_ISDIR(statbuf.st_mode))
616                 goto out;
617
618         /* skip non-readable files */
619         if ((statbuf.st_mode & S_IRUSR) == 0)
620                 goto out;
621
622         /* read attribute value */
623         fd = open(path, O_RDONLY);
624         if (fd < 0) {
625                 info(udev_device->udev, "attribute '%s' can not be opened\n", path);
626                 goto out;
627         }
628         size = read(fd, value, sizeof(value));
629         close(fd);
630         if (size < 0)
631                 goto out;
632         if (size == sizeof(value))
633                 goto out;
634
635         /* got a valid value, store it in cache and return it */
636         value[size] = '\0';
637         util_remove_trailing_chars(value, '\n');
638         info(udev_device->udev, "'%s' has attribute value '%s'\n", path, value);
639         list = list_insert(udev_device->udev, &udev_device->attr_list, attr, value, 0);
640         val = udev_list_get_value(list);
641 out:
642         return val;
643 }
644 int device_set_syspath(struct udev_device *udev_device, const char *syspath)
645 {
646         const char *pos;
647
648         udev_device->syspath = strdup(syspath);
649         if (udev_device->syspath ==  NULL)
650                 return -ENOMEM;
651         udev_device->devpath = &udev_device->syspath[strlen(udev_get_sys_path(udev_device->udev))];
652         pos = strrchr(udev_device->syspath, '/');
653         if (pos == NULL)
654                 return -EINVAL;
655         udev_device->sysname = &pos[1];
656         return 0;
657 }
658
659 int device_set_subsystem(struct udev_device *udev_device, const char *subsystem)
660 {
661         udev_device->subsystem = strdup(subsystem);
662         if (udev_device->subsystem == NULL)
663                 return -1;
664         return 0;
665 }
666
667 int device_set_devname(struct udev_device *udev_device, const char *devname)
668 {
669         udev_device->devname = strdup(devname);
670         if (udev_device->devname == NULL)
671                 return -ENOMEM;
672         return 0;
673 }
674
675 int device_add_devlink(struct udev_device *udev_device, const char *devlink)
676 {
677         if (list_insert(udev_device->udev, &udev_device->link_list, devlink, NULL, 0) == NULL)
678                 return -ENOMEM;
679         return 0;
680 }
681
682 int device_add_property(struct udev_device *udev_device, const char *key, const char *value)
683 {
684         if (list_insert(udev_device->udev, &udev_device->properties_list, key, value, 0) == NULL)
685                 return -ENOMEM;
686         return 0;
687 }
688
689 int device_add_property_from_string(struct udev_device *udev_device, const char *property)
690 {
691         char name[UTIL_PATH_SIZE];
692         char *val;
693
694         strncpy(name, property, sizeof(name));
695         val = strchr(name, '=');
696         if (val == NULL)
697                 return -1;
698         val[0] = '\0';
699         val = &val[1];
700         if (val[0] == '\0')
701                 val = NULL;
702         device_add_property(udev_device, name, val);
703         return 0;
704 }
705
706 int device_set_action(struct udev_device *udev_device, const char *action)
707 {
708         udev_device->action = strdup(action);
709         if (udev_device->action == NULL)
710                 return -ENOMEM;
711         return 0;
712 }
713
714 int device_set_driver(struct udev_device *udev_device, const char *driver)
715 {
716         udev_device->driver = strdup(driver);
717         if (udev_device->driver == NULL)
718                 return -ENOMEM;
719         return 0;
720 }
721
722 const char *device_get_devpath_old(struct udev_device *udev_device)
723 {
724         if (udev_device == NULL)
725                 return NULL;
726         return udev_device->devpath_old;
727 }
728
729 int device_set_devpath_old(struct udev_device *udev_device, const char *devpath_old)
730 {
731         udev_device->devpath_old = strdup(devpath_old);
732         if (udev_device->devpath_old == NULL)
733                 return -ENOMEM;
734         return 0;
735 }
736
737 const char *device_get_physdevpath(struct udev_device *udev_device)
738 {
739         if (udev_device == NULL)
740                 return NULL;
741         return udev_device->physdevpath;
742 }
743
744 int device_set_physdevpath(struct udev_device *udev_device, const char *physdevpath)
745 {
746         udev_device->physdevpath = strdup(physdevpath);
747         if (udev_device->physdevpath == NULL)
748                 return -ENOMEM;
749         return 0;
750 }
751
752 int device_get_timeout(struct udev_device *udev_device)
753 {
754         if (udev_device == NULL)
755                 return -1;
756         return udev_device->timeout;
757 }
758
759 int device_set_timeout(struct udev_device *udev_device, int timeout)
760 {
761         udev_device->timeout = timeout;
762         return 0;
763 }
764
765 int device_set_seqnum(struct udev_device *udev_device, unsigned long long int seqnum)
766 {
767         udev_device->seqnum = seqnum;
768         return 0;
769 }
770
771 int device_set_devnum(struct udev_device *udev_device, dev_t devnum)
772 {
773         udev_device->devnum = devnum;
774         return 0;
775 }
776
777 int device_get_num_fake_partitions(struct udev_device *udev_device)
778 {
779         if (udev_device == NULL)
780                 return -1;
781         return udev_device->num_fake_partitions;
782 }
783
784 int device_set_num_fake_partitions(struct udev_device *udev_device, int num)
785 {
786         udev_device->num_fake_partitions = num;
787         return 0;
788 }
789
790 int device_get_devlink_priority(struct udev_device *udev_device)
791 {
792         if (udev_device == NULL)
793                 return -1;
794         return udev_device->devlink_priority;
795 }
796
797 int device_set_devlink_priority(struct udev_device *udev_device, int prio)
798 {
799          udev_device->devlink_priority = prio;
800         return 0;
801 }
802
803 int device_get_ignore_remove(struct udev_device *udev_device)
804 {
805         if (udev_device == NULL)
806                 return -1;
807         return udev_device->ignore_remove;
808 }
809
810 int device_set_ignore_remove(struct udev_device *udev_device, int ignore)
811 {
812         udev_device->ignore_remove = ignore;
813         return 0;
814 }
815