chiark / gitweb /
1649b8cbf0349e4dcf6bd7a27cf465e877eefcdb
[elogind.git] / udev / udev_utils.c
1 /*
2  * Copyright (C) 2004-2005 Kay Sievers <kay.sievers@vrfy.org>
3  *
4  *      This program is free software; you can redistribute it and/or modify it
5  *      under the terms of the GNU General Public License as published by the
6  *      Free Software Foundation version 2 of the License.
7  * 
8  *      This program is distributed in the hope that it will be useful, but
9  *      WITHOUT ANY WARRANTY; without even the implied warranty of
10  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  *      General Public License for more details.
12  * 
13  *      You should have received a copy of the GNU General Public License along
14  *      with this program; if not, write to the Free Software Foundation, Inc.,
15  *      51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
16  *
17  */
18
19
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <stddef.h>
23 #include <unistd.h>
24 #include <string.h>
25 #include <fcntl.h>
26 #include <errno.h>
27 #include <ctype.h>
28 #include <dirent.h>
29 #include <syslog.h>
30 #include <pwd.h>
31 #include <grp.h>
32 #include <sys/types.h>
33 #include <sys/utsname.h>
34
35 #include "udev.h"
36
37
38 int log_priority(const char *priority)
39 {
40         char *endptr;
41         int prio;
42
43         prio = strtol(priority, &endptr, 10);
44         if (endptr[0] == '\0')
45                 return prio;
46         if (strncasecmp(priority, "err", 3) == 0)
47                 return LOG_ERR;
48         if (strcasecmp(priority, "info") == 0)
49                 return LOG_INFO;
50         if (strcasecmp(priority, "debug") == 0)
51                 return LOG_DEBUG;
52         if (string_is_true(priority))
53                 return LOG_ERR;
54
55         return 0;
56 }
57
58 struct name_entry *name_list_add(struct udev *udev, struct list_head *name_list, const char *name, int sort)
59 {
60         struct name_entry *name_loop;
61         struct name_entry *name_new;
62
63         /* avoid duplicate entries */
64         list_for_each_entry(name_loop, name_list, node) {
65                 if (strcmp(name_loop->name, name) == 0) {
66                         dbg(udev, "'%s' is already in the list\n", name);
67                         return name_loop;
68                 }
69         }
70
71         if (sort)
72                 list_for_each_entry(name_loop, name_list, node) {
73                         if (strcmp(name_loop->name, name) > 0)
74                                 break;
75                 }
76
77         name_new = malloc(sizeof(struct name_entry));
78         if (name_new == NULL)
79                 return NULL;
80         memset(name_new, 0x00, sizeof(struct name_entry));
81         strlcpy(name_new->name, name, sizeof(name_new->name));
82         dbg(udev, "adding '%s'\n", name_new->name);
83         list_add_tail(&name_new->node, &name_loop->node);
84
85         return name_new;
86 }
87
88 struct name_entry *name_list_key_add(struct udev *udev, struct list_head *name_list, const char *key, const char *value)
89 {
90         struct name_entry *name_loop;
91         struct name_entry *name_new;
92
93         list_for_each_entry(name_loop, name_list, node) {
94                 if (strncmp(name_loop->name, key, strlen(key)) == 0) {
95                         dbg(udev, "key already present '%s', replace it\n", name_loop->name);
96                         snprintf(name_loop->name, sizeof(name_loop->name), "%s=%s", key, value);
97                         name_loop->name[sizeof(name_loop->name)-1] = '\0';
98                         return name_loop;
99                 }
100         }
101
102         name_new = malloc(sizeof(struct name_entry));
103         if (name_new == NULL)
104                 return NULL;
105         memset(name_new, 0x00, sizeof(struct name_entry));
106         snprintf(name_new->name, sizeof(name_new->name), "%s=%s", key, value);
107         name_new->name[sizeof(name_new->name)-1] = '\0';
108         dbg(udev, "adding '%s'\n", name_new->name);
109         list_add_tail(&name_new->node, &name_loop->node);
110
111         return name_new;
112 }
113
114 int name_list_key_remove(struct udev *udev, struct list_head *name_list, const char *key)
115 {
116         struct name_entry *name_loop;
117         struct name_entry *name_tmp;
118         size_t keylen = strlen(key);
119         int retval = 0;
120
121         list_for_each_entry_safe(name_loop, name_tmp, name_list, node) {
122                 if (strncmp(name_loop->name, key, keylen) != 0)
123                         continue;
124                 if (name_loop->name[keylen] != '=')
125                         continue;
126                 list_del(&name_loop->node);
127                 free(name_loop);
128                 retval = 1;
129                 break;
130         }
131         return retval;
132 }
133
134 void name_list_cleanup(struct udev *udev, struct list_head *name_list)
135 {
136         struct name_entry *name_loop;
137         struct name_entry *name_tmp;
138
139         list_for_each_entry_safe(name_loop, name_tmp, name_list, node) {
140                 list_del(&name_loop->node);
141                 free(name_loop);
142         }
143 }
144
145 /* calls function for every file found in specified directory */
146 int add_matching_files(struct udev *udev, struct list_head *name_list, const char *dirname, const char *suffix)
147 {
148         struct dirent *ent;
149         DIR *dir;
150         char filename[PATH_SIZE];
151
152         dbg(udev, "open directory '%s'\n", dirname);
153         dir = opendir(dirname);
154         if (dir == NULL) {
155                 err(udev, "unable to open '%s': %s\n", dirname, strerror(errno));
156                 return -1;
157         }
158
159         while (1) {
160                 ent = readdir(dir);
161                 if (ent == NULL || ent->d_name[0] == '\0')
162                         break;
163
164                 if ((ent->d_name[0] == '.') || (ent->d_name[0] == COMMENT_CHARACTER))
165                         continue;
166
167                 /* look for file matching with specified suffix */
168                 if (suffix != NULL) {
169                         const char *ext;
170
171                         ext = strrchr(ent->d_name, '.');
172                         if (ext == NULL)
173                                 continue;
174                         if (strcmp(ext, suffix) != 0)
175                                 continue;
176                 }
177                 dbg(udev, "put file '%s/%s' into list\n", dirname, ent->d_name);
178
179                 snprintf(filename, sizeof(filename), "%s/%s", dirname, ent->d_name);
180                 filename[sizeof(filename)-1] = '\0';
181                 name_list_add(udev, name_list, filename, 1);
182         }
183
184         closedir(dir);
185         return 0;
186 }
187
188 uid_t lookup_user(struct udev *udev, const char *user)
189 {
190         struct passwd *pw;
191         uid_t uid = 0;
192
193         errno = 0;
194         pw = getpwnam(user);
195         if (pw == NULL) {
196                 if (errno == 0 || errno == ENOENT || errno == ESRCH)
197                         err(udev, "specified user '%s' unknown\n", user);
198                 else
199                         err(udev, "error resolving user '%s': %s\n", user, strerror(errno));
200         } else
201                 uid = pw->pw_uid;
202
203         return uid;
204 }
205
206 extern gid_t lookup_group(struct udev *udev, const char *group)
207 {
208         struct group *gr;
209         gid_t gid = 0;
210
211         errno = 0;
212         gr = getgrnam(group);
213         if (gr == NULL) {
214                 if (errno == 0 || errno == ENOENT || errno == ESRCH)
215                         err(udev, "specified group '%s' unknown\n", group);
216                 else
217                         err(udev, "error resolving group '%s': %s\n", group, strerror(errno));
218         } else
219                 gid = gr->gr_gid;
220
221         return gid;
222 }
223