]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
EMX lacks an implementation of link(). As Mailman wants os.link() to
authorAndrew MacIntyre <andymac@bullseye.apana.org.au>
Tue, 2 Dec 2003 12:31:09 +0000 (12:31 +0000)
committerAndrew MacIntyre <andymac@bullseye.apana.org.au>
Tue, 2 Dec 2003 12:31:09 +0000 (12:31 +0000)
implement its locking scheme, this module implements a crude link() by
way of copying the source to the destination provided the destination
doesn't already exist.

Lib/plat-os2emx/_emx_link.py [new file with mode: 0644]

diff --git a/Lib/plat-os2emx/_emx_link.py b/Lib/plat-os2emx/_emx_link.py
new file mode 100644 (file)
index 0000000..04648e2
--- /dev/null
@@ -0,0 +1,79 @@
+# _emx_link.py
+
+# Written by Andrew I MacIntyre, December 2002.
+
+"""_emx_link.py is a simplistic emulation of the Unix link(2) library routine 
+for creating so-called hard links.  It is intended to be imported into
+the os module in place of the unimplemented (on OS/2) Posix link()
+function (os.link()).
+
+We do this on OS/2 by implementing a file copy, with link(2) semantics:-
+  - the target cannot already exist;
+  - we hope that the actual file open (if successful) is actually
+    atomic...
+
+Limitations of this approach/implementation include:-
+  - no support for correct link counts (EMX stat(target).st_nlink
+    is always 1);
+  - thread safety undefined;
+  - default file permissions (r+w) used, can't be over-ridden;
+  - implemented in Python so comparatively slow, especially for large
+    source files;
+  - need sufficient free disk space to store the copy.
+
+Behaviour:-
+  - any exception should propagate to the caller;
+  - want target to be an exact copy of the source, so use binary mode;
+  - returns None, same as os.link() which is implemented in posixmodule.c;
+  - target removed in the event of a failure where possible;
+  - given the motivation to write this emulation came from trying to
+    support a Unix resource lock implementation, where minimal overhead
+    during creation of the target is desirable and the files are small,
+    we read a source block before attempting to create the target so that
+    we're ready to immediately write some data into it.
+"""
+
+import os
+import errno
+
+__all__ = ['link']
+
+def link(source, target):
+    """link(source, target) -> None
+
+    Attempt to hard link the source file to the target file name.
+    On OS/2, this creates a complete copy of the source file.
+    """
+
+    s = os.open(source, os.O_RDONLY | os.O_BINARY)
+    if os.isatty(s):
+        raise OSError, (errno.EXDEV, 'Cross-device link')
+    data = os.read(s, 1024)
+
+    try:
+        t = os.open(target, os.O_WRONLY | os.O_BINARY | os.O_CREAT | os.O_EXCL)
+    except OSError:
+        os.close(s)
+        raise
+
+    try:
+        while data:
+            os.write(t, data)
+            data = os.read(s, 1024)
+    except OSError:
+        os.close(s)
+        os.close(t)
+        os.unlink(target)
+        raise
+
+    os.close(s)
+    os.close(t)
+
+if __name__ == '__main__':
+    import sys
+    try:
+        link(sys.argv[1], sys.argv[2])
+    except IndexError:
+        print 'Usage: emx_link <source> <target>'
+    except OSError:
+        print 'emx_link: %s' % str(sys.exc_info()[1])