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 #include "FileDescriptor.h"
21
22 // The primary purpose of checking the filesystem type is to prevent
23 // watching filesystems that are known to be problematic, such as
24 // network or remote mounted filesystems. As such, we don't strictly
25 // need to have a fully comprehensive mapping of the underlying filesystem
26 // type codes to names, just the known problematic types
27
w_fstype(const char * path)28 w_string w_fstype(const char *path)
29 {
30 #ifdef __linux__
31 struct statfs sfs;
32 const char *name = "unknown";
33
34 if (statfs(path, &sfs) == 0) {
35 switch (sfs.f_type) {
36 #ifdef CIFS_MAGIC_NUMBER
37 case CIFS_MAGIC_NUMBER:
38 name = "cifs";
39 break;
40 #endif
41 #ifdef NFS_SUPER_MAGIC
42 case NFS_SUPER_MAGIC:
43 name = "nfs";
44 break;
45 #endif
46 #ifdef SMB_SUPER_MAGIC
47 case SMB_SUPER_MAGIC:
48 name = "smb";
49 break;
50 #endif
51 default:
52 name = "unknown";
53 }
54 }
55
56 return w_string(name, W_STRING_UNICODE);
57 #elif STATVFS_HAS_FSTYPE_AS_STRING
58 struct statvfs sfs;
59
60 if (statvfs(path, &sfs) == 0) {
61 #ifdef HAVE_STRUCT_STATVFS_F_FSTYPENAME
62 return w_string(sfs.f_fstypename, W_STRING_UNICODE);
63 #endif
64 #ifdef HAVE_STRUCT_STATVFS_F_BASETYPE
65 return w_string(sfs.f_basetype, W_STRING_UNICODE);
66 #endif
67 }
68 #elif HAVE_STATFS
69 struct statfs sfs;
70
71 if (statfs(path, &sfs) == 0) {
72 return w_string(sfs.f_fstypename, W_STRING_UNICODE);
73 }
74 #endif
75 #ifdef _WIN32
76 auto wpath = w_string_piece(path).asWideUNC();
77 WCHAR fstype[MAX_PATH + 1];
78 watchman::FileDescriptor h(intptr_t(CreateFileW(
79 wpath.c_str(),
80 GENERIC_READ,
81 FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
82 nullptr,
83 OPEN_EXISTING,
84 FILE_FLAG_BACKUP_SEMANTICS,
85 nullptr)));
86 if (h && GetVolumeInformationByHandleW(
87 (HANDLE)h.handle(), nullptr, 0, 0, 0, 0, fstype, MAX_PATH + 1)) {
88 return w_string(fstype, wcslen(fstype));
89 }
90 return w_string("unknown", W_STRING_UNICODE);
91 #else
92 unused_parameter(path);
93 return w_string("unknown", W_STRING_UNICODE);
94 #endif
95 }
96
97 /* vim:ts=2:sw=2:et:
98 */
99