ftp://ftp.redhat.com/pub/redhat/linux/rawhide/SRPMS/SRPMS/gnome-vfs2-2.3.8-1.src.rpm
[gnome-vfs-httpcaptive.git] / modules / fstype.c
1 /* fstype.c -- determine type of filesystems that files are on
2    Copyright (C) 1990, 91, 92, 93, 94 Free Software Foundation, Inc.
3
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.
8
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.
13
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.  */
17
18 /* This code was relicensed by the FSF on May 1 2002
19  
20    This file is free software; you can redistribute it and/or
21    modify it under the terms of the GNU Library General Public License as
22    published by the Free Software Foundation; either version 2 of the
23    License, or (at your option) any later version.
24
25    this file is distributed in the hope that it will be useful,
26    but WITHOUT ANY WARRANTY; without even the implied warranty of
27    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
28    Library General Public License for more details.
29
30    You should have received a copy of the GNU Library General Public
31    License along with the Gnome Library; see the file COPYING.LIB.  If not,
32    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
33    Boston, MA 02111-1307, USA.
34  */
35 /* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
36
37 #include <config.h>
38 #include <stdio.h>
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 #include <errno.h>
42 #ifdef STDC_HEADERS
43 #include <stdlib.h>
44 #else
45 extern int errno;
46 #endif
47 #include <string.h>
48 #include <glib.h>
49
50 #if __STDC__
51 # define P_(s) s
52 #else
53 # define P_(s) ()
54 #endif
55
56 static char *filesystem_type_uncached P_((char *path, char *relpath, struct stat *statp));
57
58 void fstype_internal_error (int level, int num, char const *fmt, ...);
59
60 #ifdef FSTYPE_MNTENT            /* 4.3BSD etc.  */
61 static int xatoi P_((char *cp));
62 #endif
63
64 #ifdef FSTYPE_MNTENT            /* 4.3BSD, SunOS, HP-UX, Dynix, Irix.  */
65 #include <mntent.h>
66 #if !defined(MOUNTED)
67 # if defined(MNT_MNTTAB)        /* HP-UX.  */
68 #  define MOUNTED MNT_MNTTAB
69 # endif
70 # if defined(MNTTABNAME)        /* Dynix.  */
71 #  define MOUNTED MNTTABNAME
72 # endif
73 #endif
74 #endif
75
76 #ifdef FSTYPE_GETMNT            /* Ultrix.  */
77 #include <sys/param.h>
78 #include <sys/mount.h>
79 #include <sys/fs_types.h>
80 #endif
81
82 #ifdef FSTYPE_USG_STATFS        /* SVR3.  */
83 #include <sys/statfs.h>
84 #include <sys/fstyp.h>
85 #endif
86
87 #ifdef FSTYPE_STATVFS           /* SVR4.  */
88 #include <sys/statvfs.h>
89 #include <sys/fstyp.h>
90 #endif
91
92 #ifdef FSTYPE_STATFS            /* 4.4BSD.  */
93 #include <sys/param.h>          /* NetBSD needs this.  */
94 #include <sys/mount.h>
95
96 #ifndef MFSNAMELEN              /* NetBSD defines this.  */
97 static char *
98 fstype_to_string (t)
99      short t;
100 {
101 #ifdef INITMOUNTNAMES           /* Defined in 4.4BSD, not in NET/2.  */
102   static char *mn[] = INITMOUNTNAMES;
103   if (t >= 0 && t <= MOUNT_MAXTYPE)
104     return mn[t];
105   else
106     return "?";
107 #else /* !INITMOUNTNAMES */
108   switch (t)
109     {
110     case MOUNT_UFS:
111       return "ufs";
112     case MOUNT_NFS:
113       return "nfs";
114 #ifdef MOUNT_PC
115     case MOUNT_PC:
116       return "pc";
117 #endif
118 #ifdef MOUNT_MFS
119     case MOUNT_MFS:
120       return "mfs";
121 #endif
122 #ifdef MOUNT_LO
123     case MOUNT_LO:
124       return "lofs";
125 #endif
126 #ifdef MOUNT_TFS
127     case MOUNT_TFS:
128       return "tfs";
129 #endif
130 #ifdef MOUNT_TMP
131     case MOUNT_TMP:
132       return "tmp";
133 #endif
134 #ifdef MOUNT_MSDOS
135     case MOUNT_MSDOS:
136       return "msdos";
137 #endif
138 #ifdef MOUNT_ISO9660
139     case MOUNT_ISO9660:
140       return "iso9660fs";
141 #endif
142     default:
143       return "?";
144     }
145 #endif /* !INITMOUNTNAMES */
146 }
147 #endif /* !MFSNAMELEN */
148 #endif /* FSTYPE_STATFS */
149
150 #ifdef FSTYPE_AIX_STATFS        /* AIX.  */
151 #include <sys/vmount.h>
152 #include <sys/statfs.h>
153
154 #define FSTYPE_STATFS           /* Otherwise like 4.4BSD.  */
155 #define f_type f_vfstype
156
157 static char *
158 fstype_to_string (t)
159      short t;
160 {
161   switch (t)
162     {
163     case MNT_AIX:
164 #if 0                           /* NFS filesystems are actually MNT_AIX. */
165       return "aix";
166 #endif
167     case MNT_NFS:
168       return "nfs";
169     case MNT_JFS:
170       return "jfs";
171     case MNT_CDROM:
172       return "cdrom";
173     default:
174       return "?";
175     }
176 }
177 #endif /* FSTYPE_AIX_STATFS */
178
179 #ifdef AFS
180 #include <netinet/in.h>
181 #include <afs/venus.h>
182 #if __STDC__
183 /* On SunOS 4, afs/vice.h defines this to rely on a pre-ANSI cpp.  */
184 #undef _VICEIOCTL
185 #define _VICEIOCTL(id)  ((unsigned int ) _IOW('V', id, struct ViceIoctl))
186 #endif
187 #ifndef _IOW
188 /* AFS on Solaris 2.3 doesn't get this definition.  */
189 #include <sys/ioccom.h>
190 #endif
191
192 static int
193 in_afs (path)
194      char *path;
195 {
196   static char space[2048];
197   struct ViceIoctl vi;
198
199   vi.in_size = 0;
200   vi.out_size = sizeof (space);
201   vi.out = space;
202
203   if (pioctl (path, VIOC_FILE_CELL_NAME, &vi, 1)
204       && (errno == EINVAL || errno == ENOENT))
205         return 0;
206   return 1;
207 }
208 #endif /* AFS */
209
210 /* Nonzero if the current filesystem's type is known.  */
211 static int fstype_known = 0;
212
213 char *filesystem_type (char *path, char *relpath, struct stat *statp);
214 /* Return a static string naming the type of filesystem that the file PATH,
215    described by STATP, is on.
216    RELPATH is the file name relative to the current directory.
217    Return "unknown" if its filesystem type is unknown.  */
218
219 char *
220 filesystem_type (path, relpath, statp)
221      char *path;
222      char *relpath;
223      struct stat *statp;
224 {
225   static char *current_fstype = NULL;
226   static dev_t current_dev;
227
228   if (current_fstype != NULL)
229     {
230       if (fstype_known && statp->st_dev == current_dev)
231         return current_fstype;  /* Cached value.  */
232       g_free (current_fstype);
233     }
234   current_dev = statp->st_dev;
235   current_fstype = filesystem_type_uncached (path, relpath, statp);
236   return current_fstype;
237 }
238
239 void
240 fstype_internal_error (int level, int num, char const *fmt, ...)
241 {
242 }
243
244 /* Return a newly allocated string naming the type of filesystem that the
245    file PATH, described by STATP, is on.
246    RELPATH is the file name relative to the current directory.
247    Return "unknown" if its filesystem type is unknown.  */
248
249 static char *
250 filesystem_type_uncached (path, relpath, statp)
251      char *path;
252      char *relpath;
253      struct stat *statp;
254 {
255   char *type = NULL;
256
257 #ifdef FSTYPE_MNTENT            /* 4.3BSD, SunOS, HP-UX, Dynix, Irix.  */
258   char *table = MOUNTED;
259   FILE *mfp;
260   struct mntent *mnt;
261
262   mfp = setmntent (table, "r");
263   if (mfp == NULL) {
264     fstype_internal_error (1, errno, "%s", table);
265     goto no_mtab;
266   }
267
268   /* Find the entry with the same device number as STATP, and return
269      that entry's fstype. */
270   while (type == NULL && (mnt = getmntent (mfp)))
271     {
272       char *devopt;
273       dev_t dev;
274       struct stat disk_stats;
275
276 #ifdef MNTTYPE_IGNORE
277       if (!strcmp (mnt->mnt_type, MNTTYPE_IGNORE))
278         continue;
279 #endif
280
281       /* Newer systems like SunOS 4.1 keep the dev number in the mtab,
282          in the options string.  For older systems, we need to stat the
283          directory that the filesystem is mounted on to get it.
284
285          Unfortunately, the HPUX 9.x mnttab entries created by automountq
286          contain a dev= option but the option value does not match the
287          st_dev value of the file (maybe the lower 16 bits match?).  */
288
289 #if !defined(hpux) && !defined(__hpux__)
290       devopt = strstr (mnt->mnt_opts, "dev=");
291       if (devopt)
292         {
293           if (devopt[4] == '0' && (devopt[5] == 'x' || devopt[5] == 'X'))
294             dev = xatoi (devopt + 6);
295           else
296             dev = xatoi (devopt + 4);
297         }
298       else
299 #endif /* not hpux */
300         {
301           if (stat (mnt->mnt_dir, &disk_stats) == -1) {
302             if (errno == EACCES)
303               continue;
304             else
305               fstype_internal_error (1, errno, "error in %s: %s", table, mnt->mnt_dir);
306           }
307           dev = disk_stats.st_dev;
308         }
309
310       if (dev == statp->st_dev)
311         type = mnt->mnt_type;
312     }
313
314   if (endmntent (mfp) == 0)
315     fstype_internal_error (0, errno, "%s", table);
316  no_mtab:
317 #endif
318
319 #ifdef FSTYPE_GETMNT            /* Ultrix.  */
320   int offset = 0;
321   struct fs_data fsd;
322
323   while (type == NULL
324          && getmnt (&offset, &fsd, sizeof (fsd), NOSTAT_MANY, 0) > 0)
325     {
326       if (fsd.fd_req.dev == statp->st_dev)
327         type = gt_names[fsd.fd_req.fstype];
328     }
329 #endif
330
331 #ifdef FSTYPE_USG_STATFS        /* SVR3.  */
332   struct statfs fss;
333   char typebuf[FSTYPSZ];
334
335   if (statfs (relpath, &fss, sizeof (struct statfs), 0) == -1)
336     {
337       /* Don't die if a file was just removed. */
338       if (errno != ENOENT)
339         fstype_internal_error (1, errno, "%s", path);
340     }
341   else if (!sysfs (GETFSTYP, fss.f_fstyp, typebuf))
342     type = typebuf;
343 #endif
344
345 #ifdef FSTYPE_STATVFS           /* SVR4.  */
346   struct statvfs fss;
347
348   if (statvfs (relpath, &fss) == -1)
349     {
350       /* Don't die if a file was just removed. */
351       if (errno != ENOENT)
352         fstype_internal_error (1, errno, "%s", path);
353     }
354   else
355     type = fss.f_basetype;
356 #endif
357
358 #ifdef FSTYPE_STATFS            /* 4.4BSD.  */
359   struct statfs fss;
360   char *p;
361
362   if (S_ISLNK (statp->st_mode))
363     p = dirname (relpath);
364   else
365     p = relpath;
366
367   if (statfs (p, &fss) == -1)
368     {
369       /* Don't die if symlink to nonexisting file, or a file that was
370          just removed. */
371       if (errno != ENOENT)
372         fstype_internal_error (1, errno, "%s", path);
373     }
374   else
375     {
376 #ifdef MFSNAMELEN               /* NetBSD.  */
377       type = fss.f_fstypename;
378 #else
379       type = fstype_to_string (fss.f_type);
380 #endif
381     }
382   if (p != relpath)
383     free (p);
384 #endif
385
386 #ifdef AFS
387   if ((!type || !strcmp (type, "xx")) && in_afs (relpath))
388     type = "afs";
389 #endif
390
391   /* An unknown value can be caused by an ENOENT error condition.
392      Don't cache those values.  */
393   fstype_known = (type != NULL);
394
395   return g_strdup (type ? type : "unknown");
396 }
397
398 #ifdef FSTYPE_MNTENT            /* 4.3BSD etc.  */
399 /* Return the value of the hexadecimal number represented by CP.
400    No prefix (like '0x') or suffix (like 'h') is expected to be
401    part of CP. */
402
403 static int
404 xatoi (cp)
405      char *cp;
406 {
407   int val;
408   
409   val = 0;
410   while (*cp)
411     {
412       if (*cp >= 'a' && *cp <= 'f')
413         val = val * 16 + *cp - 'a' + 10;
414       else if (*cp >= 'A' && *cp <= 'F')
415         val = val * 16 + *cp - 'A' + 10;
416       else if (*cp >= '0' && *cp <= '9')
417         val = val * 16 + *cp - '0';
418       else
419         break;
420       cp++;
421     }
422   return val;
423 }
424 #endif