Savannah bug #4295 - implicit declarations of ctype.h functions
[findutils.git] / find / fstype.c
blobe123e893006e8ef4cd3f29f004b270576b1edc3b
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., 9 Temple Place - Suite 330, Boston, MA 02111-1307,
17 USA.
20 /* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
22 #include "defs.h"
24 #include "dirname.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 /* Need declaration of function `xstrtoumax' */
34 #include "xstrtol.h"
36 #if ENABLE_NLS
37 # include <libintl.h>
38 # define _(Text) gettext (Text)
39 #else
40 # define _(Text) Text
41 #endif
42 #ifdef gettext_noop
43 # define N_(String) gettext_noop (String)
44 #else
45 # define N_(String) (String)
46 #endif
48 static char *filesystem_type_uncached PARAMS((char *path, char *relpath, struct stat *statp));
50 #ifdef FSTYPE_MNTENT /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
51 #include <mntent.h>
52 #if !defined(MOUNTED)
53 # if defined(MNT_MNTTAB) /* HP-UX. */
54 # define MOUNTED MNT_MNTTAB
55 # endif
56 # if defined(MNTTABNAME) /* Dynix. */
57 # define MOUNTED MNTTABNAME
58 # endif
59 #endif
60 #endif
62 #ifdef FSTYPE_GETMNT /* Ultrix. */
63 #include <sys/param.h>
64 #include <sys/mount.h>
65 #include <sys/fs_types.h>
66 #endif
68 #ifdef FSTYPE_USG_STATFS /* SVR3. */
69 #include <sys/statfs.h>
70 #include <sys/fstyp.h>
71 #endif
73 #ifdef FSTYPE_STATVFS /* SVR4. */
74 #include <sys/statvfs.h>
75 #include <sys/fstyp.h>
76 #endif
78 #ifdef FSTYPE_STATFS /* 4.4BSD. */
79 #include <sys/param.h> /* NetBSD needs this. */
80 #include <sys/mount.h>
82 #ifndef HAVE_F_FSTYPENAME_IN_STATFS
83 #ifndef MFSNAMELEN /* NetBSD defines this. */
84 static char *
85 fstype_to_string (t)
86 short t;
88 #ifdef INITMOUNTNAMES /* Defined in 4.4BSD, not in NET/2. */
89 static char *mn[] = INITMOUNTNAMES;
90 if (t >= 0 && t <= MOUNT_MAXTYPE)
91 return mn[t];
92 else
93 return "?";
94 #else /* !INITMOUNTNAMES */
95 switch (t)
97 case MOUNT_UFS:
98 return "ufs";
99 case MOUNT_NFS:
100 return "nfs";
101 #ifdef MOUNT_PC
102 case MOUNT_PC:
103 return "pc";
104 #endif
105 #ifdef MOUNT_MFS
106 case MOUNT_MFS:
107 return "mfs";
108 #endif
109 #ifdef MOUNT_LO
110 case MOUNT_LO:
111 return "lofs";
112 #endif
113 #ifdef MOUNT_TFS
114 case MOUNT_TFS:
115 return "tfs";
116 #endif
117 #ifdef MOUNT_TMP
118 case MOUNT_TMP:
119 return "tmp";
120 #endif
121 #ifdef MOUNT_MSDOS
122 case MOUNT_MSDOS:
123 return "msdos";
124 #endif
125 #ifdef MOUNT_ISO9660
126 case MOUNT_ISO9660:
127 return "iso9660fs";
128 #endif
129 default:
130 return "?";
132 #endif /* !INITMOUNTNAMES */
134 #endif /* !MFSNAMELEN */
135 #endif /* !HAVE_F_FSTYPENAME_IN_STATFS */
136 #endif /* FSTYPE_STATFS */
138 #ifdef FSTYPE_AIX_STATFS /* AIX. */
139 #include <sys/vmount.h>
140 #include <sys/statfs.h>
142 #define FSTYPE_STATFS /* Otherwise like 4.4BSD. */
143 #define f_type f_vfstype
145 static char *
146 fstype_to_string (t)
147 short t;
149 switch (t)
151 case MNT_AIX:
152 #if 0 /* NFS filesystems are actually MNT_AIX. */
153 return "aix";
154 #endif
155 case MNT_NFS:
156 return "nfs";
157 case MNT_JFS:
158 return "jfs";
159 case MNT_CDROM:
160 return "cdrom";
161 default:
162 return "?";
165 #endif /* FSTYPE_AIX_STATFS */
167 #ifdef AFS
168 #include <netinet/in.h>
169 #include <afs/venus.h>
170 #if __STDC__
171 /* On SunOS 4, afs/vice.h defines this to rely on a pre-ANSI cpp. */
172 #undef _VICEIOCTL
173 #define _VICEIOCTL(id) ((unsigned int ) _IOW('V', id, struct ViceIoctl))
174 #endif
175 #ifndef _IOW
176 /* AFS on Solaris 2.3 doesn't get this definition. */
177 #include <sys/ioccom.h>
178 #endif
180 static int
181 in_afs (path)
182 char *path;
184 static char space[2048];
185 struct ViceIoctl vi;
187 vi.in_size = 0;
188 vi.out_size = sizeof (space);
189 vi.out = space;
191 if (pioctl (path, VIOC_FILE_CELL_NAME, &vi, 1)
192 && (errno == EINVAL || errno == ENOENT))
193 return 0;
194 return 1;
196 #endif /* AFS */
198 /* Nonzero if the current filesystem's type is known. */
199 static int fstype_known = 0;
201 /* Return a static string naming the type of filesystem that the file PATH,
202 described by STATP, is on.
203 RELPATH is the file name relative to the current directory.
204 Return "unknown" if its filesystem type is unknown. */
206 char *
207 filesystem_type (char *path, char *relpath, struct stat *statp)
209 static char *current_fstype = NULL;
210 static dev_t current_dev;
212 if (current_fstype != NULL)
214 if (fstype_known && statp->st_dev == current_dev)
215 return current_fstype; /* Cached value. */
216 free (current_fstype);
218 current_dev = statp->st_dev;
219 current_fstype = filesystem_type_uncached (path, relpath, statp);
220 return current_fstype;
223 /* Return a newly allocated string naming the type of filesystem that the
224 file PATH, described by STATP, is on.
225 RELPATH is the file name relative to the current directory.
226 Return "unknown" if its filesystem type is unknown. */
228 static char *
229 filesystem_type_uncached (char *path, char *relpath, struct stat *statp)
231 char *type = NULL;
233 #ifdef FSTYPE_MNTENT /* 4.3BSD, SunOS, HP-UX, Dynix, Irix. */
234 char *table = MOUNTED;
235 FILE *mfp;
236 struct mntent *mnt;
238 mfp = setmntent (table, "r");
239 if (mfp == NULL)
240 error (1, errno, "%s", table);
242 /* Find the entry with the same device number as STATP, and return
243 that entry's fstype. */
244 while (type == NULL && (mnt = getmntent (mfp)))
246 char *devopt;
247 dev_t dev;
248 struct stat disk_stats;
250 #ifdef MNTTYPE_IGNORE
251 if (!strcmp (mnt->mnt_type, MNTTYPE_IGNORE))
252 continue;
253 #endif
255 /* Newer systems like SunOS 4.1 keep the dev number in the mtab,
256 in the options string. For older systems, we need to stat the
257 directory that the filesystem is mounted on to get it.
259 Unfortunately, the HPUX 9.x mnttab entries created by automountq
260 contain a dev= option but the option value does not match the
261 st_dev value of the file (maybe the lower 16 bits match?). */
263 #if !defined(hpux) && !defined(__hpux__)
264 devopt = strstr (mnt->mnt_opts, "dev=");
265 if (devopt)
267 uintmax_t u = 0;
268 devopt += 4;
269 if (devopt[0] == '0' && (devopt[1] == 'x' || devopt[1] == 'X'))
270 devopt += 2;
271 xstrtoumax (devopt, NULL, 16, &u, NULL);
272 dev = u;
274 else
275 #endif /* not hpux */
277 if (stat (mnt->mnt_dir, &disk_stats) == -1) {
278 if (errno == EACCES)
279 continue;
280 else
281 error (1, errno, _("error in %s: %s"), table, mnt->mnt_dir);
283 dev = disk_stats.st_dev;
286 if (dev == statp->st_dev)
287 type = mnt->mnt_type;
290 if (endmntent (mfp) == 0)
291 error (0, errno, "%s", table);
292 #endif
294 #ifdef FSTYPE_GETMNT /* Ultrix. */
295 int offset = 0;
296 struct fs_data fsd;
298 while (type == NULL
299 && getmnt (&offset, &fsd, sizeof (fsd), NOSTAT_MANY, 0) > 0)
301 if (fsd.fd_req.dev == statp->st_dev)
302 type = gt_names[fsd.fd_req.fstype];
304 #endif
306 #ifdef FSTYPE_USG_STATFS /* SVR3. */
307 struct statfs fss;
308 char typebuf[FSTYPSZ];
310 if (statfs (relpath, &fss, sizeof (struct statfs), 0) == -1)
312 /* Don't die if a file was just removed. */
313 if (errno != ENOENT)
314 error (1, errno, "%s", path);
316 else if (!sysfs (GETFSTYP, fss.f_fstyp, typebuf))
317 type = typebuf;
318 #endif
320 #ifdef FSTYPE_STATVFS /* SVR4. */
321 struct statvfs fss;
323 if (statvfs (relpath, &fss) == -1)
325 /* Don't die if a file was just removed. */
326 if (errno != ENOENT)
327 error (1, errno, "%s", path);
329 else
330 type = fss.f_basetype;
331 #endif
333 #ifdef FSTYPE_STATFS /* 4.4BSD. */
334 struct statfs fss;
335 char *p;
337 if (S_ISLNK (statp->st_mode))
338 p = dir_name (relpath);
339 else
340 p = relpath;
342 if (statfs (p, &fss) == -1)
344 /* Don't die if symlink to nonexisting file, or a file that was
345 just removed. */
346 if (errno != ENOENT)
347 error (1, errno, "%s", path);
349 else
351 #ifdef HAVE_F_FSTYPENAME_IN_STATFS
352 type = xstrdup (fss.f_fstypename);
353 #else
354 type = fstype_to_string (fss.f_type);
355 #endif
357 if (p != relpath)
358 free (p);
359 #endif
361 #ifdef AFS
362 if ((!type || !strcmp (type, "xx")) && in_afs (relpath))
363 type = "afs";
364 #endif
366 /* An unknown value can be caused by an ENOENT error condition.
367 Don't cache those values. */
368 fstype_known = (type != NULL);
370 return xstrdup (type ? type : _("unknown"));