chiark / gitweb /
[PATCH] change key names in udevinfo sysfs walk to match the kernel
[elogind.git] / udev_db.c
1 /*
2  * udev_db.c
3  *
4  * Userspace devfs
5  *
6  * Copyright (C) 2003 Greg Kroah-Hartman <greg@kroah.com>
7  * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
8  *
9  *      This program is free software; you can redistribute it and/or modify it
10  *      under the terms of the GNU General Public License as published by the
11  *      Free Software Foundation version 2 of the License.
12  * 
13  *      This program is distributed in the hope that it will be useful, but
14  *      WITHOUT ANY WARRANTY; without even the implied warranty of
15  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  *      General Public License for more details.
17  * 
18  *      You should have received a copy of the GNU General Public License along
19  *      with this program; if not, write to the Free Software Foundation, Inc.,
20  *      675 Mass Ave, Cambridge, MA 02139, USA.
21  *
22  */
23
24
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <stddef.h>
29 #include <fcntl.h>
30 #include <string.h>
31 #include <errno.h>
32 #include <dirent.h>
33
34 #include "libsysfs/sysfs/libsysfs.h"
35 #include "udev.h"
36 #include "udev_lib.h"
37 #include "logging.h"
38 #include "udev_db.h"
39
40 #define PATH_TO_NAME_CHAR               '@'
41
42 static int get_db_filename(struct udevice *udev, char *filename, int len)
43 {
44         char devpath[SYSFS_PATH_MAX];
45         char *pos;
46
47         /* replace '/' to transform path into a filename */
48         strfieldcpy(devpath, udev->devpath);
49         pos = strchr(&devpath[1], '/');
50         while (pos) {
51                 pos[0] = PATH_TO_NAME_CHAR;
52                 pos = strchr(&pos[1], '/');
53         }
54         snprintf(filename, len, "%s%s", udev_db_path, devpath);
55         filename[len-1] = '\0';
56
57         return 0;
58 }
59
60 int udev_db_add_device(struct udevice *udev)
61 {
62         char filename[SYSFS_PATH_MAX];
63         FILE *f;
64
65         if (udev->test_run)
66                 return 0;
67
68         get_db_filename(udev, filename, SYSFS_PATH_MAX);
69
70         create_path(filename);
71
72         f = fopen(filename, "w");
73         if (f == NULL) {
74                 dbg("unable to create db file '%s'", filename);
75                 return -1;
76         }
77         dbg("storing data for device '%s' in '%s'", udev->devpath, filename);
78
79         fprintf(f, "P:%s\n", udev->devpath);
80         fprintf(f, "N:%s\n", udev->name);
81         fprintf(f, "S:%s\n", udev->symlink);
82         fprintf(f, "A:%u\n", udev->partitions);
83         fprintf(f, "R:%u\n", udev->ignore_remove);
84
85         fclose(f);
86
87         return 0;
88 }
89
90 static int parse_db_file(struct udevice *udev, const char *filename)
91 {
92         char line[NAME_SIZE];
93         char *bufline;
94         char *buf;
95         size_t bufsize;
96         size_t cur;
97         size_t count;
98
99         if (file_map(filename, &buf, &bufsize) != 0) {
100                 dbg("unable to read db file '%s'", filename);
101                 return -1;
102         }
103
104         cur = 0;
105         while (cur < bufsize) {
106                 count = buf_get_line(buf, bufsize, cur);
107                 bufline = &buf[cur];
108                 cur += count+1;
109
110                 switch(bufline[0]) {
111                 case 'P':
112                         if (count > DEVPATH_SIZE)
113                                 count = DEVPATH_SIZE-1;
114                         strncpy(udev->devpath, &bufline[2], count-2);
115                         udev->devpath[count-2] = '\0';
116                         break;
117                 case 'N':
118                         if (count > NAME_SIZE)
119                                 count = NAME_SIZE-1;
120                         strncpy(udev->name, &bufline[2], count-2);
121                         udev->name[count-2] = '\0';
122                         break;
123                 case 'S':
124                         if (count > NAME_SIZE)
125                                 count = NAME_SIZE-1;
126                         strncpy(udev->symlink, &bufline[2], count-2);
127                         udev->symlink[count-2] = '\0';
128                         break;
129                 case 'A':
130                         if (count > NAME_SIZE)
131                                 count = NAME_SIZE-1;
132                         strncpy(line, &bufline[2], count-2);
133                         line[count-2] = '\0';
134                         udev->partitions = atoi(line);
135                         break;
136                 case 'R':
137                         if (count > NAME_SIZE)
138                                 count = NAME_SIZE-1;
139                         strncpy(line, &bufline[2], count-2);
140                         line[count-2] = '\0';
141                         udev->ignore_remove = atoi(line);
142                         break;
143                 }
144         }
145
146         if (udev->name[0] == '\0')
147                 return -1;
148
149         return 0;
150 }
151
152 int udev_db_get_device(struct udevice *udev)
153 {
154         char filename[SYSFS_PATH_MAX];
155
156         get_db_filename(udev, filename, SYSFS_PATH_MAX);
157
158         return parse_db_file(udev, filename);
159 }
160
161 int udev_db_delete_device(struct udevice *udev)
162 {
163         char filename[SYSFS_PATH_MAX];
164
165         get_db_filename(udev, filename, SYSFS_PATH_MAX);
166         unlink(filename);
167
168         return 0;
169 }
170
171 int udev_db_get_device_byname(struct udevice *udev, const char *name)
172 {
173         struct dirent *ent;
174         DIR *dir;
175         char filename[NAME_SIZE];
176         struct udevice db_udev;
177
178         dir = opendir(udev_db_path);
179         if (dir == NULL) {
180                 dbg("unable to udev db '%s'", udev_db_path);
181                 return -1;
182         }
183
184         while (1) {
185                 ent = readdir(dir);
186                 if (ent == NULL || ent->d_name[0] == '\0')
187                         break;
188
189                 if (ent->d_name[0] == '.')
190                         continue;
191
192                 snprintf(filename, NAME_SIZE, "%s/%s", udev_db_path, ent->d_name);
193                 filename[NAME_SIZE-1] = '\0';
194
195                 memset(&db_udev, 0x00, sizeof(struct udevice));
196                 if (parse_db_file(&db_udev, filename) == 0) {
197                         char *pos;
198                         int len;
199
200                         if (strncmp(name, db_udev.name, NAME_SIZE) == 0) {
201                                 goto found;
202                         }
203
204                         foreach_strpart(db_udev.symlink, " ", pos, len) {
205                                 if (strncmp(name, pos, len) != 0)
206                                         continue;
207
208                                 if (len == strlen(name))
209                                         goto found;
210                         }
211
212                 }
213         }
214
215         closedir(dir);
216
217         return -1;
218
219 found:
220         closedir(dir);
221
222         strfieldcpy(udev->devpath, db_udev.devpath);
223         strfieldcpy(udev->name, db_udev.name);
224         strfieldcpy(udev->symlink, db_udev.symlink);
225         udev->partitions = db_udev.partitions;
226
227         return 0;
228 }