1 /***************************************************************************
3 * hal-storage-eject.c : Eject method handler
5 * Copyright (C) 2006 David Zeuthen, <david@fubar.dk>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 **************************************************************************/
32 #include <glib/gstdio.h>
33 #include <sys/types.h>
37 #include <libhal-storage.h>
39 #include <libpolkit.h>
42 #include "hal-storage-shared.h"
44 /* possible values: "Volume", "Storage" */
45 static char *devtype
= "Volume";
51 fprintf (stderr
, "This program should only be started by hald.\n");
57 unknown_eject_error (const char *detail
)
59 fprintf (stderr
, "org.freedesktop.Hal.Device.%s.UnknownFailure\n", devtype
);
60 fprintf (stderr
, "%s\n", detail
);
66 invalid_eject_option (const char *option
, const char *uid
)
68 fprintf (stderr
, "org.freedesktop.Hal.Device.Volume.InvalidEjectOption\n");
69 fprintf (stderr
, "The option '%s' is not allowed for uid=%s\n", option
, uid
);
75 main (int argc
, char *argv
[])
79 const char *drive_udi
;
83 LibHalContext
*hal_ctx
= NULL
;
84 DBusConnection
*system_bus
= NULL
;
86 LibPolKitContext
*pol_ctx
= NULL
;
89 char *invoked_by_syscon_name
;
93 char eject_options
[1024];
97 device
= getenv ("HAL_PROP_BLOCK_DEVICE");
101 udi
= getenv ("HAL_PROP_INFO_UDI");
105 invoked_by_uid
= getenv ("HAL_METHOD_INVOKED_BY_UID");
107 invoked_by_syscon_name
= getenv ("HAL_METHOD_INVOKED_BY_SYSTEMBUS_CONNECTION_NAME");
109 dbus_error_init (&error
);
110 if ((hal_ctx
= libhal_ctx_init_direct (&error
)) == NULL
) {
111 printf ("Cannot connect to hald\n");
112 LIBHAL_FREE_DBUS_ERROR (&error
);
116 dbus_error_init (&error
);
117 system_bus
= dbus_bus_get (DBUS_BUS_SYSTEM
, &error
);
118 if (system_bus
== NULL
) {
119 printf ("Cannot connect to the system bus\n");
120 LIBHAL_FREE_DBUS_ERROR (&error
);
124 pol_ctx
= libpolkit_new_context (system_bus
);
125 if (pol_ctx
== NULL
) {
126 printf ("Cannot get libpolkit context\n");
127 unknown_eject_error ("Cannot get libpolkit context");
131 /* read from stdin */
132 if (strlen (fgets (eject_options
, sizeof (eject_options
), stdin
)) > 0)
133 eject_options
[strlen (eject_options
) - 1] = '\0';
134 /* validate that input from stdin is UTF-8 */
135 if (!g_utf8_validate (eject_options
, -1, &end
))
136 unknown_eject_error ("Error validating eject_options as UTF-8");
138 printf ("eject_options = '%s'\n", eject_options
);
141 /* delete any trailing whitespace options from splitting the string */
142 given_options
= g_strsplit (eject_options
, "\t", 0);
143 for (i
= g_strv_length (given_options
) - 1; i
>= 0; --i
) {
144 if (strlen (given_options
[i
]) > 0)
146 given_options
[i
] = NULL
;
149 /* check eject options */
150 for (i
= 0; given_options
[i
] != NULL
; i
++) {
151 char *given
= given_options
[i
];
153 /* none supported right now */
155 invalid_eject_option (given
, invoked_by_uid
);
157 g_strfreev (given_options
);
159 /* should be either volume or storage */
160 if ((volume
= libhal_volume_from_udi (hal_ctx
, udi
)) != NULL
) {
161 drive_udi
= libhal_volume_get_storage_device_udi (volume
);
163 drive_udi
= g_strdup (udi
);
166 if (drive_udi
== NULL
) {
167 unknown_eject_error ("Cannot get drive udi");
169 if ((drive
= libhal_drive_from_udi (hal_ctx
, drive_udi
)) == NULL
) {
170 unknown_eject_error ("Cannot get drive from udi");
173 /* first, unmount all volumes */
174 volume_udis
= libhal_drive_find_all_volumes (hal_ctx
, drive
, &num_volumes
);
175 if (volume_udis
== NULL
)
176 unknown_eject_error ("Cannot get all enclosed volumes");
177 for (i
= 0; i
< num_volumes
; i
++) {
179 LibHalVolume
*volume_to_unmount
;
181 volume_udi
= volume_udis
[i
];
184 printf ("processing drive's volume %s (%d of %d)\n", volume_udi
, i
+ 1, num_volumes
);
186 volume_to_unmount
= libhal_volume_from_udi (hal_ctx
, volume_udi
);
187 if (volume_to_unmount
== NULL
) {
188 unknown_eject_error ("Cannot get volume object");
191 if (libhal_volume_is_mounted (volume_to_unmount
)) {
193 printf (" unmounting\n");
195 /* only lock around unmount call because hald's /proc/mounts handler
196 * will also want to lock the /media/.hal-mtab-lock file for peeking
198 if (!lock_hal_mtab ()) {
199 unknown_eject_error ("Cannot obtain lock on /media/.hal-mtab");
201 handle_unmount (hal_ctx
,
205 volume_udi
, volume_to_unmount
, drive
,
206 libhal_volume_get_device_file (volume_to_unmount
),
207 invoked_by_uid
, invoked_by_syscon_name
,
208 FALSE
, FALSE
, system_bus
); /* use neither lazy nor force */
212 printf (" not mounted\n");
216 libhal_volume_free (volume_to_unmount
);
219 libhal_free_string_array (volume_udis
);
221 /* now attempt the eject */
222 handle_eject (hal_ctx
,
226 libhal_drive_get_udi (drive
),
228 libhal_drive_get_device_file (drive
),
230 invoked_by_syscon_name
,