]> git.ipfire.org Git - thirdparty/systemd.git/blame - udev/lib/libudev-queue.c
udevd: remove tiny bit of dead code
[thirdparty/systemd.git] / udev / lib / libudev-queue.c
CommitLineData
64ccdf82
KS
1/*
2 * libudev - interface to udev device information
3 *
4 * Copyright (C) 2008 Kay Sievers <kay.sievers@vrfy.org>
5 *
4061ab9f
KS
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
64ccdf82
KS
10 */
11
12#include <stdio.h>
13#include <stdlib.h>
14#include <stddef.h>
15#include <unistd.h>
16#include <errno.h>
17#include <string.h>
18#include <dirent.h>
19#include <fcntl.h>
20#include <sys/stat.h>
21
22#include "libudev.h"
23#include "libudev-private.h"
24
25struct udev_queue {
26 struct udev *udev;
27 int refcount;
28 unsigned long long int last_seen_udev_seqnum;
8cd2e972
KS
29 struct udev_list_node queue_list;
30 struct udev_list_node failed_list;
64ccdf82
KS
31};
32
33struct udev_queue *udev_queue_new(struct udev *udev)
34{
35 struct udev_queue *udev_queue;
36
37 if (udev == NULL)
38 return NULL;
39
b29a5e4a 40 udev_queue = calloc(1, sizeof(struct udev_queue));
64ccdf82
KS
41 if (udev_queue == NULL)
42 return NULL;
64ccdf82
KS
43 udev_queue->refcount = 1;
44 udev_queue->udev = udev;
8cd2e972
KS
45 udev_list_init(&udev_queue->queue_list);
46 udev_list_init(&udev_queue->failed_list);
64ccdf82
KS
47 return udev_queue;
48}
49
50struct udev_queue *udev_queue_ref(struct udev_queue *udev_queue)
51{
52 if (udev_queue == NULL)
53 return NULL;
54 udev_queue->refcount++;
55 return udev_queue;
56}
57
58void udev_queue_unref(struct udev_queue *udev_queue)
59{
60 if (udev_queue == NULL)
61 return;
62 udev_queue->refcount--;
63 if (udev_queue->refcount > 0)
64 return;
eb8837e1
KS
65 udev_list_cleanup_entries(udev_queue->udev, &udev_queue->queue_list);
66 udev_list_cleanup_entries(udev_queue->udev, &udev_queue->failed_list);
64ccdf82
KS
67 free(udev_queue);
68}
69
70struct udev *udev_queue_get_udev(struct udev_queue *udev_queue)
71{
72 if (udev_queue == NULL)
73 return NULL;
74 return udev_queue->udev;
75}
76
77unsigned long long int udev_queue_get_kernel_seqnum(struct udev_queue *udev_queue)
78{
79 char filename[UTIL_PATH_SIZE];
80 unsigned long long int seqnum;
81 int fd;
82 char buf[32];
83 ssize_t len;
84
85 if (udev_queue == NULL)
86 return -EINVAL;
065db052 87 util_strscpyl(filename, sizeof(filename), udev_get_sys_path(udev_queue->udev), "/kernel/uevent_seqnum", NULL);
64ccdf82
KS
88 fd = open(filename, O_RDONLY);
89 if (fd < 0)
90 return 0;
91 len = read(fd, buf, sizeof(buf));
92 close(fd);
93 if (len <= 2)
94 return 0;
95 buf[len-1] = '\0';
96 seqnum = strtoull(buf, NULL, 10);
86b57788 97 dbg(udev_queue->udev, "seqnum=%llu\n", seqnum);
64ccdf82
KS
98 return seqnum;
99}
100
101unsigned long long int udev_queue_get_udev_seqnum(struct udev_queue *udev_queue)
102{
103 char filename[UTIL_PATH_SIZE];
104 unsigned long long int seqnum;
105 int fd;
106 char buf[32];
107 ssize_t len;
108
109 if (udev_queue == NULL)
110 return -EINVAL;
065db052 111 util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_queue->udev), "/.udev/uevent_seqnum", NULL);
64ccdf82
KS
112 fd = open(filename, O_RDONLY);
113 if (fd < 0)
114 return 0;
115 len = read(fd, buf, sizeof(buf));
116 close(fd);
117 if (len <= 2)
118 return 0;
119 buf[len-1] = '\0';
120 seqnum = strtoull(buf, NULL, 10);
86b57788 121 dbg(udev_queue->udev, "seqnum=%llu\n", seqnum);
64ccdf82
KS
122 udev_queue->last_seen_udev_seqnum = seqnum;
123 return seqnum;
124}
125
11d5eec2
KS
126int udev_queue_get_udev_is_active(struct udev_queue *udev_queue)
127{
128 char filename[UTIL_PATH_SIZE];
129 struct stat statbuf;
130
131 if (udev_queue == NULL)
132 return 0;
065db052 133 util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_queue->udev), "/.udev/uevent_seqnum", NULL);
11d5eec2
KS
134 if (stat(filename, &statbuf) == 0)
135 return 1;
136 return 0;
137}
138
64ccdf82
KS
139int udev_queue_get_queue_is_empty(struct udev_queue *udev_queue)
140{
141 char queuename[UTIL_PATH_SIZE];
142 struct stat statbuf;
143 unsigned long long int seqnum_kernel;
144
145 if (udev_queue == NULL)
146 return -EINVAL;
065db052 147 util_strscpyl(queuename, sizeof(queuename), udev_get_dev_path(udev_queue->udev), "/.udev/queue", NULL);
64ccdf82 148 if (stat(queuename, &statbuf) == 0) {
86b57788 149 dbg(udev_queue->udev, "queue is not empty\n");
64ccdf82
KS
150 return 0;
151 }
152 seqnum_kernel = udev_queue_get_kernel_seqnum(udev_queue);
153 if (seqnum_kernel <= udev_queue->last_seen_udev_seqnum) {
86b57788 154 dbg(udev_queue->udev, "queue is empty\n");
64ccdf82
KS
155 return 1;
156 }
11d5eec2
KS
157 /* update udev seqnum, and check if udev is still running */
158 if (udev_queue_get_udev_seqnum(udev_queue) == 0)
159 if (!udev_queue_get_udev_is_active(udev_queue))
160 return 1;
64ccdf82 161 if (seqnum_kernel <= udev_queue->last_seen_udev_seqnum) {
86b57788 162 dbg(udev_queue->udev, "queue is empty\n");
64ccdf82
KS
163 return 1;
164 }
86b57788 165 dbg(udev_queue->udev, "queue is empty, but kernel events still pending [%llu]<->[%llu]\n",
64ccdf82
KS
166 seqnum_kernel, udev_queue->last_seen_udev_seqnum);
167 return 0;
168}
169
170int udev_queue_get_seqnum_is_finished(struct udev_queue *udev_queue, unsigned long long int seqnum)
171{
172 char filename[UTIL_PATH_SIZE];
173 struct stat statbuf;
174
175 if (udev_queue == NULL)
176 return -EINVAL;
34f55e1d 177 /* did it reach the queue? */
8c3ae785
KS
178 if (seqnum > udev_queue->last_seen_udev_seqnum)
179 if (seqnum > udev_queue_get_udev_seqnum(udev_queue))
64ccdf82 180 return 0;
34f55e1d 181 /* is it still in the queue? */
64ccdf82
KS
182 snprintf(filename, sizeof(filename), "%s/.udev/queue/%llu",
183 udev_get_dev_path(udev_queue->udev), seqnum);
a5d8cffa 184 if (lstat(filename, &statbuf) == 0)
64ccdf82 185 return 0;
86b57788 186 dbg(udev_queue->udev, "seqnum: %llu finished\n", seqnum);
64ccdf82
KS
187 return 1;
188}
189
190struct udev_list_entry *udev_queue_get_queued_list_entry(struct udev_queue *udev_queue)
191{
192 char path[UTIL_PATH_SIZE];
193 DIR *dir;
194 struct dirent *dent;
195
196 if (udev_queue == NULL)
197 return NULL;
eb8837e1 198 udev_list_cleanup_entries(udev_queue->udev, &udev_queue->queue_list);
065db052 199 util_strscpyl(path, sizeof(path), udev_get_dev_path(udev_queue->udev), "/.udev/queue", NULL);
64ccdf82
KS
200 dir = opendir(path);
201 if (dir == NULL)
202 return NULL;
203 for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
64ccdf82 204 char syspath[UTIL_PATH_SIZE];
065db052
KS
205 char *s;
206 size_t l;
64ccdf82
KS
207 ssize_t len;
208
209 if (dent->d_name[0] == '.')
210 continue;
065db052
KS
211 s = syspath;
212 l = util_strpcpyl(&s, sizeof(syspath), udev_get_sys_path(udev_queue->udev), NULL);
e6c1a2bd 213 len = readlinkat(dirfd(dir), dent->d_name, s, l);
065db052 214 if (len < 0 || (size_t)len >= l)
64ccdf82 215 continue;
065db052 216 s[len] = '\0';
86b57788 217 dbg(udev_queue->udev, "found '%s' [%s]\n", syspath, dent->d_name);
8cd2e972 218 udev_list_entry_add(udev_queue->udev, &udev_queue->queue_list, syspath, dent->d_name, 0, 0);
64ccdf82
KS
219 }
220 closedir(dir);
8cd2e972 221 return udev_list_get_entry(&udev_queue->queue_list);
64ccdf82
KS
222}
223
224struct udev_list_entry *udev_queue_get_failed_list_entry(struct udev_queue *udev_queue)
225{
226 char path[UTIL_PATH_SIZE];
227 DIR *dir;
228 struct dirent *dent;
229
230 if (udev_queue == NULL)
231 return NULL;
eb8837e1 232 udev_list_cleanup_entries(udev_queue->udev, &udev_queue->failed_list);
065db052 233 util_strscpyl(path, sizeof(path), udev_get_dev_path(udev_queue->udev), "/.udev/failed", NULL);
64ccdf82
KS
234 dir = opendir(path);
235 if (dir == NULL)
236 return NULL;
237 for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
238 char filename[UTIL_PATH_SIZE];
239 char syspath[UTIL_PATH_SIZE];
065db052
KS
240 char *s;
241 size_t l;
64ccdf82 242 ssize_t len;
065db052 243 struct stat statbuf;
64ccdf82
KS
244
245 if (dent->d_name[0] == '.')
246 continue;
065db052
KS
247 s = syspath;
248 l = util_strpcpyl(&s, sizeof(syspath), udev_get_sys_path(udev_queue->udev), NULL);
e6c1a2bd 249 len = readlinkat(dirfd(dir), dent->d_name, s, l);
065db052 250 if (len < 0 || (size_t)len >= l)
64ccdf82 251 continue;
065db052 252 s[len] = '\0';
86b57788 253 dbg(udev_queue->udev, "found '%s' [%s]\n", syspath, dent->d_name);
065db052 254 util_strscpyl(filename, sizeof(filename), syspath, "/uevent", NULL);
64ccdf82
KS
255 if (stat(filename, &statbuf) != 0)
256 continue;
8cd2e972 257 udev_list_entry_add(udev_queue->udev, &udev_queue->failed_list, syspath, NULL, 0, 0);
64ccdf82
KS
258 }
259 closedir(dir);
8cd2e972 260 return udev_list_get_entry(&udev_queue->failed_list);
64ccdf82
KS
261}
262
8cd2e972 263int udev_queue_export_udev_seqnum(struct udev_queue *udev_queue, unsigned long long int seqnum)
64ccdf82 264{
8cd2e972 265 return -1;
64ccdf82
KS
266}
267
37ed4f56 268int udev_queue_export_device_queued(struct udev_queue *udev_queue, struct udev_device *udev_device)
64ccdf82 269{
8cd2e972 270 return -1;
64ccdf82
KS
271}
272
37ed4f56 273int udev_queue_export_device_finished(struct udev_queue *udev_queue, struct udev_device *udev_device)
64ccdf82 274{
8cd2e972 275 return -1;
64ccdf82
KS
276}
277
37ed4f56 278int udev_queue_export_device_failed(struct udev_queue *udev_queue, struct udev_device *udev_device)
64ccdf82 279{
8cd2e972 280 return -1;
64ccdf82 281}