2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2018 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 void add_mtab_item(void *user_ctx, struct stat *st, const char *fstype,
71 const char *mountpoint, const char *mntopts,
74 rblist *mtab_list = (rblist *)user_ctx;
75 mtab_item *item, *ritem;
76 int len = strlen(fstype) + 1;
78 item = (mtab_item *)malloc(sizeof(mtab_item) + len);
79 item->dev = (uint64_t)st->st_dev;
80 bstrncpy(item->fstype, fstype, len);
81 ritem = (mtab_item *)mtab_list->insert((void *)item, compare_mtab_items);
83 /* Item already inserted, so we discard this one */
90 * These functions should be implemented for each OS
92 * bool fstype(FF_PKT *ff_pkt, char *fs, int fslen);
94 #if defined(HAVE_DARWIN_OS) \
95 || defined(HAVE_FREEBSD_OS ) \
96 || defined(HAVE_OPENBSD_OS)
98 #include <sys/param.h>
99 #include <sys/mount.h>
101 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
103 char *fname = ff_pkt->fname;
106 if (statfs(fname, &st) == 0) {
107 bstrncpy(fs, st.f_fstypename, fslen);
110 Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
113 #elif defined(HAVE_NETBSD_OS)
114 #include <sys/param.h>
115 #include <sys/mount.h>
116 #ifdef HAVE_SYS_STATVFS_H
117 #include <sys/statvfs.h>
119 #define statvfs statfs
122 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
124 char *fname = ff_pkt->fname;
126 if (statvfs(fname, &st) == 0) {
127 bstrncpy(fs, st.f_fstypename, fslen);
130 Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
133 #elif defined(HAVE_HPUX_OS) \
134 || defined(HAVE_IRIX_OS)
136 #include <sys/types.h>
137 #include <sys/statvfs.h>
139 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
141 char *fname = ff_pkt->fname;
143 if (statvfs(fname, &st) == 0) {
144 bstrncpy(fs, st.f_basetype, fslen);
147 Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
151 #elif defined(HAVE_LINUX_OS)
157 * Linux statfs() does not return the filesystem name type. It
158 * only returns a binary fstype, so we must look up the type name
161 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
163 char *fname = ff_pkt->fname;
167 if (statfs(fname, &st) == 0) {
168 mtab_item *item, search_item;
169 if (*ff_pkt->last_fstypename && ff_pkt->last_fstype == (uint64_t)st.f_type) {
170 bstrncpy(fs, ff_pkt->last_fstypename, fslen);
173 if (!ff_pkt->mtab_list) {
174 ff_pkt->mtab_list = New(rblist());
175 read_mtab(add_mtab_item, ff_pkt->mtab_list);
177 search_item.dev = st.f_type;
178 item = (mtab_item *)ff_pkt->mtab_list->search((void *)&search_item, compare_mtab_items);
180 ff_pkt->last_fstype = st.f_type;
181 bstrncpy(ff_pkt->last_fstypename, item->fstype, sizeof(ff_pkt->last_fstypename));
182 bstrncpy(fs, ff_pkt->last_fstypename, fslen);
186 * Values obtained from statfs(2), testing and
188 * $ grep -r SUPER_MAGIC /usr/include/linux
191 /* Known good values */
192 /* ext2, ext3, and ext4 have the same code */
193 case 0xef53: fstype = "ext2"; break; /* EXT2_SUPER_MAGIC */
194 case 0x3153464a: fstype = "jfs"; break; /* JFS_SUPER_MAGIC */
195 case 0x5346544e: fstype = "ntfs"; break; /* NTFS_SB_MAGIC */
196 case 0x9fa0: fstype = "proc"; break; /* PROC_SUPER_MAGIC */
197 case 0x52654973: fstype = "reiserfs"; break; /* REISERFS_SUPER_MAGIC */
198 case 0x58465342: fstype = "xfs"; break; /* XFS_SB_MAGIC */
199 case 0x9fa2: fstype = "usbdevfs"; break; /* USBDEVICE_SUPER_MAGIC */
200 case 0x62656572: fstype = "sysfs"; break; /* SYSFS_MAGIC */
201 case 0x517B: fstype = "smbfs"; break; /* SMB_SUPER_MAGIC */
202 case 0x9660: fstype = "iso9660"; break; /* ISOFS_SUPER_MAGIC */
203 case 0xadf5: fstype = "adfs"; break; /* ADFS_SUPER_MAGIC */
204 case 0xadff: fstype = "affs"; break; /* AFFS_SUPER_MAGIC */
205 case 0x42465331: fstype = "befs"; break; /* BEFS_SUPER_MAGIC */
206 case 0xFF534D42: fstype = "cifs"; break; /* CIFS_MAGIC_NUMBER */
207 case 0x73757245: fstype = "coda"; break; /* CODA_SUPER_MAGIC */
208 case 0x012ff7b7: fstype = "coherent"; break; /* COH_SUPER_MAGIC */
209 case 0x28cd3d45: fstype = "cramfs"; break; /* CRAMFS_MAGIC */
210 case 0x1373: fstype = "devfs"; break; /* DEVFS_SUPER_MAGIC */
211 case 0x414A53: fstype = "efs"; break; /* EFS_SUPER_MAGIC */
212 case 0x137d: fstype = "ext"; break; /* EXT_SUPER_MAGIC */
213 case 0xef51: fstype = "oldext2"; break; /* EXT2_OLD_SUPER_MAGIC */
214 case 0x4244: fstype = "hfs"; break; /* EXT2_OLD_SUPER_MAGIC */
215 case 0xf995e849: fstype = "hpfs"; break; /* HPFS_SUPER_MAGIC */
216 case 0x958458f6: fstype = "hugetlbfs"; break; /* HUGETLBFS_MAGIC */
217 case 0x72b6: fstype = "jffs2"; break; /* JFFS2_SUPER_MAGIC */
218 case 0x2468: fstype = "minix"; break; /* MINIX2_SUPER_MAGIC */
219 case 0x2478: fstype = "minix"; break; /* MINIX2_SUPER_MAGIC2 */
220 case 0x137f: fstype = "minix"; break; /* MINIX_SUPER_MAGIC */
221 case 0x138f: fstype = "minix"; break; /* MINIX_SUPER_MAGIC2 */
222 case 0x4d44: fstype = "msdos"; break; /* MSDOS_SUPER_MAGIC */
223 case 0x564c: fstype = "ncpfs"; break; /* NCP_SUPER_MAGIC */
224 case 0x6969: fstype = "nfs"; break; /* NFS_SUPER_MAGIC */
225 case 0x9fa1: fstype = "openpromfs"; break; /* OPENPROM_SUPER_MAGIC */
226 case 0x002f: fstype = "qnx4"; break; /* QNX4_SUPER_MAGIC */
227 case 0x7275: fstype = "romfs"; break; /* QNX4_SUPER_MAGIC */
228 case 0x012ff7b6: fstype = "sysv2"; break;
229 case 0x012ff7b5: fstype = "sysv4"; break;
230 case 0x01021994: fstype = "tmpfs"; break;
231 case 0x15013346: fstype = "udf"; break;
232 case 0x00011954: fstype = "ufs"; break;
233 case 0xa501FCF5: fstype = "vxfs"; break;
234 case 0x012FF7B4: fstype = "xenix"; break;
235 case 0x012FD16D: fstype = "xiafs"; break;
236 case 0x9123683e: fstype = "btrfs"; break;
238 #if 0 /* These need confirmation */
239 case 0x6B414653: fstype = "afs"; break; /* AFS_FS_MAGIC */
240 case 0x0187: fstype = "autofs"; break; /* AUTOFS_SUPER_MAGIC */
241 case 0x62646576: fstype = "bdev"; break; /* ??? */
242 case 0x1BADFACE: fstype = "bfs"; break; /* BFS_MAGIC */
243 case 0x42494e4d: fstype = "binfmt_misc"; break; /* ??? */
244 case (('C'<<8)|'N'): fstype = "capifs"; break; /* CAPIFS_SUPER_MAGIC */
245 case 0x1cd1: fstype = "devpts"; break; /* ??? */
246 case 0x03111965: fstype = "eventpollfs"; break; /* EVENTPOLLFS_MAGIC */
247 case 0xBAD1DEA: fstype = "futexfs"; break; /* ??? */
248 case 0xaee71ee7: fstype = "gadgetfs"; break; /* GADGETFS_MAGIC */
249 case 0x00c0ffee: fstype = "hostfs"; break; /* HOSTFS_SUPER_MAGIC */
250 case 0xb00000ee: fstype = "hppfs"; break; /* HPPFS_SUPER_MAGIC */
251 case 0x12061983: fstype = "hwgfs"; break; /* HWGFS_MAGIC */
252 case 0x66726f67: fstype = "ibmasmfs"; break; /* IBMASMFS_MAGIC */
253 case 0x19800202: fstype = "mqueue"; break; /* MQUEUE_MAGIC */
254 case 0x6f70726f: fstype = "oprofilefs"; break; /* OPROFILEFS_MAGIC */
255 case 0xa0b4d889: fstype = "pfmfs"; break; /* PFMFS_MAGIC */
256 case 0x50495045: fstype = "pipfs"; break; /* PIPEFS_MAGIC */
257 case 0x858458f6: fstype = "ramfs"; break; /* RAMFS_MAGIC */
258 case 0x7275: fstype = "romfs"; break; /* ROMFS_MAGIC */
259 case 0x858458f6: fstype = "rootfs"; break; /* RAMFS_MAGIC */
260 case 0x67596969: fstype = "rpc_pipefs"; break; /* RPCAUTH_GSSMAGIC */
261 case 0x534F434B: fstype = "sockfs"; break; /* SOCKFS_MAGIC */
262 case 0x858458f6: fstype = "tmpfs"; break; /* RAMFS_MAGIC */
263 case 0x01021994: fstype = "tmpfs"; break; /* TMPFS_MAGIC */
267 Dmsg2(10, "Unknown file system type \"0x%x\" for \"%s\".\n", st.f_type,
271 ff_pkt->last_fstype = st.f_type;
272 bstrncpy(ff_pkt->last_fstypename, fstype, sizeof(ff_pkt->last_fstypename));
273 bstrncpy(fs, fstype, fslen);
276 Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
280 #elif defined(HAVE_SUN_OS)
282 #include <sys/types.h>
283 #include <sys/stat.h>
285 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
287 /* Solaris has the filesystem type name in the lstat packet */
288 bstrncpy(fs, ff_pkt->statp.st_fstype, fslen);
292 #elif defined (__digital__) && defined (__unix__) /* Tru64 */
294 #include <sys/stat.h>
295 #include <sys/mount.h>
296 #include <sys/mnttab.h>
298 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
300 char *fname = ff_pkt->fname;
302 if (statfs((char *)fname, &st) == 0) {
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 */
308 Dmsg2(10, "Unknown file system type \"0x%x\" for \"%s\".\n", st.f_type,
313 Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
318 #elif defined (HAVE_WIN32)
320 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
322 char *fname = ff_pkt->fname;
323 DWORD componentlength;
329 /* Copy Drive Letter, colon, and backslash to rootpath */
330 bstrncpy(rootpath, fname, sizeof(rootpath));
332 /* We don't want any popups if there isn't any media in the drive */
333 oldmode = SetErrorMode(SEM_FAILCRITICALERRORS);
334 result = GetVolumeInformation(rootpath, NULL, 0, NULL, &componentlength, &fsflags, fs, fslen);
335 SetErrorMode(oldmode);
338 /* Windows returns NTFS, FAT, etc. Make it lowercase to be consistent with other OSes */
341 Dmsg2(10, "GetVolumeInformation() failed for \"%s\", Error = %d.\n", rootpath, GetLastError());
347 #else /* No recognised OS */
349 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
351 char *fname = ff_pkt->fname;
352 Dmsg0(10, "!!! fstype() not implemented for this OS. !!!\n");
357 /* Read mtab entries */
358 bool read_mtab(mtab_handler_t *mtab_handler, void *user_ctx)
360 #ifdef HAVE_GETMNTENT
367 if ((mntfp = setmntent("/proc/mounts", "r")) == NULL) {
368 if ((mntfp = setmntent(_PATH_MOUNTED, "r")) == NULL) {
373 while ((mnt = getmntent(mntfp)) != NULL) {
374 if (is_rootfs(mnt->mnt_type)) {
378 if (stat(mnt->mnt_dir, &st) < 0) {
381 mtab_handler(user_ctx, &st, mnt->mnt_type, mnt->mnt_dir,
382 mnt->mnt_opts, mnt->mnt_fsname);
392 if ((mntfp = bfopen(MNTTAB, "r")) == NULL) {
397 while (getmntent(mntfp, &mnt) == 0) {
398 if (is_rootfs(mnt.mnt_fstype)) {
401 if (stat(mnt.mnt_mountp, &st) < 0) {
404 mtab_handler(user_ctx, &st, mnt.mnt_fstype, mnt.mnt_mountp,
405 mnt.mnt_mntopts, mnt.mnt_special);
411 #endif /* HAVE_GETMNTENT */
413 #ifdef HAVE_GETMNTINFO
415 #if defined(ST_NOWAIT)
416 int flags = ST_NOWAIT;
417 #elif defined(MNT_NOWAIT)
418 int flags = MNT_NOWAIT;
422 #if defined(HAVE_NETBSD_OS)
423 struct statvfs *mntinfo;
425 struct statfs *mntinfo;
430 if ((nument = getmntinfo(&mntinfo, flags)) > 0) {
431 while (nument-- > 0) {
432 if (is_rootfs(mntinfo->f_fstypename)) {
435 if (stat(mntinfo->f_mntonname, &st) < 0) {
438 mtab_handler(user_ctx, &st, mntinfo->f_mntfromname,
439 mntinfo->f_mntonname, mntinfo->f_fstypename, NULL);
444 #endif /* HAVE_GETMNTINFO */
449 int main(int argc, char **argv)
456 p = (argc < 1) ? "fstype" : argv[0];
457 printf("usage:\t%s path ...\n"
458 "\t%s prints the file system type and pathname of the paths.\n",
463 if (!fstype(*argv, fs, sizeof(fs))) {
464 status = EXIT_FAILURE;
466 printf("%s\t%s\n", fs, *argv);