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 static 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 */
88 /* Compare directly the FS from a fname with a string */
89 bool fstype_cmp(FF_PKT *ff_pkt, const char *fsname)
92 if (fstype(ff_pkt, buf, sizeof(buf))) {
93 return (strcmp(buf, fsname) == 0);
99 * These functions should be implemented for each OS
101 * bool fstype(FF_PKT *ff_pkt, char *fs, int fslen);
103 #if defined(HAVE_DARWIN_OS) \
104 || defined(HAVE_FREEBSD_OS ) \
105 || defined(HAVE_KFREEBSD_OS ) \
106 || defined(HAVE_OPENBSD_OS)
108 #include <sys/param.h>
109 #include <sys/mount.h>
111 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
113 char *fname = ff_pkt->fname;
116 if (statfs(fname, &st) == 0) {
117 bstrncpy(fs, st.f_fstypename, fslen);
120 Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
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>
129 #define statvfs statfs
132 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
134 char *fname = ff_pkt->fname;
136 if (statvfs(fname, &st) == 0) {
137 bstrncpy(fs, st.f_fstypename, fslen);
140 Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
143 #elif defined(HAVE_HPUX_OS) \
144 || defined(HAVE_IRIX_OS)
146 #include <sys/types.h>
147 #include <sys/statvfs.h>
149 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
151 char *fname = ff_pkt->fname;
153 if (statvfs(fname, &st) == 0) {
154 bstrncpy(fs, st.f_basetype, fslen);
157 Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
161 #elif defined(HAVE_LINUX_OS)
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
171 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
173 char *fname = ff_pkt->fname;
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);
183 if (!ff_pkt->mtab_list) {
184 ff_pkt->mtab_list = New(rblist());
185 read_mtab(add_mtab_item, ff_pkt->mtab_list);
187 search_item.dev = st.f_type;
188 item = (mtab_item *)ff_pkt->mtab_list->search((void *)&search_item, compare_mtab_items);
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);
196 * Values obtained from statfs(2), testing and
198 * $ grep -r SUPER_MAGIC /usr/include/linux
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;
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 */
277 Dmsg2(10, "Unknown file system type \"0x%x\" for \"%s\".\n", st.f_type,
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);
286 Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
290 #elif defined(HAVE_SUN_OS)
292 #include <sys/types.h>
293 #include <sys/stat.h>
294 #include <sys/mnttab.h>
296 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
298 /* Solaris has the filesystem type name in the lstat packet */
299 bstrncpy(fs, ff_pkt->statp.st_fstype, fslen);
303 #elif defined (__digital__) && defined (__unix__) /* Tru64 */
305 #include <sys/stat.h>
306 #include <sys/mount.h>
308 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
310 char *fname = ff_pkt->fname;
312 if (statfs((char *)fname, &st) == 0) {
314 /* Known good values */
315 case 0xa: bstrncpy(fs, "advfs", fslen); return true; /* Tru64 AdvFS */
316 case 0xe: bstrncpy(fs, "nfs", fslen); return true; /* Tru64 NFS */
318 Dmsg2(10, "Unknown file system type \"0x%x\" for \"%s\".\n", st.f_type,
323 Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
328 #else /* No recognised OS */
330 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
332 char *fname = ff_pkt->fname;
333 Dmsg0(10, "!!! fstype() not implemented for this OS. !!!\n");
338 /* Read mtab entries */
339 bool read_mtab(mtab_handler_t *mtab_handler, void *user_ctx)
341 /* Debian stretch GNU/KFreeBSD has both getmntinfo and getmntent, but
342 only the first seems to work, so ordering is important here */
343 #ifdef HAVE_GETMNTINFO
345 #if defined(ST_NOWAIT)
346 int flags = ST_NOWAIT;
347 #elif defined(MNT_NOWAIT)
348 int flags = MNT_NOWAIT;
352 #if defined(HAVE_NETBSD_OS)
353 struct statvfs *mntinfo;
355 struct statfs *mntinfo;
360 if ((nument = getmntinfo(&mntinfo, flags)) > 0) {
361 while (nument-- > 0) {
362 if (is_rootfs(mntinfo->f_fstypename)) {
365 if (stat(mntinfo->f_mntonname, &st) < 0) {
368 mtab_handler(user_ctx, &st, mntinfo->f_mntfromname,
369 mntinfo->f_mntonname, mntinfo->f_fstypename, NULL);
374 /* HAVE_GETMNTINFO */
375 #elif defined(HAVE_GETMNTENT)
382 if ((mntfp = setmntent("/proc/mounts", "r")) == NULL) {
383 if ((mntfp = setmntent(_PATH_MOUNTED, "r")) == NULL) {
388 while ((mnt = getmntent(mntfp)) != NULL) {
389 if (is_rootfs(mnt->mnt_type)) {
393 if (stat(mnt->mnt_dir, &st) < 0) {
396 mtab_handler(user_ctx, &st, mnt->mnt_type, mnt->mnt_dir,
397 mnt->mnt_opts, mnt->mnt_fsname);
407 if ((mntfp = bfopen(MNTTAB, "r")) == NULL) {
412 while (getmntent(mntfp, &mnt) == 0) {
413 if (is_rootfs(mnt.mnt_fstype)) {
416 if (stat(mnt.mnt_mountp, &st) < 0) {
419 mtab_handler(user_ctx, &st, mnt.mnt_fstype, mnt.mnt_mountp,
420 mnt.mnt_mntopts, mnt.mnt_special);
426 #endif /* HAVE_GETMNTENT */
431 int main(int argc, char **argv)
438 p = (argc < 1) ? "fstype" : argv[0];
439 printf("usage:\t%s path ...\n"
440 "\t%s prints the file system type and pathname of the paths.\n",
445 if (!fstype(*argv, fs, sizeof(fs))) {
446 status = EXIT_FAILURE;
448 printf("%s\t%s\n", fs, *argv);