py-cvs-rel2_1 (Rev 1.2) merge
[python/dscho.git] / Lib / posixfile.py
blobb16b892794c3ddd4e70d6bac05567547a32a380b
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 """
56 class _posixfile_:
57 """File wrapper class that provides extra POSIX file routines."""
59 states = ['open', 'closed']
62 # Internal routines
64 def __repr__(self):
65 file = self._file_
66 return "<%s posixfile '%s', mode '%s' at %s>" % \
67 (self.states[file.closed], file.name, file.mode, \
68 hex(id(self))[2:])
71 # Initialization routines
73 def open(self, name, mode='r', bufsize=-1):
74 import __builtin__
75 return self.fileopen(__builtin__.open(name, mode, bufsize))
77 def fileopen(self, file):
78 if `type(file)` != "<type 'file'>":
79 raise TypeError, 'posixfile.fileopen() arg must be file object'
80 self._file_ = file
81 # Copy basic file methods
82 for method in file.__methods__:
83 setattr(self, method, getattr(file, method))
84 return self
87 # New methods
89 def file(self):
90 return self._file_
92 def dup(self):
93 import posix
95 if not hasattr(posix, 'fdopen'):
96 raise AttributeError, 'dup() method unavailable'
98 return posix.fdopen(posix.dup(self._file_.fileno()), self._file_.mode)
100 def dup2(self, fd):
101 import posix
103 if not hasattr(posix, 'fdopen'):
104 raise AttributeError, 'dup() method unavailable'
106 posix.dup2(self._file_.fileno(), fd)
107 return posix.fdopen(fd, self._file_.mode)
109 def flags(self, *which):
110 import fcntl
112 if which:
113 if len(which) > 1:
114 raise TypeError, 'Too many arguments'
115 which = which[0]
116 else: which = '?'
118 l_flags = 0
119 if 'n' in which: l_flags = l_flags | os.O_NDELAY
120 if 'a' in which: l_flags = l_flags | os.O_APPEND
121 if 's' in which: l_flags = l_flags | os.O_SYNC
123 file = self._file_
125 if '=' not in which:
126 cur_fl = fcntl.fcntl(file.fileno(), fcntl.F_GETFL, 0)
127 if '!' in which: l_flags = cur_fl & ~ l_flags
128 else: l_flags = cur_fl | l_flags
130 l_flags = fcntl.fcntl(file.fileno(), fcntl.F_SETFL, l_flags)
132 if 'c' in which:
133 arg = ('!' not in which) # 0 is don't, 1 is do close on exec
134 l_flags = fcntl.fcntl(file.fileno(), fcntl.F_SETFD, arg)
136 if '?' in which:
137 which = '' # Return current flags
138 l_flags = fcntl.fcntl(file.fileno(), fcntl.F_GETFL, 0)
139 if os.O_APPEND & l_flags: which = which + 'a'
140 if fcntl.fcntl(file.fileno(), fcntl.F_GETFD, 0) & 1:
141 which = which + 'c'
142 if os.O_NDELAY & l_flags: which = which + 'n'
143 if os.O_SYNC & l_flags: which = which + 's'
144 return which
146 def lock(self, how, *args):
147 import struct, fcntl
149 if 'w' in how: l_type = fcntl.F_WRLCK
150 elif 'r' in how: l_type = fcntl.F_RDLCK
151 elif 'u' in how: l_type = fcntl.F_UNLCK
152 else: raise TypeError, 'no type of lock specified'
154 if '|' in how: cmd = fcntl.F_SETLKW
155 elif '?' in how: cmd = fcntl.F_GETLK
156 else: cmd = fcntl.F_SETLK
158 l_whence = 0
159 l_start = 0
160 l_len = 0
162 if len(args) == 1:
163 l_len = args[0]
164 elif len(args) == 2:
165 l_len, l_start = args
166 elif len(args) == 3:
167 l_len, l_start, l_whence = args
168 elif len(args) > 3:
169 raise TypeError, 'too many arguments'
171 # Hack by davem@magnet.com to get locking to go on freebsd;
172 # additions for AIX by Vladimir.Marangozov@imag.fr
173 import sys, os
174 if sys.platform in ('netbsd1',
175 'openbsd2',
176 'freebsd2', 'freebsd3', 'freebsd4', 'freebsd5',
177 'bsdos2', 'bsdos3', 'bsdos4'):
178 flock = struct.pack('lxxxxlxxxxlhh', \
179 l_start, l_len, os.getpid(), l_type, l_whence)
180 elif sys.platform in ['aix3', 'aix4']:
181 flock = struct.pack('hhlllii', \
182 l_type, l_whence, l_start, l_len, 0, 0, 0)
183 else:
184 flock = struct.pack('hhllhh', \
185 l_type, l_whence, l_start, l_len, 0, 0)
187 flock = fcntl.fcntl(self._file_.fileno(), cmd, flock)
189 if '?' in how:
190 if sys.platform in ('netbsd1',
191 'openbsd2',
192 'freebsd2', 'freebsd3', 'freebsd4', 'freebsd5',
193 'bsdos2', 'bsdos3', 'bsdos4'):
194 l_start, l_len, l_pid, l_type, l_whence = \
195 struct.unpack('lxxxxlxxxxlhh', flock)
196 elif sys.platform in ['aix3', 'aix4']:
197 l_type, l_whence, l_start, l_len, l_sysid, l_pid, l_vfs = \
198 struct.unpack('hhlllii', flock)
199 elif sys.platform == "linux2":
200 l_type, l_whence, l_start, l_len, l_pid, l_sysid = \
201 struct.unpack('hhllhh', flock)
202 else:
203 l_type, l_whence, l_start, l_len, l_sysid, l_pid = \
204 struct.unpack('hhllhh', flock)
206 if l_type != fcntl.F_UNLCK:
207 if l_type == fcntl.F_RDLCK:
208 return 'r', l_len, l_start, l_whence, l_pid
209 else:
210 return 'w', l_len, l_start, l_whence, l_pid
212 def open(name, mode='r', bufsize=-1):
213 """Public routine to open a file as a posixfile object."""
214 return _posixfile_().open(name, mode, bufsize)
216 def fileopen(file):
217 """Public routine to get a posixfile object from a Python file object."""
218 return _posixfile_().fileopen(file)
221 # Constants
223 SEEK_SET = 0
224 SEEK_CUR = 1
225 SEEK_END = 2
228 # End of posixfile.py