Commit b15f9568 authored by Jim Fulton's avatar Jim Fulton

Committed files are read-only.

parent 1f74a566
...@@ -21,6 +21,7 @@ ClientStorage -- the main class, implementing the Storage API ...@@ -21,6 +21,7 @@ ClientStorage -- the main class, implementing the Storage API
import cPickle import cPickle
import os import os
import socket import socket
import stat
import sys import sys
import tempfile import tempfile
import threading import threading
...@@ -952,6 +953,7 @@ class ClientStorage(object): ...@@ -952,6 +953,7 @@ class ClientStorage(object):
def receiveBlobStop(self, oid, serial): def receiveBlobStop(self, oid, serial):
blob_filename = self.fshelper.getBlobFilename(oid, serial) blob_filename = self.fshelper.getBlobFilename(oid, serial)
os.rename(blob_filename+'.dl', blob_filename) os.rename(blob_filename+'.dl', blob_filename)
os.chmod(blob_filename, stat.S_IREAD)
def loadBlob(self, oid, serial): def loadBlob(self, oid, serial):
......
...@@ -21,6 +21,7 @@ import os ...@@ -21,6 +21,7 @@ import os
import random import random
import signal import signal
import socket import socket
import stat
import tempfile import tempfile
import threading import threading
import time import time
...@@ -532,6 +533,8 @@ class CommonBlobTests: ...@@ -532,6 +533,8 @@ class CommonBlobTests:
filename = self._storage.loadBlob(oid, serial) filename = self._storage.loadBlob(oid, serial)
self.assertEquals(somedata, open(filename, 'rb').read()) self.assertEquals(somedata, open(filename, 'rb').read())
self.assert_(not(os.stat(filename).st_mode & stat.S_IWRITE))
self.assert_((os.stat(filename).st_mode & stat.S_IREAD))
def checkTemporaryDirectory(self): def checkTemporaryDirectory(self):
self.assertEquals(self.blob_cache_dir, self.assertEquals(self.blob_cache_dir,
......
...@@ -18,6 +18,7 @@ import base64 ...@@ -18,6 +18,7 @@ import base64
import logging import logging
import os import os
import shutil import shutil
import stat
import sys import sys
import tempfile import tempfile
import threading import threading
...@@ -191,7 +192,7 @@ class Blob(persistent.Persistent): ...@@ -191,7 +192,7 @@ class Blob(persistent.Persistent):
os.unlink(target) os.unlink(target)
try: try:
rename_or_copy_blob(filename, target) rename_or_copy_blob(filename, target, chmod=False)
except: except:
# Recover from the failed consumption: First remove the file, it # Recover from the failed consumption: First remove the file, it
# might exist and mark the pointer to the uncommitted file. # might exist and mark the pointer to the uncommitted file.
...@@ -579,12 +580,14 @@ class BlobStorage(SpecificationDecoratorBase): ...@@ -579,12 +580,14 @@ class BlobStorage(SpecificationDecoratorBase):
load_result = self.loadBefore(oid, serial_id) load_result = self.loadBefore(oid, serial_id)
if load_result is None: if load_result is None:
# There was no previous revision of this blob # There was no previous revision of this blob
# object. The blob was created in the transaction # object. The blob was created in the transaction
# represented by serial_id. We copy the blob data # represented by serial_id. We copy the blob data
# to a new file that references the undo # to a new file that references the undo
# transaction in case a user wishes to undo this # transaction in case a user wishes to undo this
# undo. # undo. It would be nice if we had some way to
# link to old blobs.
orig_fn = self.fshelper.getBlobFilename(oid, serial_id) orig_fn = self.fshelper.getBlobFilename(oid, serial_id)
new_fn = self.fshelper.getBlobFilename(oid, undo_serial) new_fn = self.fshelper.getBlobFilename(oid, undo_serial)
else: else:
...@@ -608,7 +611,7 @@ class BlobStorage(SpecificationDecoratorBase): ...@@ -608,7 +611,7 @@ class BlobStorage(SpecificationDecoratorBase):
copied = logging.getLogger('ZODB.blob.copied').debug copied = logging.getLogger('ZODB.blob.copied').debug
def rename_or_copy_blob(f1, f2): def rename_or_copy_blob(f1, f2, chmod=True):
"""Try to rename f1 to f2, fallback to copy. """Try to rename f1 to f2, fallback to copy.
Under certain conditions a rename might not work, e.g. because the target Under certain conditions a rename might not work, e.g. because the target
...@@ -622,3 +625,5 @@ def rename_or_copy_blob(f1, f2): ...@@ -622,3 +625,5 @@ def rename_or_copy_blob(f1, f2):
copied("Copied blob file %r to %r.", f1, f2) copied("Copied blob file %r to %r.", f1, f2)
utils.cp(open(f1, 'rb'), open(f2, 'wb')) utils.cp(open(f1, 'rb'), open(f2, 'wb'))
os.unlink(f1) os.unlink(f1)
if chmod:
os.chmod(f2, stat.S_IREAD)
...@@ -303,7 +303,12 @@ uncommitted changes: ...@@ -303,7 +303,12 @@ uncommitted changes:
>>> open(blob.committed()).read() >>> open(blob.committed()).read()
"I'm a happy blob." "I'm a happy blob."
You can't open a committed blob file for writing:
>>> open(blob.committed(), 'w') # doctest: +ELLIPSIS
Traceback (most recent call last):
...
IOError: ...
Teardown Teardown
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment