1
0
mirror of https://github.com/systemd/systemd.git synced 2024-10-28 20:25:38 +03:00
systemd/udev_remove.c

170 lines
4.2 KiB
C
Raw Normal View History

/*
* udev-remove.c
*
* Userspace devfs
*
* Copyright (C) 2003 Greg Kroah-Hartman <greg@kroah.com>
*
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 of the License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
2004-10-19 10:14:20 +04:00
#include <sys/stat.h>
#include "udev_libc_wrapper.h"
#include "udev.h"
#include "udev_utils.h"
#include "udev_version.h"
2004-11-12 08:32:19 +03:00
#include "udev_db.h"
#include "logging.h"
static int delete_path(const char *path)
{
char *pos;
int retval;
pos = strrchr(path, '/');
while (1) {
*pos = '\0';
pos = strrchr(path, '/');
/* don't remove the last one */
if ((pos == path) || (pos == NULL))
break;
/* remove if empty */
retval = rmdir(path);
if (errno == ENOENT)
retval = 0;
if (retval) {
if (errno == ENOTEMPTY)
return 0;
dbg("rmdir(%s) failed with error '%s'",
path, strerror(errno));
break;
}
dbg("removed '%s'", path);
}
return 0;
}
static int delete_node(struct udevice *udev)
{
char filename[PATH_SIZE];
char partitionname[PATH_SIZE];
struct name_entry *name_loop;
struct stat stats;
int retval;
int i;
int num;
list_for_each_entry(name_loop, &udev->symlink_list, node) {
snprintf(filename, sizeof(filename), "%s/%s", udev_root, name_loop->name);
filename[sizeof(filename)-1] = '\0';
if (stat(filename, &stats) != 0) {
dbg("symlink '%s' not found", filename);
continue;
}
if (udev->devt && stats.st_rdev != udev->devt) {
info("symlink '%s' points to a different device, skip removal", filename);
continue;;
}
dbg("removing symlink '%s'", filename);
unlink(filename);
if (strchr(filename, '/'))
delete_path(filename);
}
snprintf(filename, sizeof(filename), "%s/%s", udev_root, udev->name);
filename[sizeof(filename)-1] = '\0';
if (stat(filename, &stats) != 0) {
dbg("device node '%s' not found", filename);
return -1;
}
2005-02-21 15:44:39 +03:00
if (udev->devt && stats.st_rdev != udev->devt) {
info("device node '%s' points to a different device, skip removal", filename);
return -1;
}
info("removing device node '%s'", filename);
retval = unlink_secure(filename);
if (retval)
return retval;
num = udev->partitions;
if (num > 0) {
info("removing all_partitions '%s[1-%i]'", filename, num);
if (num > 255) {
info("garbage from udev database, skip all_partitions removal");
return -1;
}
for (i = 1; i <= num; i++) {
snprintf(partitionname, sizeof(partitionname), "%s%d", filename, i);
partitionname[sizeof(partitionname)-1] = '\0';
unlink_secure(partitionname);
}
}
if (strchr(udev->name, '/'))
delete_path(filename);
return retval;
}
/*
* look up the sysfs path in the database to get the node name to remove
* If we can't find it, use kernel name for lack of anything else to know to do
*/
int udev_remove_device(struct udevice *udev)
{
const char *temp;
2005-03-12 23:41:57 +03:00
if (udev->type != DEV_BLOCK && udev->type != DEV_CLASS)
return 0;
if (udev_db_get_device(udev, udev->devpath) == 0) {
if (udev->ignore_remove) {
dbg("remove event for '%s' requested to be ignored by rule", udev->name);
return 0;
}
dbg("remove name='%s'", udev->name);
udev_db_delete_device(udev);
} else {
/* fall back to kernel name */
temp = strrchr(udev->devpath, '/');
[PATCH] netdev - udevdb+dev.d changes Here is a patch to change the netdev handling in the database and for the dev.d/ calls. I applies on top of the udevd.patch, cause klibc has no sysinfo(). o netdev's are also put into our database now. I want this for the udevruler gui to get a list of all handled devices. All devices in the db are stamped with the system uptime value at the creation time. 'udevinfo -d' prints it. o the DEVPATH value is the key for udevdb, but if we rename a netdev, the name is replaced in the kernel, so we add the changed name to the db to match with the remove event. NOTE: The dev.d/ scripts still get the original name from the hotplug call. Should we replace DEVPATH with the new name too? o We now only add a device to the db, if we have successfully created the main node or successfully renamed a netdev. This is the main part of the patch, cause I needed to clean the retval passing trough all the functions used for node creation. o DEVNODE sounds a bit ugly for netdev's so I exported DEVNAME too. Can we change the name? o I've added a UDEV_NO_DEVD to possibly skip the script execution and used it in udev-test.pl. udevstart is the same horror now, if you have scripts with logging statements in dev.d/ it takes minutes to finish, can we skip the scripts here too? o The get_device_type() function is changed to be more strict, cause 'udevinfo -a -p /block/' gets a class device for it and tries to print the major/minor values. o bugfix, the RESULT value has now a working newline removal and a test for this case.
2004-04-01 11:12:57 +04:00
if (temp == NULL)
return -ENODEV;
strlcpy(udev->name, &temp[1], sizeof(udev->name));
info("'%s' not found in database, falling back on default name", udev->name);
[PATCH] netdev - udevdb+dev.d changes Here is a patch to change the netdev handling in the database and for the dev.d/ calls. I applies on top of the udevd.patch, cause klibc has no sysinfo(). o netdev's are also put into our database now. I want this for the udevruler gui to get a list of all handled devices. All devices in the db are stamped with the system uptime value at the creation time. 'udevinfo -d' prints it. o the DEVPATH value is the key for udevdb, but if we rename a netdev, the name is replaced in the kernel, so we add the changed name to the db to match with the remove event. NOTE: The dev.d/ scripts still get the original name from the hotplug call. Should we replace DEVPATH with the new name too? o We now only add a device to the db, if we have successfully created the main node or successfully renamed a netdev. This is the main part of the patch, cause I needed to clean the retval passing trough all the functions used for node creation. o DEVNODE sounds a bit ugly for netdev's so I exported DEVNAME too. Can we change the name? o I've added a UDEV_NO_DEVD to possibly skip the script execution and used it in udev-test.pl. udevstart is the same horror now, if you have scripts with logging statements in dev.d/ it takes minutes to finish, can we skip the scripts here too? o The get_device_type() function is changed to be more strict, cause 'udevinfo -a -p /block/' gets a class device for it and tries to print the major/minor values. o bugfix, the RESULT value has now a working newline removal and a test for this case.
2004-04-01 11:12:57 +04:00
}
[PATCH] D-BUS patch for udev-008 Attached is a patch against udev-008 to send out a D-BUS message when a device node is added or removed. Using D-BUS lingo, udev acquires the org.kernel.udev service and sends out a NodeCreated or NodeDeleted signal on the org.kernel.udev.NodeMonitor interface. Each signal carries two parameters: the node in question and the corresponding sysfs path. [Note: the D-BUS concepts of service, interface, object can be a bit confusing at first glance] An example program listening for these messages looks like this #!/usr/bin/python import dbus import gtk def udev_signal_received(dbus_iface, member, service, object_path, message): [filename, sysfs_path] = message.get_args_list() if member=='NodeCreated': print 'Node %s created for %s'%(filename, sysfs_path) elif member=='NodeDeleted': print 'Node %s deleted for %s'%(filename, sysfs_path) def main(): bus = dbus.Bus(dbus.Bus.TYPE_SYSTEM) bus.add_signal_receiver(udev_signal_received, 'org.kernel.udev.NodeMonitor', # interface 'org.kernel.udev', # service '/org/kernel/udev/NodeMonitor') # object gtk.mainloop() if __name__ == '__main__': main() and this is the output when hot-plugging some usb-storage. [david@laptop udev-008]$ ~/node_monitor.py Node /udev/sda created for /block/sda Node /udev/sda1 created for /block/sda/sda1 Node /udev/sda1 deleted for /block/sda/sda1 Node /udev/sda deleted for /block/sda The patch requires D-BUS 0.20 or later while the python example program requires D-BUS from CVS as I only recently applied a patch against the python bindings.
2003-12-08 20:19:19 +03:00
/* use full path to the environment */
snprintf(udev->devname, sizeof(udev->devname), "%s/%s", udev_root, udev->name);
udev->devname[sizeof(udev->devname)-1] = '\0';
return delete_node(udev);
}