update values
[findutils.git] / find / fstype.c
blob56492a50c9e48d2fb707c283e9f8910ce5ac2a7e
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 char *strdup ();
34 char *strstr ();
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. */
40 #include <mntent.h>
41 #if !defined(MOUNTED)
42 # if defined(MNT_MNTTAB) /* HP-UX. */
43 # define MOUNTED MNT_MNTTAB
44 # endif
45 # if defined(MNTTABNAME) /* Dynix. */
46 # define MOUNTED MNTTABNAME
47 # endif
48 #endif
49 #endif
51 #ifdef FSTYPE_GETMNT /* Ultrix. */
52 #include <sys/param.h>
53 #include <sys/mount.h>
54 #include <sys/fs_types.h>
55 #endif
57 #ifdef FSTYPE_USG_STATFS /* SVR3. */
58 #include <sys/statfs.h>
59 #include <sys/fstyp.h>
60 #endif
62 #ifdef FSTYPE_STATVFS /* SVR4. */
63 #include <sys/statvfs.h>
64 #include <sys/fstyp.h>
65 #endif
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. */
72 static char *
73 fstype_to_string (t)
74 short t;
76 #ifdef INITMOUNTNAMES /* Defined in 4.4BSD, not in NET/2. */
77 static char *mn[] = INITMOUNTNAMES;
78 if (t >= 0 && t <= MOUNT_MAXTYPE)
79 return mn[t];
80 else
81 return "?";
82 #else /* !INITMOUNTNAMES */
83 switch (t)
85 case MOUNT_UFS:
86 return "ufs";
87 case MOUNT_NFS:
88 return "nfs";
89 #ifdef MOUNT_PC
90 case MOUNT_PC:
91 return "pc";
92 #endif
93 #ifdef MOUNT_MFS
94 case MOUNT_MFS:
95 return "mfs";
96 #endif
97 #ifdef MOUNT_LO
98 case MOUNT_LO:
99 return "lofs";
100 #endif
101 #ifdef MOUNT_TFS
102 case MOUNT_TFS:
103 return "tfs";
104 #endif
105 #ifdef MOUNT_TMP
106 case MOUNT_TMP:
107 return "tmp";
108 #endif
109 #ifdef MOUNT_MSDOS
110 case MOUNT_MSDOS:
111 return "msdos";
112 #endif
113 #ifdef MOUNT_ISO9660
114 case MOUNT_ISO9660:
115 return "iso9660fs";
116 #endif
117 default:
118 return "?";
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
132 static char *
133 fstype_to_string (t)
134 short t;
136 switch (t)
138 case MNT_AIX:
139 #if 0 /* NFS filesystems are actually MNT_AIX. */
140 return "aix";
141 #endif
142 case MNT_NFS:
143 return "nfs";
144 case MNT_JFS:
145 return "jfs";
146 case MNT_CDROM:
147 return "cdrom";
148 default:
149 return "?";
152 #endif /* FSTYPE_AIX_STATFS */
154 #ifdef AFS
155 #include <netinet/in.h>
156 #include <afs/venus.h>
157 #if __STDC__
158 /* On SunOS 4, afs/vice.h defines this to rely on a pre-ANSI cpp. */
159 #undef _VICEIOCTL
160 #define _VICEIOCTL(id) ((unsigned int ) _IOW('V', id, struct ViceIoctl))
161 #endif
162 #ifndef _IOW
163 /* AFS on Solaris 2.3 doesn't get this definition. */
164 #include <sys/ioccom.h>
165 #endif
167 static int
168 in_afs (path)
169 char *path;
171 static char space[2048];
172 struct ViceIoctl vi;
174 vi.in_size = 0;
175 vi.out_size = sizeof (space);
176 vi.out = space;
178 if (pioctl (path, VIOC_FILE_CELL_NAME, &vi, 1)
179 && (errno == EINVAL || errno == ENOENT))
180 return 0;
181 return 1;
183 #endif /* AFS */
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. */
193 char *
194 filesystem_type (path, relpath, statp)
195 char *path;
196 char *relpath;
197 struct stat *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. */
218 static char *
219 filesystem_type_uncached (path, relpath, statp)
220 char *path;
221 char *relpath;
222 struct stat *statp;
224 char *type = NULL;
226 #ifdef FSTYPE_MNTENT /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
227 char *table = MOUNTED;
228 FILE *mfp;
229 struct mntent *mnt;
231 mfp = setmntent (table, "r");
232 if (mfp == NULL)
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)))
239 char *devopt;
240 dev_t dev;
241 struct stat disk_stats;
243 #ifdef MNTTYPE_IGNORE
244 if (!strcmp (mnt->mnt_type, MNTTYPE_IGNORE))
245 continue;
246 #endif
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=");
258 if (devopt)
260 if (devopt[4] == '0' && (devopt[5] == 'x' || devopt[5] == 'X'))
261 dev = xatoi (devopt + 6);
262 else
263 dev = xatoi (devopt + 4);
265 else
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);
279 #endif
281 #ifdef FSTYPE_GETMNT /* Ultrix. */
282 int offset = 0;
283 struct fs_data fsd;
285 while (type == NULL
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];
291 #endif
293 #ifdef FSTYPE_USG_STATFS /* SVR3. */
294 struct statfs fss;
295 char typebuf[FSTYPSZ];
297 if (statfs (relpath, &fss, sizeof (struct statfs), 0) == -1)
299 /* Don't die if a file was just removed. */
300 if (errno != ENOENT)
301 error (1, errno, "%s", path);
303 else if (!sysfs (GETFSTYP, fss.f_fstyp, typebuf))
304 type = typebuf;
305 #endif
307 #ifdef FSTYPE_STATVFS /* SVR4. */
308 struct statvfs fss;
310 if (statvfs (relpath, &fss) == -1)
312 /* Don't die if a file was just removed. */
313 if (errno != ENOENT)
314 error (1, errno, "%s", path);
316 else
317 type = fss.f_basetype;
318 #endif
320 #ifdef FSTYPE_STATFS /* 4.4BSD. */
321 struct statfs fss;
322 char *p;
324 if (S_ISLNK (statp->st_mode))
325 p = dirname (relpath);
326 else
327 p = relpath;
329 if (statfs (p, &fss) == -1)
331 /* Don't die if symlink to nonexisting file, or a file that was
332 just removed. */
333 if (errno != ENOENT)
334 error (1, errno, "%s", path);
336 else
338 #ifdef MFSNAMELEN /* NetBSD. */
339 type = xstrdup (fss.f_fstypename);
340 #else
341 type = fstype_to_string (fss.f_type);
342 #endif
344 if (p != relpath)
345 free (p);
346 #endif
348 #ifdef AFS
349 if ((!type || !strcmp (type, "xx")) && in_afs (relpath))
350 type = "afs";
351 #endif
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
363 part of CP. */
365 static int
366 xatoi (cp)
367 char *cp;
369 int val;
371 val = 0;
372 while (*cp)
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';
380 else
381 break;
382 cp++;
384 return val;
386 #endif