]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/findlib/fstype.c
Fix #1449 about a FileDaemon segfault with the fstype option
[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 /* Compare directly the FS from a fname with a string */
90 bool fstype_cmp(FF_PKT *ff_pkt, const char *fsname)
91 {
92    char buf[256];
93    if (fstype(ff_pkt, buf, sizeof(buf))) {
94       return (strcmp(buf, fsname) == 0);
95    }
96    return false;
97 }
98
99 /*
100  * These functions should be implemented for each OS
101  *
102  *       bool fstype(FF_PKT *ff_pkt, char *fs, int fslen);
103  */
104 #if defined(HAVE_DARWIN_OS) \
105    || defined(HAVE_FREEBSD_OS ) \
106    || defined(HAVE_OPENBSD_OS)
107
108 #include <sys/param.h>
109 #include <sys/mount.h>
110
111 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
112 {
113    char *fname = ff_pkt->fname;
114    struct statfs st;
115  
116    if (statfs(fname, &st) == 0) {
117       bstrncpy(fs, st.f_fstypename, fslen);
118       return true;
119    }
120    Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
121    return false;
122 }
123 #elif defined(HAVE_NETBSD_OS)
124 #include <sys/param.h>
125 #include <sys/mount.h>
126 #ifdef HAVE_SYS_STATVFS_H
127 #include <sys/statvfs.h>
128 #else
129 #define statvfs statfs
130 #endif
131
132 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
133 {
134    char *fname = ff_pkt->fname;
135    struct statvfs st;
136    if (statvfs(fname, &st) == 0) {
137       bstrncpy(fs, st.f_fstypename, fslen);
138       return true;
139    }
140    Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
141    return false;
142 }
143 #elif defined(HAVE_HPUX_OS) \
144    || defined(HAVE_IRIX_OS)
145
146 #include <sys/types.h>
147 #include <sys/statvfs.h>
148
149 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
150 {
151    char *fname = ff_pkt->fname;
152    struct statvfs st;
153    if (statvfs(fname, &st) == 0) {
154       bstrncpy(fs, st.f_basetype, fslen);
155       return true;
156    }
157    Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
158    return false;
159 }
160
161 #elif defined(HAVE_LINUX_OS)
162
163 #include <sys/vfs.h>
164 #include <mntent.h>
165
166 /*
167  * Linux statfs() does not return the filesystem name type.  It
168  *  only returns a binary fstype, so we must look up the type name
169  *  in mtab.
170  */
171 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
172 {
173    char *fname = ff_pkt->fname;
174    struct statfs st;
175    const char *fstype;
176
177    if (statfs(fname, &st) == 0) {
178       mtab_item *item, search_item;
179       if (*ff_pkt->last_fstypename && ff_pkt->last_fstype == (uint64_t)st.f_type) {
180          bstrncpy(fs, ff_pkt->last_fstypename, fslen);
181          return true; 
182       }
183       if (!ff_pkt->mtab_list) {
184          ff_pkt->mtab_list = New(rblist());
185          read_mtab(add_mtab_item, ff_pkt->mtab_list);
186       }
187       search_item.dev = st.f_type;
188       item = (mtab_item *)ff_pkt->mtab_list->search((void *)&search_item, compare_mtab_items);
189       if (item) {
190          ff_pkt->last_fstype = st.f_type;
191          bstrncpy(ff_pkt->last_fstypename, item->fstype, sizeof(ff_pkt->last_fstypename));
192          bstrncpy(fs, ff_pkt->last_fstypename, fslen);
193          return true;
194       }
195       /*
196        * Values obtained from statfs(2), testing and
197        *
198        *    $ grep -r SUPER_MAGIC /usr/include/linux
199        */
200       switch (st.f_type) {
201       /* Known good values */
202       /* ext2, ext3, and ext4 have the same code */
203       case 0xef53:         fstype = "ext2"; break;          /* EXT2_SUPER_MAGIC */
204       case 0x3153464a:     fstype = "jfs"; break;           /* JFS_SUPER_MAGIC */
205       case 0x5346544e:     fstype = "ntfs"; break;          /* NTFS_SB_MAGIC */
206       case 0x9fa0:         fstype = "proc"; break;          /* PROC_SUPER_MAGIC */
207       case 0x52654973:     fstype = "reiserfs"; break;      /* REISERFS_SUPER_MAGIC */
208       case 0x58465342:     fstype = "xfs"; break;           /* XFS_SB_MAGIC */
209       case 0x9fa2:         fstype = "usbdevfs"; break;      /* USBDEVICE_SUPER_MAGIC */
210       case 0x62656572:     fstype = "sysfs"; break;         /* SYSFS_MAGIC */
211       case 0x517B:         fstype = "smbfs"; break;         /* SMB_SUPER_MAGIC */
212       case 0x9660:         fstype = "iso9660"; break;       /* ISOFS_SUPER_MAGIC */
213       case 0xadf5:         fstype = "adfs"; break;          /* ADFS_SUPER_MAGIC */
214       case 0xadff:         fstype = "affs"; break;          /* AFFS_SUPER_MAGIC */
215       case 0x42465331:     fstype = "befs"; break;          /* BEFS_SUPER_MAGIC */
216       case 0xFF534D42:     fstype = "cifs"; break;          /* CIFS_MAGIC_NUMBER */
217       case 0x73757245:     fstype = "coda"; break;          /* CODA_SUPER_MAGIC */
218       case 0x012ff7b7:     fstype = "coherent"; break;      /* COH_SUPER_MAGIC */
219       case 0x28cd3d45:     fstype = "cramfs"; break;        /* CRAMFS_MAGIC */
220       case 0x1373:         fstype = "devfs"; break;         /* DEVFS_SUPER_MAGIC */
221       case 0x414A53:       fstype = "efs"; break;           /* EFS_SUPER_MAGIC */
222       case 0x137d:         fstype = "ext"; break;           /* EXT_SUPER_MAGIC */
223       case 0xef51:         fstype = "oldext2"; break;          /* EXT2_OLD_SUPER_MAGIC */
224       case 0x4244:         fstype = "hfs"; break;          /* EXT2_OLD_SUPER_MAGIC */
225       case 0xf995e849:     fstype = "hpfs"; break;          /* HPFS_SUPER_MAGIC */
226       case 0x958458f6:     fstype = "hugetlbfs"; break;     /* HUGETLBFS_MAGIC */
227       case 0x72b6:         fstype = "jffs2"; break;         /* JFFS2_SUPER_MAGIC */
228       case 0x2468:         fstype = "minix"; break;         /* MINIX2_SUPER_MAGIC */
229       case 0x2478:         fstype = "minix"; break;         /* MINIX2_SUPER_MAGIC2 */
230       case 0x137f:         fstype = "minix"; break;         /* MINIX_SUPER_MAGIC */
231       case 0x138f:         fstype = "minix"; break;         /* MINIX_SUPER_MAGIC2 */
232       case 0x4d44:         fstype = "msdos"; break;         /* MSDOS_SUPER_MAGIC */
233       case 0x564c:         fstype = "ncpfs"; break;         /* NCP_SUPER_MAGIC */
234       case 0x6969:         fstype = "nfs"; break;           /* NFS_SUPER_MAGIC */
235       case 0x9fa1:         fstype = "openpromfs"; break;    /* OPENPROM_SUPER_MAGIC */
236       case 0x002f:         fstype = "qnx4"; break;          /* QNX4_SUPER_MAGIC */
237       case 0x7275:         fstype = "romfs"; break;          /* QNX4_SUPER_MAGIC */
238       case 0x012ff7b6:     fstype = "sysv2"; break;
239       case 0x012ff7b5:     fstype = "sysv4"; break;
240       case 0x01021994:     fstype = "tmpfs"; break;
241       case 0x15013346:     fstype = "udf"; break;
242       case 0x00011954:     fstype = "ufs"; break;
243       case 0xa501FCF5:     fstype = "vxfs"; break;
244       case 0x012FF7B4:     fstype = "xenix"; break;
245       case 0x012FD16D:     fstype = "xiafs"; break;
246       case 0x9123683e:     fstype = "btrfs"; break;
247
248 #if 0       /* These need confirmation */
249       case 0x6B414653:     fstype = "afs"; break;           /* AFS_FS_MAGIC */
250       case 0x0187:         fstype = "autofs"; break;        /* AUTOFS_SUPER_MAGIC */
251       case 0x62646576:     fstype = "bdev"; break;          /* ??? */
252       case 0x1BADFACE:     fstype = "bfs"; break;           /* BFS_MAGIC */
253       case 0x42494e4d:     fstype = "binfmt_misc"; break;   /* ??? */
254       case (('C'<<8)|'N'): fstype = "capifs"; break;        /* CAPIFS_SUPER_MAGIC */
255       case 0x1cd1:         fstype = "devpts"; break;        /* ??? */
256       case 0x03111965:     fstype = "eventpollfs"; break;   /* EVENTPOLLFS_MAGIC */
257       case 0xBAD1DEA:      fstype = "futexfs"; break;       /* ??? */
258       case 0xaee71ee7:     fstype = "gadgetfs"; break;      /* GADGETFS_MAGIC */
259       case 0x00c0ffee:     fstype = "hostfs"; break;        /* HOSTFS_SUPER_MAGIC */
260       case 0xb00000ee:     fstype = "hppfs"; break;         /* HPPFS_SUPER_MAGIC */
261       case 0x12061983:     fstype = "hwgfs"; break;         /* HWGFS_MAGIC */
262       case 0x66726f67:     fstype = "ibmasmfs"; break;      /* IBMASMFS_MAGIC */
263       case 0x19800202:     fstype = "mqueue"; break;        /* MQUEUE_MAGIC */
264       case 0x6f70726f:     fstype = "oprofilefs"; break;    /* OPROFILEFS_MAGIC */
265       case 0xa0b4d889:     fstype = "pfmfs"; break;         /* PFMFS_MAGIC */
266       case 0x50495045:     fstype = "pipfs"; break;         /* PIPEFS_MAGIC */
267       case 0x858458f6:     fstype = "ramfs"; break;         /* RAMFS_MAGIC */
268       case 0x7275:         fstype = "romfs"; break;         /* ROMFS_MAGIC */
269       case 0x858458f6:     fstype = "rootfs"; break;        /* RAMFS_MAGIC */
270       case 0x67596969:     fstype = "rpc_pipefs"; break;    /* RPCAUTH_GSSMAGIC */
271       case 0x534F434B:     fstype = "sockfs"; break;        /* SOCKFS_MAGIC */
272       case 0x858458f6:     fstype = "tmpfs"; break;         /* RAMFS_MAGIC */
273       case 0x01021994:     fstype = "tmpfs"; break;         /* TMPFS_MAGIC */
274 #endif
275
276       default:
277          Dmsg2(10, "Unknown file system type \"0x%x\" for \"%s\".\n", st.f_type,
278                fname);
279          return false;
280       }
281       ff_pkt->last_fstype = st.f_type;
282       bstrncpy(ff_pkt->last_fstypename, fstype, sizeof(ff_pkt->last_fstypename));
283       bstrncpy(fs, fstype, fslen);
284       return true;
285    }
286    Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
287    return false;
288 }
289
290 #elif defined(HAVE_SUN_OS)
291
292 #include <sys/types.h>
293 #include <sys/stat.h>
294
295 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
296 {
297    /* Solaris has the filesystem type name in the lstat packet */
298    bstrncpy(fs, ff_pkt->statp.st_fstype, fslen);
299    return true;
300 }
301  
302 #elif defined (__digital__) && defined (__unix__)  /* Tru64 */
303 /* Tru64 */
304 #include <sys/stat.h>
305 #include <sys/mount.h>
306
307 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
308 {
309    char *fname = ff_pkt->fname;
310    struct statfs st;
311    if (statfs((char *)fname, &st) == 0) {
312       switch (st.f_type) {
313       /* Known good values */
314       case 0xa:         bstrncpy(fs, "advfs", fslen); return true;        /* Tru64 AdvFS */
315       case 0xe:         bstrncpy(fs, "nfs", fslen); return true;          /* Tru64 NFS   */
316       default:
317          Dmsg2(10, "Unknown file system type \"0x%x\" for \"%s\".\n", st.f_type,
318                fname);
319          return false;
320       }
321    }
322    Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
323    return false;
324 }
325 /* Tru64 */
326
327 #else    /* No recognised OS */
328
329 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
330 {
331    char *fname = ff_pkt->fname;
332    Dmsg0(10, "!!! fstype() not implemented for this OS. !!!\n");
333    return false;
334 }
335 #endif
336
337 /* Read mtab entries  */
338 bool read_mtab(mtab_handler_t *mtab_handler, void *user_ctx)
339
340 #ifdef HAVE_GETMNTENT
341    FILE *mntfp;
342    struct stat st;
343  
344 #ifdef HAVE_LINUX_OS
345    struct mntent *mnt;
346    P(mutex);
347    if ((mntfp = setmntent("/proc/mounts", "r")) == NULL) {
348       if ((mntfp = setmntent(_PATH_MOUNTED, "r")) == NULL) {
349          V(mutex);
350          return false;
351       }
352    } 
353    while ((mnt = getmntent(mntfp)) != NULL) {
354       if (is_rootfs(mnt->mnt_type)) {
355          continue;
356       }
357
358       if (stat(mnt->mnt_dir, &st) < 0) {
359          continue;
360       }
361       mtab_handler(user_ctx, &st, mnt->mnt_type, mnt->mnt_dir,
362          mnt->mnt_opts, mnt->mnt_fsname);
363    }
364    endmntent(mntfp);
365    V(mutex);
366 #endif
367
368 #ifdef HAVE_SUN_OS
369    struct mnttab mnt;
370
371    P(mutex);
372    if ((mntfp = fopen(MNTTAB, "r")) == NULL) {
373       V(mutex);
374       return false;
375    }
376
377    while (getmntent(mntfp, &mnt) == 0) {
378       if (is_rootfs(mnt.mnt_fstype)) {
379          continue;
380       }
381       if (stat(mnt.mnt_mountp, &st) < 0) {
382          continue;
383       }
384       mtab_handler(user_ctx, &st, mnt.mnt_fstype, mnt.mnt_mountp,
385          mnt.mnt_mntopts, mnt.mnt_special);
386    }
387    fclose(mntfp);
388    V(mutex);
389 #endif
390
391 #endif /* HAVE_GETMNTENT */
392
393 #ifdef HAVE_GETMNTINFO
394    struct stat st;
395 #if defined(ST_NOWAIT)
396    int flags = ST_NOWAIT;
397 #elif defined(MNT_NOWAIT)
398    int flags = MNT_NOWAIT;
399 #else
400    int flags = 0;
401 #endif
402 #if defined(HAVE_NETBSD_OS)
403    struct statvfs *mntinfo;
404 #else
405    struct statfs *mntinfo;
406 #endif
407    int nument;
408
409    P(mutex);
410    if ((nument = getmntinfo(&mntinfo, flags)) > 0) {
411       while (nument-- > 0) {
412          if (is_rootfs(mntinfo->f_fstypename)) {
413             continue;
414          }
415          if (stat(mntinfo->f_mntonname, &st) < 0) {
416             continue;
417          }
418          mtab_handler(user_ctx, &st, mntinfo->f_mntfromname,
419             mntinfo->f_mntonname, mntinfo->f_fstypename, NULL);
420          mntinfo++;
421       }
422    }
423    V(mutex);
424 #endif /* HAVE_GETMNTINFO */
425    return true;
426
427
428 #ifdef TEST_PROGRAM
429 int main(int argc, char **argv)
430 {
431    char *p;
432    char fs[1000];
433    int status = 0;
434
435    if (argc < 2) {
436       p = (argc < 1) ? "fstype" : argv[0];
437       printf("usage:\t%s path ...\n"
438             "\t%s prints the file system type and pathname of the paths.\n",
439             p, p);
440       return EXIT_FAILURE;
441    }
442    while (*++argv) {
443       if (!fstype(*argv, fs, sizeof(fs))) {
444          status = EXIT_FAILURE;
445       } else {
446          printf("%s\t%s\n", fs, *argv);
447       }
448    }
449    return status;
450 }
451 #endif