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).
29 #ifdef HAVE_SYS_TYPES_H
30 #include <sys/types.h>
34 /* The presence of unistd.h is assumed by gnulib these days, so we
35 * might as well assume it too.
39 #ifdef HAVE_SYS_MNTIO_H
43 #include <sys/mntio.h>
45 #ifdef HAVE_SYS_MKDEV_H
46 #include <sys/mkdev.h>
56 #include "../gnulib/lib/dirname.h"
60 /* Need declaration of function `xstrtoumax' */
61 #include "../gnulib/lib/xstrtol.h"
63 #include "extendbuf.h"
64 #include "mountlist.h"
71 # define _(Text) gettext (Text)
76 # define N_(String) gettext_noop (String)
78 /* See locate.c for explanation as to why not use (String) */
79 # define N_(String) String
82 static char *file_system_type_uncached
PARAMS((const struct stat
*statp
, const char *path
));
85 /* Get MNTTYPE_IGNORE if it is available. */
91 # include <sys/mnttab.h>
99 free_file_system_list(struct mount_entry
*p
)
103 struct mount_entry
*pnext
= p
->me_next
;
106 free(p
->me_mountdir
);
108 if(p
->me_type_malloced
)
120 #include <netinet/in.h>
121 #include <afs/venus.h>
123 /* On SunOS 4, afs/vice.h defines this to rely on a pre-ANSI cpp. */
125 #define _VICEIOCTL(id) ((unsigned int ) _IOW('V', id, struct ViceIoctl))
128 /* AFS on Solaris 2.3 doesn't get this definition. */
129 #include <sys/ioccom.h>
135 static char space
[2048];
139 vi
.out_size
= sizeof (space
);
142 if (pioctl (path
, VIOC_FILE_CELL_NAME
, &vi
, 1)
143 && (errno
== EINVAL
|| errno
== ENOENT
))
149 /* Nonzero if the current file system's type is known. */
150 static int fstype_known
= 0;
152 /* Return a static string naming the type of file system 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 file system type is unknown. */
158 filesystem_type (const struct stat
*statp
, const char *path
)
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
= file_system_type_uncached (statp
, path
);
171 return current_fstype
;
175 set_fstype_devno(struct mount_entry
*p
)
179 if (p
->me_dev
== (dev_t
)-1)
181 set_stat_placeholders(&stbuf
);
182 if (0 == (options
.xstat
)(p
->me_mountdir
, &stbuf
))
184 p
->me_dev
= stbuf
.st_dev
;
192 return 0; /* not needed */
195 static struct mount_entry
*
196 must_read_fs_list(bool need_fs_type
)
198 struct mount_entry
*entries
= read_file_system_list(need_fs_type
);
201 /* We cannot determine for sure which file we were trying to
202 * use because gnulib has extracted all that stuff away.
203 * Hence we cannot issue a specific error message here.
205 error(1, 0, "Cannot read mounted file system list");
212 /* Return a newly allocated string naming the type of file system that the
213 file PATH, described by STATP, is on.
214 RELPATH is the file name relative to the current directory.
215 Return "unknown" if its file system type is unknown. */
218 file_system_type_uncached (const struct stat
*statp
, const char *path
)
220 struct mount_entry
*entries
, *entry
;
229 return xstrdup("afs");
233 entries
= must_read_fs_list(true);
234 for (type
=NULL
, entry
=entries
; entry
; entry
=entry
->me_next
)
236 #ifdef MNTTYPE_IGNORE
237 if (!strcmp (entry
->me_type
, MNTTYPE_IGNORE
))
240 set_fstype_devno(entry
);
241 if (entry
->me_dev
== statp
->st_dev
)
243 type
= xstrdup(entry
->me_type
);
247 free_file_system_list(entries
);
249 /* Don't cache unknown values. */
250 fstype_known
= (type
!= NULL
);
252 return type
? type
: xstrdup(_("unknown"));
257 get_mounted_filesystems (void)
260 size_t alloc_size
= 0u;
262 struct mount_entry
*entries
, *entry
;
264 entries
= must_read_fs_list(false);
265 for (entry
=entries
; entry
; entry
=entry
->me_next
)
269 #ifdef MNTTYPE_IGNORE
270 if (!strcmp (entry
->me_type
, MNTTYPE_IGNORE
))
273 set_fstype_devno(entry
);
275 len
= strlen(entry
->me_mountdir
) + 1;
276 result
= extendbuf(result
, used
+len
, &alloc_size
);
277 strcpy(&result
[used
], entry
->me_mountdir
);
278 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 result
= extendbuf(result
, sizeof(dev_t
)*(used
+1), &alloc_size
);
305 set_fstype_devno(entry
);
306 result
[used
] = entry
->me_dev
;
309 free_file_system_list(entries
);