| """Extended file operations available in POSIX. |
| |
| f = posixfile.open(filename, [mode, [bufsize]]) |
| will create a new posixfile object |
| |
| f = posixfile.fileopen(fileobject) |
| will create a posixfile object from a builtin file object |
| |
| f.file() |
| will return the original builtin file object |
| |
| f.dup() |
| will return a new file object based on a new filedescriptor |
| |
| f.dup2(fd) |
| will return a new file object based on the given filedescriptor |
| |
| f.flags(mode) |
| will turn on the associated flag (merge) |
| mode can contain the following characters: |
| |
| (character representing a flag) |
| a append only flag |
| c close on exec flag |
| n no delay flag |
| s synchronization flag |
| (modifiers) |
| ! turn flags 'off' instead of default 'on' |
| = copy flags 'as is' instead of default 'merge' |
| ? return a string in which the characters represent the flags |
| that are set |
| |
| note: - the '!' and '=' modifiers are mutually exclusive. |
| - the '?' modifier will return the status of the flags after they |
| have been changed by other characters in the mode string |
| |
| f.lock(mode [, len [, start [, whence]]]) |
| will (un)lock a region |
| mode can contain the following characters: |
| |
| (character representing type of lock) |
| u unlock |
| r read lock |
| w write lock |
| (modifiers) |
| | wait until the lock can be granted |
| ? return the first lock conflicting with the requested lock |
| or 'None' if there is no conflict. The lock returned is in the |
| format (mode, len, start, whence, pid) where mode is a |
| character representing the type of lock ('r' or 'w') |
| |
| note: - the '?' modifier prevents a region from being locked; it is |
| query only |
| """ |
| |
| class _posixfile_: |
| """File wrapper class that provides extra POSIX file routines.""" |
| |
| states = ['open', 'closed'] |
| |
| # |
| # Internal routines |
| # |
| def __repr__(self): |
| file = self._file_ |
| return "<%s posixfile '%s', mode '%s' at %s>" % \ |
| (self.states[file.closed], file.name, file.mode, \ |
| hex(id(self))[2:]) |
| |
| # |
| # Initialization routines |
| # |
| def open(self, name, mode='r', bufsize=-1): |
| import __builtin__ |
| return self.fileopen(__builtin__.open(name, mode, bufsize)) |
| |
| def fileopen(self, file): |
| if `type(file)` != "<type 'file'>": |
| raise TypeError, 'posixfile.fileopen() arg must be file object' |
| self._file_ = file |
| # Copy basic file methods |
| for method in file.__methods__: |
| setattr(self, method, getattr(file, method)) |
| return self |
| |
| # |
| # New methods |
| # |
| def file(self): |
| return self._file_ |
| |
| def dup(self): |
| import posix |
| |
| try: ignore = posix.fdopen |
| except: raise AttributeError, 'dup() method unavailable' |
| |
| return posix.fdopen(posix.dup(self._file_.fileno()), self._file_.mode) |
| |
| def dup2(self, fd): |
| import posix |
| |
| try: ignore = posix.fdopen |
| except: raise AttributeError, 'dup() method unavailable' |
| |
| posix.dup2(self._file_.fileno(), fd) |
| return posix.fdopen(fd, self._file_.mode) |
| |
| def flags(self, *which): |
| import fcntl, FCNTL |
| |
| if which: |
| if len(which) > 1: |
| raise TypeError, 'Too many arguments' |
| which = which[0] |
| else: which = '?' |
| |
| l_flags = 0 |
| if 'n' in which: l_flags = l_flags | FCNTL.O_NDELAY |
| if 'a' in which: l_flags = l_flags | FCNTL.O_APPEND |
| if 's' in which: l_flags = l_flags | FCNTL.O_SYNC |
| |
| file = self._file_ |
| |
| if '=' not in which: |
| cur_fl = fcntl.fcntl(file.fileno(), FCNTL.F_GETFL, 0) |
| if '!' in which: l_flags = cur_fl & ~ l_flags |
| else: l_flags = cur_fl | l_flags |
| |
| l_flags = fcntl.fcntl(file.fileno(), FCNTL.F_SETFL, l_flags) |
| |
| if 'c' in which: |
| arg = ('!' not in which) # 0 is don't, 1 is do close on exec |
| l_flags = fcntl.fcntl(file.fileno(), FCNTL.F_SETFD, arg) |
| |
| if '?' in which: |
| which = '' # Return current flags |
| l_flags = fcntl.fcntl(file.fileno(), FCNTL.F_GETFL, 0) |
| if FCNTL.O_APPEND & l_flags: which = which + 'a' |
| if fcntl.fcntl(file.fileno(), FCNTL.F_GETFD, 0) & 1: |
| which = which + 'c' |
| if FCNTL.O_NDELAY & l_flags: which = which + 'n' |
| if FCNTL.O_SYNC & l_flags: which = which + 's' |
| return which |
| |
| def lock(self, how, *args): |
| import struct, fcntl, FCNTL |
| |
| if 'w' in how: l_type = FCNTL.F_WRLCK |
| elif 'r' in how: l_type = FCNTL.F_RDLCK |
| elif 'u' in how: l_type = FCNTL.F_UNLCK |
| else: raise TypeError, 'no type of lock specified' |
| |
| if '|' in how: cmd = FCNTL.F_SETLKW |
| elif '?' in how: cmd = FCNTL.F_GETLK |
| else: cmd = FCNTL.F_SETLK |
| |
| l_whence = 0 |
| l_start = 0 |
| l_len = 0 |
| |
| if len(args) == 1: |
| l_len = args[0] |
| elif len(args) == 2: |
| l_len, l_start = args |
| elif len(args) == 3: |
| l_len, l_start, l_whence = args |
| elif len(args) > 3: |
| raise TypeError, 'too many arguments' |
| |
| # Hack by davem@magnet.com to get locking to go on freebsd; |
| # additions for AIX by Vladimir.Marangozov@imag.fr |
| import sys, os |
| if sys.platform in ('netbsd1', |
| 'openbsd2', |
| 'freebsd2', 'freebsd3', 'freebsd4', 'freebsd5', |
| 'bsdos2', 'bsdos3', 'bsdos4'): |
| flock = struct.pack('lxxxxlxxxxlhh', \ |
| l_start, l_len, os.getpid(), l_type, l_whence) |
| elif sys.platform in ['aix3', 'aix4']: |
| flock = struct.pack('hhlllii', \ |
| l_type, l_whence, l_start, l_len, 0, 0, 0) |
| else: |
| flock = struct.pack('hhllhh', \ |
| l_type, l_whence, l_start, l_len, 0, 0) |
| |
| flock = fcntl.fcntl(self._file_.fileno(), cmd, flock) |
| |
| if '?' in how: |
| if sys.platform in ('netbsd1', |
| 'openbsd2', |
| 'freebsd2', 'freebsd3', 'freebsd4', 'freebsd5', |
| 'bsdos2', 'bsdos3', 'bsdos4'): |
| l_start, l_len, l_pid, l_type, l_whence = \ |
| struct.unpack('lxxxxlxxxxlhh', flock) |
| elif sys.platform in ['aix3', 'aix4']: |
| l_type, l_whence, l_start, l_len, l_sysid, l_pid, l_vfs = \ |
| struct.unpack('hhlllii', flock) |
| elif sys.platform == "linux2": |
| l_type, l_whence, l_start, l_len, l_pid, l_sysid = \ |
| struct.unpack('hhllhh', flock) |
| else: |
| l_type, l_whence, l_start, l_len, l_sysid, l_pid = \ |
| struct.unpack('hhllhh', flock) |
| |
| if l_type != FCNTL.F_UNLCK: |
| if l_type == FCNTL.F_RDLCK: |
| return 'r', l_len, l_start, l_whence, l_pid |
| else: |
| return 'w', l_len, l_start, l_whence, l_pid |
| |
| def open(name, mode='r', bufsize=-1): |
| """Public routine to open a file as a posixfile object.""" |
| return _posixfile_().open(name, mode, bufsize) |
| |
| def fileopen(file): |
| """Public routine to get a posixfile object from a Python file object.""" |
| return _posixfile_().fileopen(file) |
| |
| # |
| # Constants |
| # |
| SEEK_SET = 0 |
| SEEK_CUR = 1 |
| SEEK_END = 2 |
| |
| # |
| # End of posixfile.py |
| # |