summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorAndrew MacIntyre <andymac@bullseye.apana.org.au>2003-12-02 12:31:09 (GMT)
committerAndrew MacIntyre <andymac@bullseye.apana.org.au>2003-12-02 12:31:09 (GMT)
commiteb477f05cffebba58299f0d2b32400c35f94d645 (patch)
tree8ca41d8d580772c424b3d7a53e7242f7dd64cf24 /Lib
parent2e8a6e0ec6729ffb490130eff6bb33ea9375c75c (diff)
downloadcpython-eb477f05cffebba58299f0d2b32400c35f94d645.zip
cpython-eb477f05cffebba58299f0d2b32400c35f94d645.tar.gz
cpython-eb477f05cffebba58299f0d2b32400c35f94d645.tar.bz2
EMX lacks an implementation of link(). As Mailman wants os.link() to
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.
Diffstat (limited to 'Lib')
-rw-r--r--Lib/plat-os2emx/_emx_link.py79
1 files changed, 79 insertions, 0 deletions
diff --git a/Lib/plat-os2emx/_emx_link.py b/Lib/plat-os2emx/_emx_link.py
new file mode 100644
index 0000000..04648e2
--- /dev/null
+++ b/Lib/plat-os2emx/_emx_link.py
@@ -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])