posixfile.py 7.8 KB

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