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