Show More
@@ -13,6 +13,7 b' posixfile = open' | |||||
13 | nulldev = '/dev/null' |
|
13 | nulldev = '/dev/null' | |
14 | normpath = os.path.normpath |
|
14 | normpath = os.path.normpath | |
15 | samestat = os.path.samestat |
|
15 | samestat = os.path.samestat | |
|
16 | rename = os.rename | |||
16 | expandglobs = False |
|
17 | expandglobs = False | |
17 |
|
18 | |||
18 | umask = os.umask(0) |
|
19 | umask = os.umask(0) |
@@ -16,7 +16,7 b' hide platform-specific details from the ' | |||||
16 | from i18n import _ |
|
16 | from i18n import _ | |
17 | import error, osutil, encoding |
|
17 | import error, osutil, encoding | |
18 | import cStringIO, errno, re, shutil, sys, tempfile, traceback |
|
18 | import cStringIO, errno, re, shutil, sys, tempfile, traceback | |
19 |
import os, stat, time, calendar, |
|
19 | import os, stat, time, calendar, textwrap | |
20 | import imp |
|
20 | import imp | |
21 |
|
21 | |||
22 | # Python compatibility |
|
22 | # Python compatibility | |
@@ -399,44 +399,6 b' def lexists(filename):' | |||||
399 | return False |
|
399 | return False | |
400 | return True |
|
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 | def unlink(f): |
|
402 | def unlink(f): | |
441 | """unlink and remove the directory if it is empty""" |
|
403 | """unlink and remove the directory if it is empty""" | |
442 | os.unlink(f) |
|
404 | os.unlink(f) |
@@ -7,7 +7,7 b'' | |||||
7 |
|
7 | |||
8 | from i18n import _ |
|
8 | from i18n import _ | |
9 | import osutil, error |
|
9 | import osutil, error | |
10 | import errno, msvcrt, os, re, sys |
|
10 | import errno, msvcrt, os, re, sys, random | |
11 |
|
11 | |||
12 | nulldev = 'NUL:' |
|
12 | nulldev = 'NUL:' | |
13 | umask = 002 |
|
13 | umask = 002 | |
@@ -283,6 +283,44 b' def unlink(f):' | |||||
283 | except OSError: |
|
283 | except OSError: | |
284 | pass |
|
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 | try: |
|
324 | try: | |
287 | # override functions with win32 versions if possible |
|
325 | # override functions with win32 versions if possible | |
288 | from win32 import * |
|
326 | from win32 import * |
General Comments 0
You need to be logged in to leave comments.
Login now