Home | History | Annotate | Download | only in Lib
      1 """Extended file operations available in POSIX.
      2 
      3 f = posixfile.open(filename, [mode, [bufsize]])
      4       will create a new posixfile object
      5 
      6 f = posixfile.fileopen(fileobject)
      7       will create a posixfile object from a builtin file object
      8 
      9 f.file()
     10       will return the original builtin file object
     11 
     12 f.dup()
     13       will return a new file object based on a new filedescriptor
     14 
     15 f.dup2(fd)
     16       will return a new file object based on the given filedescriptor
     17 
     18 f.flags(mode)
     19       will turn on the associated flag (merge)
     20       mode can contain the following characters:
     21 
     22   (character representing a flag)
     23       a       append only flag
     24       c       close on exec flag
     25       n       no delay flag
     26       s       synchronization flag
     27   (modifiers)
     28       !       turn flags 'off' instead of default 'on'
     29       =       copy flags 'as is' instead of default 'merge'
     30       ?       return a string in which the characters represent the flags
     31               that are set
     32 
     33       note: - the '!' and '=' modifiers are mutually exclusive.
     34             - the '?' modifier will return the status of the flags after they
     35               have been changed by other characters in the mode string
     36 
     37 f.lock(mode [, len [, start [, whence]]])
     38       will (un)lock a region
     39       mode can contain the following characters:
     40 
     41   (character representing type of lock)
     42       u       unlock
     43       r       read lock
     44       w       write lock
     45   (modifiers)
     46       |       wait until the lock can be granted
     47       ?       return the first lock conflicting with the requested lock
     48               or 'None' if there is no conflict. The lock returned is in the
     49               format (mode, len, start, whence, pid) where mode is a
     50               character representing the type of lock ('r' or 'w')
     51 
     52       note: - the '?' modifier prevents a region from being locked; it is
     53               query only
     54 """
     55 import warnings
     56 warnings.warn("The posixfile module is deprecated; "
     57                 "fcntl.lockf() provides better locking", DeprecationWarning, 2)
     58 
     59 class _posixfile_:
     60     """File wrapper class that provides extra POSIX file routines."""
     61 
     62     states = ['open', 'closed']
     63 
     64     #
     65     # Internal routines
     66     #
     67     def __repr__(self):
     68         file = self._file_
     69         return "<%s posixfile '%s', mode '%s' at %s>" % \
     70                 (self.states[file.closed], file.name, file.mode, \
     71                  hex(id(self))[2:])
     72 
     73     #
     74     # Initialization routines
     75     #
     76     def open(self, name, mode='r', bufsize=-1):
     77         import __builtin__
     78         return self.fileopen(__builtin__.open(name, mode, bufsize))
     79 
     80     def fileopen(self, file):
     81         import types
     82         if repr(type(file)) != "<type 'file'>":
     83             raise TypeError, 'posixfile.fileopen() arg must be file object'
     84         self._file_  = file
     85         # Copy basic file methods
     86         for maybemethod in dir(file):
     87             if not maybemethod.startswith('_'):
     88                 attr = getattr(file, maybemethod)
     89                 if isinstance(attr, types.BuiltinMethodType):
     90                     setattr(self, maybemethod, attr)
     91         return self
     92 
     93     #
     94     # New methods
     95     #
     96     def file(self):
     97         return self._file_
     98 
     99     def dup(self):
    100         import posix
    101 
    102         if not hasattr(posix, 'fdopen'):
    103             raise AttributeError, 'dup() method unavailable'
    104 
    105         return posix.fdopen(posix.dup(self._file_.fileno()), self._file_.mode)
    106 
    107     def dup2(self, fd):
    108         import posix
    109 
    110         if not hasattr(posix, 'fdopen'):
    111             raise AttributeError, 'dup() method unavailable'
    112 
    113         posix.dup2(self._file_.fileno(), fd)
    114         return posix.fdopen(fd, self._file_.mode)
    115 
    116     def flags(self, *which):
    117         import fcntl, os
    118 
    119         if which:
    120             if len(which) > 1:
    121                 raise TypeError, 'Too many arguments'
    122             which = which[0]
    123         else: which = '?'
    124 
    125         l_flags = 0
    126         if 'n' in which: l_flags = l_flags | os.O_NDELAY
    127         if 'a' in which: l_flags = l_flags | os.O_APPEND
    128         if 's' in which: l_flags = l_flags | os.O_SYNC
    129 
    130         file = self._file_
    131 
    132         if '=' not in which:
    133             cur_fl = fcntl.fcntl(file.fileno(), fcntl.F_GETFL, 0)
    134             if '!' in which: l_flags = cur_fl & ~ l_flags
    135             else: l_flags = cur_fl | l_flags
    136 
    137         l_flags = fcntl.fcntl(file.fileno(), fcntl.F_SETFL, l_flags)
    138 
    139         if 'c' in which:
    140             arg = ('!' not in which)    # 0 is don't, 1 is do close on exec
    141             l_flags = fcntl.fcntl(file.fileno(), fcntl.F_SETFD, arg)
    142 
    143         if '?' in which:
    144             which = ''                  # Return current flags
    145             l_flags = fcntl.fcntl(file.fileno(), fcntl.F_GETFL, 0)
    146             if os.O_APPEND & l_flags: which = which + 'a'
    147             if fcntl.fcntl(file.fileno(), fcntl.F_GETFD, 0) & 1:
    148                 which = which + 'c'
    149             if os.O_NDELAY & l_flags: which = which + 'n'
    150             if os.O_SYNC & l_flags: which = which + 's'
    151             return which
    152 
    153     def lock(self, how, *args):
    154         import struct, fcntl
    155 
    156         if 'w' in how: l_type = fcntl.F_WRLCK
    157         elif 'r' in how: l_type = fcntl.F_RDLCK
    158         elif 'u' in how: l_type = fcntl.F_UNLCK
    159         else: raise TypeError, 'no type of lock specified'
    160 
    161         if '|' in how: cmd = fcntl.F_SETLKW
    162         elif '?' in how: cmd = fcntl.F_GETLK
    163         else: cmd = fcntl.F_SETLK
    164 
    165         l_whence = 0
    166         l_start = 0
    167         l_len = 0
    168 
    169         if len(args) == 1:
    170             l_len = args[0]
    171         elif len(args) == 2:
    172             l_len, l_start = args
    173         elif len(args) == 3:
    174             l_len, l_start, l_whence = args
    175         elif len(args) > 3:
    176             raise TypeError, 'too many arguments'
    177 
    178         # Hack by davem (at] magnet.com to get locking to go on freebsd;
    179         # additions for AIX by Vladimir.Marangozov (at] imag.fr
    180         import sys, os
    181         if sys.platform in ('netbsd1',
    182                             'openbsd2',
    183                             'freebsd2', 'freebsd3', 'freebsd4', 'freebsd5',
    184                             'freebsd6', 'freebsd7', 'freebsd8',
    185                             'bsdos2', 'bsdos3', 'bsdos4'):
    186             flock = struct.pack('lxxxxlxxxxlhh', \
    187                   l_start, l_len, os.getpid(), l_type, l_whence)
    188         elif sys.platform in ('aix3', 'aix4'):
    189             flock = struct.pack('hhlllii', \
    190                   l_type, l_whence, l_start, l_len, 0, 0, 0)
    191         else:
    192             flock = struct.pack('hhllhh', \
    193                   l_type, l_whence, l_start, l_len, 0, 0)
    194 
    195         flock = fcntl.fcntl(self._file_.fileno(), cmd, flock)
    196 
    197         if '?' in how:
    198             if sys.platform in ('netbsd1',
    199                                 'openbsd2',
    200                                 'freebsd2', 'freebsd3', 'freebsd4', 'freebsd5',
    201                                 'bsdos2', 'bsdos3', 'bsdos4'):
    202                 l_start, l_len, l_pid, l_type, l_whence = \
    203                     struct.unpack('lxxxxlxxxxlhh', flock)
    204             elif sys.platform in ('aix3', 'aix4'):
    205                 l_type, l_whence, l_start, l_len, l_sysid, l_pid, l_vfs = \
    206                     struct.unpack('hhlllii', flock)
    207             elif sys.platform == "linux2":
    208                 l_type, l_whence, l_start, l_len, l_pid, l_sysid = \
    209                     struct.unpack('hhllhh', flock)
    210             else:
    211                 l_type, l_whence, l_start, l_len, l_sysid, l_pid = \
    212                     struct.unpack('hhllhh', flock)
    213 
    214             if l_type != fcntl.F_UNLCK:
    215                 if l_type == fcntl.F_RDLCK:
    216                     return 'r', l_len, l_start, l_whence, l_pid
    217                 else:
    218                     return 'w', l_len, l_start, l_whence, l_pid
    219 
    220 def open(name, mode='r', bufsize=-1):
    221     """Public routine to open a file as a posixfile object."""
    222     return _posixfile_().open(name, mode, bufsize)
    223 
    224 def fileopen(file):
    225     """Public routine to get a posixfile object from a Python file object."""
    226     return _posixfile_().fileopen(file)
    227 
    228 #
    229 # Constants
    230 #
    231 SEEK_SET = 0
    232 SEEK_CUR = 1
    233 SEEK_END = 2
    234 
    235 #
    236 # End of posixfile.py
    237 #
    238