Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(52)

Unified Diff: client/utils/file_path.py

Issue 2949103004: Shuffle code around in file_path. (Closed)
Patch Set: . Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: client/utils/file_path.py
diff --git a/client/utils/file_path.py b/client/utils/file_path.py
index 68e03b39c645ac2e28fbc2abf073782770493a2e..60dbb6b31353f9aaa216ba60b8807ca1c888e803 100644
--- a/client/utils/file_path.py
+++ b/client/utils/file_path.py
@@ -246,6 +246,7 @@ if sys.platform == 'win32':
if not (os.stat(path).st_mode & stat.S_IWUSR):
os.chmod(path, 0777)
+
def isabs(path):
"""Accepts X: as an absolute path, unlike python's os.path.isabs()."""
return os.path.isabs(path) or len(path) == 2 and path[1] == ':'
@@ -307,7 +308,95 @@ if sys.platform == 'win32':
return out[0].upper() + out[1:] + suffix
- def enum_processes_win():
+ def get_process_token():
+ """Get the current process token."""
+ TOKEN_ALL_ACCESS = 0xF01FF
+ token = ctypes.wintypes.HANDLE()
+ if not OpenProcessToken(
+ GetCurrentProcess(), TOKEN_ALL_ACCESS, ctypes.byref(token)):
+ # pylint: disable=undefined-variable
+ raise WindowsError('Couldn\'t get process token')
+ return token
+
+
+ def get_luid(name):
+ """Returns the LUID for a privilege."""
+ luid = LUID()
+ if not LookupPrivilegeValue(None, unicode(name), ctypes.byref(luid)):
+ # pylint: disable=undefined-variable
+ raise WindowsError('Couldn\'t lookup privilege value')
+ return luid
+
+
+ def enable_privilege(name):
+ """Enables the privilege for the current process token.
+
+ Returns:
+ - True if the assignment is successful.
+ """
+ SE_PRIVILEGE_ENABLED = 2
+ ERROR_NOT_ALL_ASSIGNED = 1300
+
+ size = ctypes.sizeof(TOKEN_PRIVILEGES) + ctypes.sizeof(LUID_AND_ATTRIBUTES)
+ buf = ctypes.create_string_buffer(size)
+ tp = ctypes.cast(buf, ctypes.POINTER(TOKEN_PRIVILEGES)).contents
+ tp.count = 1
+ tp.get_array()[0].LUID = get_luid(name)
+ tp.get_array()[0].Attributes = SE_PRIVILEGE_ENABLED
+ token = get_process_token()
+ try:
+ if not AdjustTokenPrivileges(token, False, tp, 0, None, None):
+ # pylint: disable=undefined-variable
+ raise WindowsError('Error in AdjustTokenPrivileges')
+ finally:
+ ctypes.windll.kernel32.CloseHandle(token)
+ return ctypes.windll.kernel32.GetLastError() != ERROR_NOT_ALL_ASSIGNED
+
+
+ def enable_symlink():
+ """Enable SeCreateSymbolicLinkPrivilege for the current token.
+
+ Returns:
+ - True if symlink support is enabled.
+
+ Thanks Microsoft. This is appreciated.
+ """
+ return enable_privilege(u'SeCreateSymbolicLinkPrivilege')
+
+
+ def kill_children_processes(root):
+ """Try to kill all children processes indistriminately and prints updates to
+ stderr.
+
+ Returns:
+ True if at least one child process was found.
+ """
+ processes = _get_children_processes_win(root)
+ if not processes:
+ return False
+ sys.stderr.write('Enumerating processes:\n')
+ for _, proc in sorted(processes.iteritems()):
+ sys.stderr.write(
+ '- pid %d; Handles: %d; Exe: %s; Cmd: %s\n' % (
+ proc.ProcessId,
+ proc.HandleCount,
+ proc.ExecutablePath,
+ proc.CommandLine))
+ sys.stderr.write('Terminating %d processes:\n' % len(processes))
+ for pid in sorted(processes):
+ try:
+ # Killing is asynchronous.
+ os.kill(pid, 9)
+ sys.stderr.write('- %d killed\n' % pid)
+ except OSError:
+ sys.stderr.write('- failed to kill %s\n' % pid)
+ return True
+
+
+ ## Windows private code.
+
+
+ def _enum_processes_win():
"""Returns all processes on the system that are accessible to this process.
Returns:
@@ -320,7 +409,7 @@ if sys.platform == 'win32':
return [proc for proc in wbem.ExecQuery('SELECT * FROM Win32_Process')]
- def filter_processes_dir_win(processes, root_dir):
+ def _filter_processes_dir_win(processes, root_dir):
"""Returns all processes which has their main executable located inside
root_dir.
"""
@@ -352,7 +441,7 @@ if sys.platform == 'win32':
]
- def filter_processes_tree_win(processes):
+ def _filter_processes_tree_win(processes):
"""Returns all the processes under the current process."""
# Convert to dict.
processes = dict((p.ProcessId, p) for p in processes)
@@ -371,60 +460,25 @@ if sys.platform == 'win32':
return out.values()
- def get_process_token():
- """Get the current process token."""
- TOKEN_ALL_ACCESS = 0xF01FF
- token = ctypes.wintypes.HANDLE()
- if not OpenProcessToken(
- GetCurrentProcess(), TOKEN_ALL_ACCESS, ctypes.byref(token)):
- # pylint: disable=undefined-variable
- raise WindowsError('Couldn\'t get process token')
- return token
+ def _get_children_processes_win(root):
+ """Returns a list of processes.
+ Enumerates both:
+ - all child processes from this process.
+ - processes where the main executable in inside 'root'. The reason is that
+ the ancestry may be broken so stray grand-children processes could be
+ undetected by the first technique.
- def get_luid(name):
- """Returns the LUID for a privilege."""
- luid = LUID()
- if not LookupPrivilegeValue(None, unicode(name), ctypes.byref(luid)):
- # pylint: disable=undefined-variable
- raise WindowsError('Couldn\'t lookup privilege value')
- return luid
-
-
- def enable_privilege(name):
- """Enables the privilege for the current process token.
-
- Returns:
- - True if the assignment is successful.
+ This technique is not fool-proof but gets mostly there.
"""
- SE_PRIVILEGE_ENABLED = 2
- ERROR_NOT_ALL_ASSIGNED = 1300
-
- size = ctypes.sizeof(TOKEN_PRIVILEGES) + ctypes.sizeof(LUID_AND_ATTRIBUTES)
- buf = ctypes.create_string_buffer(size)
- tp = ctypes.cast(buf, ctypes.POINTER(TOKEN_PRIVILEGES)).contents
- tp.count = 1
- tp.get_array()[0].LUID = get_luid(name)
- tp.get_array()[0].Attributes = SE_PRIVILEGE_ENABLED
- token = get_process_token()
- try:
- if not AdjustTokenPrivileges(token, False, tp, 0, None, None):
- # pylint: disable=undefined-variable
- raise WindowsError('Error in AdjustTokenPrivileges')
- finally:
- ctypes.windll.kernel32.CloseHandle(token)
- return ctypes.windll.kernel32.GetLastError() != ERROR_NOT_ALL_ASSIGNED
-
-
- def enable_symlink():
- """Enable SeCreateSymbolicLinkPrivilege for the current token.
-
- Returns:
- - True if symlink support is enabled.
-
- Thanks Microsoft. This is appreciated.
- """
- return enable_privilege(u'SeCreateSymbolicLinkPrivilege')
+ processes = _enum_processes_win()
+ tree_processes = _filter_processes_tree_win(processes)
+ dir_processes = _filter_processes_dir_win(processes, root)
+ # Convert to dict to remove duplicates.
+ processes = dict((p.ProcessId, p) for p in tree_processes)
+ processes.update((p.ProcessId, p) for p in dir_processes)
+ processes.pop(os.getpid())
+ return processes
elif sys.platform == 'darwin':
@@ -434,42 +488,6 @@ elif sys.platform == 'darwin':
isabs = os.path.isabs
- def _native_case(p):
- """Gets the native path case. Warning: this function resolves symlinks."""
- try:
- rel_ref, _ = Carbon.File.FSPathMakeRef(p.encode('utf-8'))
- # The OSX underlying code uses NFD but python strings are in NFC. This
- # will cause issues with os.listdir() for example. Since the dtrace log
- # *is* in NFC, normalize it here.
- out = unicodedata.normalize(
- 'NFC', rel_ref.FSRefMakePath().decode('utf-8'))
- if p.endswith(os.path.sep) and not out.endswith(os.path.sep):
- return out + os.path.sep
- return out
- except MacOS.Error, e:
- if e.args[0] in (-43, -120):
- # The path does not exist. Try to recurse and reconstruct the path.
- # -43 means file not found.
- # -120 means directory not found.
- base = os.path.dirname(p)
- rest = os.path.basename(p)
- return os.path.join(_native_case(base), rest)
- raise OSError(
- e.args[0], 'Failed to get native path for %s' % p, p, e.args[1])
-
-
- def _split_at_symlink_native(base_path, rest):
- """Returns the native path for a symlink."""
- base, symlink, rest = split_at_symlink(base_path, rest)
- if symlink:
- if not base_path:
- base_path = base
- else:
- base_path = safe_join(base_path, base)
- symlink = find_item_native_case(base_path, symlink)
- return base, symlink, rest
-
-
def find_item_native_case(root_path, item):
"""Gets the native path case of a single item based at root_path.
@@ -537,6 +555,45 @@ elif sys.platform == 'darwin':
return True
+ ## OSX private code.
+
+
+ def _native_case(p):
+ """Gets the native path case. Warning: this function resolves symlinks."""
+ try:
+ rel_ref, _ = Carbon.File.FSPathMakeRef(p.encode('utf-8'))
+ # The OSX underlying code uses NFD but python strings are in NFC. This
+ # will cause issues with os.listdir() for example. Since the dtrace log
+ # *is* in NFC, normalize it here.
+ out = unicodedata.normalize(
+ 'NFC', rel_ref.FSRefMakePath().decode('utf-8'))
+ if p.endswith(os.path.sep) and not out.endswith(os.path.sep):
+ return out + os.path.sep
+ return out
+ except MacOS.Error, e:
+ if e.args[0] in (-43, -120):
+ # The path does not exist. Try to recurse and reconstruct the path.
+ # -43 means file not found.
+ # -120 means directory not found.
+ base = os.path.dirname(p)
+ rest = os.path.basename(p)
+ return os.path.join(_native_case(base), rest)
+ raise OSError(
+ e.args[0], 'Failed to get native path for %s' % p, p, e.args[1])
+
+
+ def _split_at_symlink_native(base_path, rest):
+ """Returns the native path for a symlink."""
+ base, symlink, rest = split_at_symlink(base_path, rest)
+ if symlink:
+ if not base_path:
+ base_path = base
+ else:
+ base_path = safe_join(base_path, base)
+ symlink = find_item_native_case(base_path, symlink)
+ return base, symlink, rest
+
+
else: # OSes other than Windows and OSX.
@@ -652,6 +709,12 @@ if sys.platform != 'win32': # All non-Windows OSes.
return relfile, None, None
+ def kill_children_processes(root):
+ """Not yet implemented on posix."""
+ # pylint: disable=unused-argument
+ return False
+
+
def relpath(path, root):
"""os.path.relpath() that keeps trailing os.path.sep."""
out = os.path.relpath(path, root)
@@ -693,17 +756,6 @@ def posix_relpath(path, root):
return out
-def cleanup_path(x):
- """Cleans up a relative path. Converts any os.path.sep to '/' on Windows."""
- if x:
- x = x.rstrip(os.path.sep).replace(os.path.sep, '/')
- if x == '.':
- x = ''
- if x:
- x += '/'
- return x
-
-
def is_url(path):
"""Returns True if it looks like an HTTP url instead of a file path."""
return bool(re.match(r'^https?://.+$', path))
@@ -1124,7 +1176,7 @@ def rmtree(root):
# The soft way was not good enough. Try the hard way.
for i in xrange(max_tries):
- if not _kill_children_processes_win(root):
+ if not kill_children_processes(root):
break
if i != max_tries - 1:
time.sleep((i+1)*2)
@@ -1150,53 +1202,3 @@ def rmtree(root):
## Private code.
-
-
-def _kill_children_processes_win(root):
- """Try to kill all children processes indistriminately and prints updates to
- stderr.
-
- Returns:
- True if at least one child process was found.
- """
- processes = _get_children_processes_win(root)
- if not processes:
- return False
- sys.stderr.write('Enumerating processes:\n')
- for _, proc in sorted(processes.iteritems()):
- sys.stderr.write(
- '- pid %d; Handles: %d; Exe: %s; Cmd: %s\n' % (
- proc.ProcessId,
- proc.HandleCount,
- proc.ExecutablePath,
- proc.CommandLine))
- sys.stderr.write('Terminating %d processes:\n' % len(processes))
- for pid in sorted(processes):
- try:
- # Killing is asynchronous.
- os.kill(pid, 9)
- sys.stderr.write('- %d killed\n' % pid)
- except OSError:
- sys.stderr.write('- failed to kill %s\n' % pid)
- return True
-
-
-def _get_children_processes_win(root):
- """Returns a list of processes.
-
- Enumerates both:
- - all child processes from this process.
- - processes where the main executable in inside 'root'. The reason is that
- the ancestry may be broken so stray grand-children processes could be
- undetected by the first technique.
-
- This technique is not fool-proof but gets mostly there.
- """
- processes = enum_processes_win()
- tree_processes = filter_processes_tree_win(processes)
- dir_processes = filter_processes_dir_win(processes, root)
- # Convert to dict to remove duplicates.
- processes = dict((p.ProcessId, p) for p in tree_processes)
- processes.update((p.ProcessId, p) for p in dir_processes)
- processes.pop(os.getpid())
- return processes
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698