5
|
1 /* mountlist.c -- return a list of mounted filesystems |
|
2 Copyright (C) 1991, 1992 Free Software Foundation, Inc. |
|
3 |
|
4 This program is free software; you can redistribute it and/or modify |
|
5 it under the terms of the GNU General Public License as published by |
|
6 the Free Software Foundation; either version 2, or (at your option) |
|
7 any later version. |
|
8 |
|
9 This program is distributed in the hope that it will be useful, |
|
10 but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 GNU General Public License for more details. |
|
13 |
|
14 You should have received a copy of the GNU General Public License |
|
15 along with this program; if not, write to the Free Software |
|
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ |
|
17 |
|
18 #include <stdio.h> |
|
19 #include <sys/types.h> |
|
20 #include "mountlist.h" |
|
21 |
|
22 #ifdef STDC_HEADERS |
|
23 #include <stdlib.h> |
|
24 #else |
|
25 void free (); |
|
26 #endif |
20
|
27 #if defined(STDC_HEADERS) || defined(HAVE_STRING_H) |
5
|
28 #include <string.h> |
|
29 #else |
|
30 #include <strings.h> |
|
31 #endif |
|
32 |
|
33 char *strstr (); |
|
34 char *xmalloc (); |
|
35 char *xrealloc (); |
|
36 char *xstrdup (); |
|
37 void error (); |
|
38 |
57
|
39 #if defined (MOUNTED_GETFSSTAT) /* __alpha running OSF_1 */ |
|
40 # include <sys/mount.h> |
|
41 # include <sys/fs_types.h> |
|
42 #endif /* MOUNTED_GETFSSTAT */ |
|
43 |
5
|
44 #ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */ |
|
45 #include <mntent.h> |
|
46 #if !defined(MOUNTED) |
|
47 # if defined(MNT_MNTTAB) /* HP-UX. */ |
|
48 # define MOUNTED MNT_MNTTAB |
|
49 # endif |
|
50 # if defined(MNTTABNAME) /* Dynix. */ |
|
51 # define MOUNTED MNTTABNAME |
|
52 # endif |
|
53 #endif |
|
54 #endif |
|
55 |
|
56 #ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */ |
|
57 #include <sys/mount.h> |
|
58 #endif |
|
59 |
|
60 #ifdef MOUNTED_GETMNT /* Ultrix. */ |
|
61 #include <sys/param.h> |
|
62 #include <sys/mount.h> |
|
63 #include <sys/fs_types.h> |
|
64 #endif |
|
65 |
|
66 #ifdef MOUNTED_FREAD /* SVR2. */ |
|
67 #include <mnttab.h> |
|
68 #endif |
|
69 |
|
70 #ifdef MOUNTED_FREAD_FSTYP /* SVR3. */ |
|
71 #include <mnttab.h> |
|
72 #include <sys/fstyp.h> |
|
73 #include <sys/statfs.h> |
|
74 #endif |
|
75 |
|
76 #ifdef MOUNTED_GETMNTENT2 /* SVR4. */ |
|
77 #include <sys/mnttab.h> |
|
78 #endif |
|
79 |
|
80 #ifdef MOUNTED_VMOUNT /* AIX. */ |
|
81 #include <fshelp.h> |
|
82 #include <sys/vfs.h> |
|
83 #endif |
|
84 |
64
|
85 #ifdef DOLPHIN |
|
86 /* So special that it's not worth putting this in autoconf. */ |
|
87 #undef MOUNTED_FREAD_FSTYP |
|
88 #define MOUNTED_GETMNTTBL |
|
89 #endif |
|
90 |
5
|
91 #ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */ |
|
92 /* Return the value of the hexadecimal number represented by CP. |
|
93 No prefix (like '0x') or suffix (like 'h') is expected to be |
|
94 part of CP. */ |
|
95 |
|
96 static int |
|
97 xatoi (cp) |
|
98 char *cp; |
|
99 { |
|
100 int val; |
|
101 |
|
102 val = 0; |
|
103 while (*cp) |
|
104 { |
|
105 if (*cp >= 'a' && *cp <= 'f') |
|
106 val = val * 16 + *cp - 'a' + 10; |
|
107 else if (*cp >= 'A' && *cp <= 'F') |
|
108 val = val * 16 + *cp - 'A' + 10; |
|
109 else if (*cp >= '0' && *cp <= '9') |
|
110 val = val * 16 + *cp - '0'; |
|
111 else |
|
112 break; |
|
113 cp++; |
|
114 } |
|
115 return val; |
|
116 } |
|
117 #endif /* MOUNTED_GETMNTENT1. */ |
|
118 |
|
119 #ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */ |
|
120 static char * |
|
121 fstype_to_string (t) |
|
122 short t; |
|
123 { |
|
124 switch (t) |
|
125 { |
|
126 case MOUNT_UFS: |
|
127 return "ufs"; |
|
128 case MOUNT_NFS: |
|
129 return "nfs"; |
59
|
130 #ifdef MOUNT_PC |
5
|
131 case MOUNT_PC: |
|
132 return "pc"; |
59
|
133 #endif |
5
|
134 #ifdef MOUNT_MFS |
|
135 case MOUNT_MFS: |
|
136 return "mfs"; |
|
137 #endif |
|
138 #ifdef MOUNT_LO |
|
139 case MOUNT_LO: |
|
140 return "lo"; |
|
141 #endif |
|
142 #ifdef MOUNT_TFS |
|
143 case MOUNT_TFS: |
|
144 return "tfs"; |
|
145 #endif |
|
146 #ifdef MOUNT_TMP |
|
147 case MOUNT_TMP: |
|
148 return "tmp"; |
|
149 #endif |
|
150 default: |
|
151 return "?"; |
|
152 } |
|
153 } |
|
154 #endif /* MOUNTED_GETMNTINFO */ |
|
155 |
|
156 #ifdef MOUNTED_VMOUNT /* AIX. */ |
|
157 static char * |
|
158 fstype_to_string (t) |
|
159 int t; |
|
160 { |
|
161 struct vfs_ent *e; |
|
162 |
|
163 e = getvfsbytype (t); |
|
164 if (!e || !e->vfsent_name) |
|
165 return "none"; |
|
166 else |
|
167 return e->vfsent_name; |
|
168 } |
|
169 #endif /* MOUNTED_VMOUNT */ |
|
170 |
|
171 /* Return a list of the currently mounted filesystems, or NULL on error. |
|
172 Add each entry to the tail of the list so that they stay in order. |
|
173 If NEED_FS_TYPE is nonzero, ensure that the filesystem type fields in |
|
174 the returned list are valid. Otherwise, they might not be. |
|
175 If ALL_FS is zero, do not return entries for filesystems that |
|
176 are automounter (dummy) entries. */ |
|
177 |
|
178 struct mount_entry * |
|
179 read_filesystem_list (need_fs_type, all_fs) |
|
180 int need_fs_type, all_fs; |
|
181 { |
|
182 struct mount_entry *mount_list; |
|
183 struct mount_entry *me; |
|
184 struct mount_entry *mtail; |
|
185 |
|
186 /* Start the list off with a dummy entry. */ |
|
187 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry)); |
|
188 me->me_next = NULL; |
|
189 mount_list = mtail = me; |
|
190 |
|
191 #ifdef MOUNTED_GETMNTENT1 /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */ |
|
192 { |
|
193 struct mntent *mnt; |
|
194 char *table = MOUNTED; |
|
195 FILE *fp; |
|
196 char *devopt; |
|
197 |
|
198 fp = setmntent (table, "r"); |
|
199 if (fp == NULL) |
|
200 return NULL; |
|
201 |
|
202 while ((mnt = getmntent (fp))) |
|
203 { |
|
204 if (!all_fs && (!strcmp (mnt->mnt_type, "ignore") |
|
205 || !strcmp (mnt->mnt_type, "auto"))) |
|
206 continue; |
|
207 |
|
208 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry)); |
|
209 me->me_devname = xstrdup (mnt->mnt_fsname); |
|
210 me->me_mountdir = xstrdup (mnt->mnt_dir); |
|
211 me->me_type = xstrdup (mnt->mnt_type); |
|
212 devopt = strstr (mnt->mnt_opts, "dev="); |
|
213 if (devopt) |
|
214 { |
|
215 if (devopt[4] == '0' && (devopt[5] == 'x' || devopt[5] == 'X')) |
|
216 me->me_dev = xatoi (devopt + 6); |
|
217 else |
|
218 me->me_dev = xatoi (devopt + 4); |
|
219 } |
|
220 else |
|
221 me->me_dev = -1; /* Magic; means not known yet. */ |
|
222 me->me_next = NULL; |
|
223 |
|
224 /* Add to the linked list. */ |
|
225 mtail->me_next = me; |
|
226 mtail = me; |
|
227 } |
|
228 |
|
229 if (endmntent (fp) == 0) |
|
230 return NULL; |
|
231 } |
|
232 #endif /* MOUNTED_GETMNTENT1. */ |
|
233 |
|
234 #ifdef MOUNTED_GETMNTINFO /* 4.4BSD. */ |
|
235 { |
|
236 struct statfs *fsp; |
|
237 int entries; |
|
238 |
|
239 entries = getmntinfo (&fsp, MNT_NOWAIT); |
|
240 if (entries < 0) |
|
241 return NULL; |
|
242 while (entries-- > 0) |
|
243 { |
|
244 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry)); |
|
245 me->me_devname = xstrdup (fsp->f_mntfromname); |
|
246 me->me_mountdir = xstrdup (fsp->f_mntonname); |
|
247 me->me_type = fstype_to_string (fsp->f_type); |
|
248 me->me_dev = -1; /* Magic; means not known yet. */ |
|
249 me->me_next = NULL; |
|
250 |
|
251 /* Add to the linked list. */ |
|
252 mtail->me_next = me; |
|
253 mtail = me; |
|
254 fsp++; |
|
255 } |
|
256 } |
|
257 #endif /* MOUNTED_GETMNTINFO */ |
|
258 |
|
259 #ifdef MOUNTED_GETMNT /* Ultrix. */ |
|
260 { |
|
261 int offset = 0; |
|
262 int val; |
|
263 struct fs_data fsd; |
|
264 |
|
265 while ((val = getmnt (&offset, &fsd, sizeof (fsd), NOSTAT_MANY, |
|
266 (char *) 0)) > 0) |
|
267 { |
|
268 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry)); |
|
269 me->me_devname = xstrdup (fsd.fd_req.devname); |
|
270 me->me_mountdir = xstrdup (fsd.fd_req.path); |
|
271 me->me_type = gt_names[fsd.fd_req.fstype]; |
|
272 me->me_dev = fsd.fd_req.dev; |
|
273 me->me_next = NULL; |
|
274 |
|
275 /* Add to the linked list. */ |
|
276 mtail->me_next = me; |
|
277 mtail = me; |
|
278 } |
|
279 if (val < 0) |
|
280 return NULL; |
|
281 } |
|
282 #endif /* MOUNTED_GETMNT. */ |
|
283 |
57
|
284 #if defined (MOUNTED_GETFSSTAT) /* __alpha running OSF_1 */ |
|
285 { |
|
286 int numsys, counter, bufsize; |
|
287 struct statfs *stats; |
|
288 |
|
289 numsys = getfsstat ((struct statfs *)0, 0L, MNT_WAIT); |
|
290 if (numsys < 0) |
|
291 return (NULL); |
|
292 |
|
293 bufsize = (1 + numsys) * sizeof (struct statfs); |
|
294 stats = (struct statfs *)xmalloc (bufsize); |
|
295 numsys = getfsstat (stats, bufsize, MNT_WAIT); |
|
296 |
|
297 if (numsys < 0) |
|
298 { |
|
299 free (stats); |
|
300 return (NULL); |
|
301 } |
|
302 |
|
303 for (counter = 0; counter < numsys; counter++) |
|
304 { |
|
305 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry)); |
|
306 me->me_devname = xstrdup (stats[counter].f_mntfromname); |
|
307 me->me_mountdir = xstrdup (stats[counter].f_mntonname); |
|
308 me->me_type = mnt_names[stats[counter].f_type]; |
|
309 me->me_dev = -1; /* Magic; means not known yet. */ |
|
310 me->me_next = NULL; |
|
311 |
|
312 /* Add to the linked list. */ |
|
313 mtail->me_next = me; |
|
314 mtail = me; |
|
315 } |
|
316 |
|
317 free (stats); |
|
318 } |
|
319 #endif /* MOUNTED_GETFSSTAT */ |
|
320 |
5
|
321 #if defined (MOUNTED_FREAD) || defined (MOUNTED_FREAD_FSTYP) /* SVR[23]. */ |
|
322 { |
|
323 struct mnttab mnt; |
|
324 char *table = "/etc/mnttab"; |
|
325 FILE *fp; |
|
326 |
|
327 fp = fopen (table, "r"); |
|
328 if (fp == NULL) |
|
329 return NULL; |
|
330 |
|
331 while (fread (&mnt, sizeof mnt, 1, fp) > 0) |
|
332 { |
|
333 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry)); |
|
334 #ifdef GETFSTYP /* SVR3. */ |
|
335 me->me_devname = xstrdup (mnt.mt_dev); |
|
336 #else |
|
337 me->me_devname = xmalloc (strlen (mnt.mt_dev) + 6); |
|
338 strcpy (me->me_devname, "/dev/"); |
|
339 strcpy (me->me_devname + 5, mnt.mt_dev); |
|
340 #endif |
|
341 me->me_mountdir = xstrdup (mnt.mt_filsys); |
|
342 me->me_dev = -1; /* Magic; means not known yet. */ |
|
343 me->me_type = ""; |
|
344 #ifdef GETFSTYP /* SVR3. */ |
|
345 if (need_fs_type) |
|
346 { |
|
347 struct statfs fsd; |
|
348 char typebuf[FSTYPSZ]; |
|
349 |
|
350 if (statfs (me->me_mountdir, &fsd, sizeof fsd, 0) != -1 |
|
351 && sysfs (GETFSTYP, fsd.f_fstyp, typebuf) != -1) |
|
352 me->me_type = xstrdup (typebuf); |
|
353 } |
|
354 #endif |
|
355 me->me_next = NULL; |
|
356 |
|
357 /* Add to the linked list. */ |
|
358 mtail->me_next = me; |
|
359 mtail = me; |
|
360 } |
|
361 |
|
362 if (fclose (fp) == EOF) |
|
363 return NULL; |
|
364 } |
|
365 #endif /* MOUNTED_FREAD || MOUNTED_FREAD_FSTYP. */ |
|
366 |
64
|
367 #ifdef MOUNTED_GETMNTTBL /* DolphinOS goes it's own way */ |
|
368 { |
|
369 struct mntent **mnttbl=getmnttbl(),**ent; |
|
370 for (ent=mnttbl;*ent;ent++) |
|
371 { |
|
372 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry)); |
|
373 me->me_devname = xstrdup ( (*ent)->mt_resource); |
|
374 me->me_mountdir = xstrdup( (*ent)->mt_directory); |
|
375 me->me_type = xstrdup ((*ent)->mt_fstype); |
|
376 me->me_dev = -1; /* Magic; means not known yet. */ |
|
377 me->me_next = NULL; |
|
378 |
|
379 /* Add to the linked list. */ |
|
380 mtail->me_next = me; |
|
381 mtail = me; |
|
382 } |
|
383 endmnttbl(); |
|
384 } |
|
385 #endif |
|
386 |
5
|
387 #ifdef MOUNTED_GETMNTENT2 /* SVR4. */ |
|
388 { |
|
389 struct mnttab mnt; |
|
390 char *table = MNTTAB; |
|
391 FILE *fp; |
|
392 int ret; |
|
393 |
|
394 fp = fopen (table, "r"); |
|
395 if (fp == NULL) |
|
396 return NULL; |
|
397 |
|
398 while ((ret = getmntent (fp, &mnt)) == 0) |
|
399 { |
|
400 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry)); |
|
401 me->me_devname = xstrdup (mnt.mnt_special); |
|
402 me->me_mountdir = xstrdup (mnt.mnt_mountp); |
|
403 me->me_type = xstrdup (mnt.mnt_fstype); |
|
404 me->me_dev = -1; /* Magic; means not known yet. */ |
|
405 me->me_next = NULL; |
|
406 |
|
407 /* Add to the linked list. */ |
|
408 mtail->me_next = me; |
|
409 mtail = me; |
|
410 } |
|
411 |
|
412 if (ret > 0) |
|
413 return NULL; |
|
414 if (fclose (fp) == EOF) |
|
415 return NULL; |
|
416 } |
|
417 #endif /* MOUNTED_GETMNTENT2. */ |
|
418 |
|
419 #ifdef MOUNTED_VMOUNT /* AIX. */ |
|
420 { |
|
421 int bufsize; |
|
422 char *entries, *thisent; |
|
423 struct vmount *vmp; |
|
424 |
|
425 /* Ask how many bytes to allocate for the mounted filesystem info. */ |
|
426 mntctl (MCTL_QUERY, sizeof bufsize, (struct vmount *) &bufsize); |
|
427 entries = xmalloc (bufsize); |
|
428 |
|
429 /* Get the list of mounted filesystems. */ |
|
430 mntctl (MCTL_QUERY, bufsize, (struct vmount *) entries); |
|
431 |
|
432 for (thisent = entries; thisent < entries + bufsize; |
|
433 thisent += vmp->vmt_length) |
|
434 { |
|
435 vmp = (struct vmount *) thisent; |
|
436 me = (struct mount_entry *) xmalloc (sizeof (struct mount_entry)); |
|
437 if (vmp->vmt_flags & MNT_REMOTE) |
|
438 { |
|
439 char *host, *path; |
|
440 |
|
441 /* Prepend the remote pathname. */ |
|
442 host = thisent + vmp->vmt_data[VMT_HOSTNAME].vmt_off; |
|
443 path = thisent + vmp->vmt_data[VMT_OBJECT].vmt_off; |
|
444 me->me_devname = xmalloc (strlen (host) + strlen (path) + 2); |
|
445 strcpy (me->me_devname, host); |
|
446 strcat (me->me_devname, ":"); |
|
447 strcat (me->me_devname, path); |
|
448 } |
|
449 else |
|
450 { |
|
451 me->me_devname = xstrdup (thisent + |
|
452 vmp->vmt_data[VMT_OBJECT].vmt_off); |
|
453 } |
|
454 me->me_mountdir = xstrdup (thisent + vmp->vmt_data[VMT_STUB].vmt_off); |
|
455 me->me_type = xstrdup (fstype_to_string (vmp->vmt_gfstype)); |
|
456 me->me_dev = -1; /* vmt_fsid might be the info we want. */ |
|
457 me->me_next = NULL; |
|
458 |
|
459 /* Add to the linked list. */ |
|
460 mtail->me_next = me; |
|
461 mtail = me; |
|
462 } |
|
463 free (entries); |
|
464 } |
|
465 #endif /* MOUNTED_VMOUNT. */ |
|
466 |
|
467 /* Free the dummy head. */ |
|
468 me = mount_list; |
|
469 mount_list = mount_list->me_next; |
|
470 free (me); |
|
471 return mount_list; |
|
472 } |