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 /* This code was relicensed by the FSF on May 1 2002
20 This file is free software; you can redistribute it and/or
21 modify it under the terms of the GNU Library General Public License as
22 published by the Free Software Foundation; either version 2 of the
23 License, or (at your option) any later version.
25 this file is distributed in the hope that it will be useful,
26 but WITHOUT ANY WARRANTY; without even the implied warranty of
27 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28 Library General Public License for more details.
30 You should have received a copy of the GNU Library General Public
31 License along with the Gnome Library; see the file COPYING.LIB. If not,
32 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
33 Boston, MA 02111-1307, USA.
35 /* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
39 #include <sys/types.h>
56 static char *filesystem_type_uncached P_((char *path, char *relpath, struct stat *statp));
58 void fstype_internal_error (int level, int num, char const *fmt, ...);
60 #ifdef FSTYPE_MNTENT /* 4.3BSD etc. */
61 static int xatoi P_((char *cp));
64 #ifdef FSTYPE_MNTENT /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
67 # if defined(MNT_MNTTAB) /* HP-UX. */
68 # define MOUNTED MNT_MNTTAB
70 # if defined(MNTTABNAME) /* Dynix. */
71 # define MOUNTED MNTTABNAME
76 #ifdef FSTYPE_GETMNT /* Ultrix. */
77 #include <sys/param.h>
78 #include <sys/mount.h>
79 #include <sys/fs_types.h>
82 #ifdef FSTYPE_USG_STATFS /* SVR3. */
83 #include <sys/statfs.h>
84 #include <sys/fstyp.h>
87 #ifdef FSTYPE_STATVFS /* SVR4. */
88 #include <sys/statvfs.h>
89 #include <sys/fstyp.h>
92 #ifdef FSTYPE_STATFS /* 4.4BSD. */
93 #include <sys/param.h> /* NetBSD needs this. */
94 #include <sys/mount.h>
96 #ifndef MFSNAMELEN /* NetBSD defines this. */
101 #ifdef INITMOUNTNAMES /* Defined in 4.4BSD, not in NET/2. */
102 static char *mn[] = INITMOUNTNAMES;
103 if (t >= 0 && t <= MOUNT_MAXTYPE)
107 #else /* !INITMOUNTNAMES */
145 #endif /* !INITMOUNTNAMES */
147 #endif /* !MFSNAMELEN */
148 #endif /* FSTYPE_STATFS */
150 #ifdef FSTYPE_AIX_STATFS /* AIX. */
151 #include <sys/vmount.h>
152 #include <sys/statfs.h>
154 #define FSTYPE_STATFS /* Otherwise like 4.4BSD. */
155 #define f_type f_vfstype
164 #if 0 /* NFS filesystems are actually MNT_AIX. */
177 #endif /* FSTYPE_AIX_STATFS */
180 #include <netinet/in.h>
181 #include <afs/venus.h>
183 /* On SunOS 4, afs/vice.h defines this to rely on a pre-ANSI cpp. */
185 #define _VICEIOCTL(id) ((unsigned int ) _IOW('V', id, struct ViceIoctl))
188 /* AFS on Solaris 2.3 doesn't get this definition. */
189 #include <sys/ioccom.h>
196 static char space[2048];
200 vi.out_size = sizeof (space);
203 if (pioctl (path, VIOC_FILE_CELL_NAME, &vi, 1)
204 && (errno == EINVAL || errno == ENOENT))
210 /* Nonzero if the current filesystem's type is known. */
211 static int fstype_known = 0;
213 char *filesystem_type (char *path, char *relpath, struct stat *statp);
214 /* Return a static string naming the type of filesystem that the file PATH,
215 described by STATP, is on.
216 RELPATH is the file name relative to the current directory.
217 Return "unknown" if its filesystem type is unknown. */
220 filesystem_type (path, relpath, statp)
225 static char *current_fstype = NULL;
226 static dev_t current_dev;
228 if (current_fstype != NULL)
230 if (fstype_known && statp->st_dev == current_dev)
231 return current_fstype; /* Cached value. */
232 g_free (current_fstype);
234 current_dev = statp->st_dev;
235 current_fstype = filesystem_type_uncached (path, relpath, statp);
236 return current_fstype;
240 fstype_internal_error (int level, int num, char const *fmt, ...)
244 /* Return a newly allocated string naming the type of filesystem that the
245 file PATH, described by STATP, is on.
246 RELPATH is the file name relative to the current directory.
247 Return "unknown" if its filesystem type is unknown. */
250 filesystem_type_uncached (path, relpath, statp)
257 #ifdef FSTYPE_MNTENT /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
258 char *table = MOUNTED;
262 mfp = setmntent (table, "r");
264 fstype_internal_error (1, errno, "%s", table);
268 /* Find the entry with the same device number as STATP, and return
269 that entry's fstype. */
270 while (type == NULL && (mnt = getmntent (mfp)))
274 struct stat disk_stats;
276 #ifdef MNTTYPE_IGNORE
277 if (!strcmp (mnt->mnt_type, MNTTYPE_IGNORE))
281 /* Newer systems like SunOS 4.1 keep the dev number in the mtab,
282 in the options string. For older systems, we need to stat the
283 directory that the filesystem is mounted on to get it.
285 Unfortunately, the HPUX 9.x mnttab entries created by automountq
286 contain a dev= option but the option value does not match the
287 st_dev value of the file (maybe the lower 16 bits match?). */
289 #if !defined(hpux) && !defined(__hpux__)
290 devopt = strstr (mnt->mnt_opts, "dev=");
293 if (devopt[4] == '0' && (devopt[5] == 'x' || devopt[5] == 'X'))
294 dev = xatoi (devopt + 6);
296 dev = xatoi (devopt + 4);
299 #endif /* not hpux */
301 if (stat (mnt->mnt_dir, &disk_stats) == -1) {
305 fstype_internal_error (1, errno, "error in %s: %s", table, mnt->mnt_dir);
307 dev = disk_stats.st_dev;
310 if (dev == statp->st_dev)
311 type = mnt->mnt_type;
314 if (endmntent (mfp) == 0)
315 fstype_internal_error (0, errno, "%s", table);
319 #ifdef FSTYPE_GETMNT /* Ultrix. */
324 && getmnt (&offset, &fsd, sizeof (fsd), NOSTAT_MANY, 0) > 0)
326 if (fsd.fd_req.dev == statp->st_dev)
327 type = gt_names[fsd.fd_req.fstype];
331 #ifdef FSTYPE_USG_STATFS /* SVR3. */
333 char typebuf[FSTYPSZ];
335 if (statfs (relpath, &fss, sizeof (struct statfs), 0) == -1)
337 /* Don't die if a file was just removed. */
339 fstype_internal_error (1, errno, "%s", path);
341 else if (!sysfs (GETFSTYP, fss.f_fstyp, typebuf))
345 #ifdef FSTYPE_STATVFS /* SVR4. */
348 if (statvfs (relpath, &fss) == -1)
350 /* Don't die if a file was just removed. */
352 fstype_internal_error (1, errno, "%s", path);
355 type = fss.f_basetype;
358 #ifdef FSTYPE_STATFS /* 4.4BSD. */
362 if (S_ISLNK (statp->st_mode))
363 p = dirname (relpath);
367 if (statfs (p, &fss) == -1)
369 /* Don't die if symlink to nonexisting file, or a file that was
372 fstype_internal_error (1, errno, "%s", path);
376 #ifdef MFSNAMELEN /* NetBSD. */
377 type = fss.f_fstypename;
379 type = fstype_to_string (fss.f_type);
387 if ((!type || !strcmp (type, "xx")) && in_afs (relpath))
391 /* An unknown value can be caused by an ENOENT error condition.
392 Don't cache those values. */
393 fstype_known = (type != NULL);
395 return g_strdup (type ? type : "unknown");
398 #ifdef FSTYPE_MNTENT /* 4.3BSD etc. */
399 /* Return the value of the hexadecimal number represented by CP.
400 No prefix (like '0x') or suffix (like 'h') is expected to be
412 if (*cp >= 'a' && *cp <= 'f')
413 val = val * 16 + *cp - 'a' + 10;
414 else if (*cp >= 'A' && *cp <= 'F')
415 val = val * 16 + *cp - 'A' + 10;
416 else if (*cp >= '0' && *cp <= '9')
417 val = val * 16 + *cp - '0';