1 /* fstype.c -- determine type of file systems that files are on
2 Copyright (C) 1990, 1991, 1992, 1993, 1994, 2000,
3 2004, 2010 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).
30 #ifdef HAVE_SYS_TYPES_H
31 #include <sys/types.h>
35 /* The presence of unistd.h is assumed by gnulib these days, so we
36 * might as well assume it too.
41 #ifdef HAVE_SYS_MNTIO_H
42 #include <sys/mntio.h>
44 #ifdef HAVE_SYS_MKDEV_H
45 #include <sys/mkdev.h>
55 #include "../gnulib/lib/dirname.h"
58 /* Need declaration of function `xstrtoumax' */
59 #include "../gnulib/lib/xstrtol.h"
61 #include "extendbuf.h"
62 #include "mountlist.h"
69 # define _(Text) gettext (Text)
74 # define N_(String) gettext_noop (String)
76 /* See locate.c for explanation as to why not use (String) */
77 # define N_(String) String
80 static char *file_system_type_uncached (const struct stat *statp, const char *path);
83 /* Get MNTTYPE_IGNORE if it is available. */
89 # include <sys/mnttab.h>
97 free_file_system_list (struct mount_entry *p)
101 struct mount_entry *pnext = p->me_next;
103 free (p->me_devname);
104 free (p->me_mountdir);
106 if (p->me_type_malloced)
118 #include <netinet/in.h>
119 #include <afs/venus.h>
121 /* On SunOS 4, afs/vice.h defines this to rely on a pre-ANSI cpp. */
123 #define _VICEIOCTL(id) ((unsigned int ) _IOW('V', id, struct ViceIoctl))
126 /* AFS on Solaris 2.3 doesn't get this definition. */
127 #include <sys/ioccom.h>
133 static char space[2048];
137 vi.out_size = sizeof (space);
140 if (pioctl (path, VIOC_FILE_CELL_NAME, &vi, 1)
141 && (errno == EINVAL || errno == ENOENT))
147 /* Nonzero if the current file system's type is known. */
148 static int fstype_known = 0;
150 /* Return a static string naming the type of file system that the file PATH,
151 described by STATP, is on.
152 RELPATH is the file name relative to the current directory.
153 Return "unknown" if its file system type is unknown. */
156 filesystem_type (const struct stat *statp, const char *path)
158 static char *current_fstype = NULL;
159 static dev_t current_dev;
161 if (current_fstype != NULL)
163 if (fstype_known && statp->st_dev == current_dev)
164 return current_fstype; /* Cached value. */
165 free (current_fstype);
167 current_dev = statp->st_dev;
168 current_fstype = file_system_type_uncached (statp, path);
169 return current_fstype;
173 set_fstype_devno (struct mount_entry *p)
177 if (p->me_dev == (dev_t)-1)
179 set_stat_placeholders (&stbuf);
180 if (0 == (options.xstat)(p->me_mountdir, &stbuf))
182 p->me_dev = stbuf.st_dev;
190 return 0; /* not needed */
193 static struct mount_entry *
194 must_read_fs_list (bool need_fs_type)
196 struct mount_entry *entries = read_file_system_list (need_fs_type);
199 /* We cannot determine for sure which file we were trying to
200 * use because gnulib has abstracted all that stuff away.
201 * Hence we cannot issue a specific error message here.
203 error (EXIT_FAILURE, 0, _("Cannot read mounted file system list"));
210 /* Return a newly allocated string naming the type of file system that the
211 file PATH, described by STATP, is on.
212 RELPATH is the file name relative to the current directory.
213 Return "unknown" if its file system type is unknown. */
216 file_system_type_uncached (const struct stat *statp, const char *path)
218 struct mount_entry *entries, *entry;
227 return xstrdup ("afs");
231 entries = must_read_fs_list (true);
232 for (type=NULL, entry=entries; entry; entry=entry->me_next)
234 #ifdef MNTTYPE_IGNORE
235 if (!strcmp (entry->me_type, MNTTYPE_IGNORE))
238 set_fstype_devno (entry);
239 if (entry->me_dev == statp->st_dev)
241 type = xstrdup (entry->me_type);
245 free_file_system_list (entries);
247 /* Don't cache unknown values. */
248 fstype_known = (type != NULL);
250 return type ? type : xstrdup (_("unknown"));
255 get_mounted_filesystems (void)
258 size_t alloc_size = 0u;
260 struct mount_entry *entries, *entry;
263 entries = must_read_fs_list (false);
264 for (entry=entries; entry; entry=entry->me_next)
268 #ifdef MNTTYPE_IGNORE
269 if (!strcmp (entry->me_type, MNTTYPE_IGNORE))
272 set_fstype_devno (entry);
274 len = strlen (entry->me_mountdir) + 1;
275 p = extendbuf (result, used+len, &alloc_size);
279 strcpy (&result[used], entry->me_mountdir);
280 used += len; /* len already includes one for the \0 */
288 free_file_system_list (entries);
294 get_mounted_devices (size_t *n)
296 size_t alloc_size = 0u;
298 struct mount_entry *entries, *entry;
299 dev_t *result = NULL;
301 /* Use read_file_system_list () rather than must_read_fs_list()
302 * because on some system this is always called at startup,
303 * and find should only exit fatally if it needs to use the
304 * result of this operation. If we can't get the fs list
305 * but we never need the information, there is no need to fail.
307 for (entry = entries = read_file_system_list (false);
309 entry = entry->me_next)
311 void *p = extendbuf (result, sizeof(dev_t)*(used+1), &alloc_size);
315 set_fstype_devno (entry);
316 result[used] = entry->me_dev;
325 free_file_system_list (entries);