From eb477f05cffebba58299f0d2b32400c35f94d645 Mon Sep 17 00:00:00 2001 From: Andrew MacIntyre Date: Tue, 2 Dec 2003 12:31:09 +0000 Subject: 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. --- Lib/plat-os2emx/_emx_link.py | 79 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 Lib/plat-os2emx/_emx_link.py 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 ' + except OSError: + print 'emx_link: %s' % str(sys.exc_info()[1]) -- cgit v0.12