r1996: Cope slightly better with invalid filenames in various places (reported by
[rox-filer.git] / ROX-Filer / src / mount.c
blobda0ea2e4f62281f42417d91f12fe0d37c945fb4c
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"
54 /* Map mount points to mntent structures */
55 GHashTable *fstab_mounts = NULL;
56 time_t fstab_time;
58 #ifdef HAVE_SYS_MNTENT_H
59 #define THE_FSTAB VFSTAB
60 #else
61 #define THE_FSTAB "/etc/fstab"
62 #endif
64 /* Static prototypes */
65 #ifdef DO_MOUNT_POINTS
66 static void read_table(void);
67 static void clear_table(void);
68 static time_t read_time(char *path);
69 static gboolean free_mp(gpointer key, gpointer value, gpointer data);
70 #endif
73 /****************************************************************
74 * EXTERNAL INTERFACE *
75 ****************************************************************/
77 void mount_init(void)
79 fstab_mounts = g_hash_table_new(g_str_hash, g_str_equal);
81 #ifdef DO_MOUNT_POINTS
82 fstab_time = read_time(THE_FSTAB);
83 read_table();
84 #endif
87 /* If force is true then ignore the timestamps */
88 void mount_update(gboolean force)
90 #ifdef DO_MOUNT_POINTS
91 time_t time;
93 time = read_time(THE_FSTAB);
94 if (force || time != fstab_time)
96 fstab_time = time;
97 read_table();
99 #endif /* DO_MOUNT_POINTS */
102 /* TRUE iff this directory is a mount point. Uses python's method to
103 * check:
104 * The function checks whether path's parent, path/.., is on a different device
105 * than path, or whether path/.. and path point to the same i-node on the same
106 * device -- this should detect mount points for all Unix and POSIX variants.
108 * 'info' and 'parent' are both optional, saving one stat() each.
110 gboolean mount_is_mounted(const guchar *path, struct stat *info,
111 struct stat *parent)
113 struct stat info_path, info_parent;
115 if (!info)
117 info = &info_path;
118 if (stat(path, &info_path))
119 return FALSE; /* Doesn't exist => not mount point :-) */
122 if (!parent)
124 guchar *tmp;
125 parent = &info_parent;
126 tmp = g_strconcat(path, "/..", NULL);
127 if (stat(tmp, &info_parent))
129 g_free(tmp);
130 return FALSE;
132 g_free(tmp);
135 if (info->st_dev != parent->st_dev)
136 return TRUE;
138 if (info->st_ino == parent->st_ino)
139 return TRUE; /* Same device and inode */
141 return FALSE;
144 /****************************************************************
145 * INTERNAL FUNCTIONS *
146 ****************************************************************/
149 #ifdef DO_MOUNT_POINTS
151 static gboolean free_mp(gpointer key, gpointer value, gpointer data)
153 MountPoint *mp = (MountPoint *) value;
155 g_free(mp->name);
156 g_free(mp->dir);
157 g_free(mp);
159 return TRUE;
162 /* Remove all entries from mounts table, freeing them as we go */
163 static void clear_table(void)
165 g_hash_table_foreach_remove(fstab_mounts, free_mp, NULL);
168 /* Return the mtime of a file */
169 static time_t read_time(char *path)
171 struct stat info;
173 g_return_val_if_fail(stat(path, &info) == 0, 0);
175 return info.st_mtime;
178 # ifdef HAVE_MNTENT_H
179 static void read_table(void)
181 FILE *tab;
182 struct mntent *ent;
183 MountPoint *mp;
184 # ifdef HAVE_FCNTL_H
185 struct flock lb;
186 # endif
188 clear_table();
190 tab = setmntent(THE_FSTAB, "r");
191 g_return_if_fail(tab != NULL);
193 # ifdef HAVE_FCNTL_H
194 lb.l_type = F_RDLCK;
195 lb.l_whence = 0;
196 lb.l_start = 0;
197 lb.l_len = 0;
198 fcntl(fileno(tab), F_SETLKW, &lb);
199 # endif
201 while ((ent = getmntent(tab)))
203 if (strcmp(ent->mnt_dir, "swap") == 0)
204 continue;
206 mp = g_malloc(sizeof(MountPoint));
207 mp->name = g_strdup(ent->mnt_fsname);
208 mp->dir = g_strdup(ent->mnt_dir);
210 g_hash_table_insert(fstab_mounts, mp->dir, mp);
213 endmntent(tab);
216 # elif HAVE_SYS_MNTENT_H
217 static void read_table(void)
219 FILE *tab;
220 struct mnttab ent;
221 MountPoint *mp;
222 # ifdef HAVE_FCNTL_H
223 struct flock lb;
224 # endif
226 clear_table();
228 tab = fopen(THE_FSTAB, "r");
229 g_return_if_fail(tab != NULL);
231 # ifdef HAVE_FCNTL_H
232 lb.l_type = F_RDLCK;
233 lb.l_whence = 0;
234 lb.l_start = 0;
235 lb.l_len = 0;
236 fcntl(fileno(tab), F_SETLKW, &lb);
237 # endif
239 while (getmntent(tab, &ent)==0)
241 if (strcmp(ent.mnt_special, "swap") == 0)
242 continue;
244 mp = g_malloc(sizeof(MountPoint));
245 mp->dir = g_strdup(ent.mnt_mountp);
246 mp->name = g_strdup(ent.mnt_special);
248 g_hash_table_insert(fstab_mounts, mp->dir, mp);
251 fclose(tab);
254 # elif HAVE_SYS_UCRED_H /* We don't have getmntent(), etc */
256 static void read_table(void)
258 int tab;
259 struct fstab *ent;
260 MountPoint *mp;
262 clear_table();
264 tab = setfsent();
265 g_return_if_fail(tab != 0);
267 while ((ent = getfsent()))
269 if (strcmp(ent->fs_vfstype, "swap") == 0)
270 continue;
271 if (strcmp(ent->fs_vfstype, "kernfs") == 0)
272 continue;
274 mp = g_malloc(sizeof(MountPoint));
275 mp->name = g_strdup(ent->fs_spec); /* block special device name */
276 mp->dir = g_strdup(ent->fs_file); /* file system path prefix */
278 g_hash_table_insert(fstab_mounts, mp->dir, mp);
281 endfsent();
284 # endif /* HAVE_MNTENT_H */
286 #endif /* DO_MOUNT_POINTS */