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

Side by Side Diff: tools/isolate/trace_inputs.py

Issue 10753006: get_native_path_case() now preserves the trailing os.sep.path and work with non-existing path. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 5 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « tools/isolate/run_test_from_archive_smoke_test.py ('k') | tools/isolate/trace_inputs_test.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # coding=utf-8 2 # coding=utf-8
3 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 3 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be 4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file. 5 # found in the LICENSE file.
6 6
7 """Traces an executable and its child processes and extract the files accessed 7 """Traces an executable and its child processes and extract the files accessed
8 by them. 8 by them.
9 9
10 The implementation uses OS-specific API. The native Kernel logger and the ETL 10 The implementation uses OS-specific API. The native Kernel logger and the ETL
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
187 if not drive or not match.group(2): 187 if not drive or not match.group(2):
188 return drive 188 return drive
189 return drive + match.group(2) 189 return drive + match.group(2)
190 190
191 191
192 def isabs(path): 192 def isabs(path):
193 """Accepts X: as an absolute path, unlike python's os.path.isabs().""" 193 """Accepts X: as an absolute path, unlike python's os.path.isabs()."""
194 return os.path.isabs(path) or len(path) == 2 and path[1] == ':' 194 return os.path.isabs(path) or len(path) == 2 and path[1] == ':'
195 195
196 196
197 def get_native_path_case(path): 197 def get_native_path_case(p):
198 """Returns the native path case for an existing file. 198 """Returns the native path case for an existing file.
199 199
200 On Windows, removes any leading '\\?\'. 200 On Windows, removes any leading '\\?\'.
201 """ 201 """
202 if not isabs(path): 202 if not isabs(p):
203 raise ValueError( 203 raise ValueError(
204 'Can\'t get native path case for a non-absolute path: %s' % path, 204 'Can\'t get native path case for a non-absolute path: %s' % p,
205 path) 205 p)
206 # Windows used to have an option to turn on case sensitivity on non Win32 206 # Windows used to have an option to turn on case sensitivity on non Win32
207 # subsystem but that's out of scope here and isn't supported anymore. 207 # subsystem but that's out of scope here and isn't supported anymore.
208 # Go figure why GetShortPathName() is needed. 208 # Go figure why GetShortPathName() is needed.
209 try: 209 try:
210 path = GetLongPathName(GetShortPathName(path)) 210 out = GetLongPathName(GetShortPathName(p))
211 except OSError: 211 except OSError, e:
212 # This is wrong to silently eat the exception but there's nothing that can 212 if e.args[0] in (2, 3):
213 # be done about it. 213 # The path does not exist. Try to recurse and reconstruct the path.
214 logging.info('No access to %s' % path) 214 base = os.path.dirname(p)
215 if path.startswith('\\\\?\\'): 215 rest = os.path.basename(p)
216 path = path[4:] 216 return os.path.join(get_native_path_case(base), rest)
217 raise
218 if out.startswith('\\\\?\\'):
219 out = out[4:]
217 # Always upper case the first letter since GetLongPathName() will return the 220 # Always upper case the first letter since GetLongPathName() will return the
218 # drive letter in the case it was given. 221 # drive letter in the case it was given.
219 return path[0].upper() + path[1:] 222 return out[0].upper() + out[1:]
220 223
221 224
222 def CommandLineToArgvW(command_line): 225 def CommandLineToArgvW(command_line):
223 """Splits a commandline into argv using CommandLineToArgvW().""" 226 """Splits a commandline into argv using CommandLineToArgvW()."""
224 # http://msdn.microsoft.com/library/windows/desktop/bb776391.aspx 227 # http://msdn.microsoft.com/library/windows/desktop/bb776391.aspx
225 size = c_int() 228 size = c_int()
226 ptr = windll.shell32.CommandLineToArgvW(unicode(command_line), byref(size)) 229 ptr = windll.shell32.CommandLineToArgvW(unicode(command_line), byref(size))
227 try: 230 try:
228 return [arg for arg in (c_wchar_p * size.value).from_address(ptr)] 231 return [arg for arg in (c_wchar_p * size.value).from_address(ptr)]
229 finally: 232 finally:
(...skipping 17 matching lines...) Expand all
247 for element in os.listdir(root_path): 250 for element in os.listdir(root_path):
248 if element.lower() == item: 251 if element.lower() == item:
249 return element 252 return element
250 253
251 254
252 def _native_case(p): 255 def _native_case(p):
253 """Gets the native path case. Warning: this function resolves symlinks.""" 256 """Gets the native path case. Warning: this function resolves symlinks."""
254 logging.debug('native_case(%s)' % p) 257 logging.debug('native_case(%s)' % p)
255 try: 258 try:
256 rel_ref, _ = Carbon.File.FSPathMakeRef(p) 259 rel_ref, _ = Carbon.File.FSPathMakeRef(p)
257 return rel_ref.FSRefMakePath() 260 out = rel_ref.FSRefMakePath()
261 if p.endswith(os.path.sep) and not out.endswith(os.path.sep):
262 return out + os.path.sep
263 return out
258 except MacOS.Error, e: 264 except MacOS.Error, e:
265 if e.args[0] == -43:
266 # The path does not exist. Try to recurse and reconstruct the path.
267 base = os.path.dirname(p)
268 rest = os.path.basename(p)
269 return os.path.join(_native_case(base), rest)
259 raise OSError( 270 raise OSError(
260 e.args[0], 'Failed to get native path for %s' % p, p, e.args[1]) 271 e.args[0], 'Failed to get native path for %s' % p, p, e.args[1])
261 272
262 273
263 def _split_at_symlink_native(base_path, rest): 274 def _split_at_symlink_native(base_path, rest):
264 """Returns the native path for a symlink.""" 275 """Returns the native path for a symlink."""
265 base, symlink, rest = split_at_symlink(base_path, rest) 276 base, symlink, rest = split_at_symlink(base_path, rest)
266 if symlink: 277 if symlink:
267 if not base_path: 278 if not base_path:
268 base_path = base 279 base_path = base
(...skipping 18 matching lines...) Expand all
287 return path 298 return path
288 299
289 # Starts assuming there is no symlink along the path. 300 # Starts assuming there is no symlink along the path.
290 resolved = _native_case(path) 301 resolved = _native_case(path)
291 if resolved.lower() == path.lower(): 302 if resolved.lower() == path.lower():
292 # This code path is incredibly faster. 303 # This code path is incredibly faster.
293 return resolved 304 return resolved
294 305
295 # There was a symlink, process it. 306 # There was a symlink, process it.
296 base, symlink, rest = _split_at_symlink_native(None, path) 307 base, symlink, rest = _split_at_symlink_native(None, path)
297 assert symlink, (path, base, symlink, rest) 308 assert symlink, (path, base, symlink, rest, resolved)
298 prev = base 309 prev = base
299 base = safe_join(_native_case(base), symlink) 310 base = safe_join(_native_case(base), symlink)
300 assert len(base) > len(prev) 311 assert len(base) > len(prev)
301 while rest: 312 while rest:
302 prev = base 313 prev = base
303 relbase, symlink, rest = _split_at_symlink_native(base, rest) 314 relbase, symlink, rest = _split_at_symlink_native(base, rest)
304 base = safe_join(base, relbase) 315 base = safe_join(base, relbase)
305 assert len(base) > len(prev), (prev, base, symlink) 316 assert len(base) > len(prev), (prev, base, symlink)
306 if symlink: 317 if symlink:
307 base = safe_join(base, symlink) 318 base = safe_join(base, symlink)
(...skipping 19 matching lines...) Expand all
327 TODO(maruel): This is not strictly true. Implement if necessary. 338 TODO(maruel): This is not strictly true. Implement if necessary.
328 """ 339 """
329 if not isabs(path): 340 if not isabs(path):
330 raise ValueError( 341 raise ValueError(
331 'Can\'t get native path case for a non-absolute path: %s' % path, 342 'Can\'t get native path case for a non-absolute path: %s' % path,
332 path) 343 path)
333 # Give up on cygwin, as GetLongPathName() can't be called. 344 # Give up on cygwin, as GetLongPathName() can't be called.
334 # Linux traces tends to not be normalized so use this occasion to normalize 345 # Linux traces tends to not be normalized so use this occasion to normalize
335 # it. This function implementation already normalizes the path on the other 346 # it. This function implementation already normalizes the path on the other
336 # OS so this needs to be done here to be coherent between OSes. 347 # OS so this needs to be done here to be coherent between OSes.
337 return os.path.normpath(path) 348 out = os.path.normpath(path)
349 if path.endswith(os.path.sep) and not out.endswith(os.path.sep):
350 return out + os.path.sep
351 return out
338 352
339 353
340 if sys.platform != 'win32': # All non-Windows OSes. 354 if sys.platform != 'win32': # All non-Windows OSes.
341 355
342 356
343 def safe_join(*args): 357 def safe_join(*args):
344 """Joins path elements like os.path.join() but doesn't abort on absolute 358 """Joins path elements like os.path.join() but doesn't abort on absolute
345 path. 359 path.
346 360
347 os.path.join('foo', '/bar') == '/bar' 361 os.path.join('foo', '/bar') == '/bar'
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
562 self.tainted = tainted 576 self.tainted = tainted
563 # These are cache only. 577 # These are cache only.
564 self._real_path = None 578 self._real_path = None
565 self._size = None 579 self._size = None
566 580
567 # Check internal consistency. 581 # Check internal consistency.
568 assert path, path 582 assert path, path
569 assert tainted or bool(root) != bool(isabs(path)), (root, path) 583 assert tainted or bool(root) != bool(isabs(path)), (root, path)
570 assert tainted or ( 584 assert tainted or (
571 not os.path.exists(self.full_path) or 585 not os.path.exists(self.full_path) or
572 (self.full_path.rstrip(os.path.sep) == 586 (self.full_path == get_native_path_case(self.full_path))), (
573 get_native_path_case(self.full_path))), (
574 tainted, self.full_path, get_native_path_case(self.full_path)) 587 tainted, self.full_path, get_native_path_case(self.full_path))
575 588
576 @property 589 @property
577 def existent(self): 590 def existent(self):
578 return self.size != -1 591 return self.size != -1
579 592
580 @property 593 @property
581 def full_path(self): 594 def full_path(self):
582 if self.root: 595 if self.root:
583 return os.path.join(self.root, self.path) 596 return os.path.join(self.root, self.path)
(...skipping 2492 matching lines...) Expand 10 before | Expand all | Expand 10 after
3076 return command(argv[1:]) 3089 return command(argv[1:])
3077 except TracingFailure, e: 3090 except TracingFailure, e:
3078 sys.stderr.write('\nError: ') 3091 sys.stderr.write('\nError: ')
3079 sys.stderr.write(str(e)) 3092 sys.stderr.write(str(e))
3080 sys.stderr.write('\n') 3093 sys.stderr.write('\n')
3081 return 1 3094 return 1
3082 3095
3083 3096
3084 if __name__ == '__main__': 3097 if __name__ == '__main__':
3085 sys.exit(main(sys.argv[1:])) 3098 sys.exit(main(sys.argv[1:]))
OLDNEW
« no previous file with comments | « tools/isolate/run_test_from_archive_smoke_test.py ('k') | tools/isolate/trace_inputs_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698