~ubuntu-branches/debian/experimental/devicekit-disks/experimental

« back to all changes in this revision

Viewing changes to src/job-drive-detach.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2009-10-09 17:52:20 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20091009175220-qflk71dp3tmcyer3
Tags: 007-2
* debian/rules: Enable quilt patch system. Add quilt build dependency.
* Add 01-mkfs-tempdir.patch: Daemon does not create /var/run/DeviceKit-disks/,
  so mkfs jobs fail. Just create the directory in /tmp, this is what /tmp is
  for, after all. (See https://bugs.freedesktop.org/show_bug.cgi?id=24265)
* Add 00git-fix-inhibit.patch: Actually make Inhibit() work again. Taken
  from upstream git head. (LP: #428133)
* Add 02-unlock-CD-trays-after-mounting.patch: Unlike in the hal world, we
  do not have a daemon polling CD drives for eject button presses. In order
  to make hardware tray eject buttons work, unlock the tray after
  mounting a CD. This is pretty much equivalent to yanking out USB sticks,
  which we already handle reasonably (detecting disappeared device,
  force-unmounting). (https://bugs.freedesktop.org/show_bug.cgi?id=24052,
  LP: #397734)
* Add 03-fix-subsystem-check-for-firewire.patch: Firewire subsystem is
  called "ieee1394" in current Linux. Now check for both "ieee1394" and
  "firewire". This fixes firewire drives to not be considered system
  internal any more. (https://bugs.freedesktop.org/show_bug.cgi?id=24351,
  LP: #442604)
* Add 04-mount-vfat-with-shortname-mixed-by-default.patch: The previous
  default, shortname=lower, breaks all-uppercase file names ("touch
  FOO" creates "foo"), thus breaks rsync, and Windows compatibility. The
  default was changed in the Linux kernel for 2.6.32 as well.
  (https://bugs.freedesktop.org/show_bug.cgi?id=24129, LP: #428174)
* Add 00git-crash-on-removing-NULL-value-from-hash.patch: Properly handle
  the situtation where we're processing a 'change' event but the 'remove'
  event has happened but is still queued up in our own process. Also handle
  device file renames and 'move' uevents.
  (http://bugs.freedesktop.org/show_bug.cgi?id=24264, LP: #414407)
* Add 06-show-MMC-MemStick-cards-by-default.patch: Show MMC/MemStick cards
  by default; the previous whitelist in the udev rules ignored them.
  (https://bugs.freedesktop.org/show_bug.cgi?id=24053, LP: #429752)
* Add 05-german-translations.patch: Add German translations.
  (https://bugs.freedesktop.org/show_bug.cgi?id=2024420)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 
2
 *
 
3
 * Copyright (C) 2009 David Zeuthen <david@fubar.dk>
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or modify
 
6
 * it under the terms of the GNU General Public License as published by
 
7
 * the Free Software Foundation; either version 2 of the License, or
 
8
 * (at your option) any later version.
 
9
 *
 
10
 * This program is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 * GNU General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU General Public License
 
16
 * along with this program; if not, write to the Free Software
 
17
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
18
 *
 
19
 */
 
20
 
 
21
#include <stdio.h>
 
22
#include <string.h>
 
23
#include <errno.h>
 
24
#include <stdlib.h>
 
25
#include <time.h>
 
26
 
 
27
#include <scsi/sg_lib.h>
 
28
#include <scsi/sg_cmds.h>
 
29
 
 
30
#define LIBUDEV_I_KNOW_THE_API_IS_SUBJECT_TO_CHANGE
 
31
#include <libudev.h>
 
32
 
 
33
#include <glib.h>
 
34
 
 
35
static void
 
36
usage (void)
 
37
{
 
38
  g_printerr ("incorrect usage\n");
 
39
}
 
40
 
 
41
int
 
42
main (int argc, char *argv[])
 
43
{
 
44
  int ret;
 
45
  int sg_fd;
 
46
  const gchar *device;
 
47
  const gchar *sysfs_path;
 
48
  struct udev *udev;
 
49
  struct udev_device *udevice;
 
50
  struct udev_device *udevice_usb_interface;
 
51
  struct udev_device *udevice_usb_device;
 
52
  gchar *unbind_path;
 
53
  gchar *power_level_path;
 
54
  gchar *usb_interface_name;
 
55
  size_t usb_interface_name_len;
 
56
  FILE *f;
 
57
 
 
58
  udev = NULL;
 
59
  udevice = NULL;
 
60
  udevice_usb_interface = NULL;
 
61
  udevice_usb_device = NULL;
 
62
  usb_interface_name = NULL;
 
63
  unbind_path = NULL;
 
64
  power_level_path = NULL;
 
65
 
 
66
  ret = 1;
 
67
  sg_fd = -1;
 
68
 
 
69
  if (argc != 3)
 
70
    {
 
71
      usage ();
 
72
      goto out;
 
73
    }
 
74
 
 
75
  device = argv[1];
 
76
  sysfs_path = argv[2];
 
77
 
 
78
  sg_fd = sg_cmds_open_device (device, 1 /* read_only */, 1);
 
79
  if (sg_fd < 0)
 
80
    {
 
81
      g_printerr ("Cannot open %s: %m\n", device);
 
82
      goto out;
 
83
    }
 
84
 
 
85
  if (sg_ll_sync_cache_10 (sg_fd,
 
86
                           0,  /* sync_nv */
 
87
                           0,  /* immed */
 
88
                           0,  /* group */
 
89
                           0,  /* lba */
 
90
                           0,  /* count */
 
91
                           1,  /* noisy */
 
92
                           0   /* verbose */
 
93
                           ) != 0)
 
94
    {
 
95
      g_printerr ("Error SYNCHRONIZE CACHE for %s: %m\n", device);
 
96
      /* this is not a catastrophe, carry on */
 
97
    }
 
98
 
 
99
  if (sg_ll_start_stop_unit (sg_fd,
 
100
                             0,  /* immed */
 
101
                             0,  /* pc_mod__fl_num */
 
102
                             0,  /* power_cond */
 
103
                             0,  /* noflush__fl */
 
104
                             0,  /* loej */
 
105
                             0,  /* start */
 
106
                             1,  /* noisy */
 
107
                             0   /* verbose */
 
108
                             ) != 0)
 
109
    {
 
110
      g_printerr ("Error STOP UNIT for %s: %m\n", device);
 
111
      goto out;
 
112
    }
 
113
 
 
114
  /* OK, close the device */
 
115
  sg_cmds_close_device (sg_fd);
 
116
  sg_fd = -1;
 
117
 
 
118
  /* Now unbind the usb-storage driver from the usb interface */
 
119
  udev = udev_new ();
 
120
  if (udev == NULL)
 
121
    {
 
122
      g_printerr ("Error initializing libudev: %m\n");
 
123
      goto out;
 
124
    }
 
125
 
 
126
  udevice = udev_device_new_from_syspath (udev, sysfs_path);
 
127
  if (udevice == NULL)
 
128
    {
 
129
      g_printerr ("No udev device for %s: %m\n", sysfs_path);
 
130
      goto out;
 
131
    }
 
132
 
 
133
  /* unbind the mass storage driver (e.g. usb-storage) */
 
134
  udevice_usb_interface = udev_device_get_parent_with_subsystem_devtype (udevice, "usb", "usb_interface");
 
135
  if (udevice_usb_interface == NULL)
 
136
    {
 
137
      g_printerr ("No usb parent interface for %s: %m\n", sysfs_path);
 
138
      goto out;
 
139
    }
 
140
 
 
141
  usb_interface_name = g_path_get_basename (udev_device_get_devpath (udevice_usb_interface));
 
142
  usb_interface_name_len = strlen (usb_interface_name);
 
143
 
 
144
  unbind_path = g_strdup_printf ("%s/driver/unbind", udev_device_get_syspath (udevice_usb_interface));
 
145
  f = fopen (unbind_path, "w");
 
146
  if (f == NULL)
 
147
    {
 
148
      g_printerr ("Cannot open %s for writing: %m\n", unbind_path);
 
149
      goto out;
 
150
    }
 
151
  if (fwrite (usb_interface_name, sizeof (char), usb_interface_name_len, f) < usb_interface_name_len)
 
152
    {
 
153
      g_printerr ("Error writing %s to %s: %m\n", unbind_path, usb_interface_name);
 
154
      fclose (f);
 
155
      goto out;
 
156
    }
 
157
  fclose (f);
 
158
 
 
159
  /* If this is the only USB interface on the device, also suspend the
 
160
   * USB device to e.g.  make the lights on the device power off.
 
161
   *
 
162
   * Failing to do so is not an error, the user may not have
 
163
   * CONFIG_USB_SUSPEND enabled in their kernel.
 
164
   */
 
165
  ret = 0;
 
166
 
 
167
  udevice_usb_device = udev_device_get_parent_with_subsystem_devtype (udevice, "usb", "usb_device");
 
168
  if (udevice_usb_device != NULL)
 
169
    {
 
170
      const char *bNumInterfaces;
 
171
      char *endp;
 
172
      int num_interfaces;
 
173
      gchar *power_level_path;
 
174
      gchar suspend_str[] = "suspend";
 
175
 
 
176
      bNumInterfaces = udev_device_get_sysattr_value (udevice_usb_device, "bNumInterfaces");
 
177
      num_interfaces = strtol (bNumInterfaces, &endp, 0);
 
178
      if (endp != NULL && num_interfaces == 1)
 
179
        {
 
180
          power_level_path = g_strdup_printf ("%s/power/level", udev_device_get_syspath (udevice_usb_device));
 
181
          f = fopen (power_level_path, "w");
 
182
          if (f == NULL)
 
183
            {
 
184
              g_printerr ("Cannot open %s for writing: %m\n", unbind_path);
 
185
            }
 
186
          else
 
187
            {
 
188
              if (fwrite (suspend_str, sizeof (char), strlen (suspend_str), f) < strlen (suspend_str))
 
189
                {
 
190
                  g_printerr ("Error writing %s to %s: %m\n", power_level_path, suspend_str);
 
191
                }
 
192
              fclose (f);
 
193
            }
 
194
        }
 
195
    }
 
196
 
 
197
 out:
 
198
  g_free (usb_interface_name);
 
199
  g_free (unbind_path);
 
200
  g_free (power_level_path);
 
201
  if (sg_fd > 0)
 
202
    sg_cmds_close_device (sg_fd);
 
203
  if (udevice != NULL)
 
204
    udev_device_unref (udevice);
 
205
  if (udev != NULL)
 
206
    udev_unref (udev);
 
207
  return ret;
 
208
}