]>
Commit | Line | Data |
---|---|---|
8dfc8dbe | 1 | /* |
02fa9ae5 | 2 | * udev_db.c |
8dfc8dbe GKH |
3 | * |
4 | * Userspace devfs | |
5 | * | |
6 | * Copyright (C) 2003 Greg Kroah-Hartman <greg@kroah.com> | |
2b41e68a | 7 | * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org> |
8dfc8dbe GKH |
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 | ||
2b41e68a | 24 | |
8e41d35d DS |
25 | #include <stdlib.h> |
26 | #include <stdio.h> | |
8ea84a8a | 27 | #include <string.h> |
c81b35c0 | 28 | #include <stddef.h> |
8e41d35d DS |
29 | #include <fcntl.h> |
30 | #include <string.h> | |
8e41d35d | 31 | #include <errno.h> |
2b41e68a | 32 | #include <dirent.h> |
8e41d35d | 33 | |
c80da508 | 34 | #include "libsysfs/sysfs/libsysfs.h" |
6739707d | 35 | #include "udev.h" |
9af5bb2f | 36 | #include "udev_utils.h" |
54988802 | 37 | #include "logging.h" |
02fa9ae5 | 38 | #include "udev_db.h" |
8e41d35d | 39 | |
2b41e68a KS |
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 | } | |
8673dcb8 | 54 | snprintf(filename, len, "%s%s", udev_db_path, devpath); |
2b41e68a KS |
55 | filename[len-1] = '\0'; |
56 | ||
57 | return 0; | |
58 | } | |
ca999860 | 59 | |
02fa9ae5 | 60 | int udev_db_add_device(struct udevice *udev) |
ca999860 | 61 | { |
2b41e68a KS |
62 | char filename[SYSFS_PATH_MAX]; |
63 | FILE *f; | |
ca999860 | 64 | |
5d24c6ca KS |
65 | if (udev->test_run) |
66 | return 0; | |
67 | ||
2b41e68a KS |
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); | |
7e89a569 | 75 | return -1; |
2b41e68a KS |
76 | } |
77 | dbg("storing data for device '%s' in '%s'", udev->devpath, filename); | |
7e89a569 | 78 | |
2b41e68a KS |
79 | fprintf(f, "P:%s\n", udev->devpath); |
80 | fprintf(f, "N:%s\n", udev->name); | |
81 | fprintf(f, "S:%s\n", udev->symlink); | |
7efa217d KS |
82 | fprintf(f, "A:%u\n", udev->partitions); |
83 | fprintf(f, "R:%u\n", udev->ignore_remove); | |
f7b4eca4 | 84 | |
2b41e68a | 85 | fclose(f); |
00866ed2 | 86 | |
2b41e68a | 87 | return 0; |
ca999860 GKH |
88 | } |
89 | ||
2b41e68a | 90 | static int parse_db_file(struct udevice *udev, const char *filename) |
8e41d35d | 91 | { |
2b41e68a KS |
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); | |
7e89a569 | 101 | return -1; |
2b41e68a | 102 | } |
7e89a569 | 103 | |
2b41e68a KS |
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); | |
7efa217d | 115 | udev->devpath[count-2] = '\0'; |
2b41e68a KS |
116 | break; |
117 | case 'N': | |
118 | if (count > NAME_SIZE) | |
119 | count = NAME_SIZE-1; | |
120 | strncpy(udev->name, &bufline[2], count-2); | |
7efa217d | 121 | udev->name[count-2] = '\0'; |
2b41e68a KS |
122 | break; |
123 | case 'S': | |
124 | if (count > NAME_SIZE) | |
125 | count = NAME_SIZE-1; | |
126 | strncpy(udev->symlink, &bufline[2], count-2); | |
7efa217d | 127 | udev->symlink[count-2] = '\0'; |
2b41e68a KS |
128 | break; |
129 | case 'A': | |
7efa217d KS |
130 | if (count > NAME_SIZE) |
131 | count = NAME_SIZE-1; | |
132 | strncpy(line, &bufline[2], count-2); | |
133 | line[count-2] = '\0'; | |
2b41e68a KS |
134 | udev->partitions = atoi(line); |
135 | break; | |
7efa217d KS |
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; | |
2b41e68a KS |
143 | } |
144 | } | |
f7b4eca4 | 145 | |
2b41e68a KS |
146 | if (udev->name[0] == '\0') |
147 | return -1; | |
7a947ce5 | 148 | |
a56ef382 | 149 | return 0; |
8e41d35d DS |
150 | } |
151 | ||
02fa9ae5 | 152 | int udev_db_get_device(struct udevice *udev) |
8e41d35d | 153 | { |
2b41e68a | 154 | char filename[SYSFS_PATH_MAX]; |
a9ce0a41 | 155 | |
2b41e68a | 156 | get_db_filename(udev, filename, SYSFS_PATH_MAX); |
a9ce0a41 | 157 | |
2b41e68a | 158 | return parse_db_file(udev, filename); |
a9ce0a41 GKH |
159 | } |
160 | ||
02fa9ae5 | 161 | int udev_db_delete_device(struct udevice *udev) |
dbfc520c | 162 | { |
2b41e68a KS |
163 | char filename[SYSFS_PATH_MAX]; |
164 | ||
165 | get_db_filename(udev, filename, SYSFS_PATH_MAX); | |
166 | unlink(filename); | |
dbfc520c | 167 | |
5840bc63 | 168 | return 0; |
dbfc520c | 169 | } |
f4dc8d11 | 170 | |
02fa9ae5 | 171 | int udev_db_get_device_byname(struct udevice *udev, const char *name) |
f4dc8d11 | 172 | { |
2b41e68a KS |
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; | |
ee1db00d | 182 | } |
ee1db00d | 183 | |
2b41e68a KS |
184 | while (1) { |
185 | ent = readdir(dir); | |
186 | if (ent == NULL || ent->d_name[0] == '\0') | |
187 | break; | |
ee1db00d | 188 | |
2b41e68a KS |
189 | if (ent->d_name[0] == '.') |
190 | continue; | |
ee1db00d | 191 | |
8673dcb8 | 192 | snprintf(filename, NAME_SIZE, "%s/%s", udev_db_path, ent->d_name); |
2b41e68a | 193 | filename[NAME_SIZE-1] = '\0'; |
b2a21a35 | 194 | |
2b41e68a KS |
195 | memset(&db_udev, 0x00, sizeof(struct udevice)); |
196 | if (parse_db_file(&db_udev, filename) == 0) { | |
197 | char *pos; | |
198 | int len; | |
7e89a569 | 199 | |
2b41e68a KS |
200 | if (strncmp(name, db_udev.name, NAME_SIZE) == 0) { |
201 | goto found; | |
202 | } | |
b2a21a35 | 203 | |
2b41e68a KS |
204 | foreach_strpart(db_udev.symlink, " ", pos, len) { |
205 | if (strncmp(name, pos, len) != 0) | |
206 | continue; | |
b2a21a35 | 207 | |
2b41e68a KS |
208 | if (len == strlen(name)) |
209 | goto found; | |
210 | } | |
211 | ||
212 | } | |
b2a21a35 | 213 | } |
9fe3f9a9 | 214 | |
2b41e68a | 215 | closedir(dir); |
9fe3f9a9 | 216 | |
2b41e68a | 217 | return -1; |
b2a21a35 | 218 | |
2b41e68a KS |
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; | |
b2a21a35 | 228 | } |