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>
33 static char *filesystem_type_uncached
P_((char *path
, char *relpath
, struct stat
*statp
));
34 static int xatoi
P_((char *cp
));
36 #ifdef FSTYPE_MNTENT /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
39 # if defined(MNT_MNTTAB) /* HP-UX. */
40 # define MOUNTED MNT_MNTTAB
42 # if defined(MNTTABNAME) /* Dynix. */
43 # define MOUNTED MNTTABNAME
48 #ifdef FSTYPE_GETMNT /* Ultrix. */
49 #include <sys/param.h>
50 #include <sys/mount.h>
51 #include <sys/fs_types.h>
54 #ifdef FSTYPE_USG_STATFS /* SVR3. */
55 #include <sys/statfs.h>
56 #include <sys/fstyp.h>
59 #ifdef FSTYPE_STATVFS /* SVR4. */
60 #include <sys/statvfs.h>
61 #include <sys/fstyp.h>
64 #ifdef FSTYPE_STATFS /* 4.4BSD. */
65 #include <sys/param.h> /* NetBSD needs this. */
66 #include <sys/mount.h>
68 #ifndef MFSNAMELEN /* NetBSD defines this. */
73 #ifdef INITMOUNTNAMES /* Defined in 4.4BSD, not in NET/2. */
74 static char *mn
[] = INITMOUNTNAMES
;
75 if (t
>= 0 && t
<= MOUNT_MAXTYPE
)
79 #else /* !INITMOUNTNAMES */
117 #endif /* !INITMOUNTNAMES */
119 #endif /* !MFSNAMELEN */
120 #endif /* FSTYPE_STATFS */
122 #ifdef FSTYPE_AIX_STATFS /* AIX. */
123 #include <sys/vmount.h>
124 #include <sys/statfs.h>
126 #define FSTYPE_STATFS /* Otherwise like 4.4BSD. */
127 #define f_type f_vfstype
136 #if 0 /* NFS filesystems are actually MNT_AIX. */
149 #endif /* FSTYPE_AIX_STATFS */
152 #include <netinet/in.h>
153 #include <afs/venus.h>
155 /* On SunOS 4, afs/vice.h defines this to rely on a pre-ANSI cpp. */
157 #define _VICEIOCTL(id) ((unsigned int ) _IOW('V', id, struct ViceIoctl))
160 /* AFS on Solaris 2.3 doesn't get this definition. */
161 #include <sys/ioccom.h>
168 static char space
[2048];
172 vi
.out_size
= sizeof (space
);
175 if (pioctl (path
, VIOC_FILE_CELL_NAME
, &vi
, 1)
176 && (errno
== EINVAL
|| errno
== ENOENT
))
182 /* Nonzero if the current filesystem's type is known. */
183 static int fstype_known
= 0;
185 /* Return a static string naming the type of filesystem that the file PATH,
186 described by STATP, is on.
187 RELPATH is the file name relative to the current directory.
188 Return "unknown" if its filesystem type is unknown. */
191 filesystem_type (path
, relpath
, statp
)
196 static char *current_fstype
= NULL
;
197 static dev_t current_dev
;
199 if (current_fstype
!= NULL
)
201 if (fstype_known
&& statp
->st_dev
== current_dev
)
202 return current_fstype
; /* Cached value. */
203 free (current_fstype
);
205 current_dev
= statp
->st_dev
;
206 current_fstype
= filesystem_type_uncached (path
, relpath
, statp
);
207 return current_fstype
;
210 /* Return a newly allocated string naming the type of filesystem that the
211 file PATH, 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_uncached (path
, relpath
, statp
)
223 #ifdef FSTYPE_MNTENT /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
224 char *table
= MOUNTED
;
228 mfp
= setmntent (table
, "r");
230 error (1, errno
, "%s", table
);
232 /* Find the entry with the same device number as STATP, and return
233 that entry's fstype. */
234 while (type
== NULL
&& (mnt
= getmntent (mfp
)))
238 struct stat disk_stats
;
240 #ifdef MNTTYPE_IGNORE
241 if (!strcmp (mnt
->mnt_type
, MNTTYPE_IGNORE
))
245 /* Newer systems like SunOS 4.1 keep the dev number in the mtab,
246 in the options string. For older systems, we need to stat the
247 directory that the filesystem is mounted on to get it.
249 Unfortunately, the HPUX 9.x mnttab entries created by automountq
250 contain a dev= option but the option value does not match the
251 st_dev value of the file (maybe the lower 16 bits match?). */
253 #if !defined(hpux) && !defined(__hpux__)
254 devopt
= strstr (mnt
->mnt_opts
, "dev=");
257 if (devopt
[4] == '0' && (devopt
[5] == 'x' || devopt
[5] == 'X'))
258 dev
= xatoi (devopt
+ 6);
260 dev
= xatoi (devopt
+ 4);
263 #endif /* not hpux */
265 if (stat (mnt
->mnt_dir
, &disk_stats
) == -1)
266 error (1, errno
, "error in %s: %s", table
, mnt
->mnt_dir
);
267 dev
= disk_stats
.st_dev
;
270 if (dev
== statp
->st_dev
)
271 type
= mnt
->mnt_type
;
274 if (endmntent (mfp
) == 0)
275 error (0, errno
, "%s", table
);
278 #ifdef FSTYPE_GETMNT /* Ultrix. */
283 && getmnt (&offset
, &fsd
, sizeof (fsd
), NOSTAT_MANY
, 0) > 0)
285 if (fsd
.fd_req
.dev
== statp
->st_dev
)
286 type
= gt_names
[fsd
.fd_req
.fstype
];
290 #ifdef FSTYPE_USG_STATFS /* SVR3. */
292 char typebuf
[FSTYPSZ
];
294 if (statfs (relpath
, &fss
, sizeof (struct statfs
), 0) == -1)
296 /* Don't die if a file was just removed. */
298 error (1, errno
, "%s", path
);
300 else if (!sysfs (GETFSTYP
, fss
.f_fstyp
, typebuf
))
304 #ifdef FSTYPE_STATVFS /* SVR4. */
307 if (statvfs (relpath
, &fss
) == -1)
309 /* Don't die if a file was just removed. */
311 error (1, errno
, "%s", path
);
314 type
= fss
.f_basetype
;
317 #ifdef FSTYPE_STATFS /* 4.4BSD. */
321 if (S_ISLNK (statp
->st_mode
))
322 p
= dirname (relpath
);
326 if (statfs (p
, &fss
) == -1)
328 /* Don't die if symlink to nonexisting file, or a file that was
331 error (1, errno
, "%s", path
);
335 #ifdef MFSNAMELEN /* NetBSD. */
336 type
= xstrdup (fss
.f_fstypename
);
338 type
= fstype_to_string (fss
.f_type
);
346 if ((!type
|| !strcmp (type
, "xx")) && in_afs (relpath
))
350 /* An unknown value can be caused by an ENOENT error condition.
351 Don't cache those values. */
352 fstype_known
= (type
!= NULL
);
354 return xstrdup (type
? type
: "unknown");
357 #ifdef FSTYPE_MNTENT /* 4.3BSD etc. */
358 /* Return the value of the hexadecimal number represented by CP.
359 No prefix (like '0x') or suffix (like 'h') is expected to be
371 if (*cp
>= 'a' && *cp
<= 'f')
372 val
= val
* 16 + *cp
- 'a' + 10;
373 else if (*cp
>= 'A' && *cp
<= 'F')
374 val
= val
* 16 + *cp
- 'A' + 10;
375 else if (*cp
>= '0' && *cp
<= '9')
376 val
= val
* 16 + *cp
- '0';