1# _emx_link.py 2 3# Written by Andrew I MacIntyre, December 2002. 4 5"""_emx_link.py is a simplistic emulation of the Unix link(2) library routine 6for creating so-called hard links. It is intended to be imported into 7the os module in place of the unimplemented (on OS/2) Posix link() 8function (os.link()). 9 10We do this on OS/2 by implementing a file copy, with link(2) semantics:- 11 - the target cannot already exist; 12 - we hope that the actual file open (if successful) is actually 13 atomic... 14 15Limitations of this approach/implementation include:- 16 - no support for correct link counts (EMX stat(target).st_nlink 17 is always 1); 18 - thread safety undefined; 19 - default file permissions (r+w) used, can't be over-ridden; 20 - implemented in Python so comparatively slow, especially for large 21 source files; 22 - need sufficient free disk space to store the copy. 23 24Behaviour:- 25 - any exception should propagate to the caller; 26 - want target to be an exact copy of the source, so use binary mode; 27 - returns None, same as os.link() which is implemented in posixmodule.c; 28 - target removed in the event of a failure where possible; 29 - given the motivation to write this emulation came from trying to 30 support a Unix resource lock implementation, where minimal overhead 31 during creation of the target is desirable and the files are small, 32 we read a source block before attempting to create the target so that 33 we're ready to immediately write some data into it. 34""" 35 36import os 37import errno 38 39__all__ = ['link'] 40 41def link(source, target): 42 """link(source, target) -> None 43 44 Attempt to hard link the source file to the target file name. 45 On OS/2, this creates a complete copy of the source file. 46 """ 47 48 s = os.open(source, os.O_RDONLY | os.O_BINARY) 49 if os.isatty(s): 50 raise OSError, (errno.EXDEV, 'Cross-device link') 51 data = os.read(s, 1024) 52 53 try: 54 t = os.open(target, os.O_WRONLY | os.O_BINARY | os.O_CREAT | os.O_EXCL) 55 except OSError: 56 os.close(s) 57 raise 58 59 try: 60 while data: 61 os.write(t, data) 62 data = os.read(s, 1024) 63 except OSError: 64 os.close(s) 65 os.close(t) 66 os.unlink(target) 67 raise 68 69 os.close(s) 70 os.close(t) 71 72if __name__ == '__main__': 73 import sys 74 try: 75 link(sys.argv[1], sys.argv[2]) 76 except IndexError: 77 print 'Usage: emx_link <source> <target>' 78 except OSError: 79 print 'emx_link: %s' % str(sys.exc_info()[1]) 80