]>
Commit | Line | Data |
---|---|---|
bc5c5ec0 | 1 | #include "git-compat-util.h" |
508c1a57 ED |
2 | #include "fsmonitor.h" |
3 | #include "fsmonitor-path-utils.h" | |
f394e093 | 4 | #include "gettext.h" |
508c1a57 ED |
5 | |
6 | /* | |
7 | * Check remote working directory protocol. | |
8 | * | |
9 | * Return -1 if client machine cannot get remote protocol information. | |
10 | */ | |
11 | static int check_remote_protocol(wchar_t *wpath) | |
12 | { | |
13 | HANDLE h; | |
14 | FILE_REMOTE_PROTOCOL_INFO proto_info; | |
15 | ||
16 | h = CreateFileW(wpath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, | |
17 | FILE_FLAG_BACKUP_SEMANTICS, NULL); | |
18 | ||
19 | if (h == INVALID_HANDLE_VALUE) { | |
20 | error(_("[GLE %ld] unable to open for read '%ls'"), | |
21 | GetLastError(), wpath); | |
22 | return -1; | |
23 | } | |
24 | ||
25 | if (!GetFileInformationByHandleEx(h, FileRemoteProtocolInfo, | |
26 | &proto_info, sizeof(proto_info))) { | |
27 | error(_("[GLE %ld] unable to get protocol information for '%ls'"), | |
28 | GetLastError(), wpath); | |
29 | CloseHandle(h); | |
30 | return -1; | |
31 | } | |
32 | ||
33 | CloseHandle(h); | |
34 | ||
35 | trace_printf_key(&trace_fsmonitor, | |
36 | "check_remote_protocol('%ls') remote protocol %#8.8lx", | |
37 | wpath, proto_info.Protocol); | |
38 | ||
39 | return 0; | |
40 | } | |
41 | ||
42 | /* | |
43 | * Notes for testing: | |
44 | * | |
45 | * (a) Windows allows a network share to be mapped to a drive letter. | |
46 | * (This is the normal method to access it.) | |
47 | * | |
48 | * $ NET USE Z: \\server\share | |
49 | * $ git -C Z:/repo status | |
50 | * | |
51 | * (b) Windows allows a network share to be referenced WITHOUT mapping | |
52 | * it to drive letter. | |
53 | * | |
54 | * $ NET USE \\server\share\dir | |
55 | * $ git -C //server/share/repo status | |
56 | * | |
57 | * (c) Windows allows "SUBST" to create a fake drive mapping to an | |
58 | * arbitrary path (which may be remote) | |
59 | * | |
60 | * $ SUBST Q: Z:\repo | |
61 | * $ git -C Q:/ status | |
62 | * | |
63 | * (d) Windows allows a directory symlink to be created on a local | |
64 | * file system that points to a remote repo. | |
65 | * | |
66 | * $ mklink /d ./link //server/share/repo | |
67 | * $ git -C ./link status | |
68 | */ | |
69 | int fsmonitor__get_fs_info(const char *path, struct fs_info *fs_info) | |
70 | { | |
71 | wchar_t wpath[MAX_PATH]; | |
72 | wchar_t wfullpath[MAX_PATH]; | |
73 | size_t wlen; | |
74 | UINT driveType; | |
75 | ||
76 | /* | |
77 | * Do everything in wide chars because the drive letter might be | |
78 | * a multi-byte sequence. See win32_has_dos_drive_prefix(). | |
79 | */ | |
80 | if (xutftowcs_path(wpath, path) < 0) { | |
81 | return -1; | |
82 | } | |
83 | ||
84 | /* | |
85 | * GetDriveTypeW() requires a final slash. We assume that the | |
86 | * worktree pathname points to an actual directory. | |
87 | */ | |
88 | wlen = wcslen(wpath); | |
89 | if (wpath[wlen - 1] != L'\\' && wpath[wlen - 1] != L'/') { | |
90 | wpath[wlen++] = L'\\'; | |
91 | wpath[wlen] = 0; | |
92 | } | |
93 | ||
94 | /* | |
95 | * Normalize the path. If nothing else, this converts forward | |
96 | * slashes to backslashes. This is essential to get GetDriveTypeW() | |
97 | * correctly handle some UNC "\\server\share\..." paths. | |
98 | */ | |
99 | if (!GetFullPathNameW(wpath, MAX_PATH, wfullpath, NULL)) { | |
100 | return -1; | |
101 | } | |
102 | ||
103 | driveType = GetDriveTypeW(wfullpath); | |
104 | trace_printf_key(&trace_fsmonitor, | |
105 | "DriveType '%s' L'%ls' (%u)", | |
106 | path, wfullpath, driveType); | |
107 | ||
108 | if (driveType == DRIVE_REMOTE) { | |
109 | fs_info->is_remote = 1; | |
110 | if (check_remote_protocol(wfullpath) < 0) | |
111 | return -1; | |
112 | } else { | |
113 | fs_info->is_remote = 0; | |
114 | } | |
115 | ||
116 | trace_printf_key(&trace_fsmonitor, | |
117 | "'%s' is_remote: %d", | |
118 | path, fs_info->is_remote); | |
119 | ||
120 | return 0; | |
121 | } | |
122 | ||
123 | int fsmonitor__is_fs_remote(const char *path) | |
124 | { | |
125 | struct fs_info fs; | |
126 | if (fsmonitor__get_fs_info(path, &fs)) | |
127 | return -1; | |
128 | return fs.is_remote; | |
129 | } | |
12fd27df ED |
130 | |
131 | /* | |
132 | * No-op for now. | |
133 | */ | |
134 | int fsmonitor__get_alias(const char *path, struct alias_info *info) | |
135 | { | |
136 | return 0; | |
137 | } | |
138 | ||
139 | /* | |
140 | * No-op for now. | |
141 | */ | |
142 | char *fsmonitor__resolve_alias(const char *path, | |
143 | const struct alias_info *info) | |
144 | { | |
145 | return NULL; | |
146 | } |