summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Johns <chrisj@rtems.org>2017-06-07 15:00:13 +1000
committerChris Johns <chrisj@rtems.org>2017-06-14 11:22:50 +1000
commit78c152453b7ffbd2542a56cda885c0dfa6389704 (patch)
tree0b5fdfbadb966f99ee35d7fc306f2a1ceb2b06f4
parent2433c4bd5f7f1db3a46aeeefb1217ae3871facfe (diff)
downloadrtems-source-builder-78c152453b7ffbd2542a56cda885c0dfa6389704.tar.bz2
sb: Fix long path support in the copy_tree and removeall path support.
This change lets the LM32 target build on Windows which has temporary install paths greated than the Win32 API max size. The buildroot path compression is still needed as the GNU assembler does not like paths that exceed the max Windows limit. Closes #2992.
-rw-r--r--source-builder/sb/path.py99
1 files changed, 64 insertions, 35 deletions
diff --git a/source-builder/sb/path.py b/source-builder/sb/path.py
index 43f41eb..ba19883 100644
--- a/source-builder/sb/path.py
+++ b/source-builder/sb/path.py
@@ -34,6 +34,7 @@ import string
import error
windows = os.name == 'nt'
+win_maxpath = 254
def host(path):
if path is not None:
@@ -46,13 +47,16 @@ def host(path):
path[1] in string.ascii_uppercase):
path = '%s:%s' % (path[1], path[2:])
path = path.replace('/', '\\')
- if not path.startswith('\\\\?\\') and len(path) > 254:
- path = '\\\\?\\' + path
+ if len(path) > win_maxpath:
+ if path.startswith('\\\\?\\'):
+ path = path[4:]
+ path = u'\\'.join([u'\\\\?', path])
return path
def shell(path):
if path is not None:
if windows:
+ path = path.encode('ascii', 'ignore')
if path.startswith('\\\\?\\'):
path = path[4:]
if len(path) > 1 and path[1] == ':':
@@ -84,13 +88,22 @@ def splitext(path):
root, ext = os.path.splitext(host(path))
return shell(root), ext
+def listdir(path):
+ hp = host(path)
+ if not os.path.exists(hp):
+ return []
+ return os.listdir(hp)
+
def exists(paths):
+ def _exists(p):
+ return os.path.basename(p) in listdir(dirname(p))
+
if type(paths) == list:
results = []
for p in paths:
- results += [os.path.exists(host(p))]
+ results += [_exists(p)]
return results
- return os.path.exists(host(paths))
+ return _exists(paths)
def isdir(path):
return os.path.isdir(host(path))
@@ -107,7 +120,7 @@ def iswritable(path):
def ispathwritable(path):
path = host(path)
while len(path) != 0:
- if os.path.exists(path):
+ if exists(path):
return iswritable(path)
path = os.path.dirname(path)
return False
@@ -135,33 +148,48 @@ def mkdir(path):
except OSError as err:
raise error.general('cannot make directory: %s' % (path))
+def chdir(path):
+ os.chdir(host(path))
+
def removeall(path):
#
# Perform the removal of the directory tree manually so we can
- # make sure on Windows the files and correctly encoded to avoid
- # the size limit.
+ # make sure on Windows the files are correctly encoded to avoid
+ # the file name size limit. On Windows the os.walk fails once we
+ # get to the max path length on Windows.
#
- path = host(path)
- for root, dirs, files in os.walk(path, topdown = False):
- for name in files:
- file = host(os.path.join(root, name))
- if not os.path.islink(file) and not os.access(file, os.W_OK):
- os.chmod(file, stat.S_IWUSR)
- os.unlink(file)
- for name in dirs:
- dir = host(os.path.join(root, name))
- if os.path.islink(dir):
- os.unlink(dir)
+ def _isdir(path):
+ hpath = host(path)
+ return os.path.isdir(hpath) and not os.path.islink(hpath)
+
+ def _remove_node(path):
+ hpath = host(path)
+ if not os.path.islink(hpath) and not os.access(hpath, os.W_OK):
+ os.chmod(hpath, stat.S_IWUSR)
+ if _isdir(path):
+ os.rmdir(hpath)
+ else:
+ os.unlink(hpath)
+
+ def _remove(path):
+ dirs = []
+ for name in listdir(path):
+ path_ = join(path, name)
+ hname = host(path_)
+ if _isdir(path_):
+ dirs += [name]
else:
- if not os.access(dir, os.W_OK):
- os.chmod(dir, stat.S_IWUSR)
- os.rmdir(dir)
- if not os.path.islink(path) and not os.access(path, os.W_OK):
- os.chmod(path, stat.S_IWUSR)
- if os.path.islink(path):
- os.unlink(path)
- else:
- os.rmdir(path)
+ _remove_node(path_)
+ for name in dirs:
+ dir = join(path, name)
+ _remove(dir)
+ _remove_node(dir)
+
+ hpath = host(path)
+
+ if os.path.exists(hpath):
+ _remove(path)
+ _remove_node(path)
def expand(name, paths):
l = []
@@ -187,17 +215,17 @@ def copy_tree(src, dst):
hsrc = host(src)
hdst = host(dst)
- if os.path.exists(hsrc):
- names = os.listdir(hsrc)
+ if exists(hsrc):
+ names = listdir(hsrc)
else:
names = []
if trace:
print('path.copy_tree:')
- print(' src: %s' % (src))
- print(' hsrc: %s' % (hsrc))
- print(' dst: %s' % (dst))
- print(' hdst: %s' % (hdst))
+ print(' src: "%s"' % (src))
+ print(' hsrc: "%s"' % (hsrc))
+ print(' dst: "%s"' % (dst))
+ print(' hdst: "%s"' % (hdst))
print(' names: %r' % (names))
if not os.path.isdir(hdst):
@@ -215,7 +243,7 @@ def copy_tree(src, dst):
try:
if os.path.islink(srcname):
linkto = os.readlink(srcname)
- if os.path.exists(dstname):
+ if exists(dstname):
if os.path.islink(dstname):
dstlinkto = os.readlink(dstname)
if linkto != dstlinkto:
@@ -231,7 +259,8 @@ def copy_tree(src, dst):
elif os.path.isdir(srcname):
copy_tree(srcname, dstname)
else:
- shutil.copy2(host(srcname), host(dstname))
+ shutil.copyfile(host(srcname), host(dstname))
+ shutil.copystat(host(srcname), host(dstname))
except shutil.Error as err:
raise error.general('copying tree: %s -> %s: %s' % \
(hsrc, hdst, str(err)))