2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2015 Kern Sibbald
5 Copyright (C) 2004-2014 Free Software Foundation Europe e.V.
7 The original author of Bacula is Kern Sibbald, with contributions
8 from many others, a complete list can be found in the file AUTHORS.
10 You may use this file and others of this release according to the
11 license defined in the LICENSE file, which includes the Affero General
12 Public License, v3.0 ("AGPLv3") and some additional permissions and
13 terms pursuant to its AGPLv3 Section 7.
15 This notice must be preserved when any source code is
16 conveyed and/or propagated.
18 Bacula(R) is a registered trademark of Kern Sibbald.
21 * Implement routines to determine file system types.
23 * Written by Preben 'Peppe' Guldberg, December MMIV
24 * Updated by Kern Sibbald, April MMXV
32 #include <sys/types.h>
35 #else /* Set up for testing a stand alone program */
40 #define bstrncpy strncpy
41 #define Dmsg0(n,s) fprintf(stderr, s)
42 #define Dmsg1(n,s,a1) fprintf(stderr, s, a1)
43 #define Dmsg2(n,s,a1,a2) fprintf(stderr, s, a1, a2)
46 #define is_rootfs(x) bstrcmp("rootfs", x)
48 #if defined(HAVE_GETMNTINFO) || defined(HAVE_GETMNTENT)
49 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
58 /* Compare two device types */
59 static int compare_mtab_items(void *item1, void *item2)
61 mtab_item *mtab1, *mtab2;
62 mtab1 = (mtab_item *)item1;
63 mtab2 = (mtab_item *)item2;
64 if (mtab1->dev < mtab2->dev) return -1;
65 if (mtab1->dev > mtab2->dev) return 1;
69 void add_mtab_item(void *user_ctx, struct stat *st, const char *fstype,
70 const char *mountpoint, const char *mntopts,
73 rblist *mtab_list = (rblist *)user_ctx;
74 mtab_item *item, *ritem;
75 int len = strlen(fstype) + 1;
77 item = (mtab_item *)malloc(sizeof(mtab_item) + len);
78 item->dev = (uint64_t)st->st_dev;
79 bstrncpy(item->fstype, fstype, len);
80 ritem = (mtab_item *)mtab_list->insert((void *)item, compare_mtab_items);
82 /* Item already inserted, so we discard this one */
89 * These functions should be implemented for each OS
91 * bool fstype(FF_PKT *ff_pkt, char *fs, int fslen);
93 #if defined(HAVE_DARWIN_OS) \
94 || defined(HAVE_FREEBSD_OS ) \
95 || defined(HAVE_OPENBSD_OS)
97 #include <sys/param.h>
98 #include <sys/mount.h>
100 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
102 char *fname = ff_pkt->fname;
105 if (statfs(fname, &st) == 0) {
106 bstrncpy(fs, st.f_fstypename, fslen);
109 Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
112 #elif defined(HAVE_NETBSD_OS)
113 #include <sys/param.h>
114 #include <sys/mount.h>
115 #ifdef HAVE_SYS_STATVFS_H
116 #include <sys/statvfs.h>
118 #define statvfs statfs
121 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
123 char *fname = ff_pkt->fname;
125 if (statvfs(fname, &st) == 0) {
126 bstrncpy(fs, st.f_fstypename, fslen);
129 Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
132 #elif defined(HAVE_HPUX_OS) \
133 || defined(HAVE_IRIX_OS)
135 #include <sys/types.h>
136 #include <sys/statvfs.h>
138 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
140 char *fname = ff_pkt->fname;
142 if (statvfs(fname, &st) == 0) {
143 bstrncpy(fs, st.f_basetype, fslen);
146 Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
150 #elif defined(HAVE_LINUX_OS)
156 * Linux statfs() does not return the filesystem name type. It
157 * only returns a binary fstype, so we must look up the type name
160 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
162 char *fname = ff_pkt->fname;
166 if (statfs(fname, &st) == 0) {
167 mtab_item *item, search_item;
168 if (ff_pkt->last_fstypename && ff_pkt->last_fstype == (uint64_t)st.f_type) {
169 bstrncpy(fs, ff_pkt->last_fstypename, fslen);
172 if (!ff_pkt->mtab_list) {
173 ff_pkt->mtab_list = New(rblist());
174 read_mtab(add_mtab_item, ff_pkt->mtab_list);
176 search_item.dev = st.f_type;
177 item = (mtab_item *)ff_pkt->mtab_list->search((void *)&search_item, compare_mtab_items);
179 ff_pkt->last_fstype = st.f_type;
180 bstrncpy(ff_pkt->last_fstypename, item->fstype, sizeof(ff_pkt->last_fstype));
181 bstrncpy(fs, ff_pkt->last_fstypename, fslen);
185 * Values obtained from statfs(2), testing and
187 * $ grep -r SUPER_MAGIC /usr/include/linux
190 /* Known good values */
191 /* ext2, ext3, and ext4 have the same code */
192 case 0xef53: fstype = "ext2"; break; /* EXT2_SUPER_MAGIC */
193 case 0x3153464a: fstype = "jfs"; break; /* JFS_SUPER_MAGIC */
194 case 0x5346544e: fstype = "ntfs"; break; /* NTFS_SB_MAGIC */
195 case 0x9fa0: fstype = "proc"; break; /* PROC_SUPER_MAGIC */
196 case 0x52654973: fstype = "reiserfs"; break; /* REISERFS_SUPER_MAGIC */
197 case 0x58465342: fstype = "xfs"; break; /* XFS_SB_MAGIC */
198 case 0x9fa2: fstype = "usbdevfs"; break; /* USBDEVICE_SUPER_MAGIC */
199 case 0x62656572: fstype = "sysfs"; break; /* SYSFS_MAGIC */
200 case 0x517B: fstype = "smbfs"; break; /* SMB_SUPER_MAGIC */
201 case 0x9660: fstype = "iso9660"; break; /* ISOFS_SUPER_MAGIC */
202 case 0xadf5: fstype = "adfs"; break; /* ADFS_SUPER_MAGIC */
203 case 0xadff: fstype = "affs"; break; /* AFFS_SUPER_MAGIC */
204 case 0x42465331: fstype = "befs"; break; /* BEFS_SUPER_MAGIC */
205 case 0xFF534D42: fstype = "cifs"; break; /* CIFS_MAGIC_NUMBER */
206 case 0x73757245: fstype = "coda"; break; /* CODA_SUPER_MAGIC */
207 case 0x012ff7b7: fstype = "coherent"; break; /* COH_SUPER_MAGIC */
208 case 0x28cd3d45: fstype = "cramfs"; break; /* CRAMFS_MAGIC */
209 case 0x1373: fstype = "devfs"; break; /* DEVFS_SUPER_MAGIC */
210 case 0x414A53: fstype = "efs"; break; /* EFS_SUPER_MAGIC */
211 case 0x137d: fstype = "ext"; break; /* EXT_SUPER_MAGIC */
212 case 0xef51: fstype = "oldext2"; break; /* EXT2_OLD_SUPER_MAGIC */
213 case 0x4244: fstype = "hfs"; break; /* EXT2_OLD_SUPER_MAGIC */
214 case 0xf995e849: fstype = "hpfs"; break; /* HPFS_SUPER_MAGIC */
215 case 0x958458f6: fstype = "hugetlbfs"; break; /* HUGETLBFS_MAGIC */
216 case 0x72b6: fstype = "jffs2"; break; /* JFFS2_SUPER_MAGIC */
217 case 0x2468: fstype = "minix"; break; /* MINIX2_SUPER_MAGIC */
218 case 0x2478: fstype = "minix"; break; /* MINIX2_SUPER_MAGIC2 */
219 case 0x137f: fstype = "minix"; break; /* MINIX_SUPER_MAGIC */
220 case 0x138f: fstype = "minix"; break; /* MINIX_SUPER_MAGIC2 */
221 case 0x4d44: fstype = "msdos"; break; /* MSDOS_SUPER_MAGIC */
222 case 0x564c: fstype = "ncpfs"; break; /* NCP_SUPER_MAGIC */
223 case 0x6969: fstype = "nfs"; break; /* NFS_SUPER_MAGIC */
224 case 0x9fa1: fstype = "openpromfs"; break; /* OPENPROM_SUPER_MAGIC */
225 case 0x002f: fstype = "qnx4"; break; /* QNX4_SUPER_MAGIC */
226 case 0x7275: fstype = "romfs"; break; /* QNX4_SUPER_MAGIC */
227 case 0x012ff7b6: fstype = "sysv2"; break;
228 case 0x012ff7b5: fstype = "sysv4"; break;
229 case 0x01021994: fstype = "tempfs"; break;
230 case 0x15013346: fstype = "udf"; break;
231 case 0x00011954: fstype = "ufs"; break;
232 case 0xa501FCF5: fstype = "vxfs"; break;
233 case 0x012FF7B4: fstype = "xenix"; break;
234 case 0x012FD16D: fstype = "xiafs"; break;
237 #if 0 /* These need confirmation */
238 case 0x6B414653: fstype = "afs"; break; /* AFS_FS_MAGIC */
239 case 0x0187: fstype = "autofs"; break; /* AUTOFS_SUPER_MAGIC */
240 case 0x62646576: fstype = "bdev"; break; /* ??? */
241 case 0x1BADFACE: fstype = "bfs"; break; /* BFS_MAGIC */
242 case 0x42494e4d: fstype = "binfmt_misc"; break; /* ??? */
243 case (('C'<<8)|'N'): fstype = "capifs"; break; /* CAPIFS_SUPER_MAGIC */
244 case 0x1cd1: fstype = "devpts"; break; /* ??? */
245 case 0x03111965: fstype = "eventpollfs"; break; /* EVENTPOLLFS_MAGIC */
246 case 0xBAD1DEA: fstype = "futexfs"; break; /* ??? */
247 case 0xaee71ee7: fstype = "gadgetfs"; break; /* GADGETFS_MAGIC */
248 case 0x00c0ffee: fstype = "hostfs"; break; /* HOSTFS_SUPER_MAGIC */
249 case 0xb00000ee: fstype = "hppfs"; break; /* HPPFS_SUPER_MAGIC */
250 case 0x12061983: fstype = "hwgfs"; break; /* HWGFS_MAGIC */
251 case 0x66726f67: fstype = "ibmasmfs"; break; /* IBMASMFS_MAGIC */
252 case 0x19800202: fstype = "mqueue"; break; /* MQUEUE_MAGIC */
253 case 0x6f70726f: fstype = "oprofilefs"; break; /* OPROFILEFS_MAGIC */
254 case 0xa0b4d889: fstype = "pfmfs"; break; /* PFMFS_MAGIC */
255 case 0x50495045: fstype = "pipfs"; break; /* PIPEFS_MAGIC */
256 case 0x858458f6: fstype = "ramfs"; break; /* RAMFS_MAGIC */
257 case 0x7275: fstype = "romfs"; break; /* ROMFS_MAGIC */
258 case 0x858458f6: fstype = "rootfs"; break; /* RAMFS_MAGIC */
259 case 0x67596969: fstype = "rpc_pipefs"; break; /* RPCAUTH_GSSMAGIC */
260 case 0x534F434B: fstype = "sockfs"; break; /* SOCKFS_MAGIC */
261 case 0x858458f6: fstype = "tmpfs"; break; /* RAMFS_MAGIC */
262 case 0x01021994: fstype = "tmpfs"; break; /* TMPFS_MAGIC */
266 Dmsg2(10, "Unknown file system type \"0x%x\" for \"%s\".\n", st.f_type,
270 ff_pkt->last_fstype = st.f_type;
271 bstrncpy(ff_pkt->last_fstypename, fstype, sizeof(ff_pkt->last_fstypename));
272 bstrncpy(fs, fstype, fslen);
275 Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
279 #elif defined(HAVE_SUN_OS)
281 #include <sys/types.h>
282 #include <sys/stat.h>
284 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
286 /* Solaris has the filesystem type name in the lstat packet */
287 bstrncpy(fs, ff_pkt->statp.st_fstype, fslen);
291 #elif defined (__digital__) && defined (__unix__) /* Tru64 */
293 #include <sys/stat.h>
294 #include <sys/mount.h>
296 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
298 char *fname = ff_pkt->fname;
300 if (statfs((char *)fname, &st) == 0) {
302 /* Known good values */
303 case 0xa: bstrncpy(fs, "advfs", fslen); return true; /* Tru64 AdvFS */
304 case 0xe: bstrncpy(fs, "nfs", fslen); return true; /* Tru64 NFS */
306 Dmsg2(10, "Unknown file system type \"0x%x\" for \"%s\".\n", st.f_type,
311 Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
316 #else /* No recognised OS */
318 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
320 char *fname = ff_pkt->fname;
321 Dmsg0(10, "!!! fstype() not implemented for this OS. !!!\n");
326 /* Read mtab entries */
327 bool read_mtab(mtab_handler_t *mtab_handler, void *user_ctx)
329 #ifdef HAVE_GETMNTENT
336 if ((mntfp = setmntent("/proc/mounts", "r")) == NULL) {
337 if ((mntfp = setmntent(_PATH_MOUNTED, "r")) == NULL) {
342 while ((mnt = getmntent(mntfp)) != NULL) {
343 if (is_rootfs(mnt->mnt_type)) {
347 if (stat(mnt->mnt_dir, &st) < 0) {
350 mtab_handler(user_ctx, &st, mnt->mnt_type, mnt->mnt_dir,
351 mnt->mnt_opts, mnt->mnt_fsname);
361 if ((mntfp = fopen(MNTTAB, "r")) == NULL) {
366 while (getmntent(mntfp, &mnt) == 0) {
367 if (is_rootfs(mnt.mnt_fstype)) {
370 if (stat(mnt.mnt_mountp, &st) < 0) {
373 mtab_handler(user_ctx, &st, mnt.mnt_fstype, mnt.mnt_mountp,
374 mnt.mnt_mntopts, mnt.mnt_special);
380 #endif /* HAVE_GETMNTENT */
382 #ifdef HAVE_GETMNTINFO
384 #if defined(ST_NOWAIT)
385 int flags = ST_NOWAIT;
386 #elif defined(MNT_NOWAIT)
387 int flags = MNT_NOWAIT;
391 #if defined(HAVE_NETBSD_OS)
392 struct statvfs *mntinfo;
394 struct statfs *mntinfo;
399 if ((nument = getmntinfo(&mntinfo, flags)) > 0) {
400 while (nument-- > 0) {
401 if (is_rootfs(mntinfo->f_fstypename)) {
404 if (stat(mntinfo->f_mntonname, &st) < 0) {
407 mtab_handler(user_ctx, &st, mntinfo->f_mntfromname,
408 mntinfo->f_mntonname, mntinfo->f_fstypename, NULL);
413 #endif /* HAVE_GETMNTINFO */
418 int main(int argc, char **argv)
425 p = (argc < 1) ? "fstype" : argv[0];
426 printf("usage:\t%s path ...\n"
427 "\t%s prints the file system type and pathname of the paths.\n",
432 if (!fstype(*argv, fs, sizeof(fs))) {
433 status = EXIT_FAILURE;
435 printf("%s\t%s\n", fs, *argv);