1
0
mirror of https://github.com/systemd/systemd.git synced 2025-03-25 18:50:18 +03:00

move /dev/.udev/ to /dev/.run/udev/ and convert old udev database at udevd startup

This commit is contained in:
Kay Sievers 2011-03-15 17:26:08 +01:00
parent 52d54f237d
commit 5f59fa0900
18 changed files with 160 additions and 120 deletions

View File

@ -35,7 +35,7 @@ DISTCHECK_HOOKS =
# libudev
# ------------------------------------------------------------------------------
LIBUDEV_CURRENT=11
LIBUDEV_REVISION=0
LIBUDEV_REVISION=1
LIBUDEV_AGE=11
SUBDIRS += libudev/docs

12
NEWS
View File

@ -2,6 +2,18 @@ udev 167
========
Bugfixes.
The udev runtime data moved from /dev/.udev/ to /dev/.run/udev/.
On new systems the tmpfs mountpoint /var/run/ will have an
"early-boot alias" /dev/.run/ where udev and a couple of other
early-boot tools will put their runtime data.
On systems with LVM used, packagers must make sure, that the
initramfs creates the /dev/.run/ mountpoint for udev to store
the data, so that the real root will not overmount it, which
would make it invisible.
The command 'udevadm info --convert-db' is gone. The udev daemon
itself, at startup, converts any old database version if necessary.
udev 166
========
Bugfixes.

View File

@ -34,7 +34,7 @@
#include "libudev.h"
#include "libudev-private.h"
#define TMPFILE "/dev/.udev/collect"
#define TMPFILE "/dev/.run/udev/collect"
#define BUFSIZE 16
#define UDEV_ALARM_TIMEOUT 180

View File

