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., 9 Temple Place - Suite 330, Boston, MA 02111-1307,
20 /* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
24 #include "../gnulib/lib/dirname.h"
33 /* Need declaration of function `xstrtoumax' */
34 #include "../gnulib/lib/xstrtol.h"
38 # define _(Text) gettext (Text)
43 # define N_(String) gettext_noop (String)
45 /* See locate.c for explanation as to why not use (String) */
46 # define N_(String) String
49 static char *filesystem_type_uncached
PARAMS((char *path
, char *relpath
, struct stat
*statp
));
51 #ifdef FSTYPE_MNTENT /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
54 # if defined(MNT_MNTTAB) /* HP-UX. */
55 # define MOUNTED MNT_MNTTAB
57 # if defined(MNTTABNAME) /* Dynix. */
58 # define MOUNTED MNTTABNAME
63 #ifdef FSTYPE_GETMNT /* Ultrix. */
64 #include <sys/param.h>
65 #include <sys/mount.h>
66 #include <sys/fs_types.h>
69 #ifdef FSTYPE_USG_STATFS /* SVR3. */
70 #include <sys/statfs.h>
71 #include <sys/fstyp.h>
74 #ifdef FSTYPE_STATVFS /* SVR4. */
75 #include <sys/statvfs.h>
76 #include <sys/fstyp.h>
79 #ifdef FSTYPE_STATFS /* 4.4BSD. */
80 #include <sys/param.h> /* NetBSD needs this. */
81 #include <sys/mount.h>
83 #ifndef HAVE_F_FSTYPENAME_IN_STATFS
84 #ifndef MFSNAMELEN /* NetBSD defines this. */
89 #ifdef INITMOUNTNAMES /* Defined in 4.4BSD, not in NET/2. */
90 static char *mn
[] = INITMOUNTNAMES
;
91 if (t
>= 0 && t
<= MOUNT_MAXTYPE
)
95 #else /* !INITMOUNTNAMES */
133 #endif /* !INITMOUNTNAMES */
135 #endif /* !MFSNAMELEN */
136 #endif /* !HAVE_F_FSTYPENAME_IN_STATFS */
137 #endif /* FSTYPE_STATFS */
139 #ifdef FSTYPE_AIX_STATFS /* AIX. */
140 #include <sys/vmount.h>
141 #include <sys/statfs.h>
143 #define FSTYPE_STATFS /* Otherwise like 4.4BSD. */
144 #define f_type f_vfstype
153 #if 0 /* NFS filesystems are actually MNT_AIX. */
166 #endif /* FSTYPE_AIX_STATFS */
169 #include <netinet/in.h>
170 #include <afs/venus.h>
172 /* On SunOS 4, afs/vice.h defines this to rely on a pre-ANSI cpp. */
174 #define _VICEIOCTL(id) ((unsigned int ) _IOW('V', id, struct ViceIoctl))
177 /* AFS on Solaris 2.3 doesn't get this definition. */
178 #include <sys/ioccom.h>
185 static char space
[2048];
189 vi
.out_size
= sizeof (space
);
192 if (pioctl (path
, VIOC_FILE_CELL_NAME
, &vi
, 1)
193 && (errno
== EINVAL
|| errno
== ENOENT
))
199 /* Nonzero if the current filesystem's type is known. */
200 static int fstype_known
= 0;
202 /* Return a static string naming the type of filesystem that the file PATH,
203 described by STATP, is on.
204 RELPATH is the file name relative to the current directory.
205 Return "unknown" if its filesystem type is unknown. */
208 filesystem_type (char *path
, char *relpath
, struct stat
*statp
)
210 static char *current_fstype
= NULL
;
211 static dev_t current_dev
;
213 if (current_fstype
!= NULL
)
215 if (fstype_known
&& statp
->st_dev
== current_dev
)
216 return current_fstype
; /* Cached value. */
217 free (current_fstype
);
219 current_dev
= statp
->st_dev
;
220 current_fstype
= filesystem_type_uncached (path
, relpath
, statp
);
221 return current_fstype
;
224 /* Return a newly allocated string naming the type of filesystem that the
225 file PATH, described by STATP, is on.
226 RELPATH is the file name relative to the current directory.
227 Return "unknown" if its filesystem type is unknown. */
230 filesystem_type_uncached (char *path
, char *relpath
, struct stat
*statp
)
234 #ifdef FSTYPE_MNTENT /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
235 char *table
= MOUNTED
;
239 mfp
= setmntent (table
, "r");
241 error (1, errno
, "%s", table
);
243 /* Find the entry with the same device number as STATP, and return
244 that entry's fstype. */
245 while (type
== NULL
&& (mnt
= getmntent (mfp
)))
249 struct stat disk_stats
;
251 #ifdef MNTTYPE_IGNORE
252 if (!strcmp (mnt
->mnt_type
, MNTTYPE_IGNORE
))
256 /* Newer systems like SunOS 4.1 keep the dev number in the mtab,
257 in the options string. For older systems, we need to stat the
258 directory that the filesystem is mounted on to get it.
260 Unfortunately, the HPUX 9.x mnttab entries created by automountq
261 contain a dev= option but the option value does not match the
262 st_dev value of the file (maybe the lower 16 bits match?). */
264 #if !defined(hpux) && !defined(__hpux__)
265 devopt
= strstr (mnt
->mnt_opts
, "dev=");
270 if (devopt
[0] == '0' && (devopt
[1] == 'x' || devopt
[1] == 'X'))
272 xstrtoumax (devopt
, NULL
, 16, &u
, NULL
);
276 #endif /* not hpux */
278 if (stat (mnt
->mnt_dir
, &disk_stats
) == -1) {
282 error (1, errno
, _("error in %s: %s"), table
, mnt
->mnt_dir
);
284 dev
= disk_stats
.st_dev
;
287 if (dev
== statp
->st_dev
)
288 type
= mnt
->mnt_type
;
291 if (endmntent (mfp
) == 0)
292 error (0, errno
, "%s", table
);
295 #ifdef FSTYPE_GETMNT /* Ultrix. */
300 && getmnt (&offset
, &fsd
, sizeof (fsd
), NOSTAT_MANY
, 0) > 0)
302 if (fsd
.fd_req
.dev
== statp
->st_dev
)
303 type
= gt_names
[fsd
.fd_req
.fstype
];
307 #ifdef FSTYPE_USG_STATFS /* SVR3. */
309 char typebuf
[FSTYPSZ
];
311 if (statfs (relpath
, &fss
, sizeof (struct statfs
), 0) == -1)
313 /* Don't die if a file was just removed. */
315 error (1, errno
, "%s", path
);
317 else if (!sysfs (GETFSTYP
, fss
.f_fstyp
, typebuf
))
321 #ifdef FSTYPE_STATVFS /* SVR4. */
324 if (statvfs (relpath
, &fss
) == -1)
326 /* Don't die if a file was just removed. */
328 error (1, errno
, "%s", path
);
331 type
= fss
.f_basetype
;
334 #ifdef FSTYPE_STATFS /* 4.4BSD. */
338 if (S_ISLNK (statp
->st_mode
))
339 p
= dir_name (relpath
);
343 if (statfs (p
, &fss
) == -1)
345 /* Don't die if symlink to nonexisting file, or a file that was
348 error (1, errno
, "%s", path
);
352 #ifdef HAVE_F_FSTYPENAME_IN_STATFS
353 type
= xstrdup (fss
.f_fstypename
);
355 type
= fstype_to_string (fss
.f_type
);
363 if ((!type
|| !strcmp (type
, "xx")) && in_afs (relpath
))
367 /* An unknown value can be caused by an ENOENT error condition.
368 Don't cache those values. */
369 fstype_known
= (type
!= NULL
);
371 return xstrdup (type
? type
: _("unknown"));