Repository: conan-io/conan

Issue:
conan-libiconv failing when using short_paths = True due to permission problems in c:\.conan
To help us debug your issue please explain:

- [X] I've read the [CONTRIBUTING guide](https://raw.githubusercontent.com/conan-io/conan/develop/.github/CONTRIBUTING.md).
- [X] I've specified the Conan version, operating system version and any tool that can be relevant.
- [X] I've explained the steps to reproduce the error or the motivation/use case of the question/suggestion.

conan version 1.1.0

Problem was found while reviewing [inclusion request](https://github.com/bincrafters/community/issues/143) for **conan-libiconv**.

If the recipe is using **short_paths=True** Cygwing/Msys2 windows subsystems can fail while using **CONAN_USER_HOME_SHORT** (by default c:\\.conan usually NTFS file system) because by default [ACLs are evaluated in cygwing/msys2 too](https://cygwin.com/cygwin-ug-net/using-filemodes.html). 

**conan-libiconv** has a [workaround](https://github.com/bincrafters/conan-libiconv/blob/stable/1.15/conanfile.py#L109) to deal with this problem but it would be good if it's fixed in conan.



Discussion:

Resolving patch:
diff --git a/conans/util/windows.py b/conans/util/windows.py
--- a/conans/util/windows.py
+++ b/conans/util/windows.py
@@ -1,4 +1,6 @@
 import os
+import subprocess
+
 from conans.util.files import load, mkdir, save, rmdir
 import tempfile
 
@@ -48,6 +50,16 @@ def path_shortener(path, short_paths):
         drive = os.path.splitdrive(path)[0]
         short_home = drive + "/.conan"
     mkdir(short_home)
+
+    # Workaround for short_home living in NTFS file systems. Give full control permission to current user to avoid
+    # access problems in cygwin/msys2 windows subsystems when using short_home folder
+    try:
+        cmd = r'cacls %s /E /G "%s\%s":F' % (short_home, os.environ['USERDOMAIN'], os.environ['USERNAME'])
+        subprocess.check_output(cmd, stderr=subprocess.STDOUT)  # Ignoring any returned output, make command quiet
+    except subprocess.CalledProcessError:
+        # cmd can fail if trying to set ACL in non NTFS drives, ignoring it.
+        pass
+
     redirect = tempfile.mkdtemp(dir=short_home, prefix="")
     # This "1" is the way to have a non-existing directory, so commands like
     # shutil.copytree() to it, works. It can be removed without compromising the


Test patch:
diff --git a/conans/test/command/info_folders_test.py b/conans/test/command/info_folders_test.py
--- a/conans/test/command/info_folders_test.py
+++ b/conans/test/command/info_folders_test.py
@@ -2,6 +2,7 @@
 import os
 import platform
 import re
+import subprocess
 
 from conans import tools
 from conans.test.utils.tools import TestClient
@@ -142,6 +143,48 @@ def test_short_paths(self):
                 self.assertFalse(os.path.exists(path))
                 self.assertTrue(os.path.exists(os.path.dirname(path)))
 
+    def test_short_paths_home_set_acl(self):
+        """
+        When CONAN_USER_HOME_SHORT is living in NTFS file systems, current user needs to be
+        granted with full control permission to avoid access problems when cygwin/msys2 windows subsystems
+        are mounting/using that folder.
+        """
+        if platform.system() != "Windows":
+            return
+
+        folder = temp_folder(False)  # Creates a temporary folder in %HOME%\appdata\local\temp
+        short_folder = os.path.join(folder, ".cnacls")
+
+        self.assertFalse(os.path.exists(short_folder), "short_folder: %s shouldn't exists" % short_folder)
+        os.makedirs(short_folder)
+
+        current_domain = os.environ['USERDOMAIN']
+        current_user = os.environ['USERNAME']
+
+        # Explicitly revoke full control permission to current user
+        cmd = r'cacls %s /E /R "%s\%s"' % (short_folder, current_domain, current_user)
+        try:
+            subprocess.check_output(cmd, stderr=subprocess.STDOUT)
+        except subprocess.CalledProcessError as e:
+            raise Exception("Error %s setting ACL to short_folder: '%s'."
+                            "Please check that cacls.exe exists" % (e, short_folder))
+
+        # Run conan export in using short_folder
+        with tools.environment_append({"CONAN_USER_HOME_SHORT": short_folder}):
+            client = TestClient(base_folder=folder)
+            client.save({CONANFILE: conanfile_py.replace("False", "True")})
+            client.run("export . %s" % self.user_channel)
+
+        # Retrieve ACLs from short_folder
+        try:
+            short_folder_acls = subprocess.check_output("cacls %s" % short_folder, stderr=subprocess.STDOUT)
+        except subprocess.CalledProcessError as e:
+            raise Exception("Error %s getting ACL from short_folder: '%s'." % (e, short_folder))
+
+        # Check user has full control
+        user_acl = "%s\\%s:(OI)(CI)F" % (current_domain, current_user)
+        self.assertIn(user_acl.encode(), short_folder_acls)
+
     def test_direct_conanfile(self):
         client = TestClient()
         client.save({CONANFILE: conanfile_py})