1 /* fstype.c -- determine type of file systems that files are on
2 Copyright (C) 1990, 1991, 1992, 1993, 1994, 2000,
3 2004, 2010, 2011 Free Software Foundation, Inc.
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 3 of the License, or
7 (at your option) any later version.
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.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 /* Written by David MacKenzie <djm@gnu.org>.
20 * Converted to use gnulib's read_file_system_list()
21 * by James Youngman <jay@gnu.org> (which saves a lot
22 * of manual hacking of configure.in).
25 /* config.h must be included first. */
37 #ifdef HAVE_SYS_MKDEV_H
38 # include <sys/mkdev.h>
40 #ifdef HAVE_SYS_MNTIO_H
41 # include <sys/mntio.h>
44 # include <sys/mnttab.h>
47 #include <sys/types.h>
54 #include "mountlist.h"
60 #include "extendbuf.h"
64 # define _(Text) gettext (Text)
69 # define N_(String) gettext_noop (String)
71 /* See locate.c for explanation as to why not use (String) */
72 # define N_(String) String
75 static char *file_system_type_uncached (const struct stat *statp, const char *path);
79 free_file_system_list (struct mount_entry *p)
83 struct mount_entry *pnext = p->me_next;
86 free (p->me_mountdir);
88 if (p->me_type_malloced)
100 #include <netinet/in.h>
101 #include <afs/venus.h>
103 /* On SunOS 4, afs/vice.h defines this to rely on a pre-ANSI cpp. */
105 #define _VICEIOCTL(id) ((unsigned int ) _IOW('V', id, struct ViceIoctl))
108 /* AFS on Solaris 2.3 doesn't get this definition. */
109 #include <sys/ioccom.h>
115 static char space[2048];
119 vi.out_size = sizeof (space);
122 if (pioctl (path, VIOC_FILE_CELL_NAME, &vi, 1)
123 && (errno == EINVAL || errno == ENOENT))
129 /* Nonzero if the current file system's type is known. */
130 static int fstype_known = 0;
132 /* Return a static string naming the type of file system that the file PATH,
133 described by STATP, is on.
134 RELPATH is the file name relative to the current directory.
135 Return "unknown" if its file system type is unknown. */
138 filesystem_type (const struct stat *statp, const char *path)
140 static char *current_fstype = NULL;
141 static dev_t current_dev;
143 if (current_fstype != NULL)
145 if (fstype_known && statp->st_dev == current_dev)
146 return current_fstype; /* Cached value. */
147 free (current_fstype);
149 current_dev = statp->st_dev;
150 current_fstype = file_system_type_uncached (statp, path);
151 return current_fstype;
155 set_fstype_devno (struct mount_entry *p)
159 if (p->me_dev == (dev_t)-1)
161 set_stat_placeholders (&stbuf);
162 if (0 == (options.xstat)(p->me_mountdir, &stbuf))
164 p->me_dev = stbuf.st_dev;
172 return 0; /* not needed */
175 static struct mount_entry *
176 must_read_fs_list (bool need_fs_type)
178 struct mount_entry *entries = read_file_system_list (need_fs_type);
181 /* We cannot determine for sure which file we were trying to
182 * use because gnulib has abstracted all that stuff away.
183 * Hence we cannot issue a specific error message here.
185 error (EXIT_FAILURE, 0, _("Cannot read mounted file system list"));
192 /* Return a newly allocated string naming the type of file system that the
193 file PATH, described by STATP, is on.
194 RELPATH is the file name relative to the current directory.
195 Return "unknown" if its file system type is unknown. */
198 file_system_type_uncached (const struct stat *statp, const char *path)
200 struct mount_entry *entries, *entry, *best;
209 return xstrdup ("afs");
214 entries = must_read_fs_list (true);
215 for (type=NULL, entry=entries; entry; entry=entry->me_next)
217 #ifdef MNTTYPE_IGNORE
218 if (!strcmp (entry->me_type, MNTTYPE_IGNORE))
221 if (0 == set_fstype_devno (entry))
223 if (entry->me_dev == statp->st_dev)
226 /* Don't exit the loop, because some systems (for
227 example Linux-based systems in which /etc/mtab is a
228 symlink to /proc/mounts) can have duplicate entries
229 in the filesystem list. This happens most frequently
237 type = xstrdup (best->me_type);
239 free_file_system_list (entries);
241 /* Don't cache unknown values. */
242 fstype_known = (type != NULL);
244 return type ? type : xstrdup (_("unknown"));
249 get_mounted_filesystems (void)
252 size_t alloc_size = 0u;
254 struct mount_entry *entries, *entry;
257 entries = must_read_fs_list (false);
258 for (entry=entries; entry; entry=entry->me_next)
262 #ifdef MNTTYPE_IGNORE
263 if (!strcmp (entry->me_type, MNTTYPE_IGNORE))
267 len = strlen (entry->me_mountdir) + 1;
268 p = extendbuf (result, used+len, &alloc_size);
272 strcpy (&result[used], entry->me_mountdir);
273 used += len; /* len already includes one for the \0 */
281 free_file_system_list (entries);
287 get_mounted_devices (size_t *n)
289 size_t alloc_size = 0u;
291 struct mount_entry *entries, *entry;
292 dev_t *result = NULL;
294 /* Use read_file_system_list () rather than must_read_fs_list()
295 * because on some system this is always called at startup,
296 * and find should only exit fatally if it needs to use the
297 * result of this operation. If we can't get the fs list
298 * but we never need the information, there is no need to fail.
300 for (entry = entries = read_file_system_list (false);
302 entry = entry->me_next)
304 void *p = extendbuf (result, sizeof(dev_t)*(used+1), &alloc_size);
308 if (0 == set_fstype_devno (entry))
310 result[used] = entry->me_dev;
320 free_file_system_list (entries);