Updated Bulgarian translation from TP
[findutils.git] / find / fstype.c
blobb10ffa693717d3095eaca309101a0c51dbc0c104
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.
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
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).
28 #include <config.h>
29 #include <errno.h>
30 #include <stdbool.h>
32 #ifdef HAVE_SYS_TYPES_H
33 #include <sys/types.h>
34 #endif
35 #include <sys/stat.h>
37 /* The presence of unistd.h is assumed by gnulib these days, so we
38 * might as well assume it too.
40 #include <unistd.h>
42 #ifdef HAVE_SYS_MNTIO_H
43 #ifdef HAVE_FCNTL_H
44 #include <fcntl.h>
45 #endif
46 #include <sys/mntio.h>
47 #endif
48 #ifdef HAVE_SYS_MKDEV_H
49 #include <sys/mkdev.h>
50 #endif
52 #ifdef STDC_HEADERS
53 #include <stdlib.h>
54 #else
55 extern int errno;
56 #endif
58 #include "defs.h"
59 #include "../gnulib/lib/dirname.h"
60 #include "xalloc.h"
61 #include "modetype.h"
63 /* Need declaration of function `xstrtoumax' */
64 #include "../gnulib/lib/xstrtol.h"
66 #include "extendbuf.h"
67 #include "mountlist.h"
68 #include "error.h"
72 #if ENABLE_NLS
73 # include <libintl.h>
74 # define _(Text) gettext (Text)
75 #else
76 # define _(Text) Text
77 #endif
78 #ifdef gettext_noop
79 # define N_(String) gettext_noop (String)
80 #else
81 /* See locate.c for explanation as to why not use (String) */
82 # define N_(String) String
83 #endif
85 static char *file_system_type_uncached PARAMS((const struct stat *statp, const char *path));
88 /* Get MNTTYPE_IGNORE if it is available. */
89 #if HAVE_MNTENT_H
90 # include <mntent.h>
91 #endif
92 #if HAVE_SYS_MNTTAB_H
93 # include <stdio.h>
94 # include <sys/mnttab.h>
95 #endif
101 static void
102 free_file_system_list(struct mount_entry *p)
104 while (p)
106 struct mount_entry *pnext = p->me_next;
108 free(p->me_devname);
109 free(p->me_mountdir);
111 if(p->me_type_malloced)
112 free(p->me_type);
113 p->me_next = NULL;
114 free(p);
115 p = pnext;
122 #ifdef AFS
123 #include <netinet/in.h>
124 #include <afs/venus.h>
125 #if __STDC__
126 /* On SunOS 4, afs/vice.h defines this to rely on a pre-ANSI cpp. */
127 #undef _VICEIOCTL
128 #define _VICEIOCTL(id) ((unsigned int ) _IOW('V', id, struct ViceIoctl))
129 #endif
130 #ifndef _IOW
131 /* AFS on Solaris 2.3 doesn't get this definition. */
132 #include <sys/ioccom.h>
133 #endif
135 static int
136 in_afs (char *path)
138 static char space[2048];
139 struct ViceIoctl vi;
141 vi.in_size = 0;
142 vi.out_size = sizeof (space);
143 vi.out = space;
145 if (pioctl (path, VIOC_FILE_CELL_NAME, &vi, 1)
146 && (errno == EINVAL || errno == ENOENT))
147 return 0;
148 return 1;
150 #endif /* AFS */
152 /* Nonzero if the current file system's type is known. */
153 static int fstype_known = 0;
155 /* Return a static string naming the type of file system that the file PATH,
156 described by STATP, is on.
157 RELPATH is the file name relative to the current directory.
158 Return "unknown" if its file system type is unknown. */
160 char *
161 filesystem_type (const struct stat *statp, const char *path)
163 static char *current_fstype = NULL;
164 static dev_t current_dev;
166 if (current_fstype != NULL)
168 if (fstype_known && statp->st_dev == current_dev)
169 return current_fstype; /* Cached value. */
170 free (current_fstype);
172 current_dev = statp->st_dev;
173 current_fstype = file_system_type_uncached (statp, path);
174 return current_fstype;
177 static int
178 set_fstype_devno(struct mount_entry *p)
180 struct stat stbuf;
182 if (p->me_dev == (dev_t)-1)
184 set_stat_placeholders(&stbuf);
185 if (0 == (options.xstat)(p->me_mountdir, &stbuf))
187 p->me_dev = stbuf.st_dev;
188 return 0;
190 else
192 return -1;
195 return 0; /* not needed */
198 static struct mount_entry *
199 must_read_fs_list(bool need_fs_type)
201 struct mount_entry *entries = read_file_system_list(need_fs_type);
202 if (NULL == entries)
204 /* We cannot determine for sure which file we were trying to
205 * use because gnulib has extracted all that stuff away.
206 * Hence we cannot issue a specific error message here.
208 error(1, 0, "Cannot read mounted file system list");
210 return entries;
215 /* Return a newly allocated string naming the type of file system that the
216 file PATH, described by STATP, is on.
217 RELPATH is the file name relative to the current directory.
218 Return "unknown" if its file system type is unknown. */
220 static char *
221 file_system_type_uncached (const struct stat *statp, const char *path)
223 struct mount_entry *entries, *entry;
224 char *type;
226 (void) path;
228 #ifdef AFS
229 if (in_afs(path))
231 fstype_known = 1;
232 return xstrdup("afs");
234 #endif
236 entries = must_read_fs_list(true);
237 for (type=NULL, entry=entries; entry; entry=entry->me_next)
239 #ifdef MNTTYPE_IGNORE
240 if (!strcmp (entry->me_type, MNTTYPE_IGNORE))
241 continue;
242 #endif
243 set_fstype_devno(entry);
244 if (entry->me_dev == statp->st_dev)
246 type = xstrdup(entry->me_type);
247 break;
250 free_file_system_list(entries);
252 /* Don't cache unknown values. */
253 fstype_known = (type != NULL);
255 return type ? type : xstrdup(_("unknown"));
259 char *
260 get_mounted_filesystems (void)
262 char *result = NULL;
263 size_t alloc_size = 0u;
264 size_t used = 0u;
265 struct mount_entry *entries, *entry;
267 entries = must_read_fs_list(false);
268 for (entry=entries; entry; entry=entry->me_next)
270 size_t len;
272 #ifdef MNTTYPE_IGNORE
273 if (!strcmp (entry->me_type, MNTTYPE_IGNORE))
274 continue;
275 #endif
276 set_fstype_devno(entry);
278 len = strlen(entry->me_mountdir) + 1;
279 result = extendbuf(result, used+len, &alloc_size);
280 strcpy(&result[used], entry->me_mountdir);
281 used += len; /* len already includes one for the \0 */
284 free_file_system_list(entries);
285 return result;
289 dev_t *
290 get_mounted_devices (size_t *n)
292 size_t alloc_size = 0u;
293 size_t used = 0u;
294 struct mount_entry *entries, *entry;
295 dev_t *result = NULL;
297 /* Use read_file_system_list() rather than must_read_fs_list()
298 * because on some system this is always called at startup,
299 * and find should only exit fatally if it needs to use the
300 * result of this operation. If we can't get the fs list
301 * but we never need the information, there is no need to fail.
303 for (entry = entries = read_file_system_list(false);
304 entry;
305 entry = entry->me_next)
307 result = extendbuf(result, sizeof(dev_t)*(used+1), &alloc_size);
308 set_fstype_devno(entry);
309 result[used] = entry->me_dev;
310 ++used;
312 free_file_system_list(entries);
313 *n = used;
314 return result;