1 /*
2 ** 1999-01-27 -	Slim wrapper for the mntent-family of API calls. Required because it
3 **		seems to be a very unstandardized standard (different between Linux and
4 **		Solaris, for example). This has been modeled after the way it works on
5 **		Linux, so systems doing it in some other way will have to have emulation
6 **		code in here... Yuck. Since we're not into writing to these databases,
7 **		that part of the API is not supported. For details about which operations
8 **		need to be implemented for a platform, see "mntent_wrap.h".
9 */
10 
11 #include "gentoo.h"
12 
13 #include <stdio.h>
14 #include <stdlib.h>
15 
16 #include "mntent_wrap.h"
17 
18 /* ----------------------------------------------------------------------------------------- */
19 
20 struct MntEnt {
21 	gchar	*fsname;
22 	gchar	*dir;
23 };
24 
25 /* ----------------------------------------------------------------------------------------- */
26 
27 #if defined __CYGWIN__ || defined __linux__ || defined __sgi	/* Linux and IRIX implementation. */
28 
29 #include <mntent.h>
30 
mne_setmntent(const gchar * filename)31 FILE * mne_setmntent(const gchar *filename)
32 {
33 	return setmntent(filename, "r");
34 }
35 
mne_getmntent(FILE * filep)36 const MntEnt * mne_getmntent(FILE *filep)
37 {
38 	static MntEnt	me;
39 	struct mntent	*ment;
40 
41 	if((ment = getmntent(filep)) != NULL)
42 	{
43 		me.fsname = ment->mnt_fsname;
44 		me.dir	  = ment->mnt_dir;
45 		return &me;
46 	}
47 	return NULL;
48 }
49 
mne_endmntent(FILE * filep)50 gint mne_endmntent(FILE *filep)
51 {
52 	return endmntent(filep);
53 }
54 
55 /* ----------------------------------------------------------------------------------------- */
56 
57 #elif defined __svr4__		/* Very weak Solaris detection, I'm sure. */
58 
59 #include <sys/mnttab.h>
60 
61 /* 1999-01-27 -	Since Solaris doesn't include the setmntent() function as a part of their
62 **		mount database access API, but rather just use a plain fopen(), I guess
63 **		the following is a pretty natural way to wrap it.
64 */
mne_setmntent(const gchar * filename)65 FILE * mne_setmntent(const gchar *filename)
66 {
67 	return fopen(filename, "rt");
68 }
69 
70 /* 1999-01-27 -	Grab a new entry from <filep>, and package it up in our platform neutral
71 **		format. If all wrappers were this simple, I would write more of them. :)
72 */
mne_getmntent(FILE * filep)73 const MntEnt * mne_getmntent(FILE *filep)
74 {
75 	static MntEnt	me;
76 	struct mnttab	mtab;
77 
78 	if((getmntent(filep, &mtab)) == 0)
79 	{
80 		me.fsname = mtab.mnt_special;
81 		me.dir	  = mtab.mnt_mountp;
82 		return &me;
83 	}
84 	return NULL;
85 }
86 
87 /* 1999-01-27 -	Close down a mount database. The natural complement to mne_setmntent(). */
mne_endmntent(FILE * filep)88 gint mne_endmntent(FILE *filep)
89 {
90 	if(filep != NULL)
91 		return fclose(filep);
92 	return -1;
93 }
94 
95 #elif defined __OpenBSD__ || defined __FreeBSD__ || defined __NetBSD__ || defined __DragonFly__ || (defined __osf__ && defined __alpha__)
96 
97 /* Here is the implementation for BSD and Alpha Tru64 systems. */
98 
99 #include <fstab.h>
100 #include <sys/mount.h>
101 #include <sys/param.h>
102 #include <sys/ucred.h>
103 
104 /* A pointer to one of these is returned by mne_setmntent(), depending on which file
105 ** name is given as an input. Note that on BSD systems, the system calls themselves
106 ** deal with the reading of files, so gentoo will never in fact open any files. But
107 ** since the calls used to access currently mounted file systems is very dissimilar
108 ** to the one used to check _available_ file systems, we need a way of keeping track
109 ** of what kind of mount entries we're supposed to deal with. Since gentoo will
110 ** pass a FILE pointer to mne_getmntent() anyway, it seems natural to use it.
111 */
112 #ifdef __DragonFly__
113 static FILE	*p_fstab, *p_mtab;
114 #else
115 static FILE	f_fstab, f_mtab;
116 #endif
117 
118 /* These are used when we're accessing the currently mounted filesystems, using
119 ** a call to getmntinfo(). The mtab_pos and mtab_num integers are then used to
120 ** keep track of where in the returned array of statfs structs we are.
121 */
122 static struct statfs	*mtab = NULL;
123 static guint		mtab_pos = 0, mtab_num = 0;
124 
125 /* 1999-05-09 -	An attempt at a BSD implementation, after having received input from
126 **		Alexander M. Tahk <tahk@MIT.EDU>, who went ahead and ported gentoo over.
127 **		Seems the BSD interface is even less flexible than the ones on Linux and
128 **		Solaris. Big deal.
129 */
mne_setmntent(const gchar * filename)130 FILE * mne_setmntent(const gchar *filename)
131 {
132 	/* This is possibly incredibly annoying and useless, but I feel serious today. :) */
133 	if((strcmp(filename, "/etc/fstab") != 0) || (strcmp(filename, "/etc/mtab") != 0))
134 		g_warning("mntent_wrap.c: Ignoring filename '%s'", filename);
135 
136 	if(strcmp(filename, "/etc/fstab") == 0)		/* Looking for available filesystems? */
137 	{
138 		if(setfsent() == 1)
139 #ifdef __DragonFly__
140 			return p_fstab;
141 #else
142 			return &f_fstab;
143 #endif
144 	}
145 	else if(strcmp(filename, "/proc/mtab") == 0)	/* Looking for mounted filesystems? */
146 	{
147 		if((mtab_num = getmntinfo(&mtab, 0)) > 0)
148 		{
149 			mtab_pos = 0;
150 #ifdef __DragonFly__
151 			return p_mtab;
152 #else
153 			return &f_mtab;
154 #endif
155 		}
156 	}
157 	return NULL;
158 }
159 
160 /* 1999-05-09 -	Get another entry of data, either about mounted (filep == &f_mtab) or available
161 **		(filep == &f_fstab) filesystems. Returns NULL when the respective data source
162 **		is exhausted.
163 */
mne_getmntent(FILE * filep)164 const MntEnt * mne_getmntent(FILE *filep)
165 {
166 	static MntEnt	me;
167 
168 #ifdef __DragonFly__
169 	if(filep == p_fstab)
170 #else
171 	if(filep == &f_fstab)
172 #endif
173 	{
174 		struct fstab	*ment;
175 
176 		if((ment = getfsent()) != NULL)
177 		{
178 			me.fsname = ment->fs_spec;
179 			me.dir	  = ment->fs_file;
180 			return &me;
181 		}
182 	}
183 #ifdef __DragonFly__
184 	else if(filep == p_mtab)
185 #else
186 	else if(filep == &f_mtab)
187 #endif
188 	{
189 		if(mtab_pos == mtab_num)		/* Array exhausted? */
190 			return NULL;
191 		me.fsname = mtab[mtab_pos].f_mntfromname;
192 		me.dir	  = mtab[mtab_pos].f_mntonname;
193 		mtab_pos++;
194 		return &me;
195 	}
196 	else
197 		g_warning("MNTENT: Bad pointer to mnt_getmntent() (%p)", filep);
198 
199 	return NULL;
200 }
201 
202 /* 1999-05-09 -	Stop traversing mount/fs data. */
mne_endmntent(FILE * filep)203 gint mne_endmntent(FILE *filep)
204 {
205 #ifdef __DragonFly__
206 	if(filep == p_fstab)
207 #else
208 	if(filep == &f_fstab)
209 #endif
210 		endfsent();
211 
212 	return 0;
213 }
214 
215 #endif
216 
217 /* ----------------------------------------------------------------------------------------- */
218 
219 /* Functions below are platform independant. Nice. */
220 
221 /* 1999-01-27 -	Create a copy of <src>, using dynamically allocated memory. The
222 **		copy is done so that a) it shares no memory with <src>, and b)
223 **		it is contigous, because that is nice. :)
224 */
mne_copy(const MntEnt * src)225 MntEnt * mne_copy(const MntEnt *src)
226 {
227 	MntEnt	*ne = NULL;
228 	gsize	s_fs, s_dir;
229 
230 	if(src != NULL)
231 	{
232 		s_fs  = strlen(src->fsname) + 1;
233 		s_dir = strlen(src->dir) + 1;
234 		ne = g_malloc(sizeof *ne + s_fs + s_dir);
235 		ne->fsname = (gchar *) (ne + 1);
236 		ne->dir    = (gchar *) (ne + 1) + s_fs;
237 		strcpy(ne->fsname, src->fsname);
238 		strcpy(ne->dir, src->dir);
239 	}
240 	return ne;
241 }
242 
243 /* 1999-01-27 -	Destroy (free) a previously created mount entry descriptor. You can
244 **		only call this with entries created by mne_copy() above.
245 */
mne_destroy(MntEnt * me)246 void mne_destroy(MntEnt *me)
247 {
248 	if(me != NULL)
249 		g_free(me);	/* Thanks to funky g_malloc()ing, I can do this. */
250 }
251 
252 /* 1999-01-27 -	Return a pointer to a string giving the full path of the entry's mount
253 **		point.
254 */
mne_get_mountpoint(const MntEnt * me)255 const gchar * mne_get_mountpoint(const MntEnt *me)
256 {
257 	return me ? me->dir : NULL;
258 }
259 
260 /* 1999-01-27 -	Return pointer to string giving the device the entry describes. */
mne_get_device(const MntEnt * me)261 const gchar * mne_get_device(const MntEnt *me)
262 {
263 	return me ? me->fsname : NULL;
264 }
265