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 #include <sys/mnttab.h>
37 #else /* Set up for testing a stand alone program */
42 #define bstrncpy strncpy
43 #define Dmsg0(n,s) fprintf(stderr, s)
44 #define Dmsg1(n,s,a1) fprintf(stderr, s, a1)
45 #define Dmsg2(n,s,a1,a2) fprintf(stderr, s, a1, a2)
48 #define is_rootfs(x) bstrcmp("rootfs", x)
50 #if defined(HAVE_GETMNTINFO) || defined(HAVE_GETMNTENT)
51 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
60 /* Compare two device types */
61 static int compare_mtab_items(void *item1, void *item2)
63 mtab_item *mtab1, *mtab2;
64 mtab1 = (mtab_item *)item1;
65 mtab2 = (mtab_item *)item2;
66 if (mtab1->dev < mtab2->dev) return -1;
67 if (mtab1->dev > mtab2->dev) return 1;
71 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 */
89 /* Compare directly the FS from a fname with a string */
90 bool fstype_cmp(FF_PKT *ff_pkt, const char *fsname)
93 if (fstype(ff_pkt, buf, sizeof(buf))) {
94 return (strcmp(buf, fsname) == 0);
100 * These functions should be implemented for each OS
102 * bool fstype(FF_PKT *ff_pkt, char *fs, int fslen);
104 #if defined(HAVE_DARWIN_OS) \
105 || defined(HAVE_FREEBSD_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>
295 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
297 /* Solaris has the filesystem type name in the lstat packet */
298 bstrncpy(fs, ff_pkt->statp.st_fstype, fslen);
302 #elif defined (__digital__) && defined (__unix__) /* Tru64 */
304 #include <sys/stat.h>
305 #include <sys/mount.h>
307 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
309 char *fname = ff_pkt->fname;
311 if (statfs((char *)fname, &st) == 0) {
313 /* Known good values */
314 case 0xa: bstrncpy(fs, "advfs", fslen); return true; /* Tru64 AdvFS */
315 case 0xe: bstrncpy(fs, "nfs", fslen); return true; /* Tru64 NFS */
317 Dmsg2(10, "Unknown file system type \"0x%x\" for \"%s\".\n", st.f_type,
322 Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
327 #else /* No recognised OS */
329 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
331 char *fname = ff_pkt->fname;
332 Dmsg0(10, "!!! fstype() not implemented for this OS. !!!\n");
337 /* Read mtab entries */
338 bool read_mtab(mtab_handler_t *mtab_handler, void *user_ctx)
340 #ifdef HAVE_GETMNTENT
347 if ((mntfp = setmntent("/proc/mounts", "r")) == NULL) {
348 if ((mntfp = setmntent(_PATH_MOUNTED, "r")) == NULL) {
353 while ((mnt = getmntent(mntfp)) != NULL) {
354 if (is_rootfs(mnt->mnt_type)) {
358 if (stat(mnt->mnt_dir, &st) < 0) {
361 mtab_handler(user_ctx, &st, mnt->mnt_type, mnt->mnt_dir,
362 mnt->mnt_opts, mnt->mnt_fsname);
372 if ((mntfp = fopen(MNTTAB, "r")) == NULL) {
377 while (getmntent(mntfp, &mnt) == 0) {
378 if (is_rootfs(mnt.mnt_fstype)) {
381 if (stat(mnt.mnt_mountp, &st) < 0) {
384 mtab_handler(user_ctx, &st, mnt.mnt_fstype, mnt.mnt_mountp,
385 mnt.mnt_mntopts, mnt.mnt_special);
391 #endif /* HAVE_GETMNTENT */
393 #ifdef HAVE_GETMNTINFO
395 #if defined(ST_NOWAIT)
396 int flags = ST_NOWAIT;
397 #elif defined(MNT_NOWAIT)
398 int flags = MNT_NOWAIT;
402 #if defined(HAVE_NETBSD_OS)
403 struct statvfs *mntinfo;
405 struct statfs *mntinfo;
410 if ((nument = getmntinfo(&mntinfo, flags)) > 0) {
411 while (nument-- > 0) {
412 if (is_rootfs(mntinfo->f_fstypename)) {
415 if (stat(mntinfo->f_mntonname, &st) < 0) {
418 mtab_handler(user_ctx, &st, mntinfo->f_mntfromname,
419 mntinfo->f_mntonname, mntinfo->f_fstypename, NULL);
424 #endif /* HAVE_GETMNTINFO */
429 int main(int argc, char **argv)
436 p = (argc < 1) ? "fstype" : argv[0];
437 printf("usage:\t%s path ...\n"
438 "\t%s prints the file system type and pathname of the paths.\n",
443 if (!fstype(*argv, fs, sizeof(fs))) {
444 status = EXIT_FAILURE;
446 printf("%s\t%s\n", fs, *argv);