chiark / gitweb /
fc579a94512155a514186347d20fed76d5a80e63
[elogind.git] / udevdb.c
1 /*
2  * udevdb.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 "udevdb.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-1, "%s%s", udev_db_path, devpath);
55         filename[len-1] = '\0';
56
57         return 0;
58 }
59
60 int udevdb_add_dev(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:%d\n", udev->partitions);
83
84         fclose(f);
85
86         return 0;
87 }
88
89 static int parse_db_file(struct udevice *udev, const char *filename)
90 {
91         char line[NAME_SIZE];
92         char *bufline;
93         char *buf;
94         size_t bufsize;
95         size_t cur;
96         size_t count;
97
98         if (file_map(filename, &buf, &bufsize) != 0) {
99                 dbg("unable to read db file '%s'", filename);
100                 return -1;
101         }
102
103         cur = 0;
104         while (cur < bufsize) {
105                 count = buf_get_line(buf, bufsize, cur);
106                 bufline = &buf[cur];
107                 cur += count+1;
108
109                 switch(bufline[0]) {
110                 case 'P':
111                         if (count > DEVPATH_SIZE)
112                                 count = DEVPATH_SIZE-1;
113                         strncpy(udev->devpath, &bufline[2], count-2);
114                         break;
115                 case 'N':
116                         if (count > NAME_SIZE)
117                                 count = NAME_SIZE-1;
118                         strncpy(udev->name, &bufline[2], count-2);
119                         break;
120                 case 'S':
121                         if (count > NAME_SIZE)
122                                 count = NAME_SIZE-1;
123                         strncpy(udev->symlink, &bufline[2], count-2);
124                         break;
125                 case 'A':
126                         strfieldcpy(line, &bufline[2]);
127                         udev->partitions = atoi(line);
128                         break;
129                 }
130         }
131
132         if (udev->name[0] == '\0')
133                 return -1;
134
135         return 0;
136 }
137
138 int udevdb_get_dev(struct udevice *udev)
139 {
140         char filename[SYSFS_PATH_MAX];
141
142         get_db_filename(udev, filename, SYSFS_PATH_MAX);
143
144         return parse_db_file(udev, filename);
145 }
146
147 int udevdb_delete_dev(struct udevice *udev)
148 {
149         char filename[SYSFS_PATH_MAX];
150
151         get_db_filename(udev, filename, SYSFS_PATH_MAX);
152         unlink(filename);
153
154         return 0;
155 }
156
157 int udevdb_get_dev_byname(struct udevice *udev, const char *name)
158 {
159         struct dirent *ent;
160         DIR *dir;
161         char filename[NAME_SIZE];
162         struct udevice db_udev;
163
164         dir = opendir(udev_db_path);
165         if (dir == NULL) {
166                 dbg("unable to udev db '%s'", udev_db_path);
167                 return -1;
168         }
169
170         while (1) {
171                 ent = readdir(dir);
172                 if (ent == NULL || ent->d_name[0] == '\0')
173                         break;
174
175                 if (ent->d_name[0] == '.')
176                         continue;
177
178                 snprintf(filename, NAME_SIZE-1, "%s/%s", udev_db_path, ent->d_name);
179                 filename[NAME_SIZE-1] = '\0';
180
181                 memset(&db_udev, 0x00, sizeof(struct udevice));
182                 if (parse_db_file(&db_udev, filename) == 0) {
183                         char *pos;
184                         int len;
185
186                         if (strncmp(name, db_udev.name, NAME_SIZE) == 0) {
187                                 goto found;
188                         }
189
190                         foreach_strpart(db_udev.symlink, " ", pos, len) {
191                                 if (strncmp(name, pos, len) != 0)
192                                         continue;
193
194                                 if (len == strlen(name))
195                                         goto found;
196                         }
197
198                 }
199         }
200
201         closedir(dir);
202
203         return -1;
204
205 found:
206         closedir(dir);
207
208         strfieldcpy(udev->devpath, db_udev.devpath);
209         strfieldcpy(udev->name, db_udev.name);
210         strfieldcpy(udev->symlink, db_udev.symlink);
211         udev->partitions = db_udev.partitions;
212
213         return 0;
214 }