@ -147,7 +147,7 @@ int main(int argc, char **argv)
}
util_path_encode(firmware, fwencpath, sizeof(fwencpath));
util_strscpyl(misspath, sizeof(misspath), udev_get_dev_path(udev), "/.udev/firmware-missing/", fwencpath, NULL);
util_strscpyl(misspath, sizeof(misspath), udev_get_dev_path(udev), "/.run/udev/firmware-missing/", fwencpath, NULL);
util_strscpyl(loadpath, sizeof(loadpath), udev_get_sys_path(udev), devpath, "/loading", NULL);
if (fwfile == NULL) {

View File

@ -31,7 +31,7 @@ static void udev_device_tag(struct udev_device *dev, const char *tag, bool add)
id = udev_device_get_id_filename(dev);
if (id == NULL)
return;
util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.udev/tags/", tag, "/", id, NULL);
util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.run/udev/tags/", tag, "/", id, NULL);
if (add) {
int fd;
@ -115,7 +115,7 @@ int udev_device_update_db(struct udev_device *udev_device)
return -1;
has_info = device_has_info(udev_device);
util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.udev/db/", id, NULL);
util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.run/udev/db3/", id, NULL);
/* do not store anything for otherwise empty devices */
if (!has_info &&
@ -176,7 +176,7 @@ int udev_device_delete_db(struct udev_device *udev_device)
id = udev_device_get_id_filename(udev_device);
if (id == NULL)
return -1;
util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.udev/db/", id, NULL);
util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.run/udev/db3/", id, NULL);
unlink(filename);
return 0;
}

View File

@ -237,24 +237,30 @@ const char *udev_device_get_property_value(struct udev_device *udev_device, cons
return udev_list_entry_get_value(list_entry);
}
int udev_device_read_db(struct udev_device *udev_device)
int udev_device_read_db(struct udev_device *udev_device, const char *dbfile)
{
const char *id;
char filename[UTIL_PATH_SIZE];
char line[UTIL_LINE_SIZE];
FILE *f;
if (udev_device->db_loaded)
return 0;
udev_device->db_loaded = true;
/* providing a database file will always force-load it */
if (dbfile == NULL) {
const char *id;
id = udev_device_get_id_filename(udev_device);
if (id == NULL)
return -1;
util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_device->udev), "/.udev/db/", id, NULL);
f = fopen(filename, "re");
if (udev_device->db_loaded)
return 0;
udev_device->db_loaded = true;
id = udev_device_get_id_filename(udev_device);
if (id == NULL)
return -1;
util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_device->udev), "/.run/udev/db3/", id, NULL);
dbfile = filename;
}
f = fopen(dbfile, "re");
if (f == NULL) {
info(udev_device->udev, "no db file to read %s: %m\n", filename);
info(udev_device->udev, "no db file to read %s: %m\n", dbfile);
return -1;
}
udev_device->is_initialized = true;
@ -908,7 +914,7 @@ const char *udev_device_get_devnode(struct udev_device *udev_device)
return NULL;
if (!udev_device->info_loaded) {
udev_device_read_uevent_file(udev_device);
udev_device_read_db(udev_device);
udev_device_read_db(udev_device, NULL);
}
/* we might get called before we handled an event and have a db, use the kernel-provided name */
@ -1002,7 +1008,7 @@ struct udev_list_entry *udev_device_get_devlinks_list_entry(struct udev_device *
if (udev_device == NULL)
return NULL;
if (!udev_device->info_loaded)
udev_device_read_db(udev_device);
udev_device_read_db(udev_device, NULL);
return udev_list_get_entry(&udev_device->devlinks_list);
}
@ -1030,7 +1036,7 @@ struct udev_list_entry *udev_device_get_properties_list_entry(struct udev_device
return NULL;
if (!udev_device->info_loaded) {
udev_device_read_uevent_file(udev_device);
udev_device_read_db(udev_device);
udev_device_read_db(udev_device, NULL);
}
if (!udev_device->devlinks_uptodate) {
char symlinks[UTIL_PATH_SIZE];
@ -1154,7 +1160,7 @@ unsigned long long int udev_device_get_usec_since_initialized(struct udev_device
if (udev_device == NULL)
return 0;
if (!udev_device->info_loaded)
udev_device_read_db(udev_device);
udev_device_read_db(udev_device, NULL);
if (udev_device->usec_initialized == 0)
return 0;
now = usec_monotonic();
@ -1471,7 +1477,7 @@ const char *udev_device_get_id_filename(struct udev_device *udev_device)
int udev_device_get_is_initialized(struct udev_device *udev_device)
{
if (!udev_device->info_loaded)
udev_device_read_db(udev_device);
udev_device_read_db(udev_device, NULL);
return udev_device->is_initialized;
}
@ -1519,7 +1525,7 @@ int udev_device_has_tag(struct udev_device *udev_device, const char *tag)
struct udev_list_entry *list_entry;
if (!udev_device->info_loaded)
udev_device_read_db(udev_device);
udev_device_read_db(udev_device, NULL);
list_entry = udev_device_get_tags_list_entry(udev_device);
list_entry = udev_list_entry_get_by_name(list_entry, tag);
if (list_entry != NULL)
@ -1689,7 +1695,7 @@ int udev_device_set_timeout(struct udev_device *udev_device, int timeout)
int udev_device_get_event_timeout(struct udev_device *udev_device)
{
if (!udev_device->info_loaded)
udev_device_read_db(udev_device);
udev_device_read_db(udev_device, NULL);
return udev_device->event_timeout;
}
@ -1729,7 +1735,7 @@ int udev_device_set_devnum(struct udev_device *udev_device, dev_t devnum)
int udev_device_get_devlink_priority(struct udev_device *udev_device)
{
if (!udev_device->info_loaded)
udev_device_read_db(udev_device);
udev_device_read_db(udev_device, NULL);
return udev_device->devlink_priority;
}
@ -1742,7 +1748,7 @@ int udev_device_set_devlink_priority(struct udev_device *udev_device, int prio)
int udev_device_get_watch_handle(struct udev_device *udev_device)
{
if (!udev_device->info_loaded)
udev_device_read_db(udev_device);
udev_device_read_db(udev_device, NULL);
return udev_device->watch_handle;
}

View File

@ -751,7 +751,7 @@ int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate)
struct dirent *dent;
char path[UTIL_PATH_SIZE];
util_strscpyl(path, sizeof(path), udev_get_dev_path(udev), "/.udev/tags/",
util_strscpyl(path, sizeof(path), udev_get_dev_path(udev), "/.run/udev/tags/",
udev_list_entry_get_name(list_entry), NULL);
dir = opendir(path);
if (dir == NULL)

View File

@ -78,7 +78,7 @@ void udev_device_add_property_from_string_parse(struct udev_device *udev_device,
int udev_device_add_property_from_string_parse_finish(struct udev_device *udev_device);
char **udev_device_get_properties_envp(struct udev_device *udev_device);
ssize_t udev_device_get_properties_monitor_buf(struct udev_device *udev_device, const char **buf);
int udev_device_read_db(struct udev_device *udev_device);
int udev_device_read_db(struct udev_device *udev_device, const char *dbfile);
int udev_device_read_uevent_file(struct udev_device *udev_device);
int udev_device_set_action(struct udev_device *udev_device, const char *action);
int udev_device_set_driver(struct udev_device *udev_device, const char *driver);

View File

@ -103,10 +103,10 @@ void udev_queue_export_cleanup(struct udev_queue_export *udev_queue_export)
{
char filename[UTIL_PATH_SIZE];
util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_queue_export->udev), "/.udev/queue.tmp", NULL);
util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_queue_export->udev), "/.run/udev/queue.tmp", NULL);
unlink(filename);
util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_queue_export->udev), "/.udev/queue.bin", NULL);
util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_queue_export->udev), "/.run/udev/queue.bin", NULL);
unlink(filename);
}
@ -221,7 +221,7 @@ static int rebuild_queue_file(struct udev_queue_export *udev_queue_export)
}
/* create new queue file */
util_strscpyl(filename_tmp, sizeof(filename_tmp), udev_get_dev_path(udev_queue_export->udev), "/.udev/queue.tmp", NULL);
util_strscpyl(filename_tmp, sizeof(filename_tmp), udev_get_dev_path(udev_queue_export->udev), "/.run/udev/queue.tmp", NULL);
new_queue_file = fopen(filename_tmp, "w+");
if (new_queue_file == NULL)
goto error;
@ -255,7 +255,7 @@ static int rebuild_queue_file(struct udev_queue_export *udev_queue_export)
goto error;
/* rename the new file on top of the old one */
util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_queue_export->udev), "/.udev/queue.bin", NULL);
util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_queue_export->udev), "/.run/udev/queue.bin", NULL);
if (rename(filename_tmp, filename) != 0)
goto error;
@ -401,7 +401,7 @@ static void update_failed(struct udev_queue_export *udev_queue_export,
return;
/* location of failed file */
util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.udev/failed/",
util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.run/udev/failed/",
udev_device_get_subsystem(udev_device), ":", udev_device_get_sysname(udev_device), NULL);
switch (state) {

View File

@ -214,7 +214,7 @@ static FILE *open_queue_file(struct udev_queue *udev_queue, unsigned long long i
char filename[UTIL_PATH_SIZE];
FILE *queue_file;
util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_queue->udev), "/.udev/queue.bin", NULL);
util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_queue->udev), "/.run/udev/queue.bin", NULL);
queue_file = fopen(filename, "re");
if (queue_file == NULL)
return NULL;
@ -484,7 +484,7 @@ struct udev_list_entry *udev_queue_get_failed_list_entry(struct udev_queue *udev
if (udev_queue == NULL)
return NULL;
udev_list_cleanup_entries(udev_queue->udev, &udev_queue->failed_list);
util_strscpyl(path, sizeof(path), udev_get_dev_path(udev_queue->udev), "/.udev/failed", NULL);
util_strscpyl(path, sizeof(path), udev_get_dev_path(udev_queue->udev), "/.run/udev/failed", NULL);
dir = opendir(path);
if (dir == NULL)
return NULL;

View File

@ -539,7 +539,7 @@ int udev_event_execute_rules(struct udev_event *event, struct udev_rules *rules)
return -1;
if (strcmp(udev_device_get_action(dev), "remove") == 0) {
udev_device_read_db(dev);
udev_device_read_db(dev, NULL);
udev_device_delete_db(dev);
udev_device_tag_index(dev, NULL, false);
@ -553,7 +553,7 @@ int udev_event_execute_rules(struct udev_event *event, struct udev_rules *rules)
} else {
event->dev_db = udev_device_new_from_syspath(event->udev, udev_device_get_syspath(dev));
if (event->dev_db != NULL) {
udev_device_read_db(event->dev_db);
udev_device_read_db(event->dev_db, NULL);
udev_device_set_info_loaded(event->dev_db);
/* disable watch during event processing */

View File

@ -292,7 +292,7 @@ static void link_update(struct udev_device *dev, const char *slink, bool add)
dbg(udev, "update symlink '%s' of '%s'\n", slink, udev_device_get_syspath(dev));
util_path_encode(&slink[strlen(udev_get_dev_path(udev))+1], name_enc, sizeof(name_enc));
util_strscpyl(dirname, sizeof(dirname), udev_get_dev_path(udev), "/.udev/links/", name_enc, NULL);
util_strscpyl(dirname, sizeof(dirname), udev_get_dev_path(udev), "/.run/udev/links/", name_enc, NULL);
util_strscpyl(filename, sizeof(filename), dirname, "/", udev_device_get_id_filename(dev), NULL);
if (!add) {

View File

@ -1803,7 +1803,7 @@ struct udev_rules *udev_rules_new(struct udev *udev, int resolve_names)
add_matching_files(udev, &file_list, SYSCONFDIR "/udev/rules.d", ".rules");
/* read dynamic/temporary rules */
util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.udev/rules.d", NULL);
util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.run/udev/rules.d", NULL);
udev_list_init(&sort_list);
add_matching_files(udev, &sort_list, filename, ".rules");

View File

@ -54,8 +54,8 @@ void udev_watch_restore(struct udev *udev)
if (inotify_fd < 0)
return;
util_strscpyl(oldname, sizeof(oldname), udev_get_dev_path(udev), "/.udev/watch.old", NULL);
util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.udev/watch", NULL);
util_strscpyl(oldname, sizeof(oldname), udev_get_dev_path(udev), "/.run/udev/watch.old", NULL);
util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.run/udev/watch", NULL);
if (rename(filename, oldname) == 0) {
DIR *dir;
struct dirent *ent;
@ -118,7 +118,7 @@ void udev_watch_begin(struct udev *udev, struct udev_device *dev)
return;
}
snprintf(filename, sizeof(filename), "%s/.udev/watch/%d", udev_get_dev_path(udev), wd);
snprintf(filename, sizeof(filename), "%s/.run/udev/watch/%d", udev_get_dev_path(udev), wd);
util_create_path(udev, filename);
unlink(filename);
symlink(udev_device_get_id_filename(dev), filename);
@ -141,7 +141,7 @@ void udev_watch_end(struct udev *udev, struct udev_device *dev)
info(udev, "removing watch on '%s'\n", udev_device_get_devnode(dev));
inotify_rm_watch(inotify_fd, wd);
snprintf(filename, sizeof(filename), "%s/.udev/watch/%d", udev_get_dev_path(udev), wd);
snprintf(filename, sizeof(filename), "%s/.run/udev/watch/%d", udev_get_dev_path(udev), wd);
unlink(filename);
udev_device_set_watch_handle(dev, -1);
@ -158,7 +158,7 @@ struct udev_device *udev_watch_lookup(struct udev *udev, int wd)
if (inotify_fd < 0 || wd < 0)
return NULL;
snprintf(filename, sizeof(filename), "%s/.udev/watch/%d", udev_get_dev_path(udev), wd);
snprintf(filename, sizeof(filename), "%s/.run/udev/watch/%d", udev_get_dev_path(udev), wd);
s = majmin;
l = util_strpcpy(&s, sizeof(majmin), udev_get_sys_path(udev));
len = readlink(filename, s, l);

View File

@ -73,7 +73,7 @@
<para>The udev rules are read from the files located in the
default rules directory <filename>/lib/udev/rules.d/</filename>,
the custom rules directory <filename>/etc/udev/rules.d/</filename>
and the temporary rules directory <filename>/dev/.udev/rules.d/</filename>.
and the temporary rules directory <filename>/var/run/udev/rules.d/</filename>.
All rule files are sorted and processed in lexical order, regardless
in which of these directories they live. Files in
<filename>/etc/udev/rules.d/</filename> have precedence over files with

View File

@ -200,66 +200,6 @@ static int export_devices(struct udev *udev)
return 0;
}
static int convert_db(struct udev *udev)
{
struct udev_enumerate *udev_enumerate;
struct udev_list_entry *list_entry;
udev_enumerate = udev_enumerate_new(udev);
if (udev_enumerate == NULL)
return -1;
udev_enumerate_scan_devices(udev_enumerate);
udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(udev_enumerate)) {
struct udev_device *device;
device = udev_device_new_from_syspath(udev, udev_list_entry_get_name(list_entry));
if (device != NULL) {
const char *id;
struct stat stats;
char to[UTIL_PATH_SIZE];
char devpath[UTIL_PATH_SIZE];
char from[UTIL_PATH_SIZE];
id = udev_device_get_id_filename(device);
if (id == NULL) {
udev_device_unref(device);
continue;
}
util_strscpyl(to, sizeof(to), udev_get_dev_path(udev), "/.udev/db/", id, NULL);
/* find old database with $subsys:$sysname */
util_strscpyl(from, sizeof(from), udev_get_dev_path(udev),
"/.udev/db/", udev_device_get_subsystem(device), ":",
udev_device_get_sysname(device), NULL);
if (lstat(from, &stats) == 0) {
if (lstat(to, &stats) == 0)
unlink(from);
else
rename(from, to);
}
/* find old database with the encoded devpath */
util_path_encode(udev_device_get_devpath(device), devpath, sizeof(devpath));
util_strscpyl(from, sizeof(from), udev_get_dev_path(udev),
"/.udev/db/", devpath, NULL);
if (lstat(from, &stats) == 0) {
if (lstat(to, &stats) == 0)
unlink(from);
else
rename(from, to);
}
/* read the old database, and write out a new one */
udev_device_read_db(device);
udev_device_update_db(device);
udev_device_unref(device);
}
}
udev_enumerate_unref(udev_enumerate);
return 0;
}
int udevadm_info(struct udev *udev, int argc, char *argv[])
{
struct udev_device *device = NULL;
@ -277,7 +217,6 @@ int udevadm_info(struct udev *udev, int argc, char *argv[])
{ "query", required_argument, NULL, 'q' },
{ "attribute-walk", no_argument, NULL, 'a' },
{ "export-db", no_argument, NULL, 'e' },
{ "convert-db", no_argument, NULL, 'C' },
{ "root", no_argument, NULL, 'r' },
{ "device-id-of-file", required_argument, NULL, 'd' },
{ "export", no_argument, NULL, 'x' },
@ -402,9 +341,6 @@ int udevadm_info(struct udev *udev, int argc, char *argv[])
case 'e':
export_devices(udev);
goto exit;
case 'C':
convert_db(udev);
goto exit;
case 'x':
export = true;
break;
@ -431,7 +367,6 @@ int udevadm_info(struct udev *udev, int argc, char *argv[])
" --export export key/value pairs\n"
" --export-prefix export the key name with a prefix\n"
" --export-db export the content of the udev database\n"
" --convert-db convert older version of database without a reboot\n"
" --help\n\n");
goto exit;
default:

View File

@ -143,15 +143,6 @@
<para>Export the content of the udev database.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--convert-db</option></term>
<listitem>
<para>Convert the database of an earlier udev version to the current format. This
is only useful on udev version upgrades, where the content of the old database might
be needed for the running system, and it is not sufficient for it, to be re-created
with the next bootup.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>--version</option></term>
<listitem>

View File

@ -971,6 +971,99 @@ static int mem_size_mb(void)
return memsize;
}
static int convert_db(struct udev *udev)
{
char filename[UTIL_PATH_SIZE];
FILE *f;
struct udev_enumerate *udev_enumerate;
struct udev_list_entry *list_entry;
/* current database */
util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.run/udev/db3", NULL);
if (access(filename, F_OK) >= 0)
return 0;
/* make sure we do not get here again */
util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.run/udev/db3/", NULL);
util_create_path(udev, filename);
/* old database */
util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.udev/db", NULL);
if (access(filename, F_OK) < 0)
return 0;
f = fopen("/dev/kmsg", "w");
if (f != NULL) {
fprintf(f, "<6>udev[%u]: converting old udev database\n", getpid());
fclose(f);
}
udev_enumerate = udev_enumerate_new(udev);
if (udev_enumerate == NULL)
return -1;
udev_enumerate_scan_devices(udev_enumerate);
udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(udev_enumerate)) {
struct udev_device *device;
device = udev_device_new_from_syspath(udev, udev_list_entry_get_name(list_entry));
if (device == NULL)
continue;
/* try to find the old database for devices without a current one */
if (udev_device_read_db(device, NULL) < 0) {
bool have_db;
const char *id;
struct stat stats;
char devpath[UTIL_PATH_SIZE];
char from[UTIL_PATH_SIZE];
have_db = false;
/* find database in old location */
id = udev_device_get_id_filename(device);
util_strscpyl(from, sizeof(from), udev_get_dev_path(udev), "/.udev/db/", id, NULL);
if (lstat(from, &stats) == 0) {
if (!have_db) {
udev_device_read_db(device, from);
have_db = true;
}
unlink(from);
}
/* find old database with $subsys:$sysname name */
util_strscpyl(from, sizeof(from), udev_get_dev_path(udev),
"/.udev/db/", udev_device_get_subsystem(device), ":",
udev_device_get_sysname(device), NULL);
if (lstat(from, &stats) == 0) {
if (!have_db) {
udev_device_read_db(device, from);
have_db = true;
}
unlink(from);
}
/* find old database with the encoded devpath name */
util_path_encode(udev_device_get_devpath(device), devpath, sizeof(devpath));
util_strscpyl(from, sizeof(from), udev_get_dev_path(udev),
"/.udev/db/", devpath, NULL);
if (lstat(from, &stats) == 0) {
if (!have_db) {
udev_device_read_db(device, from);
have_db = true;
}
unlink(from);
}
/* write out new database */
if (have_db)
udev_device_update_db(device);
}
udev_device_unref(device);
}
udev_enumerate_unref(udev_enumerate);
return 0;
}
int main(int argc, char *argv[])
{
struct udev *udev;
@ -1159,7 +1252,7 @@ int main(int argc, char *argv[])
IN_DELETE | IN_MOVE | IN_CLOSE_WRITE);
/* watch dynamic rules directory */
util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.udev/rules.d", NULL);
util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.run/udev/rules.d", NULL);
if (stat(filename, &statbuf) != 0) {
util_create_path(udev, filename);
udev_selinux_setfscreatecon(udev, filename, S_IFDIR|0755);
@ -1203,6 +1296,9 @@ int main(int argc, char *argv[])
goto exit;
}
/* if needed, convert old database from earlier udev version */
convert_db(udev);
if (!debug) {
dup2(fd, STDIN_FILENO);
dup2(fd, STDOUT_FILENO);