Jaap: a posixfile module that supports file locking and file flags

Jaap Vermeulen (jaap@sequent.com)
Fri, 03 Dec 1993 12:39:59 -0800

[I sent this earlier, but it never got through...

While using this, I found out that routines such as marshal.load() and
marshal.dump() don't take this posixfile object. BLECH! That's why I
added a file() routine to retrieve the original builtin file object.]

Since I use file locking quite a bit, as well as non-blocking I/O, I
wrote a posixfile module that is a superset of the regular fileobject.

See the comments at the beginning of the module for usage.

Enjoy,

-Jaap-

------- Included file 'posixfile.py'
#! /bin/sh
# This is a shell archive. Remove anything before this line, then feed it
# into a shell via "sh file" or similar. To overwrite existing files,
# type "sh file -c"
#
# Wrapped by <jaap@eng1> on Fri Dec 3 12:36:12 PST 1993
#
# This archive contains:
# posixfile.py
echo "If this archive is complete, you will see the following message:"
echo ' "shar: End of archive."'
exitcode=0
if test -f 'posixfile.py' -a "${1}" != "-c"; then
echo "shar: Will not clobber existing file 'posixfile.py'"
exitcode=1
else
echo "shar: Extracting 'posixfile.py' (4546 characters)"
sed 's/^X//' > posixfile.py << 'END_OF_FILE'
X#
X# Start of posixfile.py
X#
X
X#
X# Extended file operations
X#
X# f = posixfile.open(filename, mode)
X#
X# f.file()
X# will return the original builtin file object
X#
X# f.dup()
X# will return a new file object based on a new filedescriptor
X#
X# f.dup2(fd)
X# will return a new file object based on the given filedescriptor
X#
X# f.flags(mode)
X# will turn on the associated flag (merge)
X# mode can contain the following characters:
X#
X# (character representing a flag)
X# a append only flag
X# c close on exec flag
X# n no delay flag
X# s synchronization flag
X# (modifiers)
X# ! turn flags 'off' instead of default 'on'
X# = copy flags 'as is' instead of default 'merge'
X# ? return a string in which the characters represent the flags
X# that are set
X#
X# note: - the '!' and '=' modifiers are mutually exclusive.
X# - the '?' modifier will return the status of the flags after they
X# have been changed by other characters in the mode string
X#
X# f.lock(mode [, len [, start [, whence]]])
X# will (un)lock a region
X# mode can contain the following characters:
X#
X# (character representing type of lock)
X# u unlock
X# r read lock
X# w write lock
X# (modifiers)
X# | wait until the lock can be granted
X# ? return the first lock conflicting with the requested lock
X# or 'None' if there is no conflict. The lock returned is in the
X# format (mode, len, start, whence, pid) where mode is a
X# character representing the type of lock ('r' or 'w')
X#
X# note: - the '?' modifier prevents a region from being locked; it is
X# query only
X#
X
Xclass _posixfile_:
X #
X # Internal routines
X #
X def __repr__(self):
X return repr(self._file_)
X
X def __del__(self):
X self._file_.close()
X
X #
X # Initialization routines
X #
X def open(self, name, mode):
X import builtin
X
X self._name_ = name
X self._mode_ = mode
X self._file_ = builtin.open(name, mode)
X # Copy basic file methods
X for method in self._file_.__methods__:
X setattr(self, method, getattr(self._file_, method))
X return self
X
X #
X # New methods
X #
X def file(self):
X return self._file_
X
X def dup(self):
X import posix
X
X try: ignore = posix.fdopen
X except: raise AttributeError, 'dup() method unavailable'
X
X return posix.fdopen(posix.dup(self._file_.fileno()), self._mode_)
X
X def dup2(self, fd):
X import posix
X
X try: ignore = posix.fdopen
X except: raise AttributeError, 'dup() method unavailable'
X
X posix.dup2(self._file_.fileno(), fd)
X return posix.fdopen(fd, self._mode_)
X
X def flags(self, which):
X import fcntl, FCNTL
X
X l_flags = 0
X if 'n' in which: l_flags = l_flags | FCNTL.O_NDELAY
X if 'a' in which: l_flags = l_flags | FCNTL.O_APPEND
X if 's' in which: l_flags = l_flags | FCNTL.O_SYNC
X
X if '=' not in which:
X cur_fl = fcntl.fcntl(self._file_.fileno(), FCNTL.F_GETFL, 0)
X if '!' in which: l_flags = cur_fl & ~ l_flags
X else: l_flags = cur_fl | l_flags
X
X l_flags = fcntl.fcntl(self._file_.fileno(), FCNTL.F_SETFL, l_flags)
X
X if 'c' in which:
X arg = ('!' not in which) # 1 is close
X l_flags = fcntl.fcntl(self._file_.fileno(), FCNTL.F_SETFD, arg)
X
X if '?' in which:
X which = ''
X l_flags = fcntl.fcntl(self._file_.fileno(), FCNTL.F_GETFL, 0)
X if FCNTL.O_APPEND & l_flags: which = which + 'a'
X if fcntl.fcntl(self._file_.fileno(), FCNTL.F_GETFD, 0) & 1:
X which = which + 'c'
X if FCNTL.O_NDELAY & l_flags: which = which + 'n'
X if FCNTL.O_SYNC & l_flags: which = which + 's'
X return which
X
X def lock(self, how, *args):
X import struct, fcntl, FCNTL
X
X if 'w' in how: l_type = FCNTL.F_WRLCK
X elif 'r' in how: l_type = FCNTL.F_WRLCK
X elif 'u' in how: l_type = FCNTL.F_UNLCK
X else: raise TypeError, 'no type of lock specified'
X
X if '|' in how: cmd = FCNTL.F_SETLKW
X elif '?' in how: cmd = FCNTL.F_GETLK
X else: cmd = FCNTL.F_SETLK
X
X l_whence = 0
X l_start = 0
X l_len = 0
X
X if len(args) == 1:
X l_len = args[0]
X elif len(args) == 2:
X l_len, l_start = args
X elif len(args) == 3:
X l_len, l_start, l_whence = args
X elif len(args) > 3:
X raise TypeError, 'too many arguments'
X
X flock = struct.pack('hhllhh', l_type, l_whence, l_start, l_len, 0, 0)
X flock = fcntl.fcntl(self._file_.fileno(), cmd, flock)
X
X if '?' in how:
X l_type, l_whence, l_start, l_len, l_sysid, l_pid = \
X struct.unpack('hhllhh', flock)
X if l_type != FCNTL.F_UNLCK:
X if l_type == FCNTL.F_RDLCK:
X return 'r', l_len, l_start, l_whence, l_pid
X else:
X return 'w', l_len, l_start, l_whence, l_pid
X
X#
X# Public routine to obtain a posixfile object
X#
Xdef open(name, mode):
X return _posixfile_().open(name, mode)
X
X#
X# End of posixfile.py
X#
END_OF_FILE
if test 4546 -ne `wc -c < 'posixfile.py'`; then
echo "shar: 'posixfile.py' unpacked with wrong size!"
exitcode=1
fi
# end of 'posixfile.py'
fi
echo "End of archive."
exit $exitcode
------- End of included file 'posixfile.py'

--
Jaap Vermeulen					+--------------------------+
						| Sequent Computer Systems |
	Internet : jaap@sequent.com		| Beaverton, Oregon	   |
	Uucp	 : ...uunet!sequent!jaap	+--------------------------+