]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/findlib/fstype.c
Apply patch from Leo to fix bug 2192
[bacula/bacula] / bacula / src / findlib / fstype.c
1 /*
2    Bacula(R) - The Network Backup Solution
3
4    Copyright (C) 2000-2018 Kern Sibbald
5
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.
8
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.
13
14    This notice must be preserved when any source code is
15    conveyed and/or propagated.
16
17    Bacula(R) is a registered trademark of Kern Sibbald.
18 */
19 /*
20  *  Implement routines to determine file system types.
21  *
22  *   Written by Preben 'Peppe' Guldberg, December MMIV
23  *   Updated by Kern Sibbald, April MMXV
24  */
25
26
27 #ifndef TEST_PROGRAM
28
29 #include "bacula.h"
30 #include "find.h"
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #ifdef HAVE_SUN_OS
34   #include <sys/mnttab.h>
35 #endif
36 #else /* Set up for testing a stand alone program */
37
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
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)
45 #endif
46
47 #define is_rootfs(x) bstrcmp("rootfs", x)
48
49 #if defined(HAVE_GETMNTINFO) || defined(HAVE_GETMNTENT)
50 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
51 #endif
52
53 struct mtab_item {
54    rblink link;
55    uint64_t dev;
56    char fstype[1];
57 };
58
59 /* Compare two device types */
60 static int compare_mtab_items(void *item1, void *item2)
61 {
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;
67    return 0;
68 }
69
70 void add_mtab_item(void *user_ctx, struct stat *st, const char *fstype,
71                       const char *mountpoint, const char *mntopts,
72                       const char *fsname)
73 {
74    rblist *mtab_list = (rblist *)user_ctx;
75    mtab_item *item, *ritem;
76    int len = strlen(fstype) + 1;
77    
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);
82    if (ritem != item) {
83       /* Item already inserted, so we discard this one */
84       free(item);
85    }
86 }
87
88
89 /*
90  * These functions should be implemented for each OS
91  *
92  *       bool fstype(FF_PKT *ff_pkt, char *fs, int fslen);
93  */
94 #if defined(HAVE_DARWIN_OS) \
95    || defined(HAVE_FREEBSD_OS ) \
96    || defined(HAVE_KFREEBSD_OS ) \
97    || defined(HAVE_OPENBSD_OS)
98
99 #include <sys/param.h>
100 #include <sys/mount.h>
101
102 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
103 {
104    char *fname = ff_pkt->fname;
105    struct statfs st;
106  
107    if (statfs(fname, &st) == 0) {
108       bstrncpy(fs, st.f_fstypename, fslen);
109       return true;
110    }
111    Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
112    return false;
113 }
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>
119 #else
120 #define statvfs statfs
121 #endif
122
123 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
124 {
125    char *fname = ff_pkt->fname;
126    struct statvfs st;
127    if (statvfs(fname, &st) == 0) {
128       bstrncpy(fs, st.f_fstypename, fslen);
129       return true;
130    }
131    Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
132    return false;
133 }
134 #elif defined(HAVE_HPUX_OS) \
135    || defined(HAVE_IRIX_OS)
136
137 #include <sys/types.h>
138 #include <sys/statvfs.h>
139
140 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
141 {
142    char *fname = ff_pkt->fname;
143    struct statvfs st;
144    if (statvfs(fname, &st) == 0) {
145       bstrncpy(fs, st.f_basetype, fslen);
146       return true;
147    }
148    Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
149    return false;
150 }
151
152 #elif defined(HAVE_LINUX_OS)
153
154 #include <sys/vfs.h>
155 #include <mntent.h>
156
157 /*
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
160  *  in mtab.
161  */
162 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
163 {
164    char *fname = ff_pkt->fname;
165    struct statfs st;
166    const char *fstype;
167
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);
172          return true; 
173       }
174       if (!ff_pkt->mtab_list) {
175          ff_pkt->mtab_list = New(rblist());
176          read_mtab(add_mtab_item, ff_pkt->mtab_list);
177       }
178       search_item.dev = st.f_type;
179       item = (mtab_item *)ff_pkt->mtab_list->search((void *)&search_item, compare_mtab_items);
180       if (item) {
181          ff_pkt->last_fstype = st.f_type;
182          bstrncpy(ff_pkt->last_fstypename, item->fstype, sizeof(ff_pkt->last_fstypename));
183          bstrncpy(fs, ff_pkt->last_fstypename, fslen);
184          return true;
185       }
186       /*
187        * Values obtained from statfs(2), testing and
188        *
189        *    $ grep -r SUPER_MAGIC /usr/include/linux
190        */
191       switch (st.f_type) {
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 = "tmpfs"; 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;
237       case 0x9123683e:     fstype = "btrfs"; break;
238
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 */
265 #endif
266
267       default:
268          Dmsg2(10, "Unknown file system type \"0x%x\" for \"%s\".\n", st.f_type,
269                fname);
270          return false;
271       }
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);
275       return true;
276    }
277    Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
278    return false;
279 }
280
281 #elif defined(HAVE_SUN_OS)
282
283 #include <sys/types.h>
284 #include <sys/stat.h>
285
286 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
287 {
288    /* Solaris has the filesystem type name in the lstat packet */
289    bstrncpy(fs, ff_pkt->statp.st_fstype, fslen);
290    return true;
291 }
292  
293 #elif defined (__digital__) && defined (__unix__)  /* Tru64 */
294 /* Tru64 */
295 #include <sys/stat.h>
296 #include <sys/mount.h>
297 #include <sys/mnttab.h>
298
299 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
300 {
301    char *fname = ff_pkt->fname;
302    struct statfs st;
303    if (statfs((char *)fname, &st) == 0) {
304       switch (st.f_type) {
305       /* Known good values */
306       case 0xa:         bstrncpy(fs, "advfs", fslen); return true;        /* Tru64 AdvFS */
307       case 0xe:         bstrncpy(fs, "nfs", fslen); return true;          /* Tru64 NFS   */
308       default:
309          Dmsg2(10, "Unknown file system type \"0x%x\" for \"%s\".\n", st.f_type,
310                fname);
311          return false;
312       }
313    }
314    Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
315    return false;
316 }
317 /* Tru64 */
318
319 #elif defined (HAVE_WIN32)
320 /* Windows */
321 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
322 {
323    char *fname = ff_pkt->fname;
324    DWORD componentlength;
325    DWORD fsflags;
326    CHAR rootpath[4];
327    UINT oldmode;
328    BOOL result;
329
330    /* Copy Drive Letter, colon, and backslash to rootpath */
331    bstrncpy(rootpath, fname, sizeof(rootpath));
332
333    /* We don't want any popups if there isn't any media in the drive */
334    oldmode = SetErrorMode(SEM_FAILCRITICALERRORS);
335    result = GetVolumeInformation(rootpath, NULL, 0, NULL, &componentlength, &fsflags, fs, fslen);
336    SetErrorMode(oldmode);
337
338    if (result) {
339       /* Windows returns NTFS, FAT, etc.  Make it lowercase to be consistent with other OSes */
340       lcase(fs);
341    } else {
342       Dmsg2(10, "GetVolumeInformation() failed for \"%s\", Error = %d.\n", rootpath, GetLastError());
343    }
344    return result != 0;
345 }
346 /* Windows */
347
348 #else    /* No recognised OS */
349
350 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
351 {
352    char *fname = ff_pkt->fname;
353    Dmsg0(10, "!!! fstype() not implemented for this OS. !!!\n");
354    return false;
355 }
356 #endif
357
358 /* Read mtab entries  */
359 bool read_mtab(mtab_handler_t *mtab_handler, void *user_ctx)
360 {
361 /* Debian stretch GNU/KFreeBSD has both getmntinfo and getmntent, but
362    only the first seems to work, so we skip over getmntent in this case */
363 #ifndef HAVE_KFREEBSD_OS
364 #ifdef HAVE_GETMNTENT
365    FILE *mntfp;
366    struct stat st;
367  
368 #ifdef HAVE_LINUX_OS
369    struct mntent *mnt;
370    P(mutex);
371    if ((mntfp = setmntent("/proc/mounts", "r")) == NULL) {
372       if ((mntfp = setmntent(_PATH_MOUNTED, "r")) == NULL) {
373          V(mutex);
374          return false;
375       }
376    } 
377    while ((mnt = getmntent(mntfp)) != NULL) {
378       if (is_rootfs(mnt->mnt_type)) {
379          continue;
380       }
381
382       if (stat(mnt->mnt_dir, &st) < 0) {
383          continue;
384       }
385       mtab_handler(user_ctx, &st, mnt->mnt_type, mnt->mnt_dir,
386          mnt->mnt_opts, mnt->mnt_fsname);
387    }
388    endmntent(mntfp);
389    V(mutex);
390 #endif
391
392 #ifdef HAVE_SUN_OS
393    struct mnttab mnt;
394
395    P(mutex);
396    if ((mntfp = bfopen(MNTTAB, "r")) == NULL) {
397       V(mutex);
398       return false;
399    }
400
401    while (getmntent(mntfp, &mnt) == 0) {
402       if (is_rootfs(mnt.mnt_fstype)) {
403          continue;
404       }
405       if (stat(mnt.mnt_mountp, &st) < 0) {
406          continue;
407       }
408       mtab_handler(user_ctx, &st, mnt.mnt_fstype, mnt.mnt_mountp,
409          mnt.mnt_mntopts, mnt.mnt_special);
410    }
411    fclose(mntfp);
412    V(mutex);
413 #endif
414
415 #endif /* HAVE_GETMNTENT */
416 #endif /* HAVE_KFREEBSD_OS */
417
418 #ifdef HAVE_GETMNTINFO
419    struct stat st;
420 #if defined(ST_NOWAIT)
421    int flags = ST_NOWAIT;
422 #elif defined(MNT_NOWAIT)
423    int flags = MNT_NOWAIT;
424 #else
425    int flags = 0;
426 #endif
427 #if defined(HAVE_NETBSD_OS)
428    struct statvfs *mntinfo;
429 #else
430    struct statfs *mntinfo;
431 #endif
432    int nument;
433
434    P(mutex);
435    if ((nument = getmntinfo(&mntinfo, flags)) > 0) {
436       while (nument-- > 0) {
437          if (is_rootfs(mntinfo->f_fstypename)) {
438             continue;
439          }
440          if (stat(mntinfo->f_mntonname, &st) < 0) {
441             continue;
442          }
443          mtab_handler(user_ctx, &st, mntinfo->f_mntfromname,
444             mntinfo->f_mntonname, mntinfo->f_fstypename, NULL);
445          mntinfo++;
446       }
447    }
448    V(mutex);
449 #endif /* HAVE_GETMNTINFO */
450    return true;
451
452
453 #ifdef TEST_PROGRAM
454 int main(int argc, char **argv)
455 {
456    char *p;
457    char fs[1000];
458    int status = 0;
459
460    if (argc < 2) {
461       p = (argc < 1) ? "fstype" : argv[0];
462       printf("usage:\t%s path ...\n"
463             "\t%s prints the file system type and pathname of the paths.\n",
464             p, p);
465       return EXIT_FAILURE;
466    }
467    while (*++argv) {
468       if (!fstype(*argv, fs, sizeof(fs))) {
469          status = EXIT_FAILURE;
470       } else {
471          printf("%s\t%s\n", fs, *argv);
472       }
473    }
474    return status;
475 }
476 #endif