2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2017 Kern Sibbald
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.
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.
14 This notice must be preserved when any source code is
15 conveyed and/or propagated.
17 Bacula(R) is a registered trademark of Kern Sibbald.
20 * Implement routines to determine file system types.
22 * Written by Preben 'Peppe' Guldberg, December MMIV
23 * Updated by Kern Sibbald, April MMXV
31 #include <sys/types.h>
34 #include <sys/mnttab.h>
36 #else /* Set up for testing a stand alone program */
41 #define bstrncpy strncpy
42 #define Dmsg0(n,s) fprintf(stderr, s)
43 #define Dmsg1(n,s,a1) fprintf(stderr, s, a1)
44 #define Dmsg2(n,s,a1,a2) fprintf(stderr, s, a1, a2)
47 #define is_rootfs(x) bstrcmp("rootfs", x)
49 #if defined(HAVE_GETMNTINFO) || defined(HAVE_GETMNTENT)
50 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
59 /* Compare two device types */
60 static int compare_mtab_items(void *item1, void *item2)
62 mtab_item *mtab1, *mtab2;
63 mtab1 = (mtab_item *)item1;
64 mtab2 = (mtab_item *)item2;
65 if (mtab1->dev < mtab2->dev) return -1;
66 if (mtab1->dev > mtab2->dev) return 1;
70 #if defined(HAVE_LINUX_OS)
71 static void add_mtab_item(void *user_ctx, struct stat *st, const char *fstype,
72 const char *mountpoint, const char *mntopts,
75 rblist *mtab_list = (rblist *)user_ctx;
76 mtab_item *item, *ritem;
77 int len = strlen(fstype) + 1;
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);
84 /* Item already inserted, so we discard this one */
90 /* Compare directly the FS from a fname with a string */
91 bool fstype_cmp(FF_PKT *ff_pkt, const char *fsname)
94 if (fstype(ff_pkt, buf, sizeof(buf))) {
95 return (strcmp(buf, fsname) == 0);
101 * These functions should be implemented for each OS
103 * bool fstype(FF_PKT *ff_pkt, char *fs, int fslen);
105 #if defined(HAVE_DARWIN_OS) \
106 || defined(HAVE_FREEBSD_OS ) \
107 || defined(HAVE_KFREEBSD_OS ) \
108 || defined(HAVE_OPENBSD_OS)
110 #include <sys/param.h>
111 #include <sys/mount.h>
113 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
115 char *fname = ff_pkt->fname;
118 if (statfs(fname, &st) == 0) {
119 bstrncpy(fs, st.f_fstypename, fslen);
122 Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
125 #elif defined(HAVE_NETBSD_OS)
126 #include <sys/param.h>
127 #include <sys/mount.h>
128 #ifdef HAVE_SYS_STATVFS_H
129 #include <sys/statvfs.h>
131 #define statvfs statfs
134 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
136 char *fname = ff_pkt->fname;
138 if (statvfs(fname, &st) == 0) {
139 bstrncpy(fs, st.f_fstypename, fslen);
142 Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
145 #elif defined(HAVE_HPUX_OS) \
146 || defined(HAVE_IRIX_OS)
148 #include <sys/types.h>
149 #include <sys/statvfs.h>
151 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
153 char *fname = ff_pkt->fname;
155 if (statvfs(fname, &st) == 0) {
156 bstrncpy(fs, st.f_basetype, fslen);
159 Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
163 #elif defined(HAVE_LINUX_OS)
169 * Linux statfs() does not return the filesystem name type. It
170 * only returns a binary fstype, so we must look up the type name
173 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
175 char *fname = ff_pkt->fname;
179 if (statfs(fname, &st) == 0) {
180 mtab_item *item, search_item;
181 if (*ff_pkt->last_fstypename && ff_pkt->last_fstype == (uint64_t)st.f_type) {
182 bstrncpy(fs, ff_pkt->last_fstypename, fslen);
185 if (!ff_pkt->mtab_list) {
186 ff_pkt->mtab_list = New(rblist());
187 read_mtab(add_mtab_item, ff_pkt->mtab_list);
189 search_item.dev = st.f_type;
190 item = (mtab_item *)ff_pkt->mtab_list->search((void *)&search_item, compare_mtab_items);
192 ff_pkt->last_fstype = st.f_type;
193 bstrncpy(ff_pkt->last_fstypename, item->fstype, sizeof(ff_pkt->last_fstypename));
194 bstrncpy(fs, ff_pkt->last_fstypename, fslen);
198 * Values obtained from statfs(2), testing and
200 * $ grep -r SUPER_MAGIC /usr/include/linux
203 /* Known good values */
204 /* ext2, ext3, and ext4 have the same code */
205 case 0xef53: fstype = "ext2"; break; /* EXT2_SUPER_MAGIC */
206 case 0x3153464a: fstype = "jfs"; break; /* JFS_SUPER_MAGIC */
207 case 0x5346544e: fstype = "ntfs"; break; /* NTFS_SB_MAGIC */
208 case 0x9fa0: fstype = "proc"; break; /* PROC_SUPER_MAGIC */
209 case 0x52654973: fstype = "reiserfs"; break; /* REISERFS_SUPER_MAGIC */
210 case 0x58465342: fstype = "xfs"; break; /* XFS_SB_MAGIC */
211 case 0x9fa2: fstype = "usbdevfs"; break; /* USBDEVICE_SUPER_MAGIC */
212 case 0x62656572: fstype = "sysfs"; break; /* SYSFS_MAGIC */
213 case 0x517B: fstype = "smbfs"; break; /* SMB_SUPER_MAGIC */
214 case 0x9660: fstype = "iso9660"; break; /* ISOFS_SUPER_MAGIC */
215 case 0xadf5: fstype = "adfs"; break; /* ADFS_SUPER_MAGIC */
216 case 0xadff: fstype = "affs"; break; /* AFFS_SUPER_MAGIC */
217 case 0x42465331: fstype = "befs"; break; /* BEFS_SUPER_MAGIC */
218 case 0xFF534D42: fstype = "cifs"; break; /* CIFS_MAGIC_NUMBER */
219 case 0x73757245: fstype = "coda"; break; /* CODA_SUPER_MAGIC */
220 case 0x012ff7b7: fstype = "coherent"; break; /* COH_SUPER_MAGIC */
221 case 0x28cd3d45: fstype = "cramfs"; break; /* CRAMFS_MAGIC */
222 case 0x1373: fstype = "devfs"; break; /* DEVFS_SUPER_MAGIC */
223 case 0x414A53: fstype = "efs"; break; /* EFS_SUPER_MAGIC */
224 case 0x137d: fstype = "ext"; break; /* EXT_SUPER_MAGIC */
225 case 0xef51: fstype = "oldext2"; break; /* EXT2_OLD_SUPER_MAGIC */
226 case 0x4244: fstype = "hfs"; break; /* EXT2_OLD_SUPER_MAGIC */
227 case 0xf995e849: fstype = "hpfs"; break; /* HPFS_SUPER_MAGIC */
228 case 0x958458f6: fstype = "hugetlbfs"; break; /* HUGETLBFS_MAGIC */
229 case 0x72b6: fstype = "jffs2"; break; /* JFFS2_SUPER_MAGIC */
230 case 0x2468: fstype = "minix"; break; /* MINIX2_SUPER_MAGIC */
231 case 0x2478: fstype = "minix"; break; /* MINIX2_SUPER_MAGIC2 */
232 case 0x137f: fstype = "minix"; break; /* MINIX_SUPER_MAGIC */
233 case 0x138f: fstype = "minix"; break; /* MINIX_SUPER_MAGIC2 */
234 case 0x4d44: fstype = "msdos"; break; /* MSDOS_SUPER_MAGIC */
235 case 0x564c: fstype = "ncpfs"; break; /* NCP_SUPER_MAGIC */
236 case 0x6969: fstype = "nfs"; break; /* NFS_SUPER_MAGIC */
237 case 0x9fa1: fstype = "openpromfs"; break; /* OPENPROM_SUPER_MAGIC */
238 case 0x002f: fstype = "qnx4"; break; /* QNX4_SUPER_MAGIC */
239 case 0x7275: fstype = "romfs"; break; /* QNX4_SUPER_MAGIC */
240 case 0x012ff7b6: fstype = "sysv2"; break;
241 case 0x012ff7b5: fstype = "sysv4"; break;
242 case 0x01021994: fstype = "tmpfs"; break;
243 case 0x15013346: fstype = "udf"; break;
244 case 0x00011954: fstype = "ufs"; break;
245 case 0xa501FCF5: fstype = "vxfs"; break;
246 case 0x012FF7B4: fstype = "xenix"; break;
247 case 0x012FD16D: fstype = "xiafs"; break;
248 case 0x9123683e: fstype = "btrfs"; break;
250 #if 0 /* These need confirmation */
251 case 0x6B414653: fstype = "afs"; break; /* AFS_FS_MAGIC */
252 case 0x0187: fstype = "autofs"; break; /* AUTOFS_SUPER_MAGIC */
253 case 0x62646576: fstype = "bdev"; break; /* ??? */
254 case 0x1BADFACE: fstype = "bfs"; break; /* BFS_MAGIC */
255 case 0x42494e4d: fstype = "binfmt_misc"; break; /* ??? */
256 case (('C'<<8)|'N'): fstype = "capifs"; break; /* CAPIFS_SUPER_MAGIC */
257 case 0x1cd1: fstype = "devpts"; break; /* ??? */
258 case 0x03111965: fstype = "eventpollfs"; break; /* EVENTPOLLFS_MAGIC */
259 case 0xBAD1DEA: fstype = "futexfs"; break; /* ??? */
260 case 0xaee71ee7: fstype = "gadgetfs"; break; /* GADGETFS_MAGIC */
261 case 0x00c0ffee: fstype = "hostfs"; break; /* HOSTFS_SUPER_MAGIC */
262 case 0xb00000ee: fstype = "hppfs"; break; /* HPPFS_SUPER_MAGIC */
263 case 0x12061983: fstype = "hwgfs"; break; /* HWGFS_MAGIC */
264 case 0x66726f67: fstype = "ibmasmfs"; break; /* IBMASMFS_MAGIC */
265 case 0x19800202: fstype = "mqueue"; break; /* MQUEUE_MAGIC */
266 case 0x6f70726f: fstype = "oprofilefs"; break; /* OPROFILEFS_MAGIC */
267 case 0xa0b4d889: fstype = "pfmfs"; break; /* PFMFS_MAGIC */
268 case 0x50495045: fstype = "pipfs"; break; /* PIPEFS_MAGIC */
269 case 0x858458f6: fstype = "ramfs"; break; /* RAMFS_MAGIC */
270 case 0x7275: fstype = "romfs"; break; /* ROMFS_MAGIC */
271 case 0x858458f6: fstype = "rootfs"; break; /* RAMFS_MAGIC */
272 case 0x67596969: fstype = "rpc_pipefs"; break; /* RPCAUTH_GSSMAGIC */
273 case 0x534F434B: fstype = "sockfs"; break; /* SOCKFS_MAGIC */
274 case 0x858458f6: fstype = "tmpfs"; break; /* RAMFS_MAGIC */
275 case 0x01021994: fstype = "tmpfs"; break; /* TMPFS_MAGIC */
279 Dmsg2(10, "Unknown file system type \"0x%x\" for \"%s\".\n", st.f_type,
283 ff_pkt->last_fstype = st.f_type;
284 bstrncpy(ff_pkt->last_fstypename, fstype, sizeof(ff_pkt->last_fstypename));
285 bstrncpy(fs, fstype, fslen);
288 Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
292 #elif defined(HAVE_SUN_OS)
294 #include <sys/types.h>
295 #include <sys/stat.h>
296 #include <sys/mnttab.h>
298 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
300 /* Solaris has the filesystem type name in the lstat packet */
301 bstrncpy(fs, ff_pkt->statp.st_fstype, fslen);
305 #elif defined (__digital__) && defined (__unix__) /* Tru64 */
307 #include <sys/stat.h>
308 #include <sys/mount.h>
310 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
312 char *fname = ff_pkt->fname;
314 if (statfs((char *)fname, &st) == 0) {
316 /* Known good values */
317 case 0xa: bstrncpy(fs, "advfs", fslen); return true; /* Tru64 AdvFS */
318 case 0xe: bstrncpy(fs, "nfs", fslen); return true; /* Tru64 NFS */
320 Dmsg2(10, "Unknown file system type \"0x%x\" for \"%s\".\n", st.f_type,
325 Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
330 #else /* No recognised OS */
332 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
334 char *fname = ff_pkt->fname;
335 Dmsg0(10, "!!! fstype() not implemented for this OS. !!!\n");
340 /* Read mtab entries */
341 bool read_mtab(mtab_handler_t *mtab_handler, void *user_ctx)
343 /* Debian stretch GNU/KFreeBSD has both getmntinfo and getmntent, but
344 only the first seems to work, so ordering is important here */
345 #ifdef HAVE_GETMNTINFO
347 #if defined(ST_NOWAIT)
348 int flags = ST_NOWAIT;
349 #elif defined(MNT_NOWAIT)
350 int flags = MNT_NOWAIT;
354 #if defined(HAVE_NETBSD_OS)
355 struct statvfs *mntinfo;
357 struct statfs *mntinfo;
362 if ((nument = getmntinfo(&mntinfo, flags)) > 0) {
363 while (nument-- > 0) {
364 if (is_rootfs(mntinfo->f_fstypename)) {
367 if (stat(mntinfo->f_mntonname, &st) < 0) {
370 mtab_handler(user_ctx, &st, mntinfo->f_mntfromname,
371 mntinfo->f_mntonname, mntinfo->f_fstypename, NULL);
376 /* HAVE_GETMNTINFO */
377 #elif defined(HAVE_GETMNTENT)
384 if ((mntfp = setmntent("/proc/mounts", "r")) == NULL) {
385 if ((mntfp = setmntent(_PATH_MOUNTED, "r")) == NULL) {
390 while ((mnt = getmntent(mntfp)) != NULL) {
391 if (is_rootfs(mnt->mnt_type)) {
395 if (stat(mnt->mnt_dir, &st) < 0) {
398 mtab_handler(user_ctx, &st, mnt->mnt_type, mnt->mnt_dir,
399 mnt->mnt_opts, mnt->mnt_fsname);
409 if ((mntfp = bfopen(MNTTAB, "r")) == NULL) {
414 while (getmntent(mntfp, &mnt) == 0) {
415 if (is_rootfs(mnt.mnt_fstype)) {
418 if (stat(mnt.mnt_mountp, &st) < 0) {
421 mtab_handler(user_ctx, &st, mnt.mnt_fstype, mnt.mnt_mountp,
422 mnt.mnt_mntopts, mnt.mnt_special);
428 #endif /* HAVE_GETMNTENT */
433 int main(int argc, char **argv)
440 p = (argc < 1) ? "fstype" : argv[0];
441 printf("usage:\t%s path ...\n"
442 "\t%s prints the file system type and pathname of the paths.\n",
447 if (!fstype(*argv, fs, sizeof(fs))) {
448 status = EXIT_FAILURE;
450 printf("%s\t%s\n", fs, *argv);