changed name of maintainer to kevind@rahul.net
[findutils.git] / find / fstype.c
blob5001ea41eae5e5fb86182f11b9b96887170f6fce
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)
7 any later version.
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>. */
20 #include <config.h>
21 #include <stdio.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include "defs.h"
25 #include "modetype.h"
26 #include <errno.h>
27 #ifdef STDC_HEADERS
28 #include <stdlib.h>
29 #else
30 extern int errno;
31 #endif
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. */
37 #include <mntent.h>
38 #if !defined(MOUNTED)
39 # if defined(MNT_MNTTAB) /* HP-UX. */
40 # define MOUNTED MNT_MNTTAB
41 # endif
42 # if defined(MNTTABNAME) /* Dynix. */
43 # define MOUNTED MNTTABNAME
44 # endif
45 #endif
46 #endif
48 #ifdef FSTYPE_GETMNT /* Ultrix. */
49 #include <sys/param.h>
50 #include <sys/mount.h>
51 #include <sys/fs_types.h>
52 #endif
54 #ifdef FSTYPE_USG_STATFS /* SVR3. */
55 #include <sys/statfs.h>
56 #include <sys/fstyp.h>
57 #endif
59 #ifdef FSTYPE_STATVFS /* SVR4. */
60 #include <sys/statvfs.h>
61 #include <sys/fstyp.h>
62 #endif
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. */
69 static char *
70 fstype_to_string (t)
71 short t;
73 #ifdef INITMOUNTNAMES /* Defined in 4.4BSD, not in NET/2. */
74 static char *mn[] = INITMOUNTNAMES;
75 if (t >= 0 && t <= MOUNT_MAXTYPE)
76 return mn[t];
77 else
78 return "?";
79 #else /* !INITMOUNTNAMES */
80 switch (t)
82 case MOUNT_UFS:
83 return "ufs";
84 case MOUNT_NFS:
85 return "nfs";
86 #ifdef MOUNT_PC
87 case MOUNT_PC:
88 return "pc";
89 #endif
90 #ifdef MOUNT_MFS
91 case MOUNT_MFS:
92 return "mfs";
93 #endif
94 #ifdef MOUNT_LO
95 case MOUNT_LO:
96 return "lofs";
97 #endif
98 #ifdef MOUNT_TFS
99 case MOUNT_TFS:
100 return "tfs";
101 #endif
102 #ifdef MOUNT_TMP
103 case MOUNT_TMP:
104 return "tmp";
105 #endif
106 #ifdef MOUNT_MSDOS
107 case MOUNT_MSDOS:
108 return "msdos";
109 #endif
110 #ifdef MOUNT_ISO9660
111 case MOUNT_ISO9660:
112 return "iso9660fs";
113 #endif
114 default:
115 return "?";
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
129 static char *
130 fstype_to_string (t)
131 short t;
133 switch (t)
135 case MNT_AIX:
136 #if 0 /* NFS filesystems are actually MNT_AIX. */
137 return "aix";
138 #endif
139 case MNT_NFS:
140 return "nfs";
141 case MNT_JFS:
142 return "jfs";
143 case MNT_CDROM:
144 return "cdrom";
145 default:
146 return "?";
149 #endif /* FSTYPE_AIX_STATFS */
151 #ifdef AFS
152 #include <netinet/in.h>
153 #include <afs/venus.h>
154 #if __STDC__
155 /* On SunOS 4, afs/vice.h defines this to rely on a pre-ANSI cpp. */
156 #undef _VICEIOCTL
157 #define _VICEIOCTL(id) ((unsigned int ) _IOW('V', id, struct ViceIoctl))
158 #endif
159 #ifndef _IOW
160 /* AFS on Solaris 2.3 doesn't get this definition. */
161 #include <sys/ioccom.h>
162 #endif
164 static int
165 in_afs (path)
166 char *path;
168 static char space[2048];
169 struct ViceIoctl vi;
171 vi.in_size = 0;
172 vi.out_size = sizeof (space);
173 vi.out = space;
175 if (pioctl (path, VIOC_FILE_CELL_NAME, &vi, 1)
176 && (errno == EINVAL || errno == ENOENT))
177 return 0;
178 return 1;
180 #endif /* AFS */
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. */
190 char *
191 filesystem_type (path, relpath, statp)
192 char *path;
193 char *relpath;
194 struct stat *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. */
215 static char *
216 filesystem_type_uncached (path, relpath, statp)
217 char *path;
218 char *relpath;
219 struct stat *statp;
221 char *type = NULL;
223 #ifdef FSTYPE_MNTENT /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
224 char *table = MOUNTED;
225 FILE *mfp;
226 struct mntent *mnt;
228 mfp = setmntent (table, "r");
229 if (mfp == NULL)
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)))
236 char *devopt;
237 dev_t dev;
238 struct stat disk_stats;
240 #ifdef MNTTYPE_IGNORE
241 if (!strcmp (mnt->mnt_type, MNTTYPE_IGNORE))
242 continue;
243 #endif
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=");
255 if (devopt)
257 if (devopt[4] == '0' && (devopt[5] == 'x' || devopt[5] == 'X'))
258 dev = xatoi (devopt + 6);
259 else
260 dev = xatoi (devopt + 4);
262 else
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);
276 #endif
278 #ifdef FSTYPE_GETMNT /* Ultrix. */
279 int offset = 0;
280 struct fs_data fsd;
282 while (type == NULL
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];
288 #endif
290 #ifdef FSTYPE_USG_STATFS /* SVR3. */
291 struct statfs fss;
292 char typebuf[FSTYPSZ];
294 if (statfs (relpath, &fss, sizeof (struct statfs), 0) == -1)
296 /* Don't die if a file was just removed. */
297 if (errno != ENOENT)
298 error (1, errno, "%s", path);
300 else if (!sysfs (GETFSTYP, fss.f_fstyp, typebuf))
301 type = typebuf;
302 #endif
304 #ifdef FSTYPE_STATVFS /* SVR4. */
305 struct statvfs fss;
307 if (statvfs (relpath, &fss) == -1)
309 /* Don't die if a file was just removed. */
310 if (errno != ENOENT)
311 error (1, errno, "%s", path);
313 else
314 type = fss.f_basetype;
315 #endif
317 #ifdef FSTYPE_STATFS /* 4.4BSD. */
318 struct statfs fss;
319 char *p;
321 if (S_ISLNK (statp->st_mode))
322 p = dirname (relpath);
323 else
324 p = relpath;
326 if (statfs (p, &fss) == -1)
328 /* Don't die if symlink to nonexisting file, or a file that was
329 just removed. */
330 if (errno != ENOENT)
331 error (1, errno, "%s", path);
333 else
335 #ifdef MFSNAMELEN /* NetBSD. */
336 type = xstrdup (fss.f_fstypename);
337 #else
338 type = fstype_to_string (fss.f_type);
339 #endif
341 if (p != relpath)
342 free (p);
343 #endif
345 #ifdef AFS
346 if ((!type || !strcmp (type, "xx")) && in_afs (relpath))
347 type = "afs";
348 #endif
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
360 part of CP. */
362 static int
363 xatoi (cp)
364 char *cp;
366 int val;
368 val = 0;
369 while (*cp)
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';
377 else
378 break;
379 cp++;
381 return val;
383 #endif