1 /* fstype.c -- determine type of filesystems that files are on
2 Copyright (C) 1990, 91, 92, 93, 94, 2000 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)
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,
20 /* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
24 #include "../gnulib/lib/dirname.h"
34 /* Need declaration of function `xstrtoumax' */
35 #include "../gnulib/lib/xstrtol.h"
37 #include "extendbuf.h"
42 # define _(Text) gettext (Text)
47 # define N_(String) gettext_noop (String)
49 /* See locate.c for explanation as to why not use (String) */
50 # define N_(String) String
53 static char *filesystem_type_uncached
PARAMS((const char *path
, const char *relpath
, const struct stat
*statp
));
55 #ifdef FSTYPE_MNTENT /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
58 # if defined(MNT_MNTTAB) /* HP-UX. */
59 # define MOUNTED MNT_MNTTAB
61 # if defined(MNTTABNAME) /* Dynix. */
62 # define MOUNTED MNTTABNAME
67 #ifdef FSTYPE_GETMNT /* Ultrix. */
68 #include <sys/param.h>
69 #include <sys/mount.h>
70 #include <sys/fs_types.h>
73 #ifdef FSTYPE_USG_STATFS /* SVR3. */
74 #include <sys/statfs.h>
75 #include <sys/fstyp.h>
78 #ifdef FSTYPE_STATVFS /* SVR4. */
79 #include <sys/statvfs.h>
80 #include <sys/fstyp.h>
83 #ifdef FSTYPE_STATFS /* 4.4BSD. */
84 #include <sys/param.h> /* NetBSD needs this. */
85 #include <sys/mount.h>
88 #include "xstrtol.h" /* for xstrtoumax(). */
91 #ifndef HAVE_F_FSTYPENAME_IN_STATFS
92 #ifndef MFSNAMELEN /* NetBSD defines this. */
97 #ifdef INITMOUNTNAMES /* Defined in 4.4BSD, not in NET/2. */
98 static char *mn
[] = INITMOUNTNAMES
;
99 if (t
>= 0 && t
<= MOUNT_MAXTYPE
)
103 #else /* !INITMOUNTNAMES */
141 #endif /* !INITMOUNTNAMES */
143 #endif /* !MFSNAMELEN */
144 #endif /* !HAVE_F_FSTYPENAME_IN_STATFS */
145 #endif /* FSTYPE_STATFS */
147 #ifdef FSTYPE_AIX_STATFS /* AIX. */
148 #include <sys/vmount.h>
149 #include <sys/statfs.h>
151 #define FSTYPE_STATFS /* Otherwise like 4.4BSD. */
152 #define f_type f_vfstype
161 #if 0 /* NFS filesystems are actually MNT_AIX. */
174 #endif /* FSTYPE_AIX_STATFS */
177 #include <netinet/in.h>
178 #include <afs/venus.h>
180 /* On SunOS 4, afs/vice.h defines this to rely on a pre-ANSI cpp. */
182 #define _VICEIOCTL(id) ((unsigned int ) _IOW('V', id, struct ViceIoctl))
185 /* AFS on Solaris 2.3 doesn't get this definition. */
186 #include <sys/ioccom.h>
193 static char space
[2048];
197 vi
.out_size
= sizeof (space
);
200 if (pioctl (path
, VIOC_FILE_CELL_NAME
, &vi
, 1)
201 && (errno
== EINVAL
|| errno
== ENOENT
))
207 /* Nonzero if the current filesystem's type is known. */
208 static int fstype_known
= 0;
210 /* Return a static string naming the type of filesystem that the file PATH,
211 described by STATP, is on.
212 RELPATH is the file name relative to the current directory.
213 Return "unknown" if its filesystem type is unknown. */
216 filesystem_type (const char *path
, const char *relpath
, const struct stat
*statp
)
218 static char *current_fstype
= NULL
;
219 static dev_t current_dev
;
221 if (current_fstype
!= NULL
)
223 if (fstype_known
&& statp
->st_dev
== current_dev
)
224 return current_fstype
; /* Cached value. */
225 free (current_fstype
);
227 current_dev
= statp
->st_dev
;
228 current_fstype
= filesystem_type_uncached (path
, relpath
, statp
);
229 return current_fstype
;
232 /* Return a newly allocated string naming the type of filesystem that the
233 file PATH, described by STATP, is on.
234 RELPATH is the file name relative to the current directory.
235 Return "unknown" if its filesystem type is unknown. */
238 filesystem_type_uncached (const char *path
, const char *relpath
, const struct stat
*statp
)
242 #ifdef FSTYPE_MNTENT /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
243 char *table
= MOUNTED
;
250 mfp
= setmntent (table
, "r");
252 error (1, errno
, "%s", table
);
254 /* Find the entry with the same device number as STATP, and return
255 that entry's fstype. */
256 while (type
== NULL
&& (mnt
= getmntent (mfp
)))
260 struct stat disk_stats
;
262 #ifdef MNTTYPE_IGNORE
263 if (!strcmp (mnt
->mnt_type
, MNTTYPE_IGNORE
))
267 /* Newer systems like SunOS 4.1 keep the dev number in the mtab,
268 in the options string. For older systems, we need to stat the
269 directory that the filesystem is mounted on to get it.
271 Unfortunately, the HPUX 9.x mnttab entries created by automountq
272 contain a dev= option but the option value does not match the
273 st_dev value of the file (maybe the lower 16 bits match?). */
275 #if !defined(hpux) && !defined(__hpux__)
276 devopt
= strstr (mnt
->mnt_opts
, "dev=");
281 if (devopt
[0] == '0' && (devopt
[1] == 'x' || devopt
[1] == 'X'))
283 xstrtoumax (devopt
, NULL
, 16, &u
, NULL
);
287 #endif /* not hpux */
289 if (stat (mnt
->mnt_dir
, &disk_stats
) == -1) {
293 error (1, errno
, _("error in %s: %s"), table
, mnt
->mnt_dir
);
295 dev
= disk_stats
.st_dev
;
298 if (dev
== statp
->st_dev
)
299 type
= mnt
->mnt_type
;
302 if (endmntent (mfp
) == 0)
303 error (0, errno
, "%s", table
);
306 #ifdef FSTYPE_GETMNT /* Ultrix. */
311 && getmnt (&offset
, &fsd
, sizeof (fsd
), NOSTAT_MANY
, 0) > 0)
313 if (fsd
.fd_req
.dev
== statp
->st_dev
)
314 type
= gt_names
[fsd
.fd_req
.fstype
];
318 #ifdef FSTYPE_USG_STATFS /* SVR3. */
320 char typebuf
[FSTYPSZ
];
322 if (statfs (relpath
, &fss
, sizeof (struct statfs
), 0) == -1)
324 /* Don't die if a file was just removed. */
326 error (1, errno
, "%s", path
);
328 else if (!sysfs (GETFSTYP
, fss
.f_fstyp
, typebuf
))
332 #ifdef FSTYPE_STATVFS /* SVR4. */
335 if (statvfs (relpath
, &fss
) == -1)
337 /* Don't die if a file was just removed. */
339 error (1, errno
, "%s", path
);
342 type
= fss
.f_basetype
;
345 #ifdef FSTYPE_STATFS /* 4.4BSD. */
349 if (S_ISLNK (statp
->st_mode
))
350 p
= dir_name (relpath
);
354 if (statfs (p
, &fss
) == -1)
356 /* Don't die if symlink to nonexisting file, or a file that was
359 error (1, errno
, "%s", path
);
363 #ifdef HAVE_F_FSTYPENAME_IN_STATFS
364 type
= xstrdup (fss
.f_fstypename
);
366 type
= fstype_to_string (fss
.f_type
);
374 if ((!type
|| !strcmp (type
, "xx")) && in_afs (relpath
))
378 /* An unknown value can be caused by an ENOENT error condition.
379 Don't cache those values. */
380 fstype_known
= (type
!= NULL
);
382 return xstrdup (type
? type
: _("unknown"));
390 get_mounted_filesystems (void)
392 #ifdef HAVE_GETMNTENT
393 char *table
= MOUNTED
;
397 size_t alloc_size
= 0u;
401 mfp
= setmntent (table
, "r");
403 error (1, errno
, "%s", table
);
405 while (NULL
!= (mnt
= getmntent (mfp
)))
409 #ifdef MNTTYPE_IGNORE
410 if (!strcmp (mnt
->mnt_type
, MNTTYPE_IGNORE
))
414 len
= strlen(mnt
->mnt_dir
) + 1;
415 result
= extendbuf(result
, used
+len
, &alloc_size
);
416 strcpy(&result
[used
], mnt
->mnt_dir
);
417 used
+= len
; /* len already includes one for the \0 */
419 if (endmntent (mfp
) == 0)
420 error (0, errno
, "%s", table
);
424 /* Add the extra terminating \0 */
425 result
= extendbuf(result
, used
+1, &alloc_size
);
430 assert(NULL
== result
); /* Postcondition. */
435 /* No getmntent(). */