]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/findlib/fstype.c
Restore win32 dir from Branch-5.2 and update it
[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_OPENBSD_OS)
97
98 #include <sys/param.h>
99 #include <sys/mount.h>
100
101 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
102 {
103    char *fname = ff_pkt->fname;
104    struct statfs st;
105  
106    if (statfs(fname, &st) == 0) {
107       bstrncpy(fs, st.f_fstypename, fslen);
108       return true;
109    }
110    Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
111    return false;
112 }
113 #elif defined(HAVE_NETBSD_OS)
114 #include <sys/param.h>
115 #include <sys/mount.h>
116 #ifdef HAVE_SYS_STATVFS_H
117 #include <sys/statvfs.h>
118 #else
119 #define statvfs statfs
120 #endif
121
122 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
123 {
124    char *fname = ff_pkt->fname;
125    struct statvfs st;
126    if (statvfs(fname, &st) == 0) {
127       bstrncpy(fs, st.f_fstypename, fslen);
128       return true;
129    }
130    Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
131    return false;
132 }
133 #elif defined(HAVE_HPUX_OS) \
134    || defined(HAVE_IRIX_OS)
135
136 #include <sys/types.h>
137 #include <sys/statvfs.h>
138
139 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
140 {
141    char *fname = ff_pkt->fname;
142    struct statvfs st;
143    if (statvfs(fname, &st) == 0) {
144       bstrncpy(fs, st.f_basetype, fslen);
145       return true;
146    }
147    Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
148    return false;
149 }
150
151 #elif defined(HAVE_LINUX_OS)
152
153 #include <sys/vfs.h>
154 #include <mntent.h>
155
156 /*
157  * Linux statfs() does not return the filesystem name type.  It
158  *  only returns a binary fstype, so we must look up the type name
159  *  in mtab.
160  */
161 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
162 {
163    char *fname = ff_pkt->fname;
164    struct statfs st;
165    const char *fstype;
166
167    if (statfs(fname, &st) == 0) {
168       mtab_item *item, search_item;
169       if (*ff_pkt->last_fstypename && ff_pkt->last_fstype == (uint64_t)st.f_type) {
170          bstrncpy(fs, ff_pkt->last_fstypename, fslen);
171          return true; 
172       }
173       if (!ff_pkt->mtab_list) {
174          ff_pkt->mtab_list = New(rblist());
175          read_mtab(add_mtab_item, ff_pkt->mtab_list);
176       }
177       search_item.dev = st.f_type;
178       item = (mtab_item *)ff_pkt->mtab_list->search((void *)&search_item, compare_mtab_items);
179       if (item) {
180          ff_pkt->last_fstype = st.f_type;
181          bstrncpy(ff_pkt->last_fstypename, item->fstype, sizeof(ff_pkt->last_fstypename));
182          bstrncpy(fs, ff_pkt->last_fstypename, fslen);
183          return true;
184       }
185       /*
186        * Values obtained from statfs(2), testing and
187        *
188        *    $ grep -r SUPER_MAGIC /usr/include/linux
189        */
190       switch (st.f_type) {
191       /* Known good values */
192       /* ext2, ext3, and ext4 have the same code */
193       case 0xef53:         fstype = "ext2"; break;          /* EXT2_SUPER_MAGIC */
194       case 0x3153464a:     fstype = "jfs"; break;           /* JFS_SUPER_MAGIC */
195       case 0x5346544e:     fstype = "ntfs"; break;          /* NTFS_SB_MAGIC */
196       case 0x9fa0:         fstype = "proc"; break;          /* PROC_SUPER_MAGIC */
197       case 0x52654973:     fstype = "reiserfs"; break;      /* REISERFS_SUPER_MAGIC */
198       case 0x58465342:     fstype = "xfs"; break;           /* XFS_SB_MAGIC */
199       case 0x9fa2:         fstype = "usbdevfs"; break;      /* USBDEVICE_SUPER_MAGIC */
200       case 0x62656572:     fstype = "sysfs"; break;         /* SYSFS_MAGIC */
201       case 0x517B:         fstype = "smbfs"; break;         /* SMB_SUPER_MAGIC */
202       case 0x9660:         fstype = "iso9660"; break;       /* ISOFS_SUPER_MAGIC */
203       case 0xadf5:         fstype = "adfs"; break;          /* ADFS_SUPER_MAGIC */
204       case 0xadff:         fstype = "affs"; break;          /* AFFS_SUPER_MAGIC */
205       case 0x42465331:     fstype = "befs"; break;          /* BEFS_SUPER_MAGIC */
206       case 0xFF534D42:     fstype = "cifs"; break;          /* CIFS_MAGIC_NUMBER */
207       case 0x73757245:     fstype = "coda"; break;          /* CODA_SUPER_MAGIC */
208       case 0x012ff7b7:     fstype = "coherent"; break;      /* COH_SUPER_MAGIC */
209       case 0x28cd3d45:     fstype = "cramfs"; break;        /* CRAMFS_MAGIC */
210       case 0x1373:         fstype = "devfs"; break;         /* DEVFS_SUPER_MAGIC */
211       case 0x414A53:       fstype = "efs"; break;           /* EFS_SUPER_MAGIC */
212       case 0x137d:         fstype = "ext"; break;           /* EXT_SUPER_MAGIC */
213       case 0xef51:         fstype = "oldext2"; break;          /* EXT2_OLD_SUPER_MAGIC */
214       case 0x4244:         fstype = "hfs"; break;          /* EXT2_OLD_SUPER_MAGIC */
215       case 0xf995e849:     fstype = "hpfs"; break;          /* HPFS_SUPER_MAGIC */
216       case 0x958458f6:     fstype = "hugetlbfs"; break;     /* HUGETLBFS_MAGIC */
217       case 0x72b6:         fstype = "jffs2"; break;         /* JFFS2_SUPER_MAGIC */
218       case 0x2468:         fstype = "minix"; break;         /* MINIX2_SUPER_MAGIC */
219       case 0x2478:         fstype = "minix"; break;         /* MINIX2_SUPER_MAGIC2 */
220       case 0x137f:         fstype = "minix"; break;         /* MINIX_SUPER_MAGIC */
221       case 0x138f:         fstype = "minix"; break;         /* MINIX_SUPER_MAGIC2 */
222       case 0x4d44:         fstype = "msdos"; break;         /* MSDOS_SUPER_MAGIC */
223       case 0x564c:         fstype = "ncpfs"; break;         /* NCP_SUPER_MAGIC */
224       case 0x6969:         fstype = "nfs"; break;           /* NFS_SUPER_MAGIC */
225       case 0x9fa1:         fstype = "openpromfs"; break;    /* OPENPROM_SUPER_MAGIC */
226       case 0x002f:         fstype = "qnx4"; break;          /* QNX4_SUPER_MAGIC */
227       case 0x7275:         fstype = "romfs"; break;          /* QNX4_SUPER_MAGIC */
228       case 0x012ff7b6:     fstype = "sysv2"; break;
229       case 0x012ff7b5:     fstype = "sysv4"; break;
230       case 0x01021994:     fstype = "tmpfs"; break;
231       case 0x15013346:     fstype = "udf"; break;
232       case 0x00011954:     fstype = "ufs"; break;
233       case 0xa501FCF5:     fstype = "vxfs"; break;
234       case 0x012FF7B4:     fstype = "xenix"; break;
235       case 0x012FD16D:     fstype = "xiafs"; break;
236       case 0x9123683e:     fstype = "btrfs"; break;
237
238 #if 0       /* These need confirmation */
239       case 0x6B414653:     fstype = "afs"; break;           /* AFS_FS_MAGIC */
240       case 0x0187:         fstype = "autofs"; break;        /* AUTOFS_SUPER_MAGIC */
241       case 0x62646576:     fstype = "bdev"; break;          /* ??? */
242       case 0x1BADFACE:     fstype = "bfs"; break;           /* BFS_MAGIC */
243       case 0x42494e4d:     fstype = "binfmt_misc"; break;   /* ??? */
244       case (('C'<<8)|'N'): fstype = "capifs"; break;        /* CAPIFS_SUPER_MAGIC */
245       case 0x1cd1:         fstype = "devpts"; break;        /* ??? */
246       case 0x03111965:     fstype = "eventpollfs"; break;   /* EVENTPOLLFS_MAGIC */
247       case 0xBAD1DEA:      fstype = "futexfs"; break;       /* ??? */
248       case 0xaee71ee7:     fstype = "gadgetfs"; break;      /* GADGETFS_MAGIC */
249       case 0x00c0ffee:     fstype = "hostfs"; break;        /* HOSTFS_SUPER_MAGIC */
250       case 0xb00000ee:     fstype = "hppfs"; break;         /* HPPFS_SUPER_MAGIC */
251       case 0x12061983:     fstype = "hwgfs"; break;         /* HWGFS_MAGIC */
252       case 0x66726f67:     fstype = "ibmasmfs"; break;      /* IBMASMFS_MAGIC */
253       case 0x19800202:     fstype = "mqueue"; break;        /* MQUEUE_MAGIC */
254       case 0x6f70726f:     fstype = "oprofilefs"; break;    /* OPROFILEFS_MAGIC */
255       case 0xa0b4d889:     fstype = "pfmfs"; break;         /* PFMFS_MAGIC */
256       case 0x50495045:     fstype = "pipfs"; break;         /* PIPEFS_MAGIC */
257       case 0x858458f6:     fstype = "ramfs"; break;         /* RAMFS_MAGIC */
258       case 0x7275:         fstype = "romfs"; break;         /* ROMFS_MAGIC */
259       case 0x858458f6:     fstype = "rootfs"; break;        /* RAMFS_MAGIC */
260       case 0x67596969:     fstype = "rpc_pipefs"; break;    /* RPCAUTH_GSSMAGIC */
261       case 0x534F434B:     fstype = "sockfs"; break;        /* SOCKFS_MAGIC */
262       case 0x858458f6:     fstype = "tmpfs"; break;         /* RAMFS_MAGIC */
263       case 0x01021994:     fstype = "tmpfs"; break;         /* TMPFS_MAGIC */
264 #endif
265
266       default:
267          Dmsg2(10, "Unknown file system type \"0x%x\" for \"%s\".\n", st.f_type,
268                fname);
269          return false;
270       }
271       ff_pkt->last_fstype = st.f_type;
272       bstrncpy(ff_pkt->last_fstypename, fstype, sizeof(ff_pkt->last_fstypename));
273       bstrncpy(fs, fstype, fslen);
274       return true;
275    }
276    Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
277    return false;
278 }
279
280 #elif defined(HAVE_SUN_OS)
281
282 #include <sys/types.h>
283 #include <sys/stat.h>
284
285 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
286 {
287    /* Solaris has the filesystem type name in the lstat packet */
288    bstrncpy(fs, ff_pkt->statp.st_fstype, fslen);
289    return true;
290 }
291  
292 #elif defined (__digital__) && defined (__unix__)  /* Tru64 */
293 /* Tru64 */
294 #include <sys/stat.h>
295 #include <sys/mount.h>
296 #include <sys/mnttab.h>
297
298 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
299 {
300    char *fname = ff_pkt->fname;
301    struct statfs st;
302    if (statfs((char *)fname, &st) == 0) {
303       switch (st.f_type) {
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   */
307       default:
308          Dmsg2(10, "Unknown file system type \"0x%x\" for \"%s\".\n", st.f_type,
309                fname);
310          return false;
311       }
312    }
313    Dmsg1(50, "statfs() failed for \"%s\"\n", fname);
314    return false;
315 }
316 /* Tru64 */
317
318 #elif defined (HAVE_WIN32)
319 /* Windows */
320 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
321 {
322    char *fname = ff_pkt->fname;
323    DWORD componentlength;
324    DWORD fsflags;
325    CHAR rootpath[4];
326    UINT oldmode;
327    BOOL result;
328
329    /* Copy Drive Letter, colon, and backslash to rootpath */
330    bstrncpy(rootpath, fname, sizeof(rootpath));
331
332    /* We don't want any popups if there isn't any media in the drive */
333    oldmode = SetErrorMode(SEM_FAILCRITICALERRORS);
334    result = GetVolumeInformation(rootpath, NULL, 0, NULL, &componentlength, &fsflags, fs, fslen);
335    SetErrorMode(oldmode);
336
337    if (result) {
338       /* Windows returns NTFS, FAT, etc.  Make it lowercase to be consistent with other OSes */
339       lcase(fs);
340    } else {
341       Dmsg2(10, "GetVolumeInformation() failed for \"%s\", Error = %d.\n", rootpath, GetLastError());
342    }
343    return result != 0;
344 }
345 /* Windows */
346
347 #else    /* No recognised OS */
348
349 bool fstype(FF_PKT *ff_pkt, char *fs, int fslen)
350 {
351    char *fname = ff_pkt->fname;
352    Dmsg0(10, "!!! fstype() not implemented for this OS. !!!\n");
353    return false;
354 }
355 #endif
356
357 /* Read mtab entries  */
358 bool read_mtab(mtab_handler_t *mtab_handler, void *user_ctx)
359
360 #ifdef HAVE_GETMNTENT
361    FILE *mntfp;
362    struct stat st;
363  
364 #ifdef HAVE_LINUX_OS
365    struct mntent *mnt;
366    P(mutex);
367    if ((mntfp = setmntent("/proc/mounts", "r")) == NULL) {
368       if ((mntfp = setmntent(_PATH_MOUNTED, "r")) == NULL) {
369          V(mutex);
370          return false;
371       }
372    } 
373    while ((mnt = getmntent(mntfp)) != NULL) {
374       if (is_rootfs(mnt->mnt_type)) {
375          continue;
376       }
377
378       if (stat(mnt->mnt_dir, &st) < 0) {
379          continue;
380       }
381       mtab_handler(user_ctx, &st, mnt->mnt_type, mnt->mnt_dir,
382          mnt->mnt_opts, mnt->mnt_fsname);
383    }
384    endmntent(mntfp);
385    V(mutex);
386 #endif
387
388 #ifdef HAVE_SUN_OS
389    struct mnttab mnt;
390
391    P(mutex);
392    if ((mntfp = bfopen(MNTTAB, "r")) == NULL) {
393       V(mutex);
394       return false;
395    }
396
397    while (getmntent(mntfp, &mnt) == 0) {
398       if (is_rootfs(mnt.mnt_fstype)) {
399          continue;
400       }
401       if (stat(mnt.mnt_mountp, &st) < 0) {
402          continue;
403       }
404       mtab_handler(user_ctx, &st, mnt.mnt_fstype, mnt.mnt_mountp,
405          mnt.mnt_mntopts, mnt.mnt_special);
406    }
407    fclose(mntfp);
408    V(mutex);
409 #endif
410
411 #endif /* HAVE_GETMNTENT */
412
413 #ifdef HAVE_GETMNTINFO
414    struct stat st;
415 #if defined(ST_NOWAIT)
416    int flags = ST_NOWAIT;
417 #elif defined(MNT_NOWAIT)
418    int flags = MNT_NOWAIT;
419 #else
420    int flags = 0;
421 #endif
422 #if defined(HAVE_NETBSD_OS)
423    struct statvfs *mntinfo;
424 #else
425    struct statfs *mntinfo;
426 #endif
427    int nument;
428
429    P(mutex);
430    if ((nument = getmntinfo(&mntinfo, flags)) > 0) {
431       while (nument-- > 0) {
432          if (is_rootfs(mntinfo->f_fstypename)) {
433             continue;
434          }
435          if (stat(mntinfo->f_mntonname, &st) < 0) {
436             continue;
437          }
438          mtab_handler(user_ctx, &st, mntinfo->f_mntfromname,
439             mntinfo->f_mntonname, mntinfo->f_fstypename, NULL);
440          mntinfo++;
441       }
442    }
443    V(mutex);
444 #endif /* HAVE_GETMNTINFO */
445    return true;
446
447
448 #ifdef TEST_PROGRAM
449 int main(int argc, char **argv)
450 {
451    char *p;
452    char fs[1000];
453    int status = 0;
454
455    if (argc < 2) {
456       p = (argc < 1) ? "fstype" : argv[0];
457       printf("usage:\t%s path ...\n"
458             "\t%s prints the file system type and pathname of the paths.\n",
459             p, p);
460       return EXIT_FAILURE;
461    }
462    while (*++argv) {
463       if (!fstype(*argv, fs, sizeof(fs))) {
464          status = EXIT_FAILURE;
465       } else {
466          printf("%s\t%s\n", fs, *argv);
467       }
468    }
469    return status;
470 }
471 #endif