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>
36 static char *filesystem_type_uncached
P_((char *path
, char *relpath
, struct stat
*statp
));
37 static int xatoi
P_((char *cp
));
39 #ifdef FSTYPE_MNTENT /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
42 # if defined(MNT_MNTTAB) /* HP-UX. */
43 # define MOUNTED MNT_MNTTAB
45 # if defined(MNTTABNAME) /* Dynix. */
46 # define MOUNTED MNTTABNAME
51 #ifdef FSTYPE_GETMNT /* Ultrix. */
52 #include <sys/param.h>
53 #include <sys/mount.h>
54 #include <sys/fs_types.h>
57 #ifdef FSTYPE_USG_STATFS /* SVR3. */
58 #include <sys/statfs.h>
59 #include <sys/fstyp.h>
62 #ifdef FSTYPE_STATVFS /* SVR4. */
63 #include <sys/statvfs.h>
64 #include <sys/fstyp.h>
67 #ifdef FSTYPE_STATFS /* 4.4BSD. */
68 #include <sys/param.h> /* NetBSD needs this. */
69 #include <sys/mount.h>
71 #ifndef MFSNAMELEN /* NetBSD defines this. */
76 #ifdef INITMOUNTNAMES /* Defined in 4.4BSD, not in NET/2. */
77 static char *mn
[] = INITMOUNTNAMES
;
78 if (t
>= 0 && t
<= MOUNT_MAXTYPE
)
82 #else /* !INITMOUNTNAMES */
120 #endif /* !INITMOUNTNAMES */
122 #endif /* !MFSNAMELEN */
123 #endif /* FSTYPE_STATFS */
125 #ifdef FSTYPE_AIX_STATFS /* AIX. */
126 #include <sys/vmount.h>
127 #include <sys/statfs.h>
129 #define FSTYPE_STATFS /* Otherwise like 4.4BSD. */
130 #define f_type f_vfstype
139 #if 0 /* NFS filesystems are actually MNT_AIX. */
152 #endif /* FSTYPE_AIX_STATFS */
155 #include <netinet/in.h>
156 #include <afs/venus.h>
158 /* On SunOS 4, afs/vice.h defines this to rely on a pre-ANSI cpp. */
160 #define _VICEIOCTL(id) ((unsigned int ) _IOW('V', id, struct ViceIoctl))
163 /* AFS on Solaris 2.3 doesn't get this definition. */
164 #include <sys/ioccom.h>
171 static char space
[2048];
175 vi
.out_size
= sizeof (space
);
178 if (pioctl (path
, VIOC_FILE_CELL_NAME
, &vi
, 1)
179 && (errno
== EINVAL
|| errno
== ENOENT
))
185 /* Nonzero if the current filesystem's type is known. */
186 static int fstype_known
= 0;
188 /* Return a static string naming the type of filesystem that the file PATH,
189 described by STATP, is on.
190 RELPATH is the file name relative to the current directory.
191 Return "unknown" if its filesystem type is unknown. */
194 filesystem_type (path
, relpath
, statp
)
199 static char *current_fstype
= NULL
;
200 static dev_t current_dev
;
202 if (current_fstype
!= NULL
)
204 if (fstype_known
&& statp
->st_dev
== current_dev
)
205 return current_fstype
; /* Cached value. */
206 free (current_fstype
);
208 current_dev
= statp
->st_dev
;
209 current_fstype
= filesystem_type_uncached (path
, relpath
, statp
);
210 return current_fstype
;
213 /* Return a newly allocated string naming the type of filesystem that the
214 file PATH, described by STATP, is on.
215 RELPATH is the file name relative to the current directory.
216 Return "unknown" if its filesystem type is unknown. */
219 filesystem_type_uncached (path
, relpath
, statp
)
226 #ifdef FSTYPE_MNTENT /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
227 char *table
= MOUNTED
;
231 mfp
= setmntent (table
, "r");
233 error (1, errno
, "%s", table
);
235 /* Find the entry with the same device number as STATP, and return
236 that entry's fstype. */
237 while (type
== NULL
&& (mnt
= getmntent (mfp
)))
241 struct stat disk_stats
;
243 #ifdef MNTTYPE_IGNORE
244 if (!strcmp (mnt
->mnt_type
, MNTTYPE_IGNORE
))
248 /* Newer systems like SunOS 4.1 keep the dev number in the mtab,
249 in the options string. For older systems, we need to stat the
250 directory that the filesystem is mounted on to get it.
252 Unfortunately, the HPUX 9.x mnttab entries created by automountq
253 contain a dev= option but the option value does not match the
254 st_dev value of the file (maybe the lower 16 bits match?). */
256 #if !defined(hpux) && !defined(__hpux__)
257 devopt
= strstr (mnt
->mnt_opts
, "dev=");
260 if (devopt
[4] == '0' && (devopt
[5] == 'x' || devopt
[5] == 'X'))
261 dev
= xatoi (devopt
+ 6);
263 dev
= xatoi (devopt
+ 4);
266 #endif /* not hpux */
268 if (stat (mnt
->mnt_dir
, &disk_stats
) == -1)
269 error (1, errno
, "error in %s: %s", table
, mnt
->mnt_dir
);
270 dev
= disk_stats
.st_dev
;
273 if (dev
== statp
->st_dev
)
274 type
= mnt
->mnt_type
;
277 if (endmntent (mfp
) == 0)
278 error (0, errno
, "%s", table
);
281 #ifdef FSTYPE_GETMNT /* Ultrix. */
286 && getmnt (&offset
, &fsd
, sizeof (fsd
), NOSTAT_MANY
, 0) > 0)
288 if (fsd
.fd_req
.dev
== statp
->st_dev
)
289 type
= gt_names
[fsd
.fd_req
.fstype
];
293 #ifdef FSTYPE_USG_STATFS /* SVR3. */
295 char typebuf
[FSTYPSZ
];
297 if (statfs (relpath
, &fss
, sizeof (struct statfs
), 0) == -1)
299 /* Don't die if a file was just removed. */
301 error (1, errno
, "%s", path
);
303 else if (!sysfs (GETFSTYP
, fss
.f_fstyp
, typebuf
))
307 #ifdef FSTYPE_STATVFS /* SVR4. */
310 if (statvfs (relpath
, &fss
) == -1)
312 /* Don't die if a file was just removed. */
314 error (1, errno
, "%s", path
);
317 type
= fss
.f_basetype
;
320 #ifdef FSTYPE_STATFS /* 4.4BSD. */
324 if (S_ISLNK (statp
->st_mode
))
325 p
= dirname (relpath
);
329 if (statfs (p
, &fss
) == -1)
331 /* Don't die if symlink to nonexisting file, or a file that was
334 error (1, errno
, "%s", path
);
338 #ifdef MFSNAMELEN /* NetBSD. */
339 type
= xstrdup (fss
.f_fstypename
);
341 type
= fstype_to_string (fss
.f_type
);
349 if ((!type
|| !strcmp (type
, "xx")) && in_afs (relpath
))
353 /* An unknown value can be caused by an ENOENT error condition.
354 Don't cache those values. */
355 fstype_known
= (type
!= NULL
);
357 return xstrdup (type
? type
: "unknown");
360 #ifdef FSTYPE_MNTENT /* 4.3BSD etc. */
361 /* Return the value of the hexadecimal number represented by CP.
362 No prefix (like '0x') or suffix (like 'h') is expected to be
374 if (*cp
>= 'a' && *cp
<= 'f')
375 val
= val
* 16 + *cp
- 'a' + 10;
376 else if (*cp
>= 'A' && *cp
<= 'F')
377 val
= val
* 16 + *cp
- 'A' + 10;
378 else if (*cp
>= '0' && *cp
<= '9')
379 val
= val
* 16 + *cp
- '0';