=== modified file 'django/core/files/move.py'
|
|
|
7 | 7 | |
8 | 8 | import os |
9 | 9 | from django.core.files import locks |
10 | | |
11 | | __all__ = ['file_move_safe'] |
12 | | |
13 | 10 | try: |
14 | | import shutil |
15 | | file_move = shutil.move |
| 11 | from shutil import copystat |
16 | 12 | except ImportError: |
17 | | file_move = os.rename |
| 13 | def copystat(src, dst): |
| 14 | """Copy all stat info (mode bits, atime and mtime) from src to dst""" |
| 15 | st = os.stat(src) |
| 16 | mode = stat.S_IMODE(st.st_mode) |
| 17 | if hasattr(os, 'utime'): |
| 18 | os.utime(dst, (st.st_atime, st.st_mtime)) |
| 19 | if hasattr(os, 'chmod'): |
| 20 | os.chmod(dst, mode) |
| 21 | |
| 22 | __all__ = ['file_move_safe'] |
| 23 | |
| 24 | def _samefile(src, dst): |
| 25 | # Macintosh, Unix. |
| 26 | if hasattr(os.path,'samefile'): |
| 27 | try: |
| 28 | return os.path.samefile(src, dst) |
| 29 | except OSError: |
| 30 | return False |
| 31 | |
| 32 | # All other platforms: check for same pathname. |
| 33 | return (os.path.normcase(os.path.abspath(src)) == |
| 34 | os.path.normcase(os.path.abspath(dst))) |
18 | 35 | |
19 | 36 | def file_move_safe(old_file_name, new_file_name, chunk_size = 1024*64, allow_overwrite=False): |
20 | 37 | """ |
… |
… |
|
30 | 47 | """ |
31 | 48 | |
32 | 49 | # There's no reason to move if we don't have to. |
33 | | if old_file_name == new_file_name: |
| 50 | if _samefile(old_file_name, new_file_name): |
34 | 51 | return |
35 | 52 | |
36 | | if not allow_overwrite and os.path.exists(new_file_name): |
37 | | raise IOError("Cannot overwrite existing file '%s'." % new_file_name) |
38 | | |
39 | 53 | try: |
40 | | file_move(old_file_name, new_file_name) |
| 54 | os.rename(old_file_name, new_file_name) |
41 | 55 | return |
42 | 56 | except OSError: |
43 | 57 | # This will happen with os.rename if moving to another filesystem |
| 58 | # or when moving opened files on certain operating systems |
44 | 59 | pass |
45 | 60 | |
46 | | # If the built-in didn't work, do it the hard way. |
47 | | fd = os.open(new_file_name, os.O_WRONLY | os.O_CREAT | os.O_EXCL | getattr(os, 'O_BINARY', 0)) |
| 61 | # first open the old file, so that it won't go away |
| 62 | old_file = open(old_file_name, 'rb') |
48 | 63 | try: |
49 | | locks.lock(fd, locks.LOCK_EX) |
50 | | old_file = open(old_file_name, 'rb') |
51 | | current_chunk = None |
52 | | while current_chunk != '': |
53 | | current_chunk = old_file.read(chunk_size) |
54 | | os.write(fd, current_chunk) |
| 64 | # now open the new file, not forgetting allow_overwrite |
| 65 | fd = os.open(new_file_name, os.O_WRONLY | os.O_CREAT | getattr(os, 'O_BINARY', 0) | |
| 66 | (not allow_overwrite and os.O_EXCL or 0)) |
| 67 | try: |
| 68 | locks.lock(fd, locks.LOCK_EX) |
| 69 | current_chunk = None |
| 70 | while current_chunk != '': |
| 71 | current_chunk = old_file.read(chunk_size) |
| 72 | os.write(fd, current_chunk) |
| 73 | finally: |
| 74 | locks.unlock(fd) |
| 75 | os.close(fd) |
55 | 76 | finally: |
56 | | locks.unlock(fd) |
57 | | os.close(fd) |
58 | 77 | old_file.close() |
| 78 | copystat(old_file_name, new_file_name) |
59 | 79 | |
60 | | os.remove(old_file_name) |
| 80 | try: |
| 81 | os.remove(old_file_name) |
| 82 | except OSError, e: |
| 83 | # Certain operating systems (Cygwin and Windows) |
| 84 | # fail when deleting opened files, ignore it |
| 85 | if getattr(e, 'winerror', 0) != 32: |
| 86 | # FIXME: should we also ignore errno 13? |
| 87 | raise |
=== modified file 'django/core/files/temp.py'
|
|
|
25 | 25 | fd, name = tempfile.mkstemp(suffix=suffix, prefix=prefix, |
26 | 26 | dir=dir) |
27 | 27 | self.name = name |
28 | | self._file = os.fdopen(fd, mode, bufsize) |
| 28 | self.file = os.fdopen(fd, mode, bufsize) |
| 29 | self.close_called = False |
| 30 | |
| 31 | # Because close can be called during shutdown |
| 32 | # we need to cache os.unlink and access it |
| 33 | # as self.unlink only |
| 34 | unlink = os.unlink |
| 35 | |
| 36 | def close(self): |
| 37 | if not self.close_called: |
| 38 | self.close_called = True |
| 39 | try: |
| 40 | self.file.close() |
| 41 | except (OSError, IOError): |
| 42 | pass |
| 43 | try: |
| 44 | self.unlink(self.name) |
| 45 | except (OSError): |
| 46 | pass |
29 | 47 | |
30 | 48 | def __del__(self): |
31 | | try: |
32 | | self._file.close() |
33 | | except (OSError, IOError): |
34 | | pass |
35 | | try: |
36 | | os.unlink(self.name) |
37 | | except (OSError): |
38 | | pass |
39 | | |
40 | | try: |
41 | | super(TemporaryFile, self).__del__() |
42 | | except AttributeError: |
43 | | pass |
44 | | |
45 | | |
46 | | def read(self, *args): return self._file.read(*args) |
47 | | def seek(self, offset): return self._file.seek(offset) |
48 | | def write(self, s): return self._file.write(s) |
49 | | def close(self): return self._file.close() |
50 | | def __iter__(self): return iter(self._file) |
51 | | def readlines(self, size=None): return self._file.readlines(size) |
52 | | def xreadlines(self): return self._file.xreadlines() |
| 49 | self.close() |
| 50 | |
| 51 | def read(self, *args): return self.file.read(*args) |
| 52 | def seek(self, offset): return self.file.seek(offset) |
| 53 | def write(self, s): return self.file.write(s) |
| 54 | def __iter__(self): return iter(self.file) |
| 55 | def readlines(self, size=None): return self.file.readlines(size) |
| 56 | def xreadlines(self): return self.file.xreadlines() |
53 | 57 | |
54 | 58 | NamedTemporaryFile = TemporaryFile |
55 | 59 | else: |
=== modified file 'tests/regressiontests/file_uploads/views.py'
|
|
|
2 | 2 | from django.core.files.uploadedfile import UploadedFile |
3 | 3 | from django.http import HttpResponse, HttpResponseServerError |
4 | 4 | from django.utils import simplejson |
| 5 | from models import FileModel |
5 | 6 | from uploadhandler import QuotaUploadHandler |
6 | 7 | from django.utils.hashcompat import sha_constructor |
7 | 8 | |
… |
… |
|
45 | 46 | if new_hash != submitted_hash: |
46 | 47 | return HttpResponseServerError() |
47 | 48 | |
| 49 | # Adding large file to the database should succeed |
| 50 | largefile = request.FILES['file_field2'] |
| 51 | obj = FileModel() |
| 52 | obj.testfile.save(largefile.name, largefile) |
| 53 | |
48 | 54 | return HttpResponse('') |
49 | 55 | |
50 | 56 | def file_upload_echo(request): |