diff options
Diffstat (limited to 'tools/hal-disable-polling.c')
-rw-r--r-- | tools/hal-disable-polling.c | 276 |
1 files changed, 276 insertions, 0 deletions
diff --git a/tools/hal-disable-polling.c b/tools/hal-disable-polling.c new file mode 100644 index 00000000..44d886cf --- /dev/null +++ b/tools/hal-disable-polling.c @@ -0,0 +1,276 @@ +/*************************************************************************** + * CVSID: $Id$ + * + * hal-disable-polling.c : Disable polling on a drive + * + * Copyright (C) 2007 David Zeuthen, <david@fubar.dk> + * + * Licensed under the Academic Free License version 2.1 + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + **************************************************************************/ + + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <getopt.h> +#include <glib.h> +#include <libhal.h> + +/** + * usage: + * @argc: Number of arguments given to program + * @argv: Arguments given to program + * + * Print out program usage. + */ +static void +usage (int argc, char *argv[]) +{ + fprintf (stderr, + "\n" + "usage : hal-disable-polling [--udi <udi> | --device <device-file>]\n" + " [--enable-polling]\n" + " [--help] [--version]\n"); + fprintf (stderr, + "\n" + " --udi Unique Device Id\n" + " --device Device file\n" + " --enable-polling Enable polling instead of disabling it\n" + " --version Show version and exit\n" + " --help Show this information and exit\n" + "\n" + "This program is provided to make HAL stop polling a drive. Please read.\n" + "the entire manual page before using this program.\n" + "\n"); +} + +/** + * main: + * @argc: Number of arguments given to program + * @argv: Arguments given to program + * + * Returns: Return code + * + * Main entry point + */ +int +main (int argc, char *argv[]) +{ + char *udi = NULL; + char *device = NULL; + dbus_bool_t is_version = FALSE; + dbus_bool_t enable_polling = FALSE; + DBusError error; + LibHalContext *hal_ctx; + FILE *f; + char *filename; + + if (argc <= 1) { + usage (argc, argv); + return 1; + } + + while (1) { + int c; + int option_index = 0; + const char *opt; + static struct option long_options[] = { + {"udi", 1, NULL, 0}, + {"device", 1, NULL, 0}, + {"enable-polling", 0, NULL, 0}, + {"version", 0, NULL, 0}, + {"help", 0, NULL, 0}, + {NULL, 0, NULL, 0} + }; + + c = getopt_long (argc, argv, "", + long_options, &option_index); + if (c == -1) + break; + + switch (c) { + case 0: + opt = long_options[option_index].name; + + if (strcmp (opt, "help") == 0) { + usage (argc, argv); + return 0; + } else if (strcmp (opt, "version") == 0) { + is_version = TRUE; + } else if (strcmp (opt, "udi") == 0) { + udi = strdup (optarg); + } else if (strcmp (opt, "device") == 0) { + device = strdup (optarg); + } else if (strcmp (opt, "enable-polling") == 0) { + enable_polling = TRUE; + } + break; + + default: + usage (argc, argv); + return 1; + break; + } + } + + if (is_version) { + printf ("hal-disable-polling " PACKAGE_VERSION "\n"); + return 0; + } + + if (udi == NULL && device == NULL) { + usage (argc, argv); + return 1; + } + + if (udi != NULL && device != NULL) { + usage (argc, argv); + return 1; + } + + dbus_error_init (&error); + if ((hal_ctx = libhal_ctx_new ()) == NULL) { + fprintf (stderr, "error: libhal_ctx_new\n"); + return 1; + } + if (!libhal_ctx_set_dbus_connection (hal_ctx, dbus_bus_get (DBUS_BUS_SYSTEM, &error))) { + fprintf (stderr, "error: libhal_ctx_set_dbus_connection: %s: %s\n", error.name, error.message); + LIBHAL_FREE_DBUS_ERROR (&error); + return 1; + } + if (!libhal_ctx_init (hal_ctx, &error)) { + if (dbus_error_is_set(&error)) { + fprintf (stderr, "error: libhal_ctx_init: %s: %s\n", error.name, error.message); + dbus_error_free (&error); + } + fprintf (stderr, "Could not initialise connection to hald.\n" + "Normally this means the HAL daemon (hald) is not running or not ready.\n"); + return 1; + } + + if (getuid () != 0) { + fprintf (stderr, "This program requires super user (root) privileges.\n"); + return 1; + } + + if (device != NULL) { + char **devices; + int num_devices; + int n; + + devices = libhal_manager_find_device_string_match (hal_ctx, "block.device", device, &num_devices, NULL); + if (devices == NULL) { + fprintf (stderr, "Cannot find device %s.\n", device); + return 1; + } + + for (n = 0; devices[n] != NULL; n++) { + if (libhal_device_query_capability (hal_ctx, devices[n], "storage", NULL)) { + udi = devices[n]; + break; + } + } + + if (udi == NULL) { + fprintf (stderr, "Cannot find storage device %s.\n", device); + return 1; + } + + /* mmmkay, we don't care about leaking the variable devices... mmkay? mmkay! */ + } else { + if (!libhal_device_exists (hal_ctx, udi, &error)) { + fprintf (stderr, "Cannot find device with udi %s.\n", udi); + return 1; + } + if (!libhal_device_query_capability (hal_ctx, udi, "storage", NULL)) { + fprintf (stderr, "Device with udi %s is not a storage device.\n", udi); + return 1; + } + device = libhal_device_get_property_string (hal_ctx, udi, "block.device", NULL); + if (device == NULL) { + fprintf (stderr, "Device with udi %s does not have block.device set.\n", udi); + return 1; + } + } + + if (!libhal_device_get_property_bool (hal_ctx, udi, "storage.removable", NULL)) { + fprintf (stderr, "The given drive don't use removable media so it's not polled anyway.\n"); + return 1; + } + + filename = g_strdup_printf (PACKAGE_SYSCONF_DIR "/hal/fdi/information/media-check-disable-%s.fdi", + g_basename (udi)); + + if (enable_polling) { + if (libhal_device_get_property_bool (hal_ctx, udi, "storage.media_check_enabled", NULL)) { + fprintf (stderr, "Polling is already enabled on the given drive.\n"); + return 1; + } + + if (!g_file_test (filename, G_FILE_TEST_EXISTS)) { + fprintf (stderr, "Cannot find fdi file %s. Perhaps polling wasn't disabled using this tool?\n", filename); + return 1; + } + if (unlink (filename) != 0) { + fprintf (stderr, "Cannot delete fdi file %s.\n", filename); + return 1; + } + } else { + if (!libhal_device_get_property_bool (hal_ctx, udi, "storage.media_check_enabled", NULL)) { + fprintf (stderr, "Polling is already disabled on the given drive.\n"); + return 1; + } + + if (g_file_test (filename, G_FILE_TEST_EXISTS)) { + fprintf (stderr, "The fdi file %s already exist. Cowardly refusing to overwrite it.\n", filename); + return 1; + } + + f = fopen (filename, "w"); + if (f == NULL) { + fprintf (stderr, "Cannot open %s for writing.\n", filename); + return 1; + } + fprintf (f, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + "\n" + "<deviceinfo version=\"0.2\">\n" + " <device>\n" + " <match key=\"info.udi\" string=\"%s\">\n" + " <merge key=\"storage.media_check_enabled\" type=\"bool\">false</merge>\n" + " </match>\n" + " </device>\n" + "</deviceinfo>\n" + "\n", udi); + fclose (f); + } + + libhal_device_reprobe (hal_ctx, udi, &error); + + if (enable_polling) + printf ("Polling for drive %s have been enabled. The fdi file deleted was\n" + " %s\n", device, filename); + else + printf ("Polling for drive %s have been disabled. The fdi file written was\n" + " %s\n", device, filename); + + return 0; +} |