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>. */
33 /* Need declaration of function `xstrtoumax' */
38 # define _(Text) gettext (Text)
43 # define N_(String) gettext_noop (String)
45 # define N_(String) (String)
48 static char *filesystem_type_uncached
PARAMS((char *path
, char *relpath
, struct stat
*statp
));
50 #ifdef FSTYPE_MNTENT /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
53 # if defined(MNT_MNTTAB) /* HP-UX. */
54 # define MOUNTED MNT_MNTTAB
56 # if defined(MNTTABNAME) /* Dynix. */
57 # define MOUNTED MNTTABNAME
62 #ifdef FSTYPE_GETMNT /* Ultrix. */
63 #include <sys/param.h>
64 #include <sys/mount.h>
65 #include <sys/fs_types.h>
68 #ifdef FSTYPE_USG_STATFS /* SVR3. */
69 #include <sys/statfs.h>
70 #include <sys/fstyp.h>
73 #ifdef FSTYPE_STATVFS /* SVR4. */
74 #include <sys/statvfs.h>
75 #include <sys/fstyp.h>
78 #ifdef FSTYPE_STATFS /* 4.4BSD. */
79 #include <sys/param.h> /* NetBSD needs this. */
80 #include <sys/mount.h>
82 #ifndef HAVE_F_FSTYPENAME_IN_STATFS
83 #ifndef MFSNAMELEN /* NetBSD defines this. */
88 #ifdef INITMOUNTNAMES /* Defined in 4.4BSD, not in NET/2. */
89 static char *mn
[] = INITMOUNTNAMES
;
90 if (t
>= 0 && t
<= MOUNT_MAXTYPE
)
94 #else /* !INITMOUNTNAMES */
132 #endif /* !INITMOUNTNAMES */
134 #endif /* !MFSNAMELEN */
135 #endif /* !HAVE_F_FSTYPENAME_IN_STATFS */
136 #endif /* FSTYPE_STATFS */
138 #ifdef FSTYPE_AIX_STATFS /* AIX. */
139 #include <sys/vmount.h>
140 #include <sys/statfs.h>
142 #define FSTYPE_STATFS /* Otherwise like 4.4BSD. */
143 #define f_type f_vfstype
152 #if 0 /* NFS filesystems are actually MNT_AIX. */
165 #endif /* FSTYPE_AIX_STATFS */
168 #include <netinet/in.h>
169 #include <afs/venus.h>
171 /* On SunOS 4, afs/vice.h defines this to rely on a pre-ANSI cpp. */
173 #define _VICEIOCTL(id) ((unsigned int ) _IOW('V', id, struct ViceIoctl))
176 /* AFS on Solaris 2.3 doesn't get this definition. */
177 #include <sys/ioccom.h>
184 static char space
[2048];
188 vi
.out_size
= sizeof (space
);
191 if (pioctl (path
, VIOC_FILE_CELL_NAME
, &vi
, 1)
192 && (errno
== EINVAL
|| errno
== ENOENT
))
198 /* Nonzero if the current filesystem's type is known. */
199 static int fstype_known
= 0;
201 /* Return a static string naming the type of filesystem that the file PATH,
202 described by STATP, is on.
203 RELPATH is the file name relative to the current directory.
204 Return "unknown" if its filesystem type is unknown. */
207 filesystem_type (char *path
, char *relpath
, struct stat
*statp
)
209 static char *current_fstype
= NULL
;
210 static dev_t current_dev
;
212 if (current_fstype
!= NULL
)
214 if (fstype_known
&& statp
->st_dev
== current_dev
)
215 return current_fstype
; /* Cached value. */
216 free (current_fstype
);
218 current_dev
= statp
->st_dev
;
219 current_fstype
= filesystem_type_uncached (path
, relpath
, statp
);
220 return current_fstype
;
223 /* Return a newly allocated string naming the type of filesystem that the
224 file PATH, described by STATP, is on.
225 RELPATH is the file name relative to the current directory.
226 Return "unknown" if its filesystem type is unknown. */
229 filesystem_type_uncached (char *path
, char *relpath
, struct stat
*statp
)
233 #ifdef FSTYPE_MNTENT /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
234 char *table
= MOUNTED
;
238 mfp
= setmntent (table
, "r");
240 error (1, errno
, "%s", table
);
242 /* Find the entry with the same device number as STATP, and return
243 that entry's fstype. */
244 while (type
== NULL
&& (mnt
= getmntent (mfp
)))
248 struct stat disk_stats
;
250 #ifdef MNTTYPE_IGNORE
251 if (!strcmp (mnt
->mnt_type
, MNTTYPE_IGNORE
))
255 /* Newer systems like SunOS 4.1 keep the dev number in the mtab,
256 in the options string. For older systems, we need to stat the
257 directory that the filesystem is mounted on to get it.
259 Unfortunately, the HPUX 9.x mnttab entries created by automountq
260 contain a dev= option but the option value does not match the
261 st_dev value of the file (maybe the lower 16 bits match?). */
263 #if !defined(hpux) && !defined(__hpux__)
264 devopt
= strstr (mnt
->mnt_opts
, "dev=");
269 if (devopt
[0] == '0' && (devopt
[1] == 'x' || devopt
[1] == 'X'))
271 xstrtoumax (devopt
, NULL
, 16, &u
, NULL
);
275 #endif /* not hpux */
277 if (stat (mnt
->mnt_dir
, &disk_stats
) == -1) {
281 error (1, errno
, _("error in %s: %s"), table
, mnt
->mnt_dir
);
283 dev
= disk_stats
.st_dev
;
286 if (dev
== statp
->st_dev
)
287 type
= mnt
->mnt_type
;
290 if (endmntent (mfp
) == 0)
291 error (0, errno
, "%s", table
);
294 #ifdef FSTYPE_GETMNT /* Ultrix. */
299 && getmnt (&offset
, &fsd
, sizeof (fsd
), NOSTAT_MANY
, 0) > 0)
301 if (fsd
.fd_req
.dev
== statp
->st_dev
)
302 type
= gt_names
[fsd
.fd_req
.fstype
];
306 #ifdef FSTYPE_USG_STATFS /* SVR3. */
308 char typebuf
[FSTYPSZ
];
310 if (statfs (relpath
, &fss
, sizeof (struct statfs
), 0) == -1)
312 /* Don't die if a file was just removed. */
314 error (1, errno
, "%s", path
);
316 else if (!sysfs (GETFSTYP
, fss
.f_fstyp
, typebuf
))
320 #ifdef FSTYPE_STATVFS /* SVR4. */
323 if (statvfs (relpath
, &fss
) == -1)
325 /* Don't die if a file was just removed. */
327 error (1, errno
, "%s", path
);
330 type
= fss
.f_basetype
;
333 #ifdef FSTYPE_STATFS /* 4.4BSD. */
337 if (S_ISLNK (statp
->st_mode
))
338 p
= dir_name (relpath
);
342 if (statfs (p
, &fss
) == -1)
344 /* Don't die if symlink to nonexisting file, or a file that was
347 error (1, errno
, "%s", path
);
351 #ifdef HAVE_F_FSTYPENAME_IN_STATFS
352 type
= xstrdup (fss
.f_fstypename
);
354 type
= fstype_to_string (fss
.f_type
);
362 if ((!type
|| !strcmp (type
, "xx")) && in_afs (relpath
))
366 /* An unknown value can be caused by an ENOENT error condition.
367 Don't cache those values. */
368 fstype_known
= (type
!= NULL
);
370 return xstrdup (type
? type
: _("unknown"));