Show More
@@ -13,6 +13,7 b' posixfile = open' | |||
|
13 | 13 | nulldev = '/dev/null' |
|
14 | 14 | normpath = os.path.normpath |
|
15 | 15 | samestat = os.path.samestat |
|
16 | rename = os.rename | |
|
16 | 17 | expandglobs = False |
|
17 | 18 | |
|
18 | 19 | umask = os.umask(0) |
@@ -16,7 +16,7 b' hide platform-specific details from the ' | |||
|
16 | 16 | from i18n import _ |
|
17 | 17 | import error, osutil, encoding |
|
18 | 18 | import cStringIO, errno, re, shutil, sys, tempfile, traceback |
|
19 |
import os, stat, time, calendar, |
|
|
19 | import os, stat, time, calendar, textwrap | |
|
20 | 20 | import imp |
|
21 | 21 | |
|
22 | 22 | # Python compatibility |
@@ -399,44 +399,6 b' def lexists(filename):' | |||
|
399 | 399 | return False |
|
400 | 400 | return True |
|
401 | 401 | |
|
402 | def rename(src, dst): | |
|
403 | '''atomically rename file src to dst, replacing dst if it exists''' | |
|
404 | try: | |
|
405 | os.rename(src, dst) | |
|
406 | except OSError, err: # FIXME: check err (EEXIST ?) | |
|
407 | ||
|
408 | # On windows, rename to existing file is not allowed, so we | |
|
409 | # must delete destination first. But if a file is open, unlink | |
|
410 | # schedules it for delete but does not delete it. Rename | |
|
411 | # happens immediately even for open files, so we rename | |
|
412 | # destination to a temporary name, then delete that. Then | |
|
413 | # rename is safe to do. | |
|
414 | # The temporary name is chosen at random to avoid the situation | |
|
415 | # where a file is left lying around from a previous aborted run. | |
|
416 | # The usual race condition this introduces can't be avoided as | |
|
417 | # we need the name to rename into, and not the file itself. Due | |
|
418 | # to the nature of the operation however, any races will at worst | |
|
419 | # lead to the rename failing and the current operation aborting. | |
|
420 | ||
|
421 | def tempname(prefix): | |
|
422 | for tries in xrange(10): | |
|
423 | temp = '%s-%08x' % (prefix, random.randint(0, 0xffffffff)) | |
|
424 | if not os.path.exists(temp): | |
|
425 | return temp | |
|
426 | raise IOError, (errno.EEXIST, "No usable temporary filename found") | |
|
427 | ||
|
428 | temp = tempname(dst) | |
|
429 | os.rename(dst, temp) | |
|
430 | try: | |
|
431 | os.unlink(temp) | |
|
432 | except: | |
|
433 | # Some rude AV-scanners on Windows may cause the unlink to | |
|
434 | # fail. Not aborting here just leaks the temp file, whereas | |
|
435 | # aborting at this point may leave serious inconsistencies. | |
|
436 | # Ideally, we would notify the user here. | |
|
437 | pass | |
|
438 | os.rename(src, dst) | |
|
439 | ||
|
440 | 402 | def unlink(f): |
|
441 | 403 | """unlink and remove the directory if it is empty""" |
|
442 | 404 | os.unlink(f) |
@@ -7,7 +7,7 b'' | |||
|
7 | 7 | |
|
8 | 8 | from i18n import _ |
|
9 | 9 | import osutil, error |
|
10 | import errno, msvcrt, os, re, sys | |
|
10 | import errno, msvcrt, os, re, sys, random | |
|
11 | 11 | |
|
12 | 12 | nulldev = 'NUL:' |
|
13 | 13 | umask = 002 |
@@ -283,6 +283,44 b' def unlink(f):' | |||
|
283 | 283 | except OSError: |
|
284 | 284 | pass |
|
285 | 285 | |
|
286 | def rename(src, dst): | |
|
287 | '''atomically rename file src to dst, replacing dst if it exists''' | |
|
288 | try: | |
|
289 | os.rename(src, dst) | |
|
290 | except OSError, err: # FIXME: check err (EEXIST ?) | |
|
291 | ||
|
292 | # On windows, rename to existing file is not allowed, so we | |
|
293 | # must delete destination first. But if a file is open, unlink | |
|
294 | # schedules it for delete but does not delete it. Rename | |
|
295 | # happens immediately even for open files, so we rename | |
|
296 | # destination to a temporary name, then delete that. Then | |
|
297 | # rename is safe to do. | |
|
298 | # The temporary name is chosen at random to avoid the situation | |
|
299 | # where a file is left lying around from a previous aborted run. | |
|
300 | # The usual race condition this introduces can't be avoided as | |
|
301 | # we need the name to rename into, and not the file itself. Due | |
|
302 | # to the nature of the operation however, any races will at worst | |
|
303 | # lead to the rename failing and the current operation aborting. | |
|
304 | ||
|
305 | def tempname(prefix): | |
|
306 | for tries in xrange(10): | |
|
307 | temp = '%s-%08x' % (prefix, random.randint(0, 0xffffffff)) | |
|
308 | if not os.path.exists(temp): | |
|
309 | return temp | |
|
310 | raise IOError, (errno.EEXIST, "No usable temporary filename found") | |
|
311 | ||
|
312 | temp = tempname(dst) | |
|
313 | os.rename(dst, temp) | |
|
314 | try: | |
|
315 | os.unlink(temp) | |
|
316 | except: | |
|
317 | # Some rude AV-scanners on Windows may cause the unlink to | |
|
318 | # fail. Not aborting here just leaks the temp file, whereas | |
|
319 | # aborting at this point may leave serious inconsistencies. | |
|
320 | # Ideally, we would notify the user here. | |
|
321 | pass | |
|
322 | os.rename(src, dst) | |
|
323 | ||
|
286 | 324 | try: |
|
287 | 325 | # override functions with win32 versions if possible |
|
288 | 326 | from win32 import * |
General Comments 0
You need to be logged in to leave comments.
Login now