cvsimport
[findutils.git] / find / fstype.c
blob75b33713bf06f877ec33066621030d27f2b66500
1 /* fstype.c -- determine type of file systems that files are on
2 Copyright (C) 1990, 91, 92, 93, 94, 2000, 2004 Free Software Foundation, Inc.
3 This program is free software: you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation, either version 3 of the License, or
6 (at your option) any later version.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 /* Written by David MacKenzie <djm@gnu.org>.
19 * Converted to use gnulib's read_file_system_list()
20 * by James Youngman <jay@gnu.org> (which saves a lot
21 * of manual hacking of configure.in).
25 #include <config.h>
26 #include <errno.h>
27 #include <stdbool.h>
29 #ifdef HAVE_SYS_TYPES_H
30 #include <sys/types.h>
31 #endif
32 #include <sys/stat.h>
34 /* The presence of unistd.h is assumed by gnulib these days, so we
35 * might as well assume it too.
37 #include <unistd.h>
39 #include <fcntl.h>
40 #ifdef HAVE_SYS_MNTIO_H
41 #include <sys/mntio.h>
42 #endif
43 #ifdef HAVE_SYS_MKDEV_H
44 #include <sys/mkdev.h>
45 #endif
47 #ifdef STDC_HEADERS
48 #include <stdlib.h>
49 #else
50 extern int errno;
51 #endif
53 #include "defs.h"
54 #include "../gnulib/lib/dirname.h"
55 #include "xalloc.h"
56 #include "modetype.h"
58 /* Need declaration of function `xstrtoumax' */
59 #include "../gnulib/lib/xstrtol.h"
61 #include "extendbuf.h"
62 #include "mountlist.h"
63 #include "error.h"
67 #if ENABLE_NLS
68 # include <libintl.h>
69 # define _(Text) gettext (Text)
70 #else
71 # define _(Text) Text
72 #endif
73 #ifdef gettext_noop
74 # define N_(String) gettext_noop (String)
75 #else
76 /* See locate.c for explanation as to why not use (String) */
77 # define N_(String) String
78 #endif
80 static char *file_system_type_uncached PARAMS((const struct stat *statp, const char *path));
83 /* Get MNTTYPE_IGNORE if it is available. */
84 #if HAVE_MNTENT_H
85 # include <mntent.h>
86 #endif
87 #if HAVE_SYS_MNTTAB_H
88 # include <stdio.h>
89 # include <sys/mnttab.h>
90 #endif
96 static void
97 free_file_system_list(struct mount_entry *p)
99 while (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)
107 free(p->me_type);
108 p->me_next = NULL;
109 free(p);
110 p = pnext;
117 #ifdef AFS
118 #include <netinet/in.h>
119 #include <afs/venus.h>
120 #if __STDC__
121 /* On SunOS 4, afs/vice.h defines this to rely on a pre-ANSI cpp. */
122 #undef _VICEIOCTL
123 #define _VICEIOCTL(id) ((unsigned int ) _IOW('V', id, struct ViceIoctl))
124 #endif
125 #ifndef _IOW
126 /* AFS on Solaris 2.3 doesn't get this definition. */
127 #include <sys/ioccom.h>
128 #endif
130 static int
131 in_afs (char *path)
133 static char space[2048];
134 struct ViceIoctl vi;
136 vi.in_size = 0;
137 vi.out_size = sizeof (space);
138 vi.out = space;
140 if (pioctl (path, VIOC_FILE_CELL_NAME, &vi, 1)
141 && (errno == EINVAL || errno == ENOENT))
142 return 0;
143 return 1;
145 #endif /* AFS */
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. */
155 char *
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;
172 static int
173 set_fstype_devno(struct mount_entry *p)
175 struct stat stbuf;
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;
183 return 0;
185 else
187 return -1;
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);
197 if (NULL == entries)
199 /* We cannot determine for sure which file we were trying to
200 * use because gnulib has extracted all that stuff away.
201 * Hence we cannot issue a specific error message here.
203 error(1, 0, "Cannot read mounted file system list");
205 return entries;
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. */
215 static char *
216 file_system_type_uncached (const struct stat *statp, const char *path)
218 struct mount_entry *entries, *entry;
219 char *type;
221 (void) path;
223 #ifdef AFS
224 if (in_afs(path))
226 fstype_known = 1;
227 return xstrdup("afs");
229 #endif
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))
236 continue;
237 #endif
238 set_fstype_devno(entry);
239 if (entry->me_dev == statp->st_dev)
241 type = xstrdup(entry->me_type);
242 break;
245 free_file_system_list(entries);
247 /* Don't cache unknown values. */
248 fstype_known = (type != NULL);
250 return type ? type : xstrdup(_("unknown"));
254 char *
255 get_mounted_filesystems (void)
257 char *result = NULL;
258 size_t alloc_size = 0u;
259 size_t used = 0u;
260 struct mount_entry *entries, *entry;
262 entries = must_read_fs_list(false);
263 for (entry=entries; entry; entry=entry->me_next)
265 size_t len;
267 #ifdef MNTTYPE_IGNORE
268 if (!strcmp (entry->me_type, MNTTYPE_IGNORE))
269 continue;
270 #endif
271 set_fstype_devno(entry);
273 len = strlen(entry->me_mountdir) + 1;
274 result = extendbuf(result, used+len, &alloc_size);
275 strcpy(&result[used], entry->me_mountdir);
276 used += len; /* len already includes one for the \0 */
279 free_file_system_list(entries);
280 return result;
284 dev_t *
285 get_mounted_devices (size_t *n)
287 size_t alloc_size = 0u;
288 size_t used = 0u;
289 struct mount_entry *entries, *entry;
290 dev_t *result = NULL;
292 /* Use read_file_system_list() rather than must_read_fs_list()
293 * because on some system this is always called at startup,
294 * and find should only exit fatally if it needs to use the
295 * result of this operation. If we can't get the fs list
296 * but we never need the information, there is no need to fail.
298 for (entry = entries = read_file_system_list(false);
299 entry;
300 entry = entry->me_next)
302 result = extendbuf(result, sizeof(dev_t)*(used+1), &alloc_size);
303 set_fstype_devno(entry);
304 result[used] = entry->me_dev;
305 ++used;
307 free_file_system_list(entries);
308 *n = used;
309 return result;