Removed incorrect comment about -H, -P and -follow in HISTORY.
[findutils.git] / find / fstype.c
blob6c452090616b9228d0fb177a197c305675f70332
1 /* fstype.c -- determine type of filesystems that files are on
2 Copyright (C) 1990, 91, 92, 93, 94, 2000, 2004 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 2, or (at your option)
7 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, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
17 USA.
20 /* Written by David MacKenzie <djm@gnu.org>.
22 * Converted to use gnulib's read_file_system_list()
23 * by James Youngman <jay@gnu.org> (which saves a lot
24 * of manual hacking of configure.in).
27 #include <config.h>
28 #include <errno.h>
29 #include <assert.h>
30 #include <stdbool.h>
32 #ifdef HAVE_SYS_TYPES_H
33 #include <sys/types.h>
34 #endif
36 #ifdef HAVE_UNISTD_H
37 #include <unistd.h>
38 #endif
40 #ifdef HAVE_SYS_MNTIO_H
41 #ifdef HAVE_FCNTL_H
42 #include <fcntl.h>
43 #endif
44 #include <sys/mntio.h>
45 #endif
46 #ifdef HAVE_SYS_MKDEV_H
47 #include <sys/mkdev.h>
48 #endif
50 #ifdef STDC_HEADERS
51 #include <stdlib.h>
52 #else
53 extern int errno;
54 #endif
56 #include "defs.h"
57 #include "../gnulib/lib/dirname.h"
58 #include "xalloc.h"
59 #include "modetype.h"
61 /* Need declaration of function `xstrtoumax' */
62 #include "../gnulib/lib/xstrtol.h"
64 #include "extendbuf.h"
65 #include "mountlist.h"
69 #if ENABLE_NLS
70 # include <libintl.h>
71 # define _(Text) gettext (Text)
72 #else
73 # define _(Text) Text
74 #endif
75 #ifdef gettext_noop
76 # define N_(String) gettext_noop (String)
77 #else
78 /* See locate.c for explanation as to why not use (String) */
79 # define N_(String) String
80 #endif
82 static char *filesystem_type_uncached PARAMS((const struct stat *statp));
85 /* Get MNTTYPE_IGNORE if it is available. */
86 #if HAVE_MNTENT_H
87 # include <mntent.h>
88 #endif
89 #if HAVE_SYS_MNTTAB_H
90 # include <stdio.h>
91 # include <sys/mnttab.h>
92 #endif
98 static void
99 free_file_system_list(struct mount_entry *p)
101 while (p)
103 struct mount_entry *pnext = p->me_next;
105 free(p->me_devname);
106 free(p->me_mountdir);
108 if(p->me_type_malloced)
109 free(p->me_type);
110 p->me_next = NULL;
111 free(p);
112 p = pnext;
119 #ifdef AFS
120 #include <netinet/in.h>
121 #include <afs/venus.h>
122 #if __STDC__
123 /* On SunOS 4, afs/vice.h defines this to rely on a pre-ANSI cpp. */
124 #undef _VICEIOCTL
125 #define _VICEIOCTL(id) ((unsigned int ) _IOW('V', id, struct ViceIoctl))
126 #endif
127 #ifndef _IOW
128 /* AFS on Solaris 2.3 doesn't get this definition. */
129 #include <sys/ioccom.h>
130 #endif
132 static int
133 in_afs (char *path)
135 static char space[2048];
136 struct ViceIoctl vi;
138 vi.in_size = 0;
139 vi.out_size = sizeof (space);
140 vi.out = space;
142 if (pioctl (path, VIOC_FILE_CELL_NAME, &vi, 1)
143 && (errno == EINVAL || errno == ENOENT))
144 return 0;
145 return 1;
147 #endif /* AFS */
149 /* Nonzero if the current filesystem's type is known. */
150 static int fstype_known = 0;
152 /* Return a static string naming the type of filesystem that the file PATH,
153 described by STATP, is on.
154 RELPATH is the file name relative to the current directory.
155 Return "unknown" if its filesystem type is unknown. */
157 char *
158 filesystem_type (const struct stat *statp)
160 static char *current_fstype = NULL;
161 static dev_t current_dev;
163 if (current_fstype != NULL)
165 if (fstype_known && statp->st_dev == current_dev)
166 return current_fstype; /* Cached value. */
167 free (current_fstype);
169 current_dev = statp->st_dev;
170 current_fstype = filesystem_type_uncached (statp);
171 return current_fstype;
174 static int
175 set_fstype_devno(struct mount_entry *p)
177 struct stat stbuf;
179 if (p->me_dev == (dev_t)-1)
181 if (0 == (options.xstat)(p->me_mountdir, &stbuf))
183 p->me_dev = stbuf.st_dev;
184 return 0;
186 else
188 return -1;
191 return 0; /* not needed */
195 /* Return a newly allocated string naming the type of filesystem that the
196 file PATH, described by STATP, is on.
197 RELPATH is the file name relative to the current directory.
198 Return "unknown" if its filesystem type is unknown. */
200 static char *
201 filesystem_type_uncached (const struct stat *statp)
203 struct mount_entry *entries, *entry;
204 char *type;
206 #ifdef AFS
207 if (in_afs(path))
209 fstype_known = 1;
210 return xstrdup("afs");
212 #endif
214 entries = read_file_system_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))
219 continue;
220 #endif
221 set_fstype_devno(entry);
222 if (entry->me_dev == statp->st_dev)
223 type = xstrdup(entry->me_type);
225 free_file_system_list(entries);
227 /* Don't cache unknown values. */
228 fstype_known = (type != NULL);
230 return type ? type : xstrdup(_("unknown"));
234 char *
235 get_mounted_filesystems (void)
237 char *result = NULL;
238 size_t alloc_size = 0u;
239 size_t used = 0u;
240 struct mount_entry *entries, *entry;
242 entries = read_file_system_list(false);
243 for (entry=entries; entry; entry=entry->me_next)
245 size_t len;
247 #ifdef MNTTYPE_IGNORE
248 if (!strcmp (entry->me_type, MNTTYPE_IGNORE))
249 continue;
250 #endif
251 set_fstype_devno(entry);
253 len = strlen(entry->me_mountdir) + 1;
254 result = extendbuf(result, used+len, &alloc_size);
255 strcpy(&result[used], entry->me_mountdir);
256 used += len; /* len already includes one for the \0 */
259 free_file_system_list(entries);
260 return result;
264 dev_t *
265 get_mounted_devices (size_t *n)
267 size_t alloc_size = 0u;
268 size_t used = 0u;
269 struct mount_entry *entries, *entry;
270 dev_t *result = NULL;
272 for (entry = entries = read_file_system_list(false);
273 entry;
274 entry = entry->me_next)
276 result = extendbuf(result, sizeof(dev_t)*(used+1), &alloc_size);
277 set_fstype_devno(entry);
278 result[used] = entry->me_dev;
279 ++used;
281 free_file_system_list(entries);
282 *n = used;
283 return result;