*** empty log message ***
[findutils.git] / find / fstype.c
blobcd32eaf06efaa4f3608fe5c8ac36ad551e137f6a
1 /* fstype.c -- determine type of filesystems that files are on
2 Copyright (C) 1990, 91, 92, 93, 94, 2000 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 "defs.h"
22 #include "dirname.h"
23 #include "modetype.h"
24 #include <errno.h>
25 #ifdef STDC_HEADERS
26 #include <stdlib.h>
27 #else
28 extern int errno;
29 #endif
31 #if ENABLE_NLS
32 # include <libintl.h>
33 # define _(Text) gettext (Text)
34 #else
35 # define _(Text) Text
36 #endif
37 #ifdef gettext_noop
38 # define N_(String) gettext_noop (String)
39 #else
40 # define N_(String) (String)
41 #endif
43 static char *filesystem_type_uncached PARAMS((char *path, char *relpath, struct stat *statp));
45 #ifdef FSTYPE_MNTENT /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
46 #include <mntent.h>
47 #if !defined(MOUNTED)
48 # if defined(MNT_MNTTAB) /* HP-UX. */
49 # define MOUNTED MNT_MNTTAB
50 # endif
51 # if defined(MNTTABNAME) /* Dynix. */
52 # define MOUNTED MNTTABNAME
53 # endif
54 #endif
55 #endif
57 #ifdef FSTYPE_GETMNT /* Ultrix. */
58 #include <sys/param.h>
59 #include <sys/mount.h>
60 #include <sys/fs_types.h>
61 #endif
63 #ifdef FSTYPE_USG_STATFS /* SVR3. */
64 #include <sys/statfs.h>
65 #include <sys/fstyp.h>
66 #endif
68 #ifdef FSTYPE_STATVFS /* SVR4. */
69 #include <sys/statvfs.h>
70 #include <sys/fstyp.h>
71 #endif
73 #ifdef FSTYPE_STATFS /* 4.4BSD. */
74 #include <sys/param.h> /* NetBSD needs this. */
75 #include <sys/mount.h>
77 #ifndef MFSNAMELEN /* NetBSD defines this. */
78 static char *
79 fstype_to_string (t)
80 short t;
82 #ifdef INITMOUNTNAMES /* Defined in 4.4BSD, not in NET/2. */
83 static char *mn[] = INITMOUNTNAMES;
84 if (t >= 0 && t <= MOUNT_MAXTYPE)
85 return mn[t];
86 else
87 return "?";
88 #else /* !INITMOUNTNAMES */
89 switch (t)
91 case MOUNT_UFS:
92 return "ufs";
93 case MOUNT_NFS:
94 return "nfs";
95 #ifdef MOUNT_PC
96 case MOUNT_PC:
97 return "pc";
98 #endif
99 #ifdef MOUNT_MFS
100 case MOUNT_MFS:
101 return "mfs";
102 #endif
103 #ifdef MOUNT_LO
104 case MOUNT_LO:
105 return "lofs";
106 #endif
107 #ifdef MOUNT_TFS
108 case MOUNT_TFS:
109 return "tfs";
110 #endif
111 #ifdef MOUNT_TMP
112 case MOUNT_TMP:
113 return "tmp";
114 #endif
115 #ifdef MOUNT_MSDOS
116 case MOUNT_MSDOS:
117 return "msdos";
118 #endif
119 #ifdef MOUNT_ISO9660
120 case MOUNT_ISO9660:
121 return "iso9660fs";
122 #endif
123 default:
124 return "?";
126 #endif /* !INITMOUNTNAMES */
128 #endif /* !MFSNAMELEN */
129 #endif /* FSTYPE_STATFS */
131 #ifdef FSTYPE_AIX_STATFS /* AIX. */
132 #include <sys/vmount.h>
133 #include <sys/statfs.h>
135 #define FSTYPE_STATFS /* Otherwise like 4.4BSD. */
136 #define f_type f_vfstype
138 static char *
139 fstype_to_string (t)
140 short t;
142 switch (t)
144 case MNT_AIX:
145 #if 0 /* NFS filesystems are actually MNT_AIX. */
146 return "aix";
147 #endif
148 case MNT_NFS:
149 return "nfs";
150 case MNT_JFS:
151 return "jfs";
152 case MNT_CDROM:
153 return "cdrom";
154 default:
155 return "?";
158 #endif /* FSTYPE_AIX_STATFS */
160 #ifdef AFS
161 #include <netinet/in.h>
162 #include <afs/venus.h>
163 #if __STDC__
164 /* On SunOS 4, afs/vice.h defines this to rely on a pre-ANSI cpp. */
165 #undef _VICEIOCTL
166 #define _VICEIOCTL(id) ((unsigned int ) _IOW('V', id, struct ViceIoctl))
167 #endif
168 #ifndef _IOW
169 /* AFS on Solaris 2.3 doesn't get this definition. */
170 #include <sys/ioccom.h>
171 #endif
173 static int
174 in_afs (path)
175 char *path;
177 static char space[2048];
178 struct ViceIoctl vi;
180 vi.in_size = 0;
181 vi.out_size = sizeof (space);
182 vi.out = space;
184 if (pioctl (path, VIOC_FILE_CELL_NAME, &vi, 1)
185 && (errno == EINVAL || errno == ENOENT))
186 return 0;
187 return 1;
189 #endif /* AFS */
191 /* Nonzero if the current filesystem's type is known. */
192 static int fstype_known = 0;
194 /* Return a static string naming the type of filesystem that the file PATH,
195 described by STATP, is on.
196 RELPATH is the file name relative to the current directory.
197 Return "unknown" if its filesystem type is unknown. */
199 char *
200 filesystem_type (char *path, char *relpath, struct stat *statp)
202 static char *current_fstype = NULL;
203 static dev_t current_dev;
205 if (current_fstype != NULL)
207 if (fstype_known && statp->st_dev == current_dev)
208 return current_fstype; /* Cached value. */
209 free (current_fstype);
211 current_dev = statp->st_dev;
212 current_fstype = filesystem_type_uncached (path, relpath, statp);
213 return current_fstype;
216 /* Return a newly allocated string naming the type of filesystem that the
217 file PATH, described by STATP, is on.
218 RELPATH is the file name relative to the current directory.
219 Return "unknown" if its filesystem type is unknown. */
221 static char *
222 filesystem_type_uncached (char *path, char *relpath, 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 uintmax_t u = 0;
261 devopt += 4;
262 if (devopt[0] == '0' && (devopt[1] == 'x' || devopt[1] == 'X'))
263 devopt += 2;
264 xstrtoumax (devopt, NULL, 16, &u, NULL);
265 dev = u;
267 else
268 #endif /* not hpux */
270 if (stat (mnt->mnt_dir, &disk_stats) == -1) {
271 if (errno == EACCES)
272 continue;
273 else
274 error (1, errno, _("error in %s: %s"), table, mnt->mnt_dir);
276 dev = disk_stats.st_dev;
279 if (dev == statp->st_dev)
280 type = mnt->mnt_type;
283 if (endmntent (mfp) == 0)
284 error (0, errno, "%s", table);
285 #endif
287 #ifdef FSTYPE_GETMNT /* Ultrix. */
288 int offset = 0;
289 struct fs_data fsd;
291 while (type == NULL
292 && getmnt (&offset, &fsd, sizeof (fsd), NOSTAT_MANY, 0) > 0)
294 if (fsd.fd_req.dev == statp->st_dev)
295 type = gt_names[fsd.fd_req.fstype];
297 #endif
299 #ifdef FSTYPE_USG_STATFS /* SVR3. */
300 struct statfs fss;
301 char typebuf[FSTYPSZ];
303 if (statfs (relpath, &fss, sizeof (struct statfs), 0) == -1)
305 /* Don't die if a file was just removed. */
306 if (errno != ENOENT)
307 error (1, errno, "%s", path);
309 else if (!sysfs (GETFSTYP, fss.f_fstyp, typebuf))
310 type = typebuf;
311 #endif
313 #ifdef FSTYPE_STATVFS /* SVR4. */
314 struct statvfs fss;
316 if (statvfs (relpath, &fss) == -1)
318 /* Don't die if a file was just removed. */
319 if (errno != ENOENT)
320 error (1, errno, "%s", path);
322 else
323 type = fss.f_basetype;
324 #endif
326 #ifdef FSTYPE_STATFS /* 4.4BSD. */
327 struct statfs fss;
328 char *p;
330 if (S_ISLNK (statp->st_mode))
331 p = dirname (relpath);
332 else
333 p = relpath;
335 if (statfs (p, &fss) == -1)
337 /* Don't die if symlink to nonexisting file, or a file that was
338 just removed. */
339 if (errno != ENOENT)
340 error (1, errno, "%s", path);
342 else
344 #ifdef HAVE_F_FSTYPENAME_IN_STATFS
345 type = xstrdup (fss.f_fstypename);
346 #else
347 type = fstype_to_string (fss.f_type);
348 #endif
350 if (p != relpath)
351 free (p);
352 #endif
354 #ifdef AFS
355 if ((!type || !strcmp (type, "xx")) && in_afs (relpath))
356 type = "afs";
357 #endif
359 /* An unknown value can be caused by an ENOENT error condition.
360 Don't cache those values. */
361 fstype_known = (type != NULL);
363 return xstrdup (type ? type : _("unknown"));