1 /*
2    Bacula(R) - The Network Backup Solution
3 
4    Copyright (C) 2000-2020 Kern Sibbald
5 
6    The original author of Bacula is Kern Sibbald, with contributions
7    from many others, a complete list can be found in the file AUTHORS.
8 
9    You may use this file and others of this release according to the
10    license defined in the LICENSE file, which includes the Affero General
11    Public License, v3.0 ("AGPLv3") and some additional permissions and
12    terms pursuant to its AGPLv3 Section 7.
13 
14    This notice must be preserved when any source code is
15    conveyed and/or propagated.
16 
17    Bacula(R) is a registered trademark of Kern Sibbald.
18 */
19 /*
20  *  Implement routines to determine file system types.
21  *
22  *   Written by Preben 'Peppe' Guldberg, December MMIV
23  *   Updated by Kern Sibbald, April MMXV
24  */
25 
26 
27 #ifndef TEST_PROGRAM
28 
29 #include "bacula.h"
30 #include "find.h"
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #if defined(HAVE_LINUX_OS) || defined(HAVE_FREEBSD_OS) || defined(HAVE_AIX_OS)
34   #include <paths.h>
35 #endif
36 #ifdef HAVE_DARWIN_OS
37   #include <sys/paths.h>
38 #endif
39 
40 #ifdef HAVE_SUN_OS
41   #include <sys/mnttab.h>
42 #endif
43 #else /* Set up for testing a stand alone program */
44 
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #define bstrncpy           strncpy
49 #define Dmsg0(n,s)         fprintf(stderr, s)
50 #define Dmsg1(n,s,a1)      fprintf(stderr, s, a1)
51 #define Dmsg2(n,s,a1,a2)   fprintf(stderr, s, a1, a2)
52 #endif
53 
54 #define is_rootfs(x) bstrcmp("rootfs", x)
55 
56 #if defined(HAVE_GETMNTINFO) || defined(HAVE_GETMNTENT)
57 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
58 #endif
59 
60 struct mtab_item {
61    rblink link;
62    uint64_t dev;
63    char fstype[1];
64 };
65 
66 /* Compare two device types */
compare_mtab_items(void * item1,void * item2)67 static int compare_mtab_items(void *item1, void *item2)
68 {
69    mtab_item *mtab1, *mtab2;
70    mtab1 = (mtab_item *)item1;
71    mtab2 = (mtab_item *)item2;
72    if (mtab1->dev < mtab2->dev) return -1;
73    if (mtab1->dev > mtab2->dev) return 1;
74    return 0;
75 }
76 
add_mtab_item(void * user_ctx,struct stat * st,const char * fstype,const char * mountpoint,const char * mntopts,const char * fsname)77 void add_mtab_item(void *user_ctx, struct stat *st, const char *fstype,
78                       const char *mountpoint, const char *mntopts,
79                       const char *fsname)
80 {
81    rblist *mtab_list = (rblist *)user_ctx;
82    mtab_item *item, *ritem;
83    int len = strlen(fstype) + 1;
84 
85    item = (mtab_item *)malloc(sizeof(mtab_item) + len);
86    item->dev = (uint64_t)st->st_dev;
87    bstrncpy(item->fstype, fstype, len);
88    ritem = (mtab_item *)mtab_list->insert((void *)item, compare_mtab_items);
89    if (ritem != item) {
90       /* Item already inserted, so we discard this one */
91       free(item);
92    }
93 }
94 
95 /*
96  * These functions should be implemented for each OS
97  *
98  *       bool fstype(FF_PKT *ff_pkt, char *fs, int fslen);
99  */
100 #if defined(HAVE_DARWIN_OS) \
101    || defined(HAVE_FREEBSD_OS ) \
102    || defined(HAVE_KFREEBSD_OS ) \
103    || defined(HAVE_OPENBSD_OS)
104 
105 #include <sys/param.h>
106 #include <sys/mount.h>
107 
108 /*
109  * simple return fs type magic number or zero when error
110  */
fstypeid(char * fname,FF_PKT * ff_pkt)111 uint32_t fstypeid(char *fname, FF_PKT *ff_pkt)
112 {
113    struct statfs st;
114 
115    if (statfs(fname, &st) == 0) {
116       return st.f_type;
117    }
118    return 0;
119 }
120 
fstype(FF_PKT * ff_pkt,char * fs,int fslen)121 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
122 {
123    char *fname = ff_pkt->fname;
124    struct statfs st;
125    if (!fname) {
126       return false;
127    }
128    if (statfs(fname, &st) == 0) {
129       bstrncpy(fs, st.f_fstypename, fslen);
130       return true;
131    }
132    Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
133    return false;
134 }
135 
fstype(char * fname,FF_PKT * ff_pkt,char * fs,int fslen)136 bool fstype(char *fname, FF_PKT *ff_pkt, char *fs, int fslen)
137 {
138    return fstype(ff_pkt, fs, fslen);
139 }
140 
141 #elif defined(HAVE_NETBSD_OS)
142 #include <sys/param.h>
143 #include <sys/mount.h>
144 #ifdef HAVE_SYS_STATVFS_H
145 #include <sys/statvfs.h>
146 #else
147 #define statvfs statfs
148 #endif
149 
150 /*
151  * simple return fs type magic number or zero when error
152  */
fstypeid(char * fname,FF_PKT * ff_pkt)153 uint32_t fstypeid(char *fname, FF_PKT *ff_pkt)
154 {
155    struct statvfs st;
156 
157    if (statvfs(fname, &st) == 0) {
158       return st.f_type;
159    }
160    return 0;
161 }
162 
fstype(FF_PKT * ff_pkt,char * fs,int fslen)163 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
164 {
165    char *fname = ff_pkt->fname;
166    struct statvfs st;
167    if (fname) {
168       return false;
169    }
170    if (statvfs(fname, &st) == 0) {
171       bstrncpy(fs, st.f_fstypename, fslen);
172       return true;
173    }
174    Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
175    return false;
176 }
177 
fstype(char * fname,FF_PKT * ff_pkt,char * fs,int fslen)178 bool fstype(char *fname, FF_PKT *ff_pkt, char *fs, int fslen)
179 {
180    return fstype(ff_pkt, fs, fslen);
181 }
182 
183 #elif defined(HAVE_HPUX_OS)                     \
184    || defined(HAVE_IRIX_OS)
185 
186 #include <sys/types.h>
187 #include <sys/statvfs.h>
188 
189 /*
190  * TODO: RPK: is HP-UX version really working as I cannot find required API in HP-UX docs.
191  */
192 
193 /*
194  * simple return fs type magic number or zero when error
195  */
fstypeid(char * fname,FF_PKT * ff_pkt)196 uint32_t fstypeid(char *fname, FF_PKT *ff_pkt)
197 {
198    struct statfs st;
199 
200    if (statfs(fname, &st) == 0) {
201       return st.f_fsid;
202    }
203    return 0;
204 }
205 
fstype(FF_PKT * ff_pkt,char * fs,int fslen)206 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
207 {
208    char *fname = ff_pkt->fname;
209    struct statvfs st;
210    if (!fname) {
211       return false;
212    }
213    if (statvfs(fname, &st) == 0) {
214       bstrncpy(fs, st.f_basetype, fslen);
215       return true;
216    }
217    Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
218    return false;
219 }
220 
fstype(char * fname,FF_PKT * ff_pkt,char * fs,int fslen)221 bool fstype(char *fname, FF_PKT *ff_pkt, char *fs, int fslen)
222 {
223    return fstype(ff_pkt, fs, fslen);
224 }
225 
226 #elif defined(HAVE_LINUX_OS)
227 
228 #include <sys/vfs.h>
229 #include <mntent.h>
230 
231 
232 /*
233  * simple return fs type magic number or zero when error
234  */
fstypeid(char * fname,FF_PKT * ff_pkt)235 uint32_t fstypeid(char *fname, FF_PKT *ff_pkt)
236 {
237    struct statfs st;
238 
239    if (statfs(fname, &st) == 0) {
240       return st.f_type;
241    }
242    return 0;
243 }
244 
245 /*
246  * Linux statfs() does not return the filesystem name type.  It
247  *  only returns a binary fstype, so we must look up the type name
248  *  in mtab.
249  */
fstype(char * fname,FF_PKT * ff_pkt,char * fs,int fslen)250 bool fstype(char *fname, FF_PKT *ff_pkt, char *fs, int fslen)
251 {
252    struct statfs st;
253    const char *fstype;
254    if (!fname) {
255       return false;
256    }
257    if (statfs(fname, &st) == 0) {
258       mtab_item *item, search_item;
259       if (*ff_pkt->last_fstypename && ff_pkt->last_fstype == (uint64_t)st.f_type) {
260          bstrncpy(fs, ff_pkt->last_fstypename, fslen);
261          return true;
262       }
263       if (!ff_pkt->mtab_list) {
264          ff_pkt->mtab_list = New(rblist());
265          read_mtab(add_mtab_item, ff_pkt->mtab_list);
266       }
267       search_item.dev = st.f_type;
268       item = (mtab_item *)ff_pkt->mtab_list->search((void *)&search_item, compare_mtab_items);
269       if (item) {
270          ff_pkt->last_fstype = st.f_type;
271          bstrncpy(ff_pkt->last_fstypename, item->fstype, sizeof(ff_pkt->last_fstypename));
272          bstrncpy(fs, ff_pkt->last_fstypename, fslen);
273          return true;
274       }
275       /*
276        * Values obtained from statfs(2), testing and
277        *
278        *    $ grep -r SUPER_MAGIC /usr/include/linux
279        */
280       switch ((unsigned int)st.f_type) {
281       /* Known good values */
282       /* ext2, ext3, and ext4 have the same code */
283       case 0xef53:         fstype = "ext2"; break;          /* EXT2_SUPER_MAGIC */
284       case 0x3153464a:     fstype = "jfs"; break;           /* JFS_SUPER_MAGIC */
285       case 0x5346544e:     fstype = "ntfs"; break;          /* NTFS_SB_MAGIC */
286       case 0x9fa0:         fstype = "proc"; break;          /* PROC_SUPER_MAGIC */
287       case 0x52654973:     fstype = "reiserfs"; break;      /* REISERFS_SUPER_MAGIC */
288       case 0x58465342:     fstype = "xfs"; break;           /* XFS_SB_MAGIC */
289       case 0x9fa2:         fstype = "usbdevfs"; break;      /* USBDEVICE_SUPER_MAGIC */
290       case 0x62656572:     fstype = "sysfs"; break;         /* SYSFS_MAGIC */
291       case 0x517B:         fstype = "smbfs"; break;         /* SMB_SUPER_MAGIC */
292       case 0x9660:         fstype = "iso9660"; break;       /* ISOFS_SUPER_MAGIC */
293       case 0xadf5:         fstype = "adfs"; break;          /* ADFS_SUPER_MAGIC */
294       case 0xadff:         fstype = "affs"; break;          /* AFFS_SUPER_MAGIC */
295       case 0x42465331:     fstype = "befs"; break;          /* BEFS_SUPER_MAGIC */
296       case 0xFF534D42:     fstype = "cifs"; break;          /* CIFS_MAGIC_NUMBER */
297       case 0xfe534d42:     fstype = "cifs2"; break;         /* CIFS2_MAGIC_NUMBER */
298       case 0x73757245:     fstype = "coda"; break;          /* CODA_SUPER_MAGIC */
299       case 0x012ff7b7:     fstype = "coherent"; break;      /* COH_SUPER_MAGIC */
300       case 0x28cd3d45:     fstype = "cramfs"; break;        /* CRAMFS_MAGIC */
301       case 0x1373:         fstype = "devfs"; break;         /* DEVFS_SUPER_MAGIC */
302       case 0x414A53:       fstype = "efs"; break;           /* EFS_SUPER_MAGIC */
303       case 0x137d:         fstype = "ext"; break;           /* EXT_SUPER_MAGIC */
304       case 0xef51:         fstype = "oldext2"; break;          /* EXT2_OLD_SUPER_MAGIC */
305       case 0x4244:         fstype = "hfs"; break;          /* EXT2_OLD_SUPER_MAGIC */
306       case 0xf995e849:     fstype = "hpfs"; break;          /* HPFS_SUPER_MAGIC */
307       case 0x958458f6:     fstype = "hugetlbfs"; break;     /* HUGETLBFS_MAGIC */
308       case 0x72b6:         fstype = "jffs2"; break;         /* JFFS2_SUPER_MAGIC */
309       case 0x2468:         fstype = "minix"; break;         /* MINIX2_SUPER_MAGIC */
310       case 0x2478:         fstype = "minix"; break;         /* MINIX2_SUPER_MAGIC2 */
311       case 0x137f:         fstype = "minix"; break;         /* MINIX_SUPER_MAGIC */
312       case 0x138f:         fstype = "minix"; break;         /* MINIX_SUPER_MAGIC2 */
313       case 0x4d44:         fstype = "msdos"; break;         /* MSDOS_SUPER_MAGIC */
314       case 0x564c:         fstype = "ncpfs"; break;         /* NCP_SUPER_MAGIC */
315       case 0x6969:         fstype = "nfs"; break;           /* NFS_SUPER_MAGIC */
316       case 0x9fa1:         fstype = "openpromfs"; break;    /* OPENPROM_SUPER_MAGIC */
317       case 0x002f:         fstype = "qnx4"; break;          /* QNX4_SUPER_MAGIC */
318       case 0x7275:         fstype = "romfs"; break;          /* QNX4_SUPER_MAGIC */
319       case 0x012ff7b6:     fstype = "sysv2"; break;
320       case 0x012ff7b5:     fstype = "sysv4"; break;
321       case 0x01021994:     fstype = "tmpfs"; break;
322       case 0x15013346:     fstype = "udf"; break;
323       case 0x00011954:     fstype = "ufs"; break;
324       case 0xa501FCF5:     fstype = "vxfs"; break;
325       case 0x012FF7B4:     fstype = "xenix"; break;
326       case 0x012FD16D:     fstype = "xiafs"; break;
327       case 0x9123683e:     fstype = "btrfs"; break;
328       case 0x7461636f:     fstype = "ocfs2"; break;         /* OCFS2_SUPER_MAGIC */
329 
330 #if 0       /* These need confirmation */
331       case 0x6B414653:     fstype = "afs"; break;           /* AFS_FS_MAGIC */
332       case 0x0187:         fstype = "autofs"; break;        /* AUTOFS_SUPER_MAGIC */
333       case 0x62646576:     fstype = "bdev"; break;          /* ??? */
334       case 0x1BADFACE:     fstype = "bfs"; break;           /* BFS_MAGIC */
335       case 0x42494e4d:     fstype = "binfmt_misc"; break;   /* ??? */
336       case (('C'<<8)|'N'): fstype = "capifs"; break;        /* CAPIFS_SUPER_MAGIC */
337       case 0x1cd1:         fstype = "devpts"; break;        /* ??? */
338       case 0x03111965:     fstype = "eventpollfs"; break;   /* EVENTPOLLFS_MAGIC */
339       case 0xBAD1DEA:      fstype = "futexfs"; break;       /* ??? */
340       case 0xaee71ee7:     fstype = "gadgetfs"; break;      /* GADGETFS_MAGIC */
341       case 0x00c0ffee:     fstype = "hostfs"; break;        /* HOSTFS_SUPER_MAGIC */
342       case 0xb00000ee:     fstype = "hppfs"; break;         /* HPPFS_SUPER_MAGIC */
343       case 0x12061983:     fstype = "hwgfs"; break;         /* HWGFS_MAGIC */
344       case 0x66726f67:     fstype = "ibmasmfs"; break;      /* IBMASMFS_MAGIC */
345       case 0x19800202:     fstype = "mqueue"; break;        /* MQUEUE_MAGIC */
346       case 0x6f70726f:     fstype = "oprofilefs"; break;    /* OPROFILEFS_MAGIC */
347       case 0xa0b4d889:     fstype = "pfmfs"; break;         /* PFMFS_MAGIC */
348       case 0x50495045:     fstype = "pipfs"; break;         /* PIPEFS_MAGIC */
349       case 0x858458f6:     fstype = "ramfs"; break;         /* RAMFS_MAGIC */
350       case 0x7275:         fstype = "romfs"; break;         /* ROMFS_MAGIC */
351       case 0x858458f6:     fstype = "rootfs"; break;        /* RAMFS_MAGIC */
352       case 0x67596969:     fstype = "rpc_pipefs"; break;    /* RPCAUTH_GSSMAGIC */
353       case 0x534F434B:     fstype = "sockfs"; break;        /* SOCKFS_MAGIC */
354       case 0x858458f6:     fstype = "tmpfs"; break;         /* RAMFS_MAGIC */
355       case 0x01021994:     fstype = "tmpfs"; break;         /* TMPFS_MAGIC */
356 #endif
357 
358       default:
359          Dmsg2(10, "Unknown file system type \"0x%x\" for \"%s\".\n", st.f_type,
360                fname);
361          return false;
362       }
363       ff_pkt->last_fstype = st.f_type;
364       bstrncpy(ff_pkt->last_fstypename, fstype, sizeof(ff_pkt->last_fstypename));
365       bstrncpy(fs, fstype, fslen);
366       return true;
367    }
368    Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
369    return false;
370 }
371 
372 /*
373  * Parameter wrapper for fstype
374  */
fstype(FF_PKT * ff_pkt,char * fs,int fslen)375 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
376 {
377    return fstype(ff_pkt->fname, ff_pkt, fs, fslen);
378 }
379 
380 #elif defined(HAVE_SUN_OS)
381 
382 #include <sys/types.h>
383 #include <sys/stat.h>
384 #include <sys/statvfs.h>
385 
386 #ifndef NAME_MAX
387 #define NAME_MAX FSTYPSZ
388 #endif
389 
390 /*
391  * simple return fs type magic number
392  */
fstypeid(char * fname,FF_PKT * ff_pkt)393 uint32_t fstypeid(char *fname, FF_PKT *ff_pkt)
394 {
395    struct statvfs st;
396 
397    if (statvfs(fname, &st) == 0) {
398       return st.f_fsid;
399    }
400    return 0;
401 }
402 
fstype(FF_PKT * ff_pkt,char * fs,int fslen)403 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
404 {
405    /* Solaris has the filesystem type name in the lstat packet */
406    bstrncpy(fs, ff_pkt->statp.st_fstype, fslen);
407    return true;
408 }
409 
fstype(char * fname,FF_PKT * ff_pkt,char * fs,int fslen)410 bool fstype(char *fname, FF_PKT *ff_pkt, char *fs, int fslen)
411 {
412    return fstype(ff_pkt, fs, fslen);
413 }
414 
415 #elif defined (__digital__) && defined (__unix__)  /* Tru64 */
416 /* Tru64 */
417 #include <sys/stat.h>
418 #include <sys/mount.h>
419 
420 /*
421  * TODO: RPK: Tru64 is already dead!
422  */
423 
424 /*
425  * simple return fs type magic number
426  */
fstypeid(char * fname,FF_PKT * ff_pkt)427 uint32_t fstypeid(char *fname, FF_PKT *ff_pkt)
428 {
429    struct statfs st;
430 
431    if (statfs((char *)fname, &st) == 0){
432       return st.f_type;
433    }
434    return 0;
435 }
436 
fstype(FF_PKT * ff_pkt,char * fs,int fslen)437 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
438 {
439    char *fname = ff_pkt->fname;
440    struct statfs st;
441    if (statfs((char *)fname, &st) == 0){
442       switch (st.f_type) {
443       /* Known good values */
444       case 0xa:         bstrncpy(fs, "advfs", fslen); return true;        /* Tru64 AdvFS */
445       case 0xe:         bstrncpy(fs, "nfs", fslen); return true;          /* Tru64 NFS   */
446       default:
447          Dmsg2(10, "Unknown file system type \"0x%x\" for \"%s\".\n", st.f_type,
448                fname);
449          return false;
450       }
451    }
452    Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
453    return false;
454 }
455 
fstype(char * fname,FF_PKT * ff_pkt,char * fs,int fslen)456 bool fstype(char *fname, FF_PKT *ff_pkt, char *fs, int fslen)
457 {
458    return fstype(ff_pkt, fs, fslen);
459 }
460 
461 /* Tru64 */
462 
463 #elif defined (HAVE_WIN32)
464 /* Windows */
fstype(char * fname,FF_PKT * ff_pkt,char * fs,int fslen)465 bool fstype(char *fname, FF_PKT *ff_pkt, char *fs, int fslen)
466 {
467    DWORD componentlength;
468    DWORD fsflags;
469    CHAR rootpath[4];
470    UINT oldmode;
471    BOOL result;
472 
473    /* Copy Drive Letter, colon, and backslash to rootpath */
474    bstrncpy(rootpath, fname, sizeof(rootpath));
475 
476    /* We don't want any popups if there isn't any media in the drive */
477    oldmode = SetErrorMode(SEM_FAILCRITICALERRORS);
478    result = GetVolumeInformation(rootpath, NULL, 0, NULL, &componentlength, &fsflags, fs, fslen);
479    SetErrorMode(oldmode);
480 
481    if (result) {
482       /* Windows returns NTFS, FAT, etc.  Make it lowercase to be consistent with other OSes */
483       lcase(fs);
484    } else {
485       Dmsg2(10, "GetVolumeInformation() failed for \"%s\", Error = %d.\n", rootpath, GetLastError());
486    }
487    return result != 0;
488 }
489 
490 /*
491  * Parameter wrapper for fstype
492  */
fstype(FF_PKT * ff_pkt,char * fs,int fslen)493 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
494 {
495    return fstype(ff_pkt->fname, ff_pkt, fs, fslen);
496 }
497 
498 /* Not implemented for windows, used in ACL code */
fstypeid(char * fname,FF_PKT * ff_pkt)499 uint32_t fstypeid(char *fname, FF_PKT *ff_pkt)
500 {
501    return 0;
502 }
503 
504 /* Windows */
505 
506 #else    /* No recognised OS */
507 
fstypeid(char * fname,FF_PKT * ff_pkt)508 uint32_t fstypeid(char *fname, FF_PKT *ff_pkt)
509 {
510    Dmsg0(10, "!!! fstypeid() not implemented for this OS. !!!\n");
511    return 0;
512 }
513 
fstype(FF_PKT * ff_pkt,char * fs,int fslen)514 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
515 {
516    Dmsg0(10, "!!! fstype() not implemented for this OS. !!!\n");
517    return false;
518 }
519 #endif
520 
521 /* Read mtab entries  */
read_mtab(mtab_handler_t * mtab_handler,void * user_ctx)522 bool read_mtab(mtab_handler_t *mtab_handler, void *user_ctx)
523 {
524 /* Debian stretch GNU/KFreeBSD has both getmntinfo and getmntent, but
525    only the first seems to work, so we skip over getmntent in this case */
526 #ifndef HAVE_KFREEBSD_OS
527 #ifdef HAVE_GETMNTENT
528    FILE *mntfp;
529    struct stat st;
530 
531 #ifdef HAVE_LINUX_OS
532    struct mntent *mnt;
533    P(mutex);
534    if ((mntfp = setmntent("/proc/mounts", "r")) == NULL) {
535       if ((mntfp = setmntent(_PATH_MOUNTED, "r")) == NULL) {
536          V(mutex);
537          return false;
538       }
539    }
540    while ((mnt = getmntent(mntfp)) != NULL) {
541       if (is_rootfs(mnt->mnt_type)) {
542          continue;
543       }
544 
545       if (stat(mnt->mnt_dir, &st) < 0) {
546          continue;
547       }
548       mtab_handler(user_ctx, &st, mnt->mnt_type, mnt->mnt_dir,
549          mnt->mnt_opts, mnt->mnt_fsname);
550    }
551    endmntent(mntfp);
552    V(mutex);
553 #endif
554 
555 #ifdef HAVE_SUN_OS
556    struct mnttab mnt;
557 
558    P(mutex);
559    if ((mntfp = bfopen(MNTTAB, "r")) == NULL) {
560       V(mutex);
561       return false;
562    }
563 
564    while (getmntent(mntfp, &mnt) == 0) {
565       if (is_rootfs(mnt.mnt_fstype)) {
566          continue;
567       }
568       if (stat(mnt.mnt_mountp, &st) < 0) {
569          continue;
570       }
571       mtab_handler(user_ctx, &st, mnt.mnt_fstype, mnt.mnt_mountp,
572          mnt.mnt_mntopts, mnt.mnt_special);
573    }
574    fclose(mntfp);
575    V(mutex);
576 #endif
577 
578 #endif /* HAVE_GETMNTENT */
579 #endif /* HAVE_KFREEBSD_OS */
580 
581 #ifdef HAVE_GETMNTINFO
582    struct stat st;
583 #if defined(ST_NOWAIT)
584    int flags = ST_NOWAIT;
585 #elif defined(MNT_NOWAIT)
586    int flags = MNT_NOWAIT;
587 #else
588    int flags = 0;
589 #endif
590 #if defined(HAVE_NETBSD_OS)
591    struct statvfs *mntinfo;
592 #else
593    struct statfs *mntinfo;
594 #endif
595    int nument;
596 
597    P(mutex);
598    if ((nument = getmntinfo(&mntinfo, flags)) > 0) {
599       while (nument-- > 0) {
600          if (is_rootfs(mntinfo->f_fstypename)) {
601             continue;
602          }
603          if (stat(mntinfo->f_mntonname, &st) < 0) {
604             continue;
605          }
606          mtab_handler(user_ctx, &st, mntinfo->f_mntfromname,
607             mntinfo->f_mntonname, mntinfo->f_fstypename, NULL);
608          mntinfo++;
609       }
610    }
611    V(mutex);
612 #endif /* HAVE_GETMNTINFO */
613    return true;
614 }
615 
616 /*
617  * compares current fstype from FF_PKT for required fstype_name
618  */
check_current_fs(char * fname,FF_PKT * ff,const char * fstype_name)619 bool check_current_fs(char *fname, FF_PKT *ff, const char *fstype_name)
620 {
621    if (fstype_name != NULL){
622       // read current fs name and compare it to required
623       char fsname[NAME_MAX];
624       if (fstype(fname, ff, fsname, NAME_MAX)){
625          return bstrcmp(fsname, fstype_name);
626       }
627    }
628    return false;
629 };
630 
631 /*
632  * compares current fstype from FF_PKT for required fstype_magic
633  */
check_current_fs(char * fname,FF_PKT * ff,uint32_t fstype_magic)634 bool check_current_fs(char *fname, FF_PKT *ff, uint32_t fstype_magic)
635 {
636    uint32_t fsid;
637 
638    if (fstype_magic > 0){
639       // get fsid for file
640       if (ff->last_fstype != 0){
641          fsid = ff->last_fstype;
642       } else {
643          fsid = fstypeid(fname, ff);
644          ff->last_fstype = fsid;
645       }
646       if (fsid != 0){
647          return fsid == fstype_magic;
648       }
649    }
650    return false;
651 }
652 
653 #ifdef TEST_PROGRAM
main(int argc,char ** argv)654 int main(int argc, char **argv)
655 {
656    char *p;
657    char fs[1000];
658    int status = 0;
659 
660    if (argc < 2) {
661       p = (argc < 1) ? "fstype" : argv[0];
662       printf("usage:\t%s path ...\n"
663             "\t%s prints the file system type and pathname of the paths.\n",
664             p, p);
665       return EXIT_FAILURE;
666    }
667    while (*++argv) {
668       if (!fstype(*argv, fs, sizeof(fs))) {
669          status = EXIT_FAILURE;
670       } else {
671          printf("%s\t%s\n", fs, *argv);
672       }
673    }
674    return status;
675 }
676 #endif
677