|
12 | 12 |
|
13 | 13 | import sys
|
14 | 14 | import pickle
|
| 15 | +import subprocess |
15 | 16 | import gzip
|
16 | 17 | import hashlib
|
17 | 18 | from hashlib import md5
|
@@ -237,6 +238,30 @@ def hash_timestamp(afile):
|
237 | 238 | return md5hex
|
238 | 239 |
|
239 | 240 |
|
| 241 | +def _on_cifs(fname): |
| 242 | + """ Checks whether a PATH is on a CIFS filesystem mounted in a POSIX |
| 243 | + host (i.e., has the "mount" command). |
| 244 | +
|
| 245 | + CIFS shares are how Docker mounts Windows host directories into containers. |
| 246 | + CIFS has partial support for symlinks that can break, causing misleading |
| 247 | + errors, so this test is used to disable them on such systems. |
| 248 | + """ |
| 249 | + exit_code, output = subprocess.getstatusoutput("mount") |
| 250 | + # Not POSIX |
| 251 | + if exit_code != 0: |
| 252 | + return False |
| 253 | + |
| 254 | + # (path, fstype) tuples, sorted by path length (longest first) |
| 255 | + paths_types = sorted((line.split()[2:5:2] for line in output.splitlines()), |
| 256 | + key=lambda x: len(x[0]), |
| 257 | + reverse=True) |
| 258 | + # Only the first match counts |
| 259 | + for fspath, fstype in paths_types: |
| 260 | + if fname.startswith(fspath): |
| 261 | + return fstype == 'cifs' |
| 262 | + return False |
| 263 | + |
| 264 | + |
240 | 265 | def copyfile(originalfile, newfile, copy=False, create_new=False,
|
241 | 266 | hashmethod=None, use_hardlink=False,
|
242 | 267 | copy_related_files=True):
|
@@ -288,6 +313,10 @@ def copyfile(originalfile, newfile, copy=False, create_new=False,
|
288 | 313 | if hashmethod is None:
|
289 | 314 | hashmethod = config.get('execution', 'hash_method').lower()
|
290 | 315 |
|
| 316 | + # Don't try creating symlinks on CIFS |
| 317 | + if _on_cifs(newfile): |
| 318 | + copy = True |
| 319 | + |
291 | 320 | # Existing file
|
292 | 321 | # -------------
|
293 | 322 | # Options:
|
|
0 commit comments