chiark / gitweb /
59c4d194dd4d1a447a9f29bd5035eb22205ced70
[elogind.git] / udev / udev-util.c
1 /*
2  * Copyright (C) 2004-2008 Kay Sievers <kay.sievers@vrfy.org>
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 #include <stdlib.h>
19 #include <stdio.h>
20 #include <stddef.h>
21 #include <unistd.h>
22 #include <string.h>
23 #include <fcntl.h>
24 #include <errno.h>
25 #include <ctype.h>
26 #include <pwd.h>
27 #include <grp.h>
28
29 #include "udev.h"
30
31 int create_path(struct udev *udev, const char *path)
32 {
33         char p[UTIL_PATH_SIZE];
34         char *pos;
35         struct stat stats;
36         int ret;
37
38         util_strlcpy(p, path, sizeof(p));
39         pos = strrchr(p, '/');
40         if (pos == p || pos == NULL)
41                 return 0;
42
43         while (pos[-1] == '/')
44                 pos--;
45         pos[0] = '\0';
46
47         dbg(udev, "stat '%s'\n", p);
48         if (stat(p, &stats) == 0 && (stats.st_mode & S_IFMT) == S_IFDIR)
49                 return 0;
50
51         if (create_path(udev, p) != 0)
52                 return -1;
53
54         dbg(udev, "mkdir '%s'\n", p);
55         udev_selinux_setfscreatecon(udev, p, S_IFDIR|0755);
56         ret = mkdir(p, 0755);
57         udev_selinux_resetfscreatecon(udev);
58         if (ret == 0)
59                 return 0;
60
61         if (errno == EEXIST)
62                 if (stat(p, &stats) == 0 && (stats.st_mode & S_IFMT) == S_IFDIR)
63                         return 0;
64         return -1;
65 }
66
67 int delete_path(struct udev *udev, const char *path)
68 {
69         char p[UTIL_PATH_SIZE];
70         char *pos;
71         int retval;
72
73         strcpy (p, path);
74         pos = strrchr(p, '/');
75         if (pos == p || pos == NULL)
76                 return 0;
77
78         while (1) {
79                 *pos = '\0';
80                 pos = strrchr(p, '/');
81
82                 /* don't remove the last one */
83                 if ((pos == p) || (pos == NULL))
84                         break;
85
86                 /* remove if empty */
87                 retval = rmdir(p);
88                 if (errno == ENOENT)
89                         retval = 0;
90                 if (retval) {
91                         if (errno == ENOTEMPTY)
92                                 return 0;
93                         err(udev, "rmdir(%s) failed: %m\n", p);
94                         break;
95                 }
96                 dbg(udev, "removed '%s'\n", p);
97         }
98         return 0;
99 }
100
101 /* Reset permissions on the device node, before unlinking it to make sure,
102  * that permisions of possible hard links will be removed too.
103  */
104 int unlink_secure(struct udev *udev, const char *filename)
105 {
106         int retval;
107
108         retval = chown(filename, 0, 0);
109         if (retval)
110                 err(udev, "chown(%s, 0, 0) failed: %m\n", filename);
111
112         retval = chmod(filename, 0000);
113         if (retval)
114                 err(udev, "chmod(%s, 0000) failed: %m\n", filename);
115
116         retval = unlink(filename);
117         if (errno == ENOENT)
118                 retval = 0;
119
120         if (retval)
121                 err(udev, "unlink(%s) failed: %m\n", filename);
122
123         return retval;
124 }
125
126 uid_t lookup_user(struct udev *udev, const char *user)
127 {
128         struct passwd *pw;
129         uid_t uid = 0;
130
131         errno = 0;
132         pw = getpwnam(user);
133         if (pw == NULL) {
134                 if (errno == 0 || errno == ENOENT || errno == ESRCH)
135                         err(udev, "specified user '%s' unknown\n", user);
136                 else
137                         err(udev, "error resolving user '%s': %m\n", user);
138         } else
139                 uid = pw->pw_uid;
140
141         return uid;
142 }
143
144 extern gid_t lookup_group(struct udev *udev, const char *group)
145 {
146         struct group *gr;
147         gid_t gid = 0;
148
149         errno = 0;
150         gr = getgrnam(group);
151         if (gr == NULL) {
152                 if (errno == 0 || errno == ENOENT || errno == ESRCH)
153                         err(udev, "specified group '%s' unknown\n", group);
154                 else
155                         err(udev, "error resolving group '%s': %m\n", group);
156         } else
157                 gid = gr->gr_gid;
158
159         return gid;
160 }