5

Using Python 2.5+, UNIX:

I have a program which simulates directory "copy-on-write" functionality, by hardlinking all entries. Currently all the underlying code, some of which I don't have access to, uses standard open(fname, 'w') to write the regular files.

But with hardlinks, this means the same inode is used (just truncated), so the original content is destroyed as well. For copy-on-write, I would of course want the original to remain untouched (old inode) and the open('w') call to create a new inode.

Any ideas on the best way to achieve this? Monkey-patch open somehow?

What I came up with so far is overriding open to try to delete the file first (if it exists) and only then do open('w'):

import __builtin__
_open = __builtin__.open

def my_open(name, mode='r', *args, **kwargs):
    """Simulate copy-on-write, by deleting the file first if it exists"""
    if 'w' in mode and os.path.exists(name): # TODO: use isfile()?
        os.remove(name)
    return _open(name, mode, *args, **kwargs)

__builtin__.open = my_open
user124114
  • 8,372
  • 11
  • 41
  • 63

1 Answers1

2

Were you looking for something like this?

import sys
old_open = __builtins__.open    

# Override builtin open()
def my_open(fname, *args, **kwargs):
    # If the path is a hardlink, (ie, check that st_nlink >1)
    if os.path.isfile(fname) and os.stat(fname).st_nlink > 1: 
        os.unlink(fname)
    return old_open(fname, *args, **kwargs)
__buitlins__.open = my_open
brice
  • 24,329
  • 7
  • 79
  • 95
  • Yes, except i don't have access to all the libraries that call `open()` internally, and which may be imported in any order, so the solution needs to be more global. – user124114 Mar 29 '12 at 12:19
  • I see what you mean. changed to override open, then reload all modules. – brice Mar 29 '12 at 12:37
  • @user124114 Ok, that should do the trick and be pretty general. – brice Mar 29 '12 at 12:50
  • 2
    The `__builtin__` module is shared globally per process, I don't think the reload is necessary. Anyway, this is the solution I have right now (see the last sentence) :-) I was wondering if there is another, cleverer way -- overriding built-ins is kinda nasty. – user124114 Mar 29 '12 at 12:51
  • Add `if 'w' in mode and not '+' in mode` ? – kxr Mar 03 '21 at 16:26