]> git.ipfire.org Git - thirdparty/systemd.git/blob - udev_lib.c
[PATCH] $local user
[thirdparty/systemd.git] / udev_lib.c
1 /*
2 * udev_lib - generic stuff used by udev
3 *
4 * Copyright (C) 2004 Kay Sievers <kay@vrfy.org>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation version 2 of the License.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 675 Mass Ave, Cambridge, MA 02139, USA.
18 *
19 */
20
21
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <stddef.h>
25 #include <unistd.h>
26 #include <fcntl.h>
27 #include <errno.h>
28 #include <dirent.h>
29 #include <sys/stat.h>
30 #include <sys/mman.h>
31
32 #include "udev.h"
33 #include "logging.h"
34 #include "udev_lib.h"
35 #include "list.h"
36
37
38 char *get_action(void)
39 {
40 char *action;
41
42 action = getenv("ACTION");
43 if (action != NULL && strlen(action) > ACTION_SIZE)
44 action[ACTION_SIZE-1] = '\0';
45
46 return action;
47 }
48
49 char *get_devpath(void)
50 {
51 char *devpath;
52
53 devpath = getenv("DEVPATH");
54 if (devpath != NULL && strlen(devpath) > DEVPATH_SIZE)
55 devpath[DEVPATH_SIZE-1] = '\0';
56
57 return devpath;
58 }
59
60 char *get_devname(void)
61 {
62 char *devname;
63
64 devname = getenv("DEVNAME");
65 if (devname != NULL && strlen(devname) > NAME_SIZE)
66 devname[NAME_SIZE-1] = '\0';
67
68 return devname;
69 }
70
71 char *get_seqnum(void)
72 {
73 char *seqnum;
74
75 seqnum = getenv("SEQNUM");
76
77 return seqnum;
78 }
79
80 char *get_subsystem(char *subsystem)
81 {
82 if (subsystem != NULL && strlen(subsystem) > SUBSYSTEM_SIZE)
83 subsystem[SUBSYSTEM_SIZE-1] = '\0';
84
85 return subsystem;
86 }
87
88 #define BLOCK_PATH "/block/"
89 #define CLASS_PATH "/class/"
90 #define NET_PATH "/class/net/"
91
92 char get_device_type(const char *path, const char *subsystem)
93 {
94 if (strcmp(subsystem, "block") == 0)
95 return 'b';
96
97 if (strcmp(subsystem, "net") == 0)
98 return 'n';
99
100 if (strncmp(path, BLOCK_PATH, strlen(BLOCK_PATH)) == 0 &&
101 strlen(path) > strlen(BLOCK_PATH))
102 return 'b';
103
104 if (strncmp(path, NET_PATH, strlen(NET_PATH)) == 0 &&
105 strlen(path) > strlen(NET_PATH))
106 return 'n';
107
108 if (strncmp(path, CLASS_PATH, strlen(CLASS_PATH)) == 0 &&
109 strlen(path) > strlen(CLASS_PATH))
110 return 'c';
111
112 return '\0';
113 }
114
115 void udev_set_values(struct udevice *udev, const char* devpath, const char *subsystem)
116 {
117 memset(udev, 0x00, sizeof(struct udevice));
118 strfieldcpy(udev->devpath, devpath);
119 strfieldcpy(udev->subsystem, subsystem);
120 udev->type = get_device_type(devpath, subsystem);
121 }
122
123 int file_map(const char *filename, char **buf, size_t *bufsize)
124 {
125 struct stat stats;
126 int fd;
127
128 fd = open(filename, O_RDONLY);
129 if (fd < 0) {
130 return -1;
131 }
132
133 if (fstat(fd, &stats) < 0) {
134 close(fd);
135 return -1;
136 }
137
138 *buf = mmap(NULL, stats.st_size, PROT_READ, MAP_SHARED, fd, 0);
139 if (*buf == MAP_FAILED) {
140 close(fd);
141 return -1;
142 }
143 *bufsize = stats.st_size;
144
145 close(fd);
146
147 return 0;
148 }
149
150 void file_unmap(char *buf, size_t bufsize)
151 {
152 munmap(buf, bufsize);
153 }
154
155 size_t buf_get_line(char *buf, size_t buflen, size_t cur)
156 {
157 size_t count = 0;
158
159 for (count = cur; count < buflen && buf[count] != '\n'; count++);
160
161 return count - cur;
162 }
163
164 void leading_slash(char *path)
165 {
166 int len;
167
168 len = strlen(path);
169 if (len > 0 && path[len-1] != '/') {
170 path[len] = '/';
171 path[len+1] = '\0';
172 }
173 }
174
175 void no_leading_slash(char *path)
176 {
177 int len;
178
179 len = strlen(path);
180 if (len > 0 && path[len-1] == '/')
181 path[len-1] = '\0';
182 }
183
184 struct files {
185 struct list_head list;
186 char name[NAME_SIZE];
187 };
188
189 /* sort files in lexical order */
190 static int file_list_insert(char *filename, struct list_head *file_list)
191 {
192 struct files *loop_file;
193 struct files *new_file;
194
195 list_for_each_entry(loop_file, file_list, list) {
196 if (strcmp(loop_file->name, filename) > 0) {
197 break;
198 }
199 }
200
201 new_file = malloc(sizeof(struct files));
202 if (new_file == NULL) {
203 dbg("error malloc");
204 return -ENOMEM;
205 }
206
207 strfieldcpy(new_file->name, filename);
208 list_add_tail(&new_file->list, &loop_file->list);
209 return 0;
210 }
211
212 /* calls function for every file found in specified directory */
213 int call_foreach_file(int fnct(char *f) , char *dirname, char *suffix)
214 {
215 struct dirent *ent;
216 DIR *dir;
217 char *ext;
218 char file[NAME_SIZE];
219 struct files *loop_file;
220 struct files *tmp_file;
221 LIST_HEAD(file_list);
222
223 dbg("open directory '%s'", dirname);
224 dir = opendir(dirname);
225 if (dir == NULL) {
226 dbg("unable to open '%s'", dirname);
227 return -1;
228 }
229
230 while (1) {
231 ent = readdir(dir);
232 if (ent == NULL || ent->d_name[0] == '\0')
233 break;
234
235 if ((ent->d_name[0] == '.') || (ent->d_name[0] == COMMENT_CHARACTER))
236 continue;
237
238 /* look for file with specified suffix */
239 ext = strrchr(ent->d_name, '.');
240 if (ext == NULL)
241 continue;
242
243 if (strcmp(ext, suffix) != 0)
244 continue;
245
246 dbg("put file '%s/%s' in list", dirname, ent->d_name);
247 file_list_insert(ent->d_name, &file_list);
248 }
249
250 /* call function for every file in the list */
251 list_for_each_entry_safe(loop_file, tmp_file, &file_list, list) {
252 strfieldcpy(file, dirname);
253 strfieldcat(file, "/");
254 strfieldcat(file, loop_file->name);
255
256 fnct(file);
257
258 list_del(&loop_file->list);
259 free(loop_file);
260 }
261
262 closedir(dir);
263 return 0;
264 }
265
266 /* Set the FD_CLOEXEC flag of desc if value is nonzero,
267 or clear the flag if value is 0.
268 Return 0 on success, or -1 on error with errno set. */
269
270 int set_cloexec_flag (int desc, int value)
271 {
272 int oldflags = fcntl (desc, F_GETFD, 0);
273 /* If reading the flags failed, return error indication now. */
274 if (oldflags < 0)
275 return oldflags;
276 /* Set just the flag we want to set. */
277 if (value != 0)
278 oldflags |= FD_CLOEXEC;
279 else
280 oldflags &= ~FD_CLOEXEC;
281 /* Store modified flag word in the descriptor. */
282 return fcntl (desc, F_SETFD, oldflags);
283 }