* xargs/Makefile.am: add ansi2knr
[findutils.git] / find / fstype.c
blob5c316d5e7a09415ae16c4e3a86536e5e27d06b44
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 #if ENABLE_NLS
34 # include <libintl.h>
35 # define _(Text) gettext (Text)
36 #else
37 # define _(Text) Text
38 #endif
39 #ifdef gettext_noop
40 # define N_(String) gettext_noop (String)
41 #else
42 # define N_(String) (String)
43 #endif
45 static char *filesystem_type_uncached PARAMS((char *path, char *relpath, struct stat *statp));
46 static int xatoi PARAMS((char *cp));
48 #ifdef FSTYPE_MNTENT /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
49 #include <mntent.h>
50 #if !defined(MOUNTED)
51 # if defined(MNT_MNTTAB) /* HP-UX. */
52 # define MOUNTED MNT_MNTTAB
53 # endif
54 # if defined(MNTTABNAME) /* Dynix. */
55 # define MOUNTED MNTTABNAME
56 # endif
57 #endif
58 #endif
60 #ifdef FSTYPE_GETMNT /* Ultrix. */
61 #include <sys/param.h>
62 #include <sys/mount.h>
63 #include <sys/fs_types.h>
64 #endif
66 #ifdef FSTYPE_USG_STATFS /* SVR3. */
67 #include <sys/statfs.h>
68 #include <sys/fstyp.h>
69 #endif
71 #ifdef FSTYPE_STATVFS /* SVR4. */
72 #include <sys/statvfs.h>
73 #include <sys/fstyp.h>
74 #endif
76 #ifdef FSTYPE_STATFS /* 4.4BSD. */
77 #include <sys/param.h> /* NetBSD needs this. */
78 #include <sys/mount.h>
80 #ifndef MFSNAMELEN /* NetBSD defines this. */
81 static char *
82 fstype_to_string (t)
83 short t;
85 #ifdef INITMOUNTNAMES /* Defined in 4.4BSD, not in NET/2. */
86 static char *mn[] = INITMOUNTNAMES;
87 if (t >= 0 && t <= MOUNT_MAXTYPE)
88 return mn[t];
89 else
90 return "?";
91 #else /* !INITMOUNTNAMES */
92 switch (t)
94 case MOUNT_UFS:
95 return "ufs";
96 case MOUNT_NFS:
97 return "nfs";
98 #ifdef MOUNT_PC
99 case MOUNT_PC:
100 return "pc";
101 #endif
102 #ifdef MOUNT_MFS
103 case MOUNT_MFS:
104 return "mfs";
105 #endif
106 #ifdef MOUNT_LO
107 case MOUNT_LO:
108 return "lofs";
109 #endif
110 #ifdef MOUNT_TFS
111 case MOUNT_TFS:
112 return "tfs";
113 #endif
114 #ifdef MOUNT_TMP
115 case MOUNT_TMP:
116 return "tmp";
117 #endif
118 #ifdef MOUNT_MSDOS
119 case MOUNT_MSDOS:
120 return "msdos";
121 #endif
122 #ifdef MOUNT_ISO9660
123 case MOUNT_ISO9660:
124 return "iso9660fs";
125 #endif
126 default:
127 return "?";
129 #endif /* !INITMOUNTNAMES */
131 #endif /* !MFSNAMELEN */
132 #endif /* FSTYPE_STATFS */
134 #ifdef FSTYPE_AIX_STATFS /* AIX. */
135 #include <sys/vmount.h>
136 #include <sys/statfs.h>
138 #define FSTYPE_STATFS /* Otherwise like 4.4BSD. */
139 #define f_type f_vfstype
141 static char *
142 fstype_to_string (t)
143 short t;
145 switch (t)
147 case MNT_AIX:
148 #if 0 /* NFS filesystems are actually MNT_AIX. */
149 return "aix";
150 #endif
151 case MNT_NFS:
152 return "nfs";
153 case MNT_JFS:
154 return "jfs";
155 case MNT_CDROM:
156 return "cdrom";
157 default:
158 return "?";
161 #endif /* FSTYPE_AIX_STATFS */
163 #ifdef AFS
164 #include <netinet/in.h>
165 #include <afs/venus.h>
166 #if __STDC__
167 /* On SunOS 4, afs/vice.h defines this to rely on a pre-ANSI cpp. */
168 #undef _VICEIOCTL
169 #define _VICEIOCTL(id) ((unsigned int ) _IOW('V', id, struct ViceIoctl))
170 #endif
171 #ifndef _IOW
172 /* AFS on Solaris 2.3 doesn't get this definition. */
173 #include <sys/ioccom.h>
174 #endif
176 static int
177 in_afs (path)
178 char *path;
180 static char space[2048];
181 struct ViceIoctl vi;
183 vi.in_size = 0;
184 vi.out_size = sizeof (space);
185 vi.out = space;
187 if (pioctl (path, VIOC_FILE_CELL_NAME, &vi, 1)
188 && (errno == EINVAL || errno == ENOENT))
189 return 0;
190 return 1;
192 #endif /* AFS */
194 /* Nonzero if the current filesystem's type is known. */
195 static int fstype_known = 0;
197 /* Return a static string naming the type of filesystem that the file PATH,
198 described by STATP, is on.
199 RELPATH is the file name relative to the current directory.
200 Return "unknown" if its filesystem type is unknown. */
202 char *
203 filesystem_type (char *path, char *relpath, struct stat *statp)
205 static char *current_fstype = NULL;
206 static dev_t current_dev;
208 if (current_fstype != NULL)
210 if (fstype_known && statp->st_dev == current_dev)
211 return current_fstype; /* Cached value. */
212 free (current_fstype);
214 current_dev = statp->st_dev;
215 current_fstype = filesystem_type_uncached (path, relpath, statp);
216 return current_fstype;
219 /* Return a newly allocated string naming the type of filesystem that the
220 file PATH, described by STATP, is on.
221 RELPATH is the file name relative to the current directory.
222 Return "unknown" if its filesystem type is unknown. */
224 static char *
225 filesystem_type_uncached (char *path, char *relpath, struct stat *statp)
227 char *type = NULL;
229 #ifdef FSTYPE_MNTENT /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
230 char *table = MOUNTED;
231 FILE *mfp;
232 struct mntent *mnt;
234 mfp = setmntent (table, "r");
235 if (mfp == NULL)
236 error (1, errno, "%s", table);
238 /* Find the entry with the same device number as STATP, and return
239 that entry's fstype. */
240 while (type == NULL && (mnt = getmntent (mfp)))
242 char *devopt;
243 dev_t dev;
244 struct stat disk_stats;
246 #ifdef MNTTYPE_IGNORE
247 if (!strcmp (mnt->mnt_type, MNTTYPE_IGNORE))
248 continue;
249 #endif
251 /* Newer systems like SunOS 4.1 keep the dev number in the mtab,
252 in the options string. For older systems, we need to stat the
253 directory that the filesystem is mounted on to get it.
255 Unfortunately, the HPUX 9.x mnttab entries created by automountq
256 contain a dev= option but the option value does not match the
257 st_dev value of the file (maybe the lower 16 bits match?). */
259 #if !defined(hpux) && !defined(__hpux__)
260 devopt = strstr (mnt->mnt_opts, "dev=");
261 if (devopt)
263 if (devopt[4] == '0' && (devopt[5] == 'x' || devopt[5] == 'X'))
264 dev = xatoi (devopt + 6);
265 else
266 dev = xatoi (devopt + 4);
268 else
269 #endif /* not hpux */
271 if (stat (mnt->mnt_dir, &disk_stats) == -1) {
272 if (errno == EACCES)
273 continue;
274 else
275 error (1, errno, _("error in %s: %s"), table, mnt->mnt_dir);
277 dev = disk_stats.st_dev;
280 if (dev == statp->st_dev)
281 type = mnt->mnt_type;
284 if (endmntent (mfp) == 0)
285 error (0, errno, "%s", table);
286 #endif
288 #ifdef FSTYPE_GETMNT /* Ultrix. */
289 int offset = 0;
290 struct fs_data fsd;
292 while (type == NULL
293 && getmnt (&offset, &fsd, sizeof (fsd), NOSTAT_MANY, 0) > 0)
295 if (fsd.fd_req.dev == statp->st_dev)
296 type = gt_names[fsd.fd_req.fstype];
298 #endif
300 #ifdef FSTYPE_USG_STATFS /* SVR3. */
301 struct statfs fss;
302 char typebuf[FSTYPSZ];
304 if (statfs (relpath, &fss, sizeof (struct statfs), 0) == -1)
306 /* Don't die if a file was just removed. */
307 if (errno != ENOENT)
308 error (1, errno, "%s", path);
310 else if (!sysfs (GETFSTYP, fss.f_fstyp, typebuf))
311 type = typebuf;
312 #endif
314 #ifdef FSTYPE_STATVFS /* SVR4. */
315 struct statvfs fss;
317 if (statvfs (relpath, &fss) == -1)
319 /* Don't die if a file was just removed. */
320 if (errno != ENOENT)
321 error (1, errno, "%s", path);
323 else
324 type = fss.f_basetype;
325 #endif
327 #ifdef FSTYPE_STATFS /* 4.4BSD. */
328 struct statfs fss;
329 char *p;
331 if (S_ISLNK (statp->st_mode))
332 p = dirname (relpath);
333 else
334 p = relpath;
336 if (statfs (p, &fss) == -1)
338 /* Don't die if symlink to nonexisting file, or a file that was
339 just removed. */
340 if (errno != ENOENT)
341 error (1, errno, "%s", path);
343 else
345 #ifdef HAVE_F_FSTYPENAME_IN_STATFS
346 type = xstrdup (fss.f_fstypename);
347 #else
348 type = fstype_to_string (fss.f_type);
349 #endif
351 if (p != relpath)
352 free (p);
353 #endif
355 #ifdef AFS
356 if ((!type || !strcmp (type, "xx")) && in_afs (relpath))
357 type = "afs";
358 #endif
360 /* An unknown value can be caused by an ENOENT error condition.
361 Don't cache those values. */
362 fstype_known = (type != NULL);
364 return xstrdup (type ? type : _("unknown"));
367 #ifdef FSTYPE_MNTENT /* 4.3BSD etc. */
368 /* Return the value of the hexadecimal number represented by CP.
369 No prefix (like '0x') or suffix (like 'h') is expected to be
370 part of CP. */
372 static int
373 xatoi (char *cp)
375 int val;
377 val = 0;
378 while (*cp)
380 if (*cp >= 'a' && *cp <= 'f')
381 val = val * 16 + *cp - 'a' + 10;
382 else if (*cp >= 'A' && *cp <= 'F')
383 val = val * 16 + *cp - 'A' + 10;
384 else if (*cp >= '0' && *cp <= '9')
385 val = val * 16 + *cp - '0';
386 else
387 break;
388 cp++;
390 return val;
392 #endif