]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/findlib/fstype.c
Backport from Bacula Enterprise
[bacula/bacula] / bacula / src / findlib / fstype.c
1 /*
2    Bacula(R) - The Network Backup Solution
3
4    Copyright (C) 2000-2015 Kern Sibbald
5    Copyright (C) 2004-2014 Free Software Foundation Europe e.V.
6
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.
9
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.
14
15    This notice must be preserved when any source code is 
16    conveyed and/or propagated.
17
18    Bacula(R) is a registered trademark of Kern Sibbald.
19 */
20 /*
21  *  Implement routines to determine file system types.
22  *
23  *   Written by Preben 'Peppe' Guldberg, December MMIV
24  *   Updated by Kern Sibbald, April MMXV
25  */
26
27
28 #ifndef TEST_PROGRAM
29
30 #include "bacula.h"
31 #include "find.h"
32 #include <sys/types.h>
33 #include <sys/stat.h>
34
35 #else /* Set up for testing a stand alone program */
36
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
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)
44 #endif
45
46 #define is_rootfs(x) bstrcmp("rootfs", x)
47
48 #if defined(HAVE_GETMNTINFO) || defined(HAVE_GETMNTENT)
49 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
50 #endif
51
52 struct mtab_item {
53    rblink link;
54    uint64_t dev;
55    char fstype[1];
56 };
57
58 /* Compare two device types */
59 static int compare_mtab_items(void *item1, void *item2)
60 {
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;
66    return 0;
67 }
68
69 void add_mtab_item(void *user_ctx, struct stat *st, const char *fstype,
70                       const char *mountpoint, const char *mntopts,
71                       const char *fsname)
72 {
73    rblist *mtab_list = (rblist *)user_ctx;
74    mtab_item *item, *ritem;
75    int len = strlen(fstype) + 1;
76    
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);
81    if (ritem != item) {
82       /* Item already inserted, so we discard this one */
83       free(item);
84    }
85 }
86
87
88 /*
89  * These functions should be implemented for each OS
90  *
91  *       bool fstype(FF_PKT *ff_pkt, char *fs, int fslen);
92  */
93 #if defined(HAVE_DARWIN_OS) \
94    || defined(HAVE_FREEBSD_OS ) \
95    || defined(HAVE_OPENBSD_OS)
96
97 #include <sys/param.h>
98 #include <sys/mount.h>
99
100 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
101 {
102    char *fname = ff_pkt->fname;
103    struct statfs st;
104  
105    if (statfs(fname, &st) == 0) {
106       bstrncpy(fs, st.f_fstypename, fslen);
107       return true;
108    }
109    Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
110    return false;
111 }
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>
117 #else
118 #define statvfs statfs
119 #endif
120
121 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
122 {
123    char *fname = ff_pkt->fname;
124    struct statvfs st;
125    if (statvfs(fname, &st) == 0) {
126       bstrncpy(fs, st.f_fstypename, fslen);
127       return true;
128    }
129    Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
130    return false;
131 }
132 #elif defined(HAVE_HPUX_OS) \
133    || defined(HAVE_IRIX_OS)
134
135 #include <sys/types.h>
136 #include <sys/statvfs.h>
137
138 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
139 {
140    char *fname = ff_pkt->fname;
141    struct statvfs st;
142    if (statvfs(fname, &st) == 0) {
143       bstrncpy(fs, st.f_basetype, fslen);
144       return true;
145    }
146    Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
147    return false;
148 }
149
150 #elif defined(HAVE_LINUX_OS)
151
152 #include <sys/vfs.h>
153 #include <mntent.h>
154
155 /*
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
158  *  in mtab.
159  */
160 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
161 {
162    char *fname = ff_pkt->fname;
163    struct statfs st;
164    const char *fstype;
165
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);
170          return true; 
171       }
172       if (!ff_pkt->mtab_list) {
173          ff_pkt->mtab_list = New(rblist());
174          read_mtab(add_mtab_item, ff_pkt->mtab_list);
175       }
176       search_item.dev = st.f_type;
177       item = (mtab_item *)ff_pkt->mtab_list->search((void *)&search_item, compare_mtab_items);
178       if (item) {
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);
182          return true;
183       }
184       /*
185        * Values obtained from statfs(2), testing and
186        *
187        *    $ grep -r SUPER_MAGIC /usr/include/linux
188        */
189       switch (st.f_type) {
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;
235
236
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 */
263 #endif
264
265       default:
266          Dmsg2(10, "Unknown file system type \"0x%x\" for \"%s\".\n", st.f_type,
267                fname);
268          return false;
269       }
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);
273       return true;
274    }
275    Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
276    return false;
277 }
278
279 #elif defined(HAVE_SUN_OS)
280
281 #include <sys/types.h>
282 #include <sys/stat.h>
283
284 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
285 {
286    /* Solaris has the filesystem type name in the lstat packet */
287    bstrncpy(fs, ff_pkt->statp.st_fstype, fslen);
288    return true;
289 }
290  
291 #elif defined (__digital__) && defined (__unix__)  /* Tru64 */
292 /* Tru64 */
293 #include <sys/stat.h>
294 #include <sys/mount.h>
295
296 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
297 {
298    char *fname = ff_pkt->fname;
299    struct statfs st;
300    if (statfs((char *)fname, &st) == 0) {
301       switch (st.f_type) {
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   */
305       default:
306          Dmsg2(10, "Unknown file system type \"0x%x\" for \"%s\".\n", st.f_type,
307                fname);
308          return false;
309       }
310    }
311    Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
312    return false;
313 }
314 /* Tru64 */
315
316 #else    /* No recognised OS */
317
318 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
319 {
320    char *fname = ff_pkt->fname;
321    Dmsg0(10, "!!! fstype() not implemented for this OS. !!!\n");
322    return false;
323 }
324 #endif
325
326 /* Read mtab entries  */
327 bool read_mtab(mtab_handler_t *mtab_handler, void *user_ctx)
328
329 #ifdef HAVE_GETMNTENT
330    FILE *mntfp;
331    struct stat st;
332  
333 #ifdef HAVE_LINUX_OS
334    struct mntent *mnt;
335    P(mutex);
336    if ((mntfp = setmntent("/proc/mounts", "r")) == NULL) {
337       if ((mntfp = setmntent(_PATH_MOUNTED, "r")) == NULL) {
338          V(mutex);
339          return false;
340       }
341    } 
342    while ((mnt = getmntent(mntfp)) != NULL) {
343       if (is_rootfs(mnt->mnt_type)) {
344          continue;
345       }
346
347       if (stat(mnt->mnt_dir, &st) < 0) {
348          continue;
349       }
350       mtab_handler(user_ctx, &st, mnt->mnt_type, mnt->mnt_dir,
351          mnt->mnt_opts, mnt->mnt_fsname);
352    }
353    endmntent(mntfp);
354    V(mutex);
355 #endif
356
357 #ifdef HAVE_SUN_OS
358    struct mnttab mnt;
359
360    P(mutex);
361    if ((mntfp = fopen(MNTTAB, "r")) == NULL) {
362       V(mutex);
363       return false;
364    }
365
366    while (getmntent(mntfp, &mnt) == 0) {
367       if (is_rootfs(mnt.mnt_fstype)) {
368          continue;
369       }
370       if (stat(mnt.mnt_mountp, &st) < 0) {
371          continue;
372       }
373       mtab_handler(user_ctx, &st, mnt.mnt_fstype, mnt.mnt_mountp,
374          mnt.mnt_mntopts, mnt.mnt_special);
375    }
376    fclose(fp);
377    V(mutex);
378 #endif
379
380 #endif /* HAVE_GETMNTENT */
381
382 #ifdef HAVE_GETMNTINFO
383    struct stat st;
384 #if defined(ST_NOWAIT)
385    int flags = ST_NOWAIT;
386 #elif defined(MNT_NOWAIT)
387    int flags = MNT_NOWAIT;
388 #else
389    int flags = 0;
390 #endif
391 #if defined(HAVE_NETBSD_OS)
392    struct statvfs *mntinfo;
393 #else
394    struct statfs *mntinfo;
395 #endif
396    int nument;
397
398    P(mutex);
399    if ((nument = getmntinfo(&mntinfo, flags)) > 0) {
400       while (nument-- > 0) {
401          if (is_rootfs(mntinfo->f_fstypename)) {
402             continue;
403          }
404          if (stat(mntinfo->f_mntonname, &st) < 0) {
405             continue;
406          }
407          mtab_handler(user_ctx, &st, mntinfo->f_mntfromname,
408             mntinfo->f_mntonname, mntinfo->f_fstypename, NULL);
409          mntinfo++;
410       }
411    }
412    V(mutex);
413 #endif /* HAVE_GETMNTINFO */
414    return true;
415
416
417 #ifdef TEST_PROGRAM
418 int main(int argc, char **argv)
419 {
420    char *p;
421    char fs[1000];
422    int status = 0;
423
424    if (argc < 2) {
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",
428             p, p);
429       return EXIT_FAILURE;
430    }
431    while (*++argv) {
432       if (!fstype(*argv, fs, sizeof(fs))) {
433          status = EXIT_FAILURE;
434       } else {
435          printf("%s\t%s\n", fs, *argv);
436       }
437    }
438    return status;
439 }
440 #endif