r2228: Made 'Automatic' an icon size, rather than a separate option.
[rox-filer.git] / ROX-Filer / src / mount.c
blob9791d0ddf75e7a4c5b38c91279cba813d50dd555
1 /*
2 * $Id$
4 * ROX-Filer, filer for the ROX desktop project
5 * Copyright (C) 2002, the ROX-Filer team.
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the Free
9 * Software Foundation; either version 2 of the License, or (at your option)
10 * any later version.
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
17 * You should have received a copy of the GNU General Public License along with
18 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19 * Place, Suite 330, Boston, MA 02111-1307 USA
22 /* mount.c - code for handling mount points */
24 #include "config.h"
25 #include <stdio.h>
26 #include <string.h>
27 #ifdef HAVE_FCNTL_H
28 #include <fcntl.h>
29 #endif
30 #ifdef HAVE_MNTENT_H
31 /* Linux, etc */
32 # include <mntent.h>
33 #elif HAVE_SYS_UCRED_H
34 /* NetBSD, OSF1, etc */
35 # include <fstab.h>
36 # include <sys/types.h>
37 # include <sys/param.h>
38 # include <sys/ucred.h>
39 # include <sys/mount.h>
40 # include <stdlib.h>
41 #elif HAVE_SYS_MNTENT_H
42 /* SunOS */
43 # include <sys/mntent.h>
44 # include <sys/mnttab.h>
45 #endif
46 #include <sys/time.h>
48 #include <gtk/gtk.h>
50 #include "global.h"
52 #include "mount.h"
53 #include "support.h"
55 /* Map mount points to mntent structures */
56 GHashTable *fstab_mounts = NULL;
57 time_t fstab_time;
59 /* Keys are mount points that the user mounted. Values are ignored. */
60 static GHashTable *user_mounts = NULL;
62 #ifdef HAVE_SYS_MNTENT_H
63 #define THE_FSTAB VFSTAB
64 #else
65 #define THE_FSTAB "/etc/fstab"
66 #endif
68 /* Static prototypes */
69 #ifdef DO_MOUNT_POINTS
70 static void read_table(void);
71 static void clear_table(void);
72 static time_t read_time(char *path);
73 static gboolean free_mp(gpointer key, gpointer value, gpointer data);
74 #endif
77 /****************************************************************
78 * EXTERNAL INTERFACE *
79 ****************************************************************/
81 void mount_init(void)
83 fstab_mounts = g_hash_table_new(g_str_hash, g_str_equal);
84 user_mounts = g_hash_table_new_full(g_str_hash, g_str_equal,
85 g_free, NULL);
87 #ifdef DO_MOUNT_POINTS
88 fstab_time = read_time(THE_FSTAB);
89 read_table();
90 #endif
93 /* If force is true then ignore the timestamps */
94 void mount_update(gboolean force)
96 #ifdef DO_MOUNT_POINTS
97 time_t time;
99 time = read_time(THE_FSTAB);
100 if (force || time != fstab_time)
102 fstab_time = time;
103 read_table();
105 #endif /* DO_MOUNT_POINTS */
108 /* The user has just finished mounting/unmounting this path.
109 * Update the list of user-mounted filesystems.
111 void mount_user_mount(const char *path)
113 if (mount_is_mounted(path, NULL, NULL))
114 g_hash_table_insert(user_mounts, pathdup(path), "yes");
115 else
116 g_hash_table_remove(user_mounts, path);
119 /* TRUE iff this directory is a mount point. Uses python's method to
120 * check:
121 * The function checks whether path's parent, path/.., is on a different device
122 * than path, or whether path/.. and path point to the same i-node on the same
123 * device -- this should detect mount points for all Unix and POSIX variants.
125 * 'info' and 'parent' are both optional, saving one stat() each.
127 gboolean mount_is_mounted(const guchar *path, struct stat *info,
128 struct stat *parent)
130 struct stat info_path, info_parent;
132 if (!info)
134 info = &info_path;
135 if (stat(path, &info_path))
136 return FALSE; /* Doesn't exist => not mount point :-) */
139 if (!parent)
141 guchar *tmp;
142 parent = &info_parent;
143 tmp = g_strconcat(path, "/..", NULL);
144 if (stat(tmp, &info_parent))
146 g_free(tmp);
147 return FALSE;
149 g_free(tmp);
152 if (info->st_dev != parent->st_dev)
153 return TRUE;
155 if (info->st_ino == parent->st_ino)
156 return TRUE; /* Same device and inode */
158 return FALSE;
161 /* TRUE if this mount point was mounted by the user, and still is */
162 gboolean mount_is_user_mounted(const gchar *path)
164 gboolean retval;
165 gchar *real;
167 real = pathdup(path);
169 retval = g_hash_table_lookup(user_mounts, path) != NULL;
171 if (retval)
173 /* Check the status is up-to-date */
174 mount_user_mount(real);
175 retval = g_hash_table_lookup(user_mounts, path) != NULL;
178 g_free(real);
180 return retval;
183 /****************************************************************
184 * INTERNAL FUNCTIONS *
185 ****************************************************************/
188 #ifdef DO_MOUNT_POINTS
190 static gboolean free_mp(gpointer key, gpointer value, gpointer data)
192 MountPoint *mp = (MountPoint *) value;
194 g_free(mp->name);
195 g_free(mp->dir);
196 g_free(mp);
198 return TRUE;
201 /* Remove all entries from mounts table, freeing them as we go */
202 static void clear_table(void)
204 g_hash_table_foreach_remove(fstab_mounts, free_mp, NULL);
207 /* Return the mtime of a file */
208 static time_t read_time(char *path)
210 struct stat info;
212 g_return_val_if_fail(stat(path, &info) == 0, 0);
214 return info.st_mtime;
217 # ifdef HAVE_MNTENT_H
218 static void read_table(void)
220 FILE *tab;
221 struct mntent *ent;
222 MountPoint *mp;
223 # ifdef HAVE_FCNTL_H
224 struct flock lb;
225 # endif
227 clear_table();
229 tab = setmntent(THE_FSTAB, "r");
230 g_return_if_fail(tab != NULL);
232 # ifdef HAVE_FCNTL_H
233 lb.l_type = F_RDLCK;
234 lb.l_whence = 0;
235 lb.l_start = 0;
236 lb.l_len = 0;
237 fcntl(fileno(tab), F_SETLKW, &lb);
238 # endif
240 while ((ent = getmntent(tab)))
242 if (strcmp(ent->mnt_dir, "swap") == 0)
243 continue;
245 mp = g_malloc(sizeof(MountPoint));
246 mp->name = g_strdup(ent->mnt_fsname);
247 mp->dir = g_strdup(ent->mnt_dir);
249 g_hash_table_insert(fstab_mounts, mp->dir, mp);
252 endmntent(tab);
255 # elif HAVE_SYS_MNTENT_H
256 static void read_table(void)
258 FILE *tab;
259 struct mnttab ent;
260 MountPoint *mp;
261 # ifdef HAVE_FCNTL_H
262 struct flock lb;
263 # endif
265 clear_table();
267 tab = fopen(THE_FSTAB, "r");
268 g_return_if_fail(tab != NULL);
270 # ifdef HAVE_FCNTL_H
271 lb.l_type = F_RDLCK;
272 lb.l_whence = 0;
273 lb.l_start = 0;
274 lb.l_len = 0;
275 fcntl(fileno(tab), F_SETLKW, &lb);
276 # endif
278 while (getmntent(tab, &ent)==0)
280 if (strcmp(ent.mnt_special, "swap") == 0)
281 continue;
283 mp = g_malloc(sizeof(MountPoint));
284 mp->dir = g_strdup(ent.mnt_mountp);
285 mp->name = g_strdup(ent.mnt_special);
287 g_hash_table_insert(fstab_mounts, mp->dir, mp);
290 fclose(tab);
293 # elif HAVE_SYS_UCRED_H /* We don't have getmntent(), etc */
295 static void read_table(void)
297 int tab;
298 struct fstab *ent;
299 MountPoint *mp;
301 clear_table();
303 tab = setfsent();
304 g_return_if_fail(tab != 0);
306 while ((ent = getfsent()))
308 if (strcmp(ent->fs_vfstype, "swap") == 0)
309 continue;
310 if (strcmp(ent->fs_vfstype, "kernfs") == 0)
311 continue;
313 mp = g_malloc(sizeof(MountPoint));
314 mp->name = g_strdup(ent->fs_spec); /* block special device name */
315 mp->dir = g_strdup(ent->fs_file); /* file system path prefix */
317 g_hash_table_insert(fstab_mounts, mp->dir, mp);
320 endfsent();
323 # endif /* HAVE_MNTENT_H */
325 #endif /* DO_MOUNT_POINTS */