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 */
91 * These functions should be implemented for each OS
93 * bool fstype(FF_PKT *ff_pkt, char *fs, int fslen);
95 #if defined(HAVE_DARWIN_OS) \
96 || defined(HAVE_FREEBSD_OS ) \
97 || defined(HAVE_OPENBSD_OS)
99 #include <sys/param.h>
100 #include <sys/mount.h>
102 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
104 char *fname = ff_pkt->fname;
107 if (statfs(fname, &st) == 0) {
108 bstrncpy(fs, st.f_fstypename, fslen);
111 Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
114 #elif defined(HAVE_NETBSD_OS)
115 #include <sys/param.h>
116 #include <sys/mount.h>
117 #ifdef HAVE_SYS_STATVFS_H
118 #include <sys/statvfs.h>
120 #define statvfs statfs
123 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
125 char *fname = ff_pkt->fname;
127 if (statvfs(fname, &st) == 0) {
128 bstrncpy(fs, st.f_fstypename, fslen);
131 Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
134 #elif defined(HAVE_HPUX_OS) \
135 || defined(HAVE_IRIX_OS)
137 #include <sys/types.h>
138 #include <sys/statvfs.h>
140 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
142 char *fname = ff_pkt->fname;
144 if (statvfs(fname, &st) == 0) {
145 bstrncpy(fs, st.f_basetype, fslen);
148 Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
152 #elif defined(HAVE_LINUX_OS)
158 * Linux statfs() does not return the filesystem name type. It
159 * only returns a binary fstype, so we must look up the type name
162 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
164 char *fname = ff_pkt->fname;
168 if (statfs(fname, &st) == 0) {
169 mtab_item *item, search_item;
170 if (ff_pkt->last_fstypename && ff_pkt->last_fstype == (uint64_t)st.f_type) {
171 bstrncpy(fs, ff_pkt->last_fstypename, fslen);
174 if (!ff_pkt->mtab_list) {
175 ff_pkt->mtab_list = New(rblist());
176 read_mtab(add_mtab_item, ff_pkt->mtab_list);
178 search_item.dev = st.f_type;
179 item = (mtab_item *)ff_pkt->mtab_list->search((void *)&search_item, compare_mtab_items);
181 ff_pkt->last_fstype = st.f_type;
182 bstrncpy(ff_pkt->last_fstypename, item->fstype, sizeof(ff_pkt->last_fstype));
183 bstrncpy(fs, ff_pkt->last_fstypename, fslen);
187 * Values obtained from statfs(2), testing and
189 * $ grep -r SUPER_MAGIC /usr/include/linux
192 /* Known good values */
193 /* ext2, ext3, and ext4 have the same code */
194 case 0xef53: fstype = "ext2"; break; /* EXT2_SUPER_MAGIC */
195 case 0x3153464a: fstype = "jfs"; break; /* JFS_SUPER_MAGIC */
196 case 0x5346544e: fstype = "ntfs"; break; /* NTFS_SB_MAGIC */
197 case 0x9fa0: fstype = "proc"; break; /* PROC_SUPER_MAGIC */
198 case 0x52654973: fstype = "reiserfs"; break; /* REISERFS_SUPER_MAGIC */
199 case 0x58465342: fstype = "xfs"; break; /* XFS_SB_MAGIC */
200 case 0x9fa2: fstype = "usbdevfs"; break; /* USBDEVICE_SUPER_MAGIC */
201 case 0x62656572: fstype = "sysfs"; break; /* SYSFS_MAGIC */
202 case 0x517B: fstype = "smbfs"; break; /* SMB_SUPER_MAGIC */
203 case 0x9660: fstype = "iso9660"; break; /* ISOFS_SUPER_MAGIC */
204 case 0xadf5: fstype = "adfs"; break; /* ADFS_SUPER_MAGIC */
205 case 0xadff: fstype = "affs"; break; /* AFFS_SUPER_MAGIC */
206 case 0x42465331: fstype = "befs"; break; /* BEFS_SUPER_MAGIC */
207 case 0xFF534D42: fstype = "cifs"; break; /* CIFS_MAGIC_NUMBER */
208 case 0x73757245: fstype = "coda"; break; /* CODA_SUPER_MAGIC */
209 case 0x012ff7b7: fstype = "coherent"; break; /* COH_SUPER_MAGIC */
210 case 0x28cd3d45: fstype = "cramfs"; break; /* CRAMFS_MAGIC */
211 case 0x1373: fstype = "devfs"; break; /* DEVFS_SUPER_MAGIC */
212 case 0x414A53: fstype = "efs"; break; /* EFS_SUPER_MAGIC */
213 case 0x137d: fstype = "ext"; break; /* EXT_SUPER_MAGIC */
214 case 0xef51: fstype = "oldext2"; break; /* EXT2_OLD_SUPER_MAGIC */
215 case 0x4244: fstype = "hfs"; break; /* EXT2_OLD_SUPER_MAGIC */
216 case 0xf995e849: fstype = "hpfs"; break; /* HPFS_SUPER_MAGIC */
217 case 0x958458f6: fstype = "hugetlbfs"; break; /* HUGETLBFS_MAGIC */
218 case 0x72b6: fstype = "jffs2"; break; /* JFFS2_SUPER_MAGIC */
219 case 0x2468: fstype = "minix"; break; /* MINIX2_SUPER_MAGIC */
220 case 0x2478: fstype = "minix"; break; /* MINIX2_SUPER_MAGIC2 */
221 case 0x137f: fstype = "minix"; break; /* MINIX_SUPER_MAGIC */
222 case 0x138f: fstype = "minix"; break; /* MINIX_SUPER_MAGIC2 */
223 case 0x4d44: fstype = "msdos"; break; /* MSDOS_SUPER_MAGIC */
224 case 0x564c: fstype = "ncpfs"; break; /* NCP_SUPER_MAGIC */
225 case 0x6969: fstype = "nfs"; break; /* NFS_SUPER_MAGIC */
226 case 0x9fa1: fstype = "openpromfs"; break; /* OPENPROM_SUPER_MAGIC */
227 case 0x002f: fstype = "qnx4"; break; /* QNX4_SUPER_MAGIC */
228 case 0x7275: fstype = "romfs"; break; /* QNX4_SUPER_MAGIC */
229 case 0x012ff7b6: fstype = "sysv2"; break;
230 case 0x012ff7b5: fstype = "sysv4"; break;
231 case 0x01021994: fstype = "tempfs"; break;
232 case 0x15013346: fstype = "udf"; break;
233 case 0x00011954: fstype = "ufs"; break;
234 case 0xa501FCF5: fstype = "vxfs"; break;
235 case 0x012FF7B4: fstype = "xenix"; break;
236 case 0x012FD16D: fstype = "xiafs"; break;
239 #if 0 /* These need confirmation */
240 case 0x6B414653: fstype = "afs"; break; /* AFS_FS_MAGIC */
241 case 0x0187: fstype = "autofs"; break; /* AUTOFS_SUPER_MAGIC */
242 case 0x62646576: fstype = "bdev"; break; /* ??? */
243 case 0x1BADFACE: fstype = "bfs"; break; /* BFS_MAGIC */
244 case 0x42494e4d: fstype = "binfmt_misc"; break; /* ??? */
245 case (('C'<<8)|'N'): fstype = "capifs"; break; /* CAPIFS_SUPER_MAGIC */
246 case 0x1cd1: fstype = "devpts"; break; /* ??? */
247 case 0x03111965: fstype = "eventpollfs"; break; /* EVENTPOLLFS_MAGIC */
248 case 0xBAD1DEA: fstype = "futexfs"; break; /* ??? */
249 case 0xaee71ee7: fstype = "gadgetfs"; break; /* GADGETFS_MAGIC */
250 case 0x00c0ffee: fstype = "hostfs"; break; /* HOSTFS_SUPER_MAGIC */
251 case 0xb00000ee: fstype = "hppfs"; break; /* HPPFS_SUPER_MAGIC */
252 case 0x12061983: fstype = "hwgfs"; break; /* HWGFS_MAGIC */
253 case 0x66726f67: fstype = "ibmasmfs"; break; /* IBMASMFS_MAGIC */
254 case 0x19800202: fstype = "mqueue"; break; /* MQUEUE_MAGIC */
255 case 0x6f70726f: fstype = "oprofilefs"; break; /* OPROFILEFS_MAGIC */
256 case 0xa0b4d889: fstype = "pfmfs"; break; /* PFMFS_MAGIC */
257 case 0x50495045: fstype = "pipfs"; break; /* PIPEFS_MAGIC */
258 case 0x858458f6: fstype = "ramfs"; break; /* RAMFS_MAGIC */
259 case 0x7275: fstype = "romfs"; break; /* ROMFS_MAGIC */
260 case 0x858458f6: fstype = "rootfs"; break; /* RAMFS_MAGIC */
261 case 0x67596969: fstype = "rpc_pipefs"; break; /* RPCAUTH_GSSMAGIC */
262 case 0x534F434B: fstype = "sockfs"; break; /* SOCKFS_MAGIC */
263 case 0x858458f6: fstype = "tmpfs"; break; /* RAMFS_MAGIC */
264 case 0x01021994: fstype = "tmpfs"; break; /* TMPFS_MAGIC */
268 Dmsg2(10, "Unknown file system type \"0x%x\" for \"%s\".\n", st.f_type,
272 ff_pkt->last_fstype = st.f_type;
273 bstrncpy(ff_pkt->last_fstypename, fstype, sizeof(ff_pkt->last_fstypename));
274 bstrncpy(fs, fstype, fslen);
277 Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
281 #elif defined(HAVE_SUN_OS)
283 #include <sys/types.h>
284 #include <sys/stat.h>
286 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
288 /* Solaris has the filesystem type name in the lstat packet */
289 bstrncpy(fs, ff_pkt->statp.st_fstype, fslen);
293 #elif defined (__digital__) && defined (__unix__) /* Tru64 */
295 #include <sys/stat.h>
296 #include <sys/mount.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 #else /* No recognised OS */
320 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
322 char *fname = ff_pkt->fname;
323 Dmsg0(10, "!!! fstype() not implemented for this OS. !!!\n");
328 /* Read mtab entries */
329 bool read_mtab(mtab_handler_t *mtab_handler, void *user_ctx)
331 #ifdef HAVE_GETMNTENT
338 if ((mntfp = setmntent("/proc/mounts", "r")) == NULL) {
339 if ((mntfp = setmntent(_PATH_MOUNTED, "r")) == NULL) {
344 while ((mnt = getmntent(mntfp)) != NULL) {
345 if (is_rootfs(mnt->mnt_type)) {
349 if (stat(mnt->mnt_dir, &st) < 0) {
352 mtab_handler(user_ctx, &st, mnt->mnt_type, mnt->mnt_dir,
353 mnt->mnt_opts, mnt->mnt_fsname);
363 if ((mntfp = fopen(MNTTAB, "r")) == NULL) {
368 while (getmntent(mntfp, &mnt) == 0) {
369 if (is_rootfs(mnt.mnt_fstype)) {
372 if (stat(mnt.mnt_mountp, &st) < 0) {
375 mtab_handler(user_ctx, &st, mnt.mnt_fstype, mnt.mnt_mountp,
376 mnt.mnt_mntopts, mnt.mnt_special);
382 #endif /* HAVE_GETMNTENT */
384 #ifdef HAVE_GETMNTINFO
386 #if defined(ST_NOWAIT)
387 int flags = ST_NOWAIT;
388 #elif defined(MNT_NOWAIT)
389 int flags = MNT_NOWAIT;
393 #if defined(HAVE_NETBSD_OS)
394 struct statvfs *mntinfo;
396 struct statfs *mntinfo;
401 if ((nument = getmntinfo(&mntinfo, flags)) > 0) {
402 while (nument-- > 0) {
403 if (is_rootfs(mntinfo->f_fstypename)) {
406 if (stat(mntinfo->f_mntonname, &st) < 0) {
409 mtab_handler(user_ctx, &st, mntinfo->f_mntfromname,
410 mntinfo->f_mntonname, mntinfo->f_fstypename, NULL);
415 #endif /* HAVE_GETMNTINFO */
420 int main(int argc, char **argv)
427 p = (argc < 1) ? "fstype" : argv[0];
428 printf("usage:\t%s path ...\n"
429 "\t%s prints the file system type and pathname of the paths.\n",
434 if (!fstype(*argv, fs, sizeof(fs))) {
435 status = EXIT_FAILURE;
437 printf("%s\t%s\n", fs, *argv);