corrected some lines too long...
[midnight-commander.git] / gnome / gmount.c
blob3c7918dc3d7bf0e033df77f55b34e6dc05c27606
1 /* Mount/umount support for the Midnight Commander
3 * Copyright (C) 1998-1999 The Free Software Foundation
5 * Authors: Miguel de Icaza <miguel@nuclecu.unam.mx>
6 * Federico Mena <federico@nuclecu.unam.mx>
7 */
9 #include <config.h>
10 #include <stdio.h>
12 #ifdef STDC_HEADERS
13 #include <stdlib.h>
14 #else
15 void free (void *ptr);
16 #endif
17 #if defined(STDC_HEADERS) || defined(HAVE_STRING_H)
18 #include <string.h>
19 #else
20 #include <strings.h>
21 #endif
23 #ifdef HAVE_SYS_PARAM_H
24 #include <sys/param.h>
25 #endif
27 #if defined (MOUNTED_GETFSSTAT) /* __alpha running OSF_1 */
28 #include <sys/mount.h>
29 #include <sys/fs_types.h>
30 #endif /* MOUNTED_GETFSSTAT */
32 #ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
33 #include <mntent.h>
34 #if !defined(MOUNTED)
35 #if defined(MNT_MNTTAB) /* HP-UX. */
36 #define MOUNTED MNT_MNTTAB
37 #endif
38 #if defined(MNTTABNAME) /* Dynix. */
39 #define MOUNTED MNTTABNAME
40 #endif
41 #endif
42 #endif
44 #ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */
45 #include <sys/mount.h>
46 #endif
48 #ifdef MOUNTED_GETMNT /* Ultrix. */
49 #include <sys/mount.h>
50 #include <sys/fs_types.h>
51 #endif
53 #ifdef MOUNTED_FREAD /* SVR2. */
54 #include <mnttab.h>
55 #endif
57 #ifdef MOUNTED_FREAD_FSTYP /* SVR3. */
58 #include <mnttab.h>
59 #include <sys/fstyp.h>
60 #include <sys/statfs.h>
61 #endif
63 #ifdef MOUNTED_GETMNTENT2 /* SVR4. */
64 #include <sys/mnttab.h>
65 #endif
67 #ifdef MOUNTED_VMOUNT /* AIX. */
68 #include <fshelp.h>
69 #include <sys/vfs.h>
70 #endif
72 /* 4.4BSD2 derived systems */
73 #if defined(__bsdi__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
74 # ifndef MOUNT_UFS
75 # define xBSD
76 # endif
77 #endif
79 /* void error (void); FIXME -- needed? */
81 #ifdef DOLPHIN
82 /* So special that it's not worth putting this in autoconf. */
83 #undef MOUNTED_FREAD_FSTYP
84 #define MOUNTED_GETMNTTBL
85 #endif
87 #ifdef HAVE_CORBA
88 #include <libgnorba/gnorba.h>
89 #include "magicdev.h"
90 #endif HAVE_CORBA
92 #include <dirent.h>
93 #include <sys/types.h>
94 #include <unistd.h>
95 #include <gnome.h>
96 #include "../vfs/vfs.h"
97 #include "dialog.h"
98 #include "gdesktop.h"
99 #include "gmount.h"
100 #include "util.h"
101 #include "i18n.h"
105 /* Information for a mountable device */
106 typedef struct {
107 char *devname;
108 char *mount_point;
110 /* This is just a good guess */
111 enum {
112 TYPE_UNKNOWN,
113 TYPE_CDROM,
114 TYPE_NFS
115 } type;
116 } devname_info_t;
120 static gboolean
121 option_has_user (char *str)
123 char *p;
124 if ((p = strstr (str, "user")) != NULL) {
125 if ((p - 2) >= str) {
126 if (strncmp (p - 2, "nouser", 6) == 0)
127 return FALSE;
129 return TRUE;
131 return FALSE;
136 #ifdef MOUNTED_GETMNTENT1
138 /* Returns whether the mount entry has the owner flag and our euid matches the
139 * device file.
141 static gboolean
142 option_has_owner (struct mntent *mnt)
144 struct stat st;
146 if (strstr (mnt->mnt_opts, "owner") == NULL)
147 return FALSE;
149 if (stat (mnt->mnt_fsname, &st) != 0)
150 return FALSE;
152 if (st.st_uid != geteuid ())
153 return FALSE;
155 return TRUE;
158 /* Returns whether devname is mountable: NULL if it is not or g_strdup()ed
159 * string with the mount point.
161 char *
162 is_block_device_mountable (char *mount_point)
164 FILE *f;
165 struct mntent *mnt;
166 char *retval = NULL;
168 f = setmntent ("/etc/fstab", "r");
169 if (f == NULL)
170 return NULL;
172 while ((mnt = getmntent (f)) != NULL) {
173 if (strcmp (mnt->mnt_dir, mount_point) != 0) {
174 /* This second test is for compatibility with older
175 * desktops that might be using this.
177 if (strcmp (mnt->mnt_dir, mount_point) != 0)
178 continue;
181 if (getuid () == 0) {
182 retval = g_strdup (mnt->mnt_dir);
183 break;
186 if (option_has_user (mnt->mnt_opts) || option_has_owner (mnt)) {
187 retval = g_strdup (mnt->mnt_dir);
188 break;
192 endmntent (f);
193 return retval;
196 gboolean
197 is_block_device_mounted (char *filename)
199 FILE *f;
200 struct mntent *mnt;
201 gboolean retval = FALSE;
203 f = setmntent ("/etc/mtab", "r");
204 if (f == NULL)
205 return FALSE;
207 while ((mnt = getmntent (f)) != NULL) {
208 if (strcmp (mnt->mnt_dir, filename) == 0)
209 retval = TRUE;
212 endmntent (f);
213 return retval;
216 static GList *
217 get_mountable_devices (void)
219 FILE *f;
220 struct mntent *mnt;
221 GList *list = NULL;
223 f = setmntent ("/etc/fstab", "r");
224 if (f == NULL) {
225 message (1, MSG_ERROR, _("Could not open the /etc/fstab file"));
226 return NULL;
229 while ((mnt = getmntent (f)) != NULL) {
230 if (option_has_user (mnt->mnt_opts) || option_has_owner (mnt)) {
231 devname_info_t *dit;
233 dit = g_new0 (devname_info_t, 1);
234 dit->devname = g_strdup (mnt->mnt_fsname);
235 dit->mount_point = g_strdup (mnt->mnt_dir);
236 dit->type = TYPE_UNKNOWN;
238 if (strcmp (mnt->mnt_type, "iso9660") == 0)
239 dit->type = TYPE_CDROM;
241 if (strcmp (mnt->mnt_type, "nfs") == 0)
242 dit->type = TYPE_NFS;
244 list = g_list_prepend (list, dit);
248 endmntent (f);
250 list = g_list_reverse (list);
251 return list;
254 char *
255 mount_point_to_device (char *mount_point)
257 FILE *f;
258 struct mntent *mnt;
260 f = setmntent ("/etc/fstab", "r");
261 if (f == NULL)
262 return NULL;
264 while ((mnt = getmntent (f))) {
265 if (strcmp (mnt->mnt_dir, mount_point) == 0) {
266 char *v;
268 v = g_strdup (mnt->mnt_fsname);
269 endmntent (f);
270 return v;
273 endmntent (f);
274 return NULL;
279 #else
281 char *
282 is_block_device_mountable (char *mount_point)
284 return NULL;
287 static GList *
288 get_mountable_devices (void)
290 return NULL;
293 gboolean
294 is_block_device_mounted (char *mount_point)
296 return TRUE;
299 char *
300 mount_point_to_device (char *mount_point)
302 return NULL;
304 #endif
308 /* Returns whether our supported automounter is running */
309 static gboolean
310 automounter_is_running (void)
312 #if defined(HAVE_CORBA)
313 CORBA_Object server;
314 CORBA_Environment ev;
315 gboolean result = FALSE;
317 CORBA_exception_init (&ev);
319 server = goad_server_activate_with_id (NULL,
320 "GOAD:magicdev:19990913",
321 GOAD_ACTIVATE_EXISTING_ONLY,
322 NULL);
324 if (!CORBA_Object_is_nil (server, &ev)) {
325 result = GNOME_MagicDev_is_running (server, &ev);
326 if (ev._major != CORBA_NO_EXCEPTION)
327 result = FALSE;
329 CORBA_Object_release (server, &ev);
332 return result;
334 #else /* !HAVE_CORBA */
335 return FALSE;
336 #endif /* HAVE_CORBA */
341 /* Cleans up the desktop directory from device files. Includes block devices
342 * and printers.
344 void
345 desktop_cleanup_devices (void)
347 DIR *dir;
348 struct dirent *dent;
350 dir = mc_opendir (desktop_directory);
351 if (!dir) {
352 g_warning ("Could not clean up desktop devices");
353 return;
356 gnome_metadata_lock ();
357 while ((dent = mc_readdir (dir)) != NULL) {
358 char *full_name;
359 char *buf;
360 int size;
362 full_name = g_concat_dir_and_file (desktop_directory, dent->d_name);
363 if (gnome_metadata_get (full_name, "is-desktop-device", &size, &buf) == 0) {
364 mc_unlink (full_name);
365 gnome_metadata_delete (full_name);
366 g_free (buf);
368 g_free (full_name);
370 gnome_metadata_unlock ();
372 mc_closedir (dir);
375 /* Creates the desktop link for the specified device */
376 static void
377 create_device_link (char *dev_name, char *short_dev_name, char *caption, char *icon,
378 gboolean ejectable)
380 char *full_name;
381 char *icon_full;
382 char type = 'D';
383 char ejectable_c = ejectable;
385 icon_full = g_concat_dir_and_file (ICONDIR, icon);
386 full_name = g_concat_dir_and_file (desktop_directory, short_dev_name);
387 if (mc_symlink (dev_name, full_name) != 0) {
388 message (FALSE,
389 _("Warning"),
390 _("Could not symlink %s to %s; "
391 "will not have such a desktop device icon."),
392 dev_name, full_name);
393 return;
396 gnome_metadata_set (full_name, "icon-filename", strlen (icon_full) + 1, icon_full);
397 gnome_metadata_set (full_name, "icon-caption", strlen (caption) + 1, caption);
398 gnome_metadata_set (full_name, "device-is-ejectable", 1, &ejectable_c);
399 gnome_metadata_set (full_name, "is-desktop-device", 1, &type); /* hack a boolean value */
401 g_free (full_name);
402 g_free (icon_full);
405 /* Creates the desktop links to the mountable devices */
406 static void
407 setup_devices (void)
409 GList *list, *l;
410 int floppy_count;
411 int hd_count;
412 int cdrom_count;
413 int generic_count;
414 int nfs_count;
415 int automounter;
417 list = get_mountable_devices ();
418 automounter = automounter_is_running ();
420 hd_count = 0;
421 cdrom_count = 0;
422 floppy_count = 0;
423 generic_count = 0;
425 for (l = list; l; l = l->next) {
426 devname_info_t *dit = l->data;
427 char *dev_name;
428 char *short_dev_name;
429 char *format;
430 char *icon;
431 int count;
432 char buffer[128];
433 gboolean release_format;
434 gboolean ejectable;
435 gboolean do_create;
437 dev_name = dit->devname;
438 short_dev_name = x_basename (dev_name);
440 release_format = FALSE;
441 ejectable = FALSE;
442 do_create = TRUE;
444 /* Create the format/icon/count. This could use better heuristics. */
445 if (dit->type == TYPE_CDROM || strncmp (short_dev_name, "cdrom", 5) == 0) {
446 format = _("CD-ROM %d");
447 icon = "i-cdrom.png";
448 count = cdrom_count++;
449 ejectable = TRUE;
451 /* If our supported automounter is running, then we can
452 * be nice and create only the links for CD-ROMS that
453 * are actually mounted.
455 if (automounter && !is_block_device_mounted (dit->mount_point))
456 do_create = FALSE;
457 } else if (strncmp (short_dev_name, "fd", 2) == 0) {
458 format = _("Floppy %d");
459 icon = "i-floppy.png";
460 count = floppy_count++;
461 ejectable = TRUE;
462 } else if (strncmp (short_dev_name, "hd", 2) == 0
463 || strncmp (short_dev_name, "sd", 2) == 0) {
464 format = _("Disk %d");
465 icon = "i-blockdev.png";
466 count = hd_count++;
467 } else if (dit->type == TYPE_NFS) {
468 release_format = TRUE;
469 format = g_strdup_printf (_("NFS dir %s"), dit->mount_point);
470 icon = "i-nfs.png";
471 count = nfs_count++;
472 } else {
473 format = _("Device %d");
474 icon = "i-blockdev.png";
475 count = generic_count++;
478 g_snprintf (buffer, sizeof (buffer), format, count);
479 if (release_format) {
480 g_free (format);
481 format = NULL;
484 /* Create the actual link */
486 if (do_create)
487 create_device_link (dit->mount_point, short_dev_name,
488 buffer, icon, ejectable);
490 g_free (dit->devname);
491 g_free (dit->mount_point);
492 g_free (dit);
495 g_list_free (list);
498 void
499 gmount_setup_devices (void)
501 setup_devices ();