1 /* Copyright 2014-present Facebook, Inc.
2 * Licensed under the Apache License, Version 2.0 */
3
4 #include "watchman.h"
5 #ifdef HAVE_SYS_VFS_H
6 # include <sys/vfs.h>
7 #endif
8 #ifdef HAVE_SYS_STATVFS_H
9 # include <sys/statvfs.h>
10 #endif
11 #ifdef HAVE_SYS_PARAM_H
12 # include <sys/param.h>
13 #endif
14 #ifdef HAVE_SYS_MOUNT_H
15 # include <sys/mount.h>
16 #endif
17 #ifdef __linux__
18 #include <linux/magic.h>
19 #endif
20
21 // The primary purpose of checking the filesystem type is to prevent
22 // watching filesystems that are known to be problematic, such as
23 // network or remote mounted filesystems. As such, we don't strictly
24 // need to have a fully comprehensive mapping of the underlying filesystem
25 // type codes to names, just the known problematic types
26
w_fstype(const char * path)27 w_string_t *w_fstype(const char *path)
28 {
29 #ifdef __linux__
30 struct statfs sfs;
31 const char *name = "unknown";
32
33 if (statfs(path, &sfs) == 0) {
34 switch (sfs.f_type) {
35 #ifdef CIFS_MAGIC_NUMBER
36 case CIFS_MAGIC_NUMBER:
37 name = "cifs";
38 break;
39 #endif
40 #ifdef NFS_SUPER_MAGIC
41 case NFS_SUPER_MAGIC:
42 name = "nfs";
43 break;
44 #endif
45 #ifdef SMB_SUPER_MAGIC
46 case SMB_SUPER_MAGIC:
47 name = "smb";
48 break;
49 #endif
50 default:
51 name = "unknown";
52 }
53 }
54
55 return w_string_new(name);
56 #elif STATVFS_HAS_FSTYPE_AS_STRING
57 struct statvfs sfs;
58
59 if (statvfs(path, &sfs) == 0) {
60 #ifdef HAVE_STRUCT_STATVFS_F_FSTYPENAME
61 return w_string_new(sfs.f_fstypename);
62 #endif
63 #ifdef HAVE_STRUCT_STATVFS_F_BASETYPE
64 return w_string_new(sfs.f_basetype);
65 #endif
66 }
67 #elif HAVE_STATFS
68 struct statfs sfs;
69
70 if (statfs(path, &sfs) == 0) {
71 return w_string_new(sfs.f_fstypename);
72 }
73 #endif
74 #ifdef _WIN32
75 WCHAR *wpath = w_utf8_to_win_unc(path, -1);
76 w_string_t *fstype_name = NULL;
77 if (wpath) {
78 WCHAR fstype[MAX_PATH+1];
79 HANDLE h = CreateFileW(wpath, GENERIC_READ,
80 FILE_SHARE_DELETE|FILE_SHARE_READ|FILE_SHARE_WRITE,
81 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
82 if (h) {
83 if (GetVolumeInformationByHandleW(h, NULL, 0, 0, 0, 0, fstype,
84 MAX_PATH+1)) {
85 fstype_name = w_string_new_wchar(fstype, -1);
86 }
87 CloseHandle(h);
88 }
89 free(wpath);
90 }
91 if (fstype_name) {
92 return fstype_name;
93 }
94 return w_string_new("unknown");
95 #else
96 unused_parameter(path);
97 return w_string_new("unknown");
98 #endif
99 }
100
101 /* vim:ts=2:sw=2:et:
102 */
103