diff options
author | David Zeuthen <david@fubar.dk> | 2003-11-30 23:08:59 +0000 |
---|---|---|
committer | David Zeuthen <david@fubar.dk> | 2003-11-30 23:08:59 +0000 |
commit | 14cf3e928ebd192c89ecbcb7ec0c1fb154dc5f18 (patch) | |
tree | 787eb46332cf83f6b807e90b692781373e4d06d8 | |
parent | 496b444ffcd7f4ca729037f387c80e9af481641d (diff) | |
download | hal-14cf3e928ebd192c89ecbcb7ec0c1fb154dc5f18.tar.gz |
new file, the /etc/mtab monitoring code is still a bit cheesy (especially
the sleep(1) :-) Someone with more linux-skills will hopefully rewrite
it some day!
new file
Fixed potential bug for whitespace-strip loop
Call etc_mtab_process_all_block_devices() to inspect /etc/mtab and set
correct information for the block devices that is already mounted
(main): Add new option --monitor to start in monitoring mode. Right now
only /etc/mtab is monitored but network link detection is planned.
Don't rebuild entire tree if properties on a device is changing but just
get the changes from hald and change the internal representation. Helps
performance a lot.
-rw-r--r-- | ChangeLog | 22 | ||||
-rw-r--r-- | agents/linux26/sysfs/Makefile.am | 4 | ||||
-rw-r--r-- | agents/linux26/sysfs/hal_monitor.c | 346 | ||||
-rw-r--r-- | agents/linux26/sysfs/hal_monitor.h | 35 | ||||
-rw-r--r-- | agents/linux26/sysfs/hal_usb.c | 2 | ||||
-rw-r--r-- | agents/linux26/sysfs/main.c | 22 | ||||
-rwxr-xr-x | tools/hal-device-manager | 41 |
7 files changed, 458 insertions, 14 deletions
@@ -1,3 +1,25 @@ +2003-12-01 David Zeuthen <david@fubar.dk> + + * agents/linux26/sysfs/hal_monitor.c: new file, the /etc/mtab + monitoring code is still a bit cheesy (especially the sleep(1) :-) + Someone with more linux-skills will hopefully rewrite it some day! + + * agents/linux26/sysfs/hal_monitor.h: new file + + * agents/linux26/sysfs/hal_usb.c (visit_device_usb): Fixed potential + bug for whitespace-strip loop + + * agents/linux26/sysfs/main.c (hal_sysfs_probe): Call + etc_mtab_process_all_block_devices() to inspect /etc/mtab and set + correct information for the block devices that is already mounted + (main): Add new option --monitor to start in monitoring mode. Right + now only /etc/mtab is monitored but network link detection is planned. + + * tools/hal-device-manager: Don't rebuild entire tree if properties + on a device is changing but just get the changes from hald and change + the internal representation. Helps performance a lot. + + 2003-11-30 David Zeuthen <david@fubar.dk> * agents/linux26/sysfs/hal_net.c: new file diff --git a/agents/linux26/sysfs/Makefile.am b/agents/linux26/sysfs/Makefile.am index 1b9e7b03..a283876c 100644 --- a/agents/linux26/sysfs/Makefile.am +++ b/agents/linux26/sysfs/Makefile.am @@ -19,7 +19,9 @@ hal_sysfs_agent_hotplug_SOURCES = \ hal_scsi.c hal_scsi.h \ hal_block.c hal_block.h \ hal_net.c hal_net.h \ - hal_input.c hal_input.h + hal_input.c hal_input.h \ + hal_monitor.c hal_monitor.h + #hal_sysfs_agent_hotplug_LDADD = @PACKAGE_LIBS@ diff --git a/agents/linux26/sysfs/hal_monitor.c b/agents/linux26/sysfs/hal_monitor.c new file mode 100644 index 00000000..8e5a3225 --- /dev/null +++ b/agents/linux26/sysfs/hal_monitor.c @@ -0,0 +1,346 @@ +/*************************************************************************** + * CVSID: $Id$ + * + * hal_monitor.c : monitor mode for watching stuff about devices + * + * Copyright (C) 2003 David Zeuthen, <david@fubar.dk> + * + * Licensed under the Academic Free License version 2.0 + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + **************************************************************************/ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <getopt.h> +#include <assert.h> +#include <unistd.h> +#include <stdarg.h> +#include <syslog.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> + +#define _GNU_SOURCE 1 +#include <linux/fcntl.h> +#include <linux/kdev_t.h> + +#include <sys/signal.h> + +#include <errno.h> + +#include <dbus/dbus.h> +#include <dbus/dbus-glib.h> +#include <libsysfs.h> + +#include <libhal/libhal.h> + +#include "main.h" +#include "hal_monitor.h" + +#define MOUNT_POINT_MAX 256 +#define MOUNT_POINT_STRING_SIZE 128 + +/** Structure for holding mount point information */ +struct mount_point_s +{ + int major; /**< Major device number */ + int minor; /**< Minor device number */ + char device[MOUNT_POINT_STRING_SIZE]; /**< Device filename */ + char mount_point[MOUNT_POINT_STRING_SIZE]; /**< Mount point */ + char fs_type[MOUNT_POINT_STRING_SIZE]; /**< Filesystem type */ +}; + +/** Array holding (valid) mount points from /etc/mtab. */ +static struct mount_point_s mount_points[MOUNT_POINT_MAX]; + +/** Number of elements in #mount_points array */ +static int num_mount_points; + +static int etc_fd = -1; + + +/** Process a line in /etc/mtab. The given string will be modifed by + * this function. + * + * @param s Line of /etc/mtab + */ +static void etc_mtab_process_line(char* s) +{ + int i; + char* p; + char* delim = " \t\n"; + char buf[256]; + char* bufp = buf; + struct stat stat_buf; + int major = 0; + int minor = 0; + char* device = NULL; + char* mount_point = NULL; + char* fs_type = NULL; + + i=0; + p = strtok_r(s, delim, &bufp); + while( p!=NULL ) + { + /*printf("token: '%s'\n", p);*/ + switch(i) + { + case 0: + if( strcmp(p, "none")==0 ) + return; + if( p[0]!='/' ) + return; + device = p; + /* Find major/minor for this device */ + + if( stat(p, &stat_buf)!=0 ) + { + return; + } + major = MAJOR(stat_buf.st_rdev); + minor = MINOR(stat_buf.st_rdev); + break; + + case 1: + mount_point = p; + break; + + case 2: + fs_type = p; + break; + + case 3: + break; + + case 4: + break; + + case 5: + break; + } + + p = strtok_r(NULL, delim, &bufp); + i++; + } + + /** @todo FIXME: Use a linked list or something that doesn't restrict + * us like this + */ + if( num_mount_points==MOUNT_POINT_MAX ) + return; + + mount_points[num_mount_points].major = major; + mount_points[num_mount_points].minor = minor; + strncpy(mount_points[num_mount_points].device, device, + MOUNT_POINT_STRING_SIZE); + strncpy(mount_points[num_mount_points].mount_point, mount_point, + MOUNT_POINT_STRING_SIZE); + strncpy(mount_points[num_mount_points].fs_type, fs_type, + MOUNT_POINT_STRING_SIZE); + + num_mount_points++; +} + +/** Last mtime when /etc/mtab was processed */ +static time_t etc_mtab_mtime = 0; + + +/** Reads /etc/mtab and fill out #mount_points and #num_mount_points + * variables accordingly + * + * This function holds the file open for further access + * + * @return FALSE if there was no changes to /etc/mtab + * since last invocation or an error occured + */ +static dbus_bool_t read_etc_mtab() +{ + int fd; + char buf[256]; + FILE* f; + struct stat stat_buf; + + num_mount_points=0; + + fd = open("/etc/mtab", O_RDONLY); + + if( fd==-1 ) + { + printf("Cannot open /etc/mtab\n"); + return FALSE; + } + + if( fstat(fd, &stat_buf)!=0 ) + { + printf("Cannot fstat /etc/mtab fd, errno=%d\n", errno); + return FALSE; + } + + if( etc_mtab_mtime==stat_buf.st_mtime ) + { + /*printf("No modification, etc_mtab_mtime=%d\n", etc_mtab_mtime);*/ + return FALSE; + } + + etc_mtab_mtime = stat_buf.st_mtime; + + /*printf("Modification, etc_mtab_mtime=%d\n", etc_mtab_mtime);*/ + + f = fdopen(fd, "r"); + + if( f==NULL ) + { + printf("Cannot fdopen /etc/mtab fd\n"); + return FALSE; + } + + while( !feof(f) ) + { + if( fgets(buf, 256, f)==NULL ) + break; + /*printf("got line: '%s'\n", buf);*/ + etc_mtab_process_line(buf); + } + + fclose(f); + + close(fd); + + return TRUE; +} + +static void sigio_handler(int sig); + +/** Global to see if we have setup the watcher on /etc */ +static dbus_bool_t have_setup_watcher = FALSE; + +/** Load /etc/mtab and process all HAL block devices and set properties + * according to mount status. Also, optionally, sets up a watcher to do + * this whenever /etc/mtab changes + * + * @param setup_watcher Monitor /etc/mtab + */ +void etc_mtab_process_all_block_devices(dbus_bool_t setup_watcher) +{ + int i, j; + struct mount_point_s* mp; + int etc_mtab_num_block_devices; + char** etc_mtab_block_devices; + + /* Start or continue watching /etc */ + if( setup_watcher && !have_setup_watcher ) + { + have_setup_watcher = TRUE; + + signal(SIGIO, sigio_handler); + etc_fd = open("/etc", O_RDONLY); + fcntl(etc_fd, F_NOTIFY, DN_MODIFY|DN_MULTISHOT); + } + + /* Just return if /etc/mtab wasn't modified */ + if( !read_etc_mtab() ) + return; + + /* Find all HAL block devices */ + etc_mtab_block_devices = hal_manager_find_device_string_match( + "Bus", "block", + &etc_mtab_num_block_devices); + + /* Process all HAL block devices */ + for(i=0; i<etc_mtab_num_block_devices; i++) + { + char* udi; + int major, minor; + dbus_bool_t found_mount_point; + + udi = etc_mtab_block_devices[i]; + major = hal_device_get_property_int(udi, "block.major"); + minor = hal_device_get_property_int(udi, "block.minor"); + + printf("udi %s: major,minor=%d,%d\n", udi, major, minor); + + /* Search all mount points */ + found_mount_point = FALSE; + for(j=0; j<num_mount_points; j++) + { + mp = &mount_points[j]; + + if( mp->major==major && mp->minor==minor ) + { + printf("%s mounted at %s, major=%d, minor=%d, fstype=%s\n", + mp->device, mp->mount_point, mp->major, mp->minor, + mp->fs_type); + + /* Yay! Found a mount point; set properties accordingly */ + hal_device_set_property_string(udi, "block.device", + mp->device); + hal_device_set_property_string(udi, "block.mountPoint", + mp->mount_point); + hal_device_set_property_string(udi, "block.fileSystem", + mp->fs_type); + hal_device_set_property_bool(udi, "block.isMounted", TRUE); + + found_mount_point = TRUE; + } + } + + /* No mount point found; (possibly) remove all information */ + if( !found_mount_point ) + { + hal_device_set_property_bool(udi, "block.isMounted", FALSE); + hal_device_remove_property(udi, "block.mountPoint"); + hal_device_remove_property(udi, "block.fileSystem"); + hal_device_remove_property(udi, "block.device"); + } + } + +} + +/** Signal handler for watching /etc + * + * @param sig Signal number + */ +static void sigio_handler(int sig) +{ + printf("file changed, sig=%d, SIGIO=%d\n", sig, SIGIO); + + /** @todo FIXME: Isn't it evil to sleep in a signal handler */ + sleep(1); + + etc_mtab_process_all_block_devices(TRUE); +} + + +/** Enter monitor mode + * + * @param loop G-Lib mainloop + */ +void hal_monitor_enter(GMainLoop* loop) +{ + syslog(LOG_INFO, "Entering monitor mode.."); + + etc_mtab_process_all_block_devices(TRUE); + + g_main_loop_run(loop); +} diff --git a/agents/linux26/sysfs/hal_monitor.h b/agents/linux26/sysfs/hal_monitor.h new file mode 100644 index 00000000..675b4e46 --- /dev/null +++ b/agents/linux26/sysfs/hal_monitor.h @@ -0,0 +1,35 @@ +/*************************************************************************** + * CVSID: $Id$ + * + * hal_monitor.h : monitor mode for watching stuff about devices + * + * Copyright (C) 2003 David Zeuthen, <david@fubar.dk> + * + * Licensed under the Academic Free License version 2.0 + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + **************************************************************************/ + +#ifndef HAL_MONITOR_H +#define HAL_MONITOR_H + +#include "main.h" + +void hal_monitor_enter(GMainLoop* loop); + +void etc_mtab_process_all_block_devices(dbus_bool_t setup_watcher); + +#endif /* HAL_MONITOR_H */ diff --git a/agents/linux26/sysfs/hal_usb.c b/agents/linux26/sysfs/hal_usb.c index 946302e4..68a4d1fd 100644 --- a/agents/linux26/sysfs/hal_usb.c +++ b/agents/linux26/sysfs/hal_usb.c @@ -739,7 +739,7 @@ void visit_device_usb(const char* path, struct sysfs_device *device) /* strip whitespace */ len = strlen(cur->value); - for(i=len-1; isspace(cur->value[i]) && i>=0; --i) + for(i=len-1; i>=0 && isspace(cur->value[i]); --i) cur->value[i] = '\0'; /*printf("attr_name=%s -> '%s'\n", attr_name, cur->value);*/ diff --git a/agents/linux26/sysfs/main.c b/agents/linux26/sysfs/main.c index 2e2849c8..87e2be6b 100644 --- a/agents/linux26/sysfs/main.c +++ b/agents/linux26/sysfs/main.c @@ -52,6 +52,7 @@ #include "hal_net.h" #include "hal_input.h" +#include "hal_monitor.h" /** @defgroup HalAgentsLinux26 Linux 2.6 sysfs * @ingroup HalAgentsLinux @@ -884,6 +885,11 @@ static void hal_sysfs_probe() /* Find the input devices (no yet in sysfs) */ hal_input_probe(); + + /* Process /etc/mtab and modify block devices we indeed have mounted + * (dont set up the watcher) + */ + etc_mtab_process_all_block_devices(FALSE); } /** This function is invoked on hotplug add events */ @@ -1176,6 +1182,7 @@ static void usage() "usage : hal-sysfs-agent [--help] [--probe]\n" "\n" " --probe Probe devices present in sysfs\n" +" --monitor Monitor devices (link detection, mount points)\n" " --help Show this information and exit\n" "\n" "This program is supposed to only be invoked from the linux-hotplug package\n" @@ -1191,7 +1198,7 @@ static void usage() */ int main(int argc, char* argv[]) { - //GMainLoop* loop; + GMainLoop* loop; LibHalFunctions hal_functions = {mainloop_integration, NULL /*property_changed*/, NULL /*device_added*/, @@ -1206,13 +1213,15 @@ int main(int argc, char* argv[]) fprintf(stderr, "hal-sysfs-agent " PACKAGE_VERSION "\r\n"); + loop = g_main_loop_new(NULL, FALSE); + if( hal_initialize(&hal_functions) ) { fprintf(stderr, "error: hal_initialize failed\r\n"); exit(1); } - openlog("hal-sysfs-agent", LOG_CONS|LOG_PID, LOG_DAEMON); + openlog("hal-sysfs-agent", LOG_CONS|LOG_PID|LOG_PERROR, LOG_DAEMON); hal_pci_init(); hal_usb_init(); @@ -1231,6 +1240,7 @@ int main(int argc, char* argv[]) { {"help", 0, NULL, 0}, {"probe", 0, NULL, 0}, + {"monitor", 0, NULL, 0}, {NULL, 0, NULL, 0} }; @@ -1252,10 +1262,16 @@ int main(int argc, char* argv[]) else if( strcmp(opt, "probe")==0 ) { hal_sysfs_probe(); - sleep(1); return 0; } + else if( strcmp(opt, "monitor")==0 ) + { + /* Go into monitor mode to monitor /etc/mtab and do network + * link detection + */ + hal_monitor_enter(loop); + } default: usage(); diff --git a/tools/hal-device-manager b/tools/hal-device-manager index e7e5dce1..ce051928 100755 --- a/tools/hal-device-manager +++ b/tools/hal-device-manager @@ -145,13 +145,12 @@ class GUI: def udi_to_device(self, device_udi): return self.virtual_root.find_by_udi(device_udi) - def build_device_tree(self): device_names = self.hal_manager.GetAllDevices() device_names.sort() virtual_root = Device("virtual_root", None, {}) - device_list = [virtual_root] + self.device_list = [virtual_root] # first build list of Device objects for name in device_names: @@ -164,14 +163,14 @@ class GUI: # no parent, must be parent of virtual_root parent_name = "/" device = Device(name, parent_name, properties) - device_list.append(device) + self.device_list.append(device) # set parent_device and children for each Device object - for device in device_list: + for device in self.device_list: parent_name = device.parent_name device.parent_device = virtual_root if parent_name!="/": - for p in device_list: + for p in self.device_list: if p.device_name==parent_name: device.parent_device = p p.children.append(device) @@ -365,7 +364,13 @@ class GUI: self.update_tab_usb(device) self.update_tab_pci(device) - + def get_current_focus_udi(self): + (tree_model, tree_iter) = self.tree_selection.get_selected() + if tree_iter: + device_udi = tree_model.get_value(tree_iter, UDI_COLUMN) + return device_udi + return None + def on_device_tree_selection_changed(self, tree_selection): (tree_model, tree_iter) = tree_selection.get_selected() if tree_iter: @@ -376,9 +381,27 @@ class GUI: def device_changed(self, dbus_if, dbus_member, dbus_svc, dbus_obj_path, dbus_message): [property_name] = dbus_message.get_args_list() # TODO: Update appropriate device - #if property_name=="Parent": - # update_device_list() - self.update_device_list() + #self.update_device_list() + if property_name=="Parent": + self.update_device_list() + else: + device_udi = dbus_obj_path + device_udi_obj = self.hal_service.get_object(device_udi, + "org.freedesktop.Hal.Device") + device_obj = self.udi_to_device(device_udi) + + if device_udi_obj.PropertyExists(property_name): + #ptype = device_udi_obj.GetPropertyType(property_name) + device_obj.properties[property_name] = device_udi_obj.GetProperty(property_name) + else: + if device_obj != None: + try: + del device_obj.properties[property_name] + except: + pass + if self.get_current_focus_udi()==device_udi: + self.update_device_notebook(device_obj) + def gdl_changed(self, dbus_if, dbus_member, dbus_svc, dbus_obj_path, dbus_message): if dbus_member=="DeviceAdded": |