]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/findlib/fstype.c
5e92fb8ea5ed19da33daa4293d07c94ca326a570
[bacula/bacula] / bacula / src / findlib / fstype.c
1 /*
2    Bacula(R) - The Network Backup Solution
3
4    Copyright (C) 2000-2015 Kern Sibbald
5    Copyright (C) 2004-2014 Free Software Foundation Europe e.V.
6
7    The original author of Bacula is Kern Sibbald, with contributions
8    from many others, a complete list can be found in the file AUTHORS.
9
10    You may use this file and others of this release according to the
11    license defined in the LICENSE file, which includes the Affero General
12    Public License, v3.0 ("AGPLv3") and some additional permissions and
13    terms pursuant to its AGPLv3 Section 7.
14
15    This notice must be preserved when any source code is 
16    conveyed and/or propagated.
17
18    Bacula(R) is a registered trademark of Kern Sibbald.
19 */
20 /*
21  *  Implement routines to determine file system types.
22  *
23  *   Written by Preben 'Peppe' Guldberg, December MMIV
24  *   Updated by Kern Sibbald, April MMXV
25  */
26
27
28 #ifndef TEST_PROGRAM
29
30 #include "bacula.h"
31 #include "find.h"
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #ifdef HAVE_SUN_OS
35   #include <sys/mnttab.h>
36 #endif
37 #else /* Set up for testing a stand alone program */
38
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #define bstrncpy           strncpy
43 #define Dmsg0(n,s)         fprintf(stderr, s)
44 #define Dmsg1(n,s,a1)      fprintf(stderr, s, a1)
45 #define Dmsg2(n,s,a1,a2)   fprintf(stderr, s, a1, a2)
46 #endif
47
48 #define is_rootfs(x) bstrcmp("rootfs", x)
49
50 #if defined(HAVE_GETMNTINFO) || defined(HAVE_GETMNTENT)
51 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
52 #endif
53
54 struct mtab_item {
55    rblink link;
56    uint64_t dev;
57    char fstype[1];
58 };
59
60 /* Compare two device types */
61 static int compare_mtab_items(void *item1, void *item2)
62 {
63    mtab_item *mtab1, *mtab2;
64    mtab1 = (mtab_item *)item1;
65    mtab2 = (mtab_item *)item2;
66    if (mtab1->dev < mtab2->dev) return -1;
67    if (mtab1->dev > mtab2->dev) return 1;
68    return 0;
69 }
70
71 void add_mtab_item(void *user_ctx, struct stat *st, const char *fstype,
72                       const char *mountpoint, const char *mntopts,
73                       const char *fsname)
74 {
75    rblist *mtab_list = (rblist *)user_ctx;
76    mtab_item *item, *ritem;
77    int len = strlen(fstype) + 1;
78    
79    item = (mtab_item *)malloc(sizeof(mtab_item) + len);
80    item->dev = (uint64_t)st->st_dev;
81    bstrncpy(item->fstype, fstype, len);
82    ritem = (mtab_item *)mtab_list->insert((void *)item, compare_mtab_items);
83    if (ritem != item) {
84       /* Item already inserted, so we discard this one */
85       free(item);
86    }
87 }
88
89
90 /*
91  * These functions should be implemented for each OS
92  *
93  *       bool fstype(FF_PKT *ff_pkt, char *fs, int fslen);
94  */
95 #if defined(HAVE_DARWIN_OS) \
96    || defined(HAVE_FREEBSD_OS ) \
97    || defined(HAVE_OPENBSD_OS)
98
99 #include <sys/param.h>
100 #include <sys/mount.h>
101
102 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
103 {
104    char *fname = ff_pkt->fname;
105    struct statfs st;
106  
107    if (statfs(fname, &st) == 0) {
108       bstrncpy(fs, st.f_fstypename, fslen);
109       return true;
110    }
111    Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
112    return false;
113 }
114 #elif defined(HAVE_NETBSD_OS)
115 #include <sys/param.h>
116 #include <sys/mount.h>
117 #ifdef HAVE_SYS_STATVFS_H
118 #include <sys/statvfs.h>
119 #else
120 #define statvfs statfs
121 #endif
122
123 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
124 {
125    char *fname = ff_pkt->fname;
126    struct statvfs st;
127    if (statvfs(fname, &st) == 0) {
128       bstrncpy(fs, st.f_fstypename, fslen);
129       return true;
130    }
131    Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
132    return false;
133 }
134 #elif defined(HAVE_HPUX_OS) \
135    || defined(HAVE_IRIX_OS)
136
137 #include <sys/types.h>
138 #include <sys/statvfs.h>
139
140 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
141 {
142    char *fname = ff_pkt->fname;
143    struct statvfs st;
144    if (statvfs(fname, &st) == 0) {
145       bstrncpy(fs, st.f_basetype, fslen);
146       return true;
147    }
148    Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
149    return false;
150 }
151
152 #elif defined(HAVE_LINUX_OS)
153
154 #include <sys/vfs.h>
155 #include <mntent.h>
156
157 /*
158  * Linux statfs() does not return the filesystem name type.  It
159  *  only returns a binary fstype, so we must look up the type name
160  *  in mtab.
161  */
162 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
163 {
164    char *fname = ff_pkt->fname;
165    struct statfs st;
166    const char *fstype;
167
168    if (statfs(fname, &st) == 0) {
169       mtab_item *item, search_item;
170       if (ff_pkt->last_fstypename && ff_pkt->last_fstype == (uint64_t)st.f_type) {
171          bstrncpy(fs, ff_pkt->last_fstypename, fslen);
172          return true; 
173       }
174       if (!ff_pkt->mtab_list) {
175          ff_pkt->mtab_list = New(rblist());
176          read_mtab(add_mtab_item, ff_pkt->mtab_list);
177       }
178       search_item.dev = st.f_type;
179       item = (mtab_item *)ff_pkt->mtab_list->search((void *)&search_item, compare_mtab_items);
180       if (item) {
181          ff_pkt->last_fstype = st.f_type;
182          bstrncpy(ff_pkt->last_fstypename, item->fstype, sizeof(ff_pkt->last_fstype));
183          bstrncpy(fs, ff_pkt->last_fstypename, fslen);
184          return true;
185       }
186       /*
187        * Values obtained from statfs(2), testing and
188        *
189        *    $ grep -r SUPER_MAGIC /usr/include/linux
190        */
191       switch (st.f_type) {
192       /* Known good values */
193       /* ext2, ext3, and ext4 have the same code */
194       case 0xef53:         fstype = "ext2"; break;          /* EXT2_SUPER_MAGIC */
195       case 0x3153464a:     fstype = "jfs"; break;           /* JFS_SUPER_MAGIC */
196       case 0x5346544e:     fstype = "ntfs"; break;          /* NTFS_SB_MAGIC */
197       case 0x9fa0:         fstype = "proc"; break;          /* PROC_SUPER_MAGIC */
198       case 0x52654973:     fstype = "reiserfs"; break;      /* REISERFS_SUPER_MAGIC */
199       case 0x58465342:     fstype = "xfs"; break;           /* XFS_SB_MAGIC */
200       case 0x9fa2:         fstype = "usbdevfs"; break;      /* USBDEVICE_SUPER_MAGIC */
201       case 0x62656572:     fstype = "sysfs"; break;         /* SYSFS_MAGIC */
202       case 0x517B:         fstype = "smbfs"; break;         /* SMB_SUPER_MAGIC */
203       case 0x9660:         fstype = "iso9660"; break;       /* ISOFS_SUPER_MAGIC */
204       case 0xadf5:         fstype = "adfs"; break;          /* ADFS_SUPER_MAGIC */
205       case 0xadff:         fstype = "affs"; break;          /* AFFS_SUPER_MAGIC */
206       case 0x42465331:     fstype = "befs"; break;          /* BEFS_SUPER_MAGIC */
207       case 0xFF534D42:     fstype = "cifs"; break;          /* CIFS_MAGIC_NUMBER */
208       case 0x73757245:     fstype = "coda"; break;          /* CODA_SUPER_MAGIC */
209       case 0x012ff7b7:     fstype = "coherent"; break;      /* COH_SUPER_MAGIC */
210       case 0x28cd3d45:     fstype = "cramfs"; break;        /* CRAMFS_MAGIC */
211       case 0x1373:         fstype = "devfs"; break;         /* DEVFS_SUPER_MAGIC */
212       case 0x414A53:       fstype = "efs"; break;           /* EFS_SUPER_MAGIC */
213       case 0x137d:         fstype = "ext"; break;           /* EXT_SUPER_MAGIC */
214       case 0xef51:         fstype = "oldext2"; break;          /* EXT2_OLD_SUPER_MAGIC */
215       case 0x4244:         fstype = "hfs"; break;          /* EXT2_OLD_SUPER_MAGIC */
216       case 0xf995e849:     fstype = "hpfs"; break;          /* HPFS_SUPER_MAGIC */
217       case 0x958458f6:     fstype = "hugetlbfs"; break;     /* HUGETLBFS_MAGIC */
218       case 0x72b6:         fstype = "jffs2"; break;         /* JFFS2_SUPER_MAGIC */
219       case 0x2468:         fstype = "minix"; break;         /* MINIX2_SUPER_MAGIC */
220       case 0x2478:         fstype = "minix"; break;         /* MINIX2_SUPER_MAGIC2 */
221       case 0x137f:         fstype = "minix"; break;         /* MINIX_SUPER_MAGIC */
222       case 0x138f:         fstype = "minix"; break;         /* MINIX_SUPER_MAGIC2 */
223       case 0x4d44:         fstype = "msdos"; break;         /* MSDOS_SUPER_MAGIC */
224       case 0x564c:         fstype = "ncpfs"; break;         /* NCP_SUPER_MAGIC */
225       case 0x6969:         fstype = "nfs"; break;           /* NFS_SUPER_MAGIC */
226       case 0x9fa1:         fstype = "openpromfs"; break;    /* OPENPROM_SUPER_MAGIC */
227       case 0x002f:         fstype = "qnx4"; break;          /* QNX4_SUPER_MAGIC */
228       case 0x7275:         fstype = "romfs"; break;          /* QNX4_SUPER_MAGIC */
229       case 0x012ff7b6:     fstype = "sysv2"; break;
230       case 0x012ff7b5:     fstype = "sysv4"; break;
231       case 0x01021994:     fstype = "tempfs"; break;
232       case 0x15013346:     fstype = "udf"; break;
233       case 0x00011954:     fstype = "ufs"; break;
234       case 0xa501FCF5:     fstype = "vxfs"; break;
235       case 0x012FF7B4:     fstype = "xenix"; break;
236       case 0x012FD16D:     fstype = "xiafs"; break;
237
238
239 #if 0       /* These need confirmation */
240       case 0x6B414653:     fstype = "afs"; break;           /* AFS_FS_MAGIC */
241       case 0x0187:         fstype = "autofs"; break;        /* AUTOFS_SUPER_MAGIC */
242       case 0x62646576:     fstype = "bdev"; break;          /* ??? */
243       case 0x1BADFACE:     fstype = "bfs"; break;           /* BFS_MAGIC */
244       case 0x42494e4d:     fstype = "binfmt_misc"; break;   /* ??? */
245       case (('C'<<8)|'N'): fstype = "capifs"; break;        /* CAPIFS_SUPER_MAGIC */
246       case 0x1cd1:         fstype = "devpts"; break;        /* ??? */
247       case 0x03111965:     fstype = "eventpollfs"; break;   /* EVENTPOLLFS_MAGIC */
248       case 0xBAD1DEA:      fstype = "futexfs"; break;       /* ??? */
249       case 0xaee71ee7:     fstype = "gadgetfs"; break;      /* GADGETFS_MAGIC */
250       case 0x00c0ffee:     fstype = "hostfs"; break;        /* HOSTFS_SUPER_MAGIC */
251       case 0xb00000ee:     fstype = "hppfs"; break;         /* HPPFS_SUPER_MAGIC */
252       case 0x12061983:     fstype = "hwgfs"; break;         /* HWGFS_MAGIC */
253       case 0x66726f67:     fstype = "ibmasmfs"; break;      /* IBMASMFS_MAGIC */
254       case 0x19800202:     fstype = "mqueue"; break;        /* MQUEUE_MAGIC */
255       case 0x6f70726f:     fstype = "oprofilefs"; break;    /* OPROFILEFS_MAGIC */
256       case 0xa0b4d889:     fstype = "pfmfs"; break;         /* PFMFS_MAGIC */
257       case 0x50495045:     fstype = "pipfs"; break;         /* PIPEFS_MAGIC */
258       case 0x858458f6:     fstype = "ramfs"; break;         /* RAMFS_MAGIC */
259       case 0x7275:         fstype = "romfs"; break;         /* ROMFS_MAGIC */
260       case 0x858458f6:     fstype = "rootfs"; break;        /* RAMFS_MAGIC */
261       case 0x67596969:     fstype = "rpc_pipefs"; break;    /* RPCAUTH_GSSMAGIC */
262       case 0x534F434B:     fstype = "sockfs"; break;        /* SOCKFS_MAGIC */
263       case 0x858458f6:     fstype = "tmpfs"; break;         /* RAMFS_MAGIC */
264       case 0x01021994:     fstype = "tmpfs"; break;         /* TMPFS_MAGIC */
265 #endif
266
267       default:
268          Dmsg2(10, "Unknown file system type \"0x%x\" for \"%s\".\n", st.f_type,
269                fname);
270          return false;
271       }
272       ff_pkt->last_fstype = st.f_type;
273       bstrncpy(ff_pkt->last_fstypename, fstype, sizeof(ff_pkt->last_fstypename));
274       bstrncpy(fs, fstype, fslen);
275       return true;
276    }
277    Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
278    return false;
279 }
280
281 #elif defined(HAVE_SUN_OS)
282
283 #include <sys/types.h>
284 #include <sys/stat.h>
285
286 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
287 {
288    /* Solaris has the filesystem type name in the lstat packet */
289    bstrncpy(fs, ff_pkt->statp.st_fstype, fslen);
290    return true;
291 }
292  
293 #elif defined (__digital__) && defined (__unix__)  /* Tru64 */
294 /* Tru64 */
295 #include <sys/stat.h>
296 #include <sys/mount.h>
297
298 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
299 {
300    char *fname = ff_pkt->fname;
301    struct statfs st;
302    if (statfs((char *)fname, &st) == 0) {
303       switch (st.f_type) {
304       /* Known good values */
305       case 0xa:         bstrncpy(fs, "advfs", fslen); return true;        /* Tru64 AdvFS */
306       case 0xe:         bstrncpy(fs, "nfs", fslen); return true;          /* Tru64 NFS   */
307       default:
308          Dmsg2(10, "Unknown file system type \"0x%x\" for \"%s\".\n", st.f_type,
309                fname);
310          return false;
311       }
312    }
313    Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
314    return false;
315 }
316 /* Tru64 */
317
318 #else    /* No recognised OS */
319
320 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
321 {
322    char *fname = ff_pkt->fname;
323    Dmsg0(10, "!!! fstype() not implemented for this OS. !!!\n");
324    return false;
325 }
326 #endif
327
328 /* Read mtab entries  */
329 bool read_mtab(mtab_handler_t *mtab_handler, void *user_ctx)
330
331 #ifdef HAVE_GETMNTENT
332    FILE *mntfp;
333    struct stat st;
334  
335 #ifdef HAVE_LINUX_OS
336    struct mntent *mnt;
337    P(mutex);
338    if ((mntfp = setmntent("/proc/mounts", "r")) == NULL) {
339       if ((mntfp = setmntent(_PATH_MOUNTED, "r")) == NULL) {
340          V(mutex);
341          return false;
342       }
343    } 
344    while ((mnt = getmntent(mntfp)) != NULL) {
345       if (is_rootfs(mnt->mnt_type)) {
346          continue;
347       }
348
349       if (stat(mnt->mnt_dir, &st) < 0) {
350          continue;
351       }
352       mtab_handler(user_ctx, &st, mnt->mnt_type, mnt->mnt_dir,
353          mnt->mnt_opts, mnt->mnt_fsname);
354    }
355    endmntent(mntfp);
356    V(mutex);
357 #endif
358
359 #ifdef HAVE_SUN_OS
360    struct mnttab mnt;
361
362    P(mutex);
363    if ((mntfp = fopen(MNTTAB, "r")) == NULL) {
364       V(mutex);
365       return false;
366    }
367
368    while (getmntent(mntfp, &mnt) == 0) {
369       if (is_rootfs(mnt.mnt_fstype)) {
370          continue;
371       }
372       if (stat(mnt.mnt_mountp, &st) < 0) {
373          continue;
374       }
375       mtab_handler(user_ctx, &st, mnt.mnt_fstype, mnt.mnt_mountp,
376          mnt.mnt_mntopts, mnt.mnt_special);
377    }
378    fclose(mntfp);
379    V(mutex);
380 #endif
381
382 #endif /* HAVE_GETMNTENT */
383
384 #ifdef HAVE_GETMNTINFO
385    struct stat st;
386 #if defined(ST_NOWAIT)
387    int flags = ST_NOWAIT;
388 #elif defined(MNT_NOWAIT)
389    int flags = MNT_NOWAIT;
390 #else
391    int flags = 0;
392 #endif
393 #if defined(HAVE_NETBSD_OS)
394    struct statvfs *mntinfo;
395 #else
396    struct statfs *mntinfo;
397 #endif
398    int nument;
399
400    P(mutex);
401    if ((nument = getmntinfo(&mntinfo, flags)) > 0) {
402       while (nument-- > 0) {
403          if (is_rootfs(mntinfo->f_fstypename)) {
404             continue;
405          }
406          if (stat(mntinfo->f_mntonname, &st) < 0) {
407             continue;
408          }
409          mtab_handler(user_ctx, &st, mntinfo->f_mntfromname,
410             mntinfo->f_mntonname, mntinfo->f_fstypename, NULL);
411          mntinfo++;
412       }
413    }
414    V(mutex);
415 #endif /* HAVE_GETMNTINFO */
416    return true;
417
418
419 #ifdef TEST_PROGRAM
420 int main(int argc, char **argv)
421 {
422    char *p;
423    char fs[1000];
424    int status = 0;
425
426    if (argc < 2) {
427       p = (argc < 1) ? "fstype" : argv[0];
428       printf("usage:\t%s path ...\n"
429             "\t%s prints the file system type and pathname of the paths.\n",
430             p, p);
431       return EXIT_FAILURE;
432    }
433    while (*++argv) {
434       if (!fstype(*argv, fs, sizeof(fs))) {
435          status = EXIT_FAILURE;
436       } else {
437          printf("%s\t%s\n", fs, *argv);
438       }
439    }
440    return status;
441 }
442 #endif