This should finally fix #6896. Let's watch the buildbots.
[python.git] / Lib / posixfile.py
blobff2910779bc6511afe41066a600ce53f16545bae
1 """Extended file operations available in POSIX.
3 f = posixfile.open(filename, [mode, [bufsize]])
4 will create a new posixfile object
6 f = posixfile.fileopen(fileobject)
7 will create a posixfile object from a builtin file object
9 f.file()
10 will return the original builtin file object
12 f.dup()
13 will return a new file object based on a new filedescriptor
15 f.dup2(fd)
16 will return a new file object based on the given filedescriptor
18 f.flags(mode)
19 will turn on the associated flag (merge)
20 mode can contain the following characters:
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
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
37 f.lock(mode [, len [, start [, whence]]])
38 will (un)lock a region
39 mode can contain the following characters:
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')
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)
59 class _posixfile_:
60 """File wrapper class that provides extra POSIX file routines."""
62 states = ['open', 'closed']
65 # Internal routines
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:])
74 # Initialization routines
76 def open(self, name, mode='r', bufsize=-1):
77 import __builtin__
78 return self.fileopen(__builtin__.open(name, mode, bufsize))
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
94 # New methods
96 def file(self):
97 return self._file_
99 def dup(self):
100 import posix
102 if not hasattr(posix, 'fdopen'):
103 raise AttributeError, 'dup() method unavailable'
105 return posix.fdopen(posix.dup(self._file_.fileno()), self._file_.mode)
107 def dup2(self, fd):
108 import posix
110 if not hasattr(posix, 'fdopen'):
111 raise AttributeError, 'dup() method unavailable'
113 posix.dup2(self._file_.fileno(), fd)
114 return posix.fdopen(fd, self._file_.mode)
116 def flags(self, *which):
117 import fcntl, os
119 if which:
120 if len(which) > 1:
121 raise TypeError, 'Too many arguments'
122 which = which[0]
123 else: which = '?'
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
130 file = self._file_
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
137 l_flags = fcntl.fcntl(file.fileno(), fcntl.F_SETFL, l_flags)
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)
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
153 def lock(self, how, *args):
154 import struct, fcntl
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'
161 if '|' in how: cmd = fcntl.F_SETLKW
162 elif '?' in how: cmd = fcntl.F_GETLK
163 else: cmd = fcntl.F_SETLK
165 l_whence = 0
166 l_start = 0
167 l_len = 0
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'
178 # Hack by davem@magnet.com to get locking to go on freebsd;
179 # additions for AIX by Vladimir.Marangozov@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)
195 flock = fcntl.fcntl(self._file_.fileno(), cmd, flock)
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)
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
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)
224 def fileopen(file):
225 """Public routine to get a posixfile object from a Python file object."""
226 return _posixfile_().fileopen(file)
229 # Constants
231 SEEK_SET = 0
232 SEEK_CUR = 1
233 SEEK_END = 2
236 # End of posixfile.py