4 * ROX-Filer, filer for the ROX desktop project
5 * Copyright (C) 2000, Thomas Leonard, <tal197@ecs.soton.ac.uk>.
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)
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
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 */
32 #elif HAVE_SYS_UCRED_H
35 # include <sys/param.h>
36 # include <sys/ucred.h>
37 # include <sys/mount.h>
39 #elif HAVE_SYS_MNTENT_H
41 # include <sys/mntent.h>
42 # include <sys/mnttab.h>
53 /* Map mount points to mntent structures */
54 GHashTable
*fstab_mounts
= NULL
;
55 GHashTable
*mtab_mounts
= NULL
;
58 #ifdef HAVE_SYS_MNTENT_H
59 #define THE_MTAB MNTTAB
60 #define THE_FSTAB VFSTAB
62 #define THE_MTAB "/etc/mtab"
63 #define THE_FSTAB "/etc/fstab"
66 #if defined(HAVE_MNTENT_H) || defined(HAVE_SYS_MNTENT_H)
70 /* Static prototypes */
71 #ifdef HAVE_SYS_UCRED_H
72 static GHashTable
*build_mtab_table(GHashTable
*mount_points
);
74 #ifdef DO_MOUNT_POINTS
75 static GHashTable
*read_table(GHashTable
*mount_points
, char *path
);
76 static void clear_table(GHashTable
*table
);
77 static time_t read_time(char *path
);
78 static gboolean
free_mp(gpointer key
, gpointer value
, gpointer data
);
83 fstab_mounts
= g_hash_table_new(g_str_hash
, g_str_equal
);
84 mtab_mounts
= g_hash_table_new(g_str_hash
, g_str_equal
);
86 #ifdef DO_MOUNT_POINTS
87 fstab_time
= read_time(THE_FSTAB
);
88 read_table(fstab_mounts
, THE_FSTAB
);
89 # if defined(HAVE_MNTENT_H) || defined(HAVE_SYS_MNTENT_H)
90 mtab_time
= read_time(THE_MTAB
);
91 read_table(mtab_mounts
, THE_MTAB
);
92 # elif HAVE_SYS_UCRED_H
93 /* mtab_time not used */
94 build_mtab_table(mtab_mounts
);
96 #endif /* DO_MOUNT_POINTS */
99 /* If force is true then ignore the timestamps */
100 void mount_update(gboolean force
)
102 #ifdef DO_MOUNT_POINTS
104 /* Ensure everything is uptodate */
106 time
= read_time(THE_FSTAB
);
107 if (force
|| time
!= fstab_time
)
110 read_table(fstab_mounts
, THE_FSTAB
);
112 # if defined(HAVE_MNTENT_H) || defined(HAVE_SYS_MNTENT_H)
113 time
= read_time(THE_MTAB
);
114 if (force
|| time
!= mtab_time
)
117 read_table(mtab_mounts
, THE_MTAB
);
120 build_mtab_table(mtab_mounts
);
122 #endif /* DO_MOUNT_POINTS */
126 #ifdef DO_MOUNT_POINTS
128 static gboolean
free_mp(gpointer key
, gpointer value
, gpointer data
)
130 MountPoint
*mp
= (MountPoint
*) value
;
139 /* Remove all entries from a hash table, freeing them as we go */
140 static void clear_table(GHashTable
*table
)
142 g_hash_table_foreach_remove(table
, free_mp
, NULL
);
145 /* Return the mtime of a file */
146 static time_t read_time(char *path
)
150 g_return_val_if_fail(stat(path
, &info
) == 0, 0);
152 return info
.st_mtime
;
158 static GHashTable
*read_table(GHashTable
*mount_points
, char *path
)
164 clear_table(mount_points
);
166 tab
= setmntent(path
, "r");
167 g_return_val_if_fail(tab
!= NULL
, NULL
);
169 while ((ent
= getmntent(tab
)))
171 if (strcmp(ent
->mnt_dir
, "swap") == 0)
174 mp
= g_malloc(sizeof(MountPoint
));
175 mp
->name
= g_strdup(ent
->mnt_fsname
);
176 mp
->dir
= g_strdup(ent
->mnt_dir
);
178 g_hash_table_insert(mount_points
, mp
->dir
, mp
);
186 #elif HAVE_SYS_MNTENT_H
187 static GHashTable
*read_table(GHashTable
*mount_points
, char *path
)
196 tab
= fopen(path
, "r");
197 g_return_val_if_fail(tab
!= NULL
, NULL
);
198 clear_table(mount_points
);
205 fcntl(fileno(tab
), F_SETLKW
, &lb
);
208 while (getmntent(tab
, &ent
)==0)
210 if (strcmp(ent
.mnt_special
, "swap") == 0)
213 mp
= g_malloc(sizeof(MountPoint
));
214 mp
->dir
= g_strdup(ent
.mnt_mountp
);
215 mp
->name
= g_strdup(ent
.mnt_special
);
217 g_hash_table_insert(mount_points
, mp
->dir
, mp
);
225 #elif HAVE_SYS_UCRED_H /* We don't have /etc/mtab */
227 static GHashTable
*read_table(GHashTable
*mount_points
, char *path
)
233 clear_table(mount_points
);
236 g_return_val_if_fail(tab
!= 0, NULL
);
238 while ((ent
= getfsent()))
240 if (strcmp(ent
->fs_vfstype
, "swap") == 0)
242 if (strcmp(ent
->fs_vfstype
, "kernfs") == 0)
245 mp
= g_malloc(sizeof(MountPoint
));
246 mp
->name
= g_strdup(ent
->fs_spec
); /* block special device name */
247 mp
->dir
= g_strdup(ent
->fs_file
); /* file system path prefix */
249 g_hash_table_insert(mount_points
, mp
->dir
, mp
);
258 /* build table of mounted file systems */
259 static GHashTable
*build_mtab_table(GHashTable
*mount_points
)
263 struct statfs
*mntbufp
;
266 clear_table( mount_points
);
268 /* we could use getfsstat twice and do the memory allocation
269 * ourselves, but I feel lazy today. we can't free memory after use
272 fsstat_entries
= getmntinfo( &mntbufp
, MNT_WAIT
);
273 /* wait for mount entries to be updated by each file system.
274 * Use MNT_NOWAIT if you don't want this to block, but results
275 * may not be up to date.
277 g_return_val_if_fail(fsstat_entries
>= 0, NULL
);
278 if (fsstat_entries
== 0) return NULL
;
279 /* not a failure but nothing mounted! */
281 for (fsstat_index
= 0; fsstat_index
< fsstat_entries
; fsstat_index
++)
283 if(strcmp(mntbufp
[fsstat_index
].f_fstypename
, "swap") == 0)
285 if(strcmp(mntbufp
[fsstat_index
].f_fstypename
, "kernfs") == 0)
288 mp
= g_malloc(sizeof(MountPoint
));
289 mp
->name
= g_strdup( mntbufp
[fsstat_index
].f_mntfromname
);
290 mp
->dir
= g_strdup( mntbufp
[fsstat_index
].f_mntonname
);
292 g_hash_table_insert(mount_points
, mp
->dir
, mp
);