1 /* fstype.c -- determine type of filesystems that files are on
2 Copyright (C) 1990, 91, 92, 93, 94 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., 675 Mass Ave, Cambridge, MA 02139, USA. */
18 /* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
22 #include <sys/types.h>
35 # define _(Text) gettext (Text)
40 # define N_(String) gettext_noop (String)
42 # define N_(String) (String)
45 static char *filesystem_type_uncached
PARAMS((char *path
, char *relpath
, struct stat
*statp
));
46 static int xatoi
PARAMS((char *cp
));
48 #ifdef FSTYPE_MNTENT /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
51 # if defined(MNT_MNTTAB) /* HP-UX. */
52 # define MOUNTED MNT_MNTTAB
54 # if defined(MNTTABNAME) /* Dynix. */
55 # define MOUNTED MNTTABNAME
60 #ifdef FSTYPE_GETMNT /* Ultrix. */
61 #include <sys/param.h>
62 #include <sys/mount.h>
63 #include <sys/fs_types.h>
66 #ifdef FSTYPE_USG_STATFS /* SVR3. */
67 #include <sys/statfs.h>
68 #include <sys/fstyp.h>
71 #ifdef FSTYPE_STATVFS /* SVR4. */
72 #include <sys/statvfs.h>
73 #include <sys/fstyp.h>
76 #ifdef FSTYPE_STATFS /* 4.4BSD. */
77 #include <sys/param.h> /* NetBSD needs this. */
78 #include <sys/mount.h>
80 #ifndef MFSNAMELEN /* NetBSD defines this. */
85 #ifdef INITMOUNTNAMES /* Defined in 4.4BSD, not in NET/2. */
86 static char *mn
[] = INITMOUNTNAMES
;
87 if (t
>= 0 && t
<= MOUNT_MAXTYPE
)
91 #else /* !INITMOUNTNAMES */
129 #endif /* !INITMOUNTNAMES */
131 #endif /* !MFSNAMELEN */
132 #endif /* FSTYPE_STATFS */
134 #ifdef FSTYPE_AIX_STATFS /* AIX. */
135 #include <sys/vmount.h>
136 #include <sys/statfs.h>
138 #define FSTYPE_STATFS /* Otherwise like 4.4BSD. */
139 #define f_type f_vfstype
148 #if 0 /* NFS filesystems are actually MNT_AIX. */
161 #endif /* FSTYPE_AIX_STATFS */
164 #include <netinet/in.h>
165 #include <afs/venus.h>
167 /* On SunOS 4, afs/vice.h defines this to rely on a pre-ANSI cpp. */
169 #define _VICEIOCTL(id) ((unsigned int ) _IOW('V', id, struct ViceIoctl))
172 /* AFS on Solaris 2.3 doesn't get this definition. */
173 #include <sys/ioccom.h>
180 static char space
[2048];
184 vi
.out_size
= sizeof (space
);
187 if (pioctl (path
, VIOC_FILE_CELL_NAME
, &vi
, 1)
188 && (errno
== EINVAL
|| errno
== ENOENT
))
194 /* Nonzero if the current filesystem's type is known. */
195 static int fstype_known
= 0;
197 /* Return a static string naming the type of filesystem that the file PATH,
198 described by STATP, is on.
199 RELPATH is the file name relative to the current directory.
200 Return "unknown" if its filesystem type is unknown. */
203 filesystem_type (char *path
, char *relpath
, struct stat
*statp
)
205 static char *current_fstype
= NULL
;
206 static dev_t current_dev
;
208 if (current_fstype
!= NULL
)
210 if (fstype_known
&& statp
->st_dev
== current_dev
)
211 return current_fstype
; /* Cached value. */
212 free (current_fstype
);
214 current_dev
= statp
->st_dev
;
215 current_fstype
= filesystem_type_uncached (path
, relpath
, statp
);
216 return current_fstype
;
219 /* Return a newly allocated string naming the type of filesystem that the
220 file PATH, described by STATP, is on.
221 RELPATH is the file name relative to the current directory.
222 Return "unknown" if its filesystem type is unknown. */
225 filesystem_type_uncached (char *path
, char *relpath
, struct stat
*statp
)
229 #ifdef FSTYPE_MNTENT /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
230 char *table
= MOUNTED
;
234 mfp
= setmntent (table
, "r");
236 error (1, errno
, "%s", table
);
238 /* Find the entry with the same device number as STATP, and return
239 that entry's fstype. */
240 while (type
== NULL
&& (mnt
= getmntent (mfp
)))
244 struct stat disk_stats
;
246 #ifdef MNTTYPE_IGNORE
247 if (!strcmp (mnt
->mnt_type
, MNTTYPE_IGNORE
))
251 /* Newer systems like SunOS 4.1 keep the dev number in the mtab,
252 in the options string. For older systems, we need to stat the
253 directory that the filesystem is mounted on to get it.
255 Unfortunately, the HPUX 9.x mnttab entries created by automountq
256 contain a dev= option but the option value does not match the
257 st_dev value of the file (maybe the lower 16 bits match?). */
259 #if !defined(hpux) && !defined(__hpux__)
260 devopt
= strstr (mnt
->mnt_opts
, "dev=");
263 if (devopt
[4] == '0' && (devopt
[5] == 'x' || devopt
[5] == 'X'))
264 dev
= xatoi (devopt
+ 6);
266 dev
= xatoi (devopt
+ 4);
269 #endif /* not hpux */
271 if (stat (mnt
->mnt_dir
, &disk_stats
) == -1) {
275 error (1, errno
, _("error in %s: %s"), table
, mnt
->mnt_dir
);
277 dev
= disk_stats
.st_dev
;
280 if (dev
== statp
->st_dev
)
281 type
= mnt
->mnt_type
;
284 if (endmntent (mfp
) == 0)
285 error (0, errno
, "%s", table
);
288 #ifdef FSTYPE_GETMNT /* Ultrix. */
293 && getmnt (&offset
, &fsd
, sizeof (fsd
), NOSTAT_MANY
, 0) > 0)
295 if (fsd
.fd_req
.dev
== statp
->st_dev
)
296 type
= gt_names
[fsd
.fd_req
.fstype
];
300 #ifdef FSTYPE_USG_STATFS /* SVR3. */
302 char typebuf
[FSTYPSZ
];
304 if (statfs (relpath
, &fss
, sizeof (struct statfs
), 0) == -1)
306 /* Don't die if a file was just removed. */
308 error (1, errno
, "%s", path
);
310 else if (!sysfs (GETFSTYP
, fss
.f_fstyp
, typebuf
))
314 #ifdef FSTYPE_STATVFS /* SVR4. */
317 if (statvfs (relpath
, &fss
) == -1)
319 /* Don't die if a file was just removed. */
321 error (1, errno
, "%s", path
);
324 type
= fss
.f_basetype
;
327 #ifdef FSTYPE_STATFS /* 4.4BSD. */
331 if (S_ISLNK (statp
->st_mode
))
332 p
= dirname (relpath
);
336 if (statfs (p
, &fss
) == -1)
338 /* Don't die if symlink to nonexisting file, or a file that was
341 error (1, errno
, "%s", path
);
345 #ifdef HAVE_F_FSTYPENAME_IN_STATFS
346 type
= xstrdup (fss
.f_fstypename
);
348 type
= fstype_to_string (fss
.f_type
);
356 if ((!type
|| !strcmp (type
, "xx")) && in_afs (relpath
))
360 /* An unknown value can be caused by an ENOENT error condition.
361 Don't cache those values. */
362 fstype_known
= (type
!= NULL
);
364 return xstrdup (type
? type
: _("unknown"));
367 #ifdef FSTYPE_MNTENT /* 4.3BSD etc. */
368 /* Return the value of the hexadecimal number represented by CP.
369 No prefix (like '0x') or suffix (like 'h') is expected to be
380 if (*cp
>= 'a' && *cp
<= 'f')
381 val
= val
* 16 + *cp
- 'a' + 10;
382 else if (*cp
>= 'A' && *cp
<= 'F')
383 val
= val
* 16 + *cp
- 'A' + 10;
384 else if (*cp
>= '0' && *cp
<= '9')
385 val
= val
* 16 + *cp
- '0';