summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Zeuthen <david@fubar.dk>2003-11-30 23:08:59 +0000
committerDavid Zeuthen <david@fubar.dk>2003-11-30 23:08:59 +0000
commit14cf3e928ebd192c89ecbcb7ec0c1fb154dc5f18 (patch)
tree787eb46332cf83f6b807e90b692781373e4d06d8
parent496b444ffcd7f4ca729037f387c80e9af481641d (diff)
downloadhal-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--ChangeLog22
-rw-r--r--agents/linux26/sysfs/Makefile.am4
-rw-r--r--agents/linux26/sysfs/hal_monitor.c346
-rw-r--r--agents/linux26/sysfs/hal_monitor.h35
-rw-r--r--agents/linux26/sysfs/hal_usb.c2
-rw-r--r--agents/linux26/sysfs/main.c22
-rwxr-xr-xtools/hal-device-manager41
7 files changed, 458 insertions, 14 deletions
diff --git a/ChangeLog b/ChangeLog
index 29260f74..8659ec7b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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":