]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/udev/libudev-util-private.c
udev: fix a few issues detected by the llvm static analyzer
[thirdparty/systemd.git] / src / udev / libudev-util-private.c
CommitLineData
c81b35c0 1/*
44b49d37 2 * libudev - interface to udev device information
c81b35c0 3 *
fc206fbe 4 * Copyright (C) 2003-2009 Kay Sievers <kay.sievers@vrfy.org>
c81b35c0 5 *
44b49d37
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.
c81b35c0
KS
10 */
11
c81b35c0
KS
12#include <stdlib.h>
13#include <stdio.h>
4a539daf 14#include <stddef.h>
c81b35c0 15#include <unistd.h>
01618658 16#include <string.h>
c81b35c0 17#include <fcntl.h>
4a539daf 18#include <errno.h>
9f8dfa19 19#include <ctype.h>
3a020a85
KS
20#include <pwd.h>
21#include <grp.h>
257bb4cd 22#include <sys/param.h>
c81b35c0 23
44b49d37
KS
24#include "libudev.h"
25#include "libudev-private.h"
c81b35c0 26
51f43b53 27static int create_path(struct udev *udev, const char *path, bool selinux)
4a539daf 28{
912541b0
KS
29 char p[UTIL_PATH_SIZE];
30 char *pos;
31 struct stat stats;
32 int err;
33
34 util_strscpy(p, sizeof(p), path);
35 pos = strrchr(p, '/');
36 if (pos == NULL)
37 return 0;
38 while (pos != p && pos[-1] == '/')
39 pos--;
40 if (pos == p)
41 return 0;
42 pos[0] = '\0';
43
912541b0
KS
44 if (stat(p, &stats) == 0) {
45 if ((stats.st_mode & S_IFMT) == S_IFDIR)
46 return 0;
47 else
48 return -ENOTDIR;
49 }
50
51 err = util_create_path(udev, p);
52 if (err != 0)
53 return err;
54
912541b0
KS
55 if (selinux)
56 udev_selinux_setfscreatecon(udev, p, S_IFDIR|0755);
57 err = mkdir(p, 0755);
58 if (err != 0) {
59 err = -errno;
60 if (err == -EEXIST && stat(p, &stats) == 0) {
61 if ((stats.st_mode & S_IFMT) == S_IFDIR)
62 err = 0;
63 else
64 err = -ENOTDIR;
65 }
66 }
67 if (selinux)
68 udev_selinux_resetfscreatecon(udev);
69 return err;
a390e6f7 70}
4a539daf 71
51f43b53
KS
72int util_create_path(struct udev *udev, const char *path)
73{
912541b0 74 return create_path(udev, path, false);
51f43b53
KS
75}
76
77int util_create_path_selinux(struct udev *udev, const char *path)
78{
912541b0 79 return create_path(udev, path, true);
51f43b53
KS
80}
81
54808d77 82int util_delete_path(struct udev *udev, const char *path)
a390e6f7 83{
912541b0
KS
84 char p[UTIL_PATH_SIZE];
85 char *pos;
86 int err = 0;
87
88 if (path[0] == '/')
89 while(path[1] == '/')
90 path++;
91 util_strscpy(p, sizeof(p), path);
92 pos = strrchr(p, '/');
93 if (pos == p || pos == NULL)
94 return 0;
95
96 for (;;) {
97 *pos = '\0';
98 pos = strrchr(p, '/');
99
100 /* don't remove the last one */
101 if ((pos == p) || (pos == NULL))
102 break;
103
104 err = rmdir(p);
105 if (err < 0) {
106 if (errno == ENOENT)
107 err = 0;
108 break;
109 }
110 }
111 return err;
b8476286
KS
112}
113
54808d77 114uid_t util_lookup_user(struct udev *udev, const char *user)
3a020a85 115{
912541b0 116 char *endptr;
912541b0
KS
117 struct passwd pwbuf;
118 struct passwd *pw;
119 uid_t uid;
fc863dea
KS
120 size_t buflen = sysconf(_SC_GETPW_R_SIZE_MAX);
121 char *buf = alloca(buflen);
912541b0
KS
122
123 if (strcmp(user, "root") == 0)
124 return 0;
125 uid = strtoul(user, &endptr, 10);
126 if (endptr[0] == '\0')
127 return uid;
128
129 errno = getpwnam_r(user, &pwbuf, buf, buflen, &pw);
130 if (pw != NULL)
131 return pw->pw_uid;
132 if (errno == 0 || errno == ENOENT || errno == ESRCH)
133 err(udev, "specified user '%s' unknown\n", user);
134 else
135 err(udev, "error resolving user '%s': %m\n", user);
136 return 0;
90024521 137}
3a020a85 138
37ed4f56 139gid_t util_lookup_group(struct udev *udev, const char *group)
90024521 140{
912541b0 141 char *endptr;
912541b0
KS
142 struct group grbuf;
143 struct group *gr;
144 gid_t gid = 0;
fc863dea 145 size_t buflen = sysconf(_SC_GETPW_R_SIZE_MAX);
b49d9b50 146 char *buf = NULL;
912541b0
KS
147
148 if (strcmp(group, "root") == 0)
149 return 0;
150 gid = strtoul(group, &endptr, 10);
151 if (endptr[0] == '\0')
152 return gid;
912541b0
KS
153 gid = 0;
154 for (;;) {
155 char *newbuf;
156
157 newbuf = realloc(buf, buflen);
158 if (!newbuf)
159 break;
160 buf = newbuf;
161 errno = getgrnam_r(group, &grbuf, buf, buflen, &gr);
162 if (gr != NULL) {
163 gid = gr->gr_gid;
164 } else if (errno == ERANGE) {
165 buflen *= 2;
166 continue;
167 } else if (errno == 0 || errno == ENOENT || errno == ESRCH) {
168 err(udev, "specified group '%s' unknown\n", group);
169 } else {
170 err(udev, "error resolving group '%s': %m\n", group);
171 }
172 break;
173 }
174 free(buf);
175 return gid;
90024521 176}
d0db192f 177
14f40256
KS
178/* handle "[<SUBSYSTEM>/<KERNEL>]<attribute>" format */
179int util_resolve_subsys_kernel(struct udev *udev, const char *string,
912541b0 180 char *result, size_t maxsize, int read_value)
14f40256 181{
912541b0
KS
182 char temp[UTIL_PATH_SIZE];
183 char *subsys;
184 char *sysname;
185 struct udev_device *dev;
186 char *attr;
187
188 if (string[0] != '[')
189 return -1;
190
191 util_strscpy(temp, sizeof(temp), string);
192
193 subsys = &temp[1];
194
195 sysname = strchr(subsys, '/');
196 if (sysname == NULL)
197 return -1;
198 sysname[0] = '\0';
199 sysname = &sysname[1];
200
201 attr = strchr(sysname, ']');
202 if (attr == NULL)
203 return -1;
204 attr[0] = '\0';
205 attr = &attr[1];
206 if (attr[0] == '/')
207 attr = &attr[1];
208 if (attr[0] == '\0')
209 attr = NULL;
210
211 if (read_value && attr == NULL)
212 return -1;
213
214 dev = udev_device_new_from_subsystem_sysname(udev, subsys, sysname);
215 if (dev == NULL)
216 return -1;
217
218 if (read_value) {
219 const char *val;
220
221 val = udev_device_get_sysattr_value(dev, attr);
222 if (val != NULL)
223 util_strscpy(result, maxsize, val);
224 else
225 result[0] = '\0';
baa30fbc 226 dbg(udev, "value '[%s/%s]%s' is '%s'\n", subsys, sysname, attr, result);
912541b0
KS
227 } else {
228 size_t l;
229 char *s;
230
231 s = result;
232 l = util_strpcpyl(&s, maxsize, udev_device_get_syspath(dev), NULL);
233 if (attr != NULL)
234 util_strpcpyl(&s, l, "/", attr, NULL);
baa30fbc 235 dbg(udev, "path '[%s/%s]%s' is '%s'\n", subsys, sysname, attr, result);
912541b0
KS
236 }
237 udev_device_unref(dev);
238 return 0;
14f40256 239}