blob: dcd65cd69d088f76e5ad9174ca153ef07ad6b745 [file] [log] [blame]
Guido van Rossum54f22ed2000-02-04 15:10:34 +00001"""Extended file operations available in POSIX.
Guido van Rossum78f8dea1994-05-18 11:07:44 +00002
Guido van Rossum54f22ed2000-02-04 15:10:34 +00003f = posixfile.open(filename, [mode, [bufsize]])
4 will create a new posixfile object
5
6f = posixfile.fileopen(fileobject)
7 will create a posixfile object from a builtin file object
8
9f.file()
10 will return the original builtin file object
11
12f.dup()
13 will return a new file object based on a new filedescriptor
14
15f.dup2(fd)
16 will return a new file object based on the given filedescriptor
17
18f.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
37f.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"""
Guido van Rossum78f8dea1994-05-18 11:07:44 +000055
56class _posixfile_:
Guido van Rossum54f22ed2000-02-04 15:10:34 +000057 """File wrapper class that provides extra POSIX file routines."""
58
Guido van Rossumc762bec1994-05-18 11:08:10 +000059 states = ['open', 'closed']
60
Guido van Rossum78f8dea1994-05-18 11:07:44 +000061 #
62 # Internal routines
63 #
64 def __repr__(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000065 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:])
Guido van Rossum78f8dea1994-05-18 11:07:44 +000069
Guido van Rossum78f8dea1994-05-18 11:07:44 +000070 #
71 # Initialization routines
72 #
Guido van Rossum13c503e1995-03-16 15:58:12 +000073 def open(self, name, mode='r', bufsize=-1):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000074 import __builtin__
75 return self.fileopen(__builtin__.open(name, mode, bufsize))
Guido van Rossum78f8dea1994-05-18 11:07:44 +000076
Guido van Rossumc762bec1994-05-18 11:08:10 +000077 def fileopen(self, file):
Tim Peters22cd7682001-09-18 05:40:24 +000078 import types
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000079 if `type(file)` != "<type 'file'>":
80 raise TypeError, 'posixfile.fileopen() arg must be file object'
81 self._file_ = file
82 # Copy basic file methods
Tim Peters22cd7682001-09-18 05:40:24 +000083 for maybemethod in dir(file):
84 if not maybemethod.startswith('_'):
85 attr = getattr(file, maybemethod)
86 if isinstance(attr, types.BuiltinMethodType):
87 setattr(self, maybemethod, attr)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000088 return self
Guido van Rossum78f8dea1994-05-18 11:07:44 +000089
90 #
91 # New methods
92 #
93 def file(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000094 return self._file_
Guido van Rossum78f8dea1994-05-18 11:07:44 +000095
96 def dup(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000097 import posix
Guido van Rossum78f8dea1994-05-18 11:07:44 +000098
Guido van Rossume9901f32001-04-10 15:44:33 +000099 if not hasattr(posix, 'fdopen'):
100 raise AttributeError, 'dup() method unavailable'
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000101
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000102 return posix.fdopen(posix.dup(self._file_.fileno()), self._file_.mode)
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000103
104 def dup2(self, fd):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000105 import posix
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000106
Guido van Rossume9901f32001-04-10 15:44:33 +0000107 if not hasattr(posix, 'fdopen'):
108 raise AttributeError, 'dup() method unavailable'
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000109
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000110 posix.dup2(self._file_.fileno(), fd)
111 return posix.fdopen(fd, self._file_.mode)
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000112
Guido van Rossumc762bec1994-05-18 11:08:10 +0000113 def flags(self, *which):
Andrew M. Kuchling86c7e222001-08-13 14:47:12 +0000114 import fcntl, os
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000115
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000116 if which:
117 if len(which) > 1:
118 raise TypeError, 'Too many arguments'
119 which = which[0]
120 else: which = '?'
Guido van Rossumc762bec1994-05-18 11:08:10 +0000121
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000122 l_flags = 0
Fred Drakea94414a2001-05-10 15:33:31 +0000123 if 'n' in which: l_flags = l_flags | os.O_NDELAY
124 if 'a' in which: l_flags = l_flags | os.O_APPEND
125 if 's' in which: l_flags = l_flags | os.O_SYNC
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000126
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000127 file = self._file_
Guido van Rossumc762bec1994-05-18 11:08:10 +0000128
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000129 if '=' not in which:
Fred Drakea94414a2001-05-10 15:33:31 +0000130 cur_fl = fcntl.fcntl(file.fileno(), fcntl.F_GETFL, 0)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000131 if '!' in which: l_flags = cur_fl & ~ l_flags
132 else: l_flags = cur_fl | l_flags
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000133
Fred Drakea94414a2001-05-10 15:33:31 +0000134 l_flags = fcntl.fcntl(file.fileno(), fcntl.F_SETFL, l_flags)
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000135
Tim Peters2344fae2001-01-15 00:50:52 +0000136 if 'c' in which:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000137 arg = ('!' not in which) # 0 is don't, 1 is do close on exec
Fred Drakea94414a2001-05-10 15:33:31 +0000138 l_flags = fcntl.fcntl(file.fileno(), fcntl.F_SETFD, arg)
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000139
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000140 if '?' in which:
141 which = '' # Return current flags
Fred Drakea94414a2001-05-10 15:33:31 +0000142 l_flags = fcntl.fcntl(file.fileno(), fcntl.F_GETFL, 0)
143 if os.O_APPEND & l_flags: which = which + 'a'
144 if fcntl.fcntl(file.fileno(), fcntl.F_GETFD, 0) & 1:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000145 which = which + 'c'
Fred Drakea94414a2001-05-10 15:33:31 +0000146 if os.O_NDELAY & l_flags: which = which + 'n'
147 if os.O_SYNC & l_flags: which = which + 's'
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000148 return which
Tim Peters2344fae2001-01-15 00:50:52 +0000149
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000150 def lock(self, how, *args):
Fred Drakea94414a2001-05-10 15:33:31 +0000151 import struct, fcntl
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000152
Fred Drakea94414a2001-05-10 15:33:31 +0000153 if 'w' in how: l_type = fcntl.F_WRLCK
154 elif 'r' in how: l_type = fcntl.F_RDLCK
155 elif 'u' in how: l_type = fcntl.F_UNLCK
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000156 else: raise TypeError, 'no type of lock specified'
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000157
Fred Drakea94414a2001-05-10 15:33:31 +0000158 if '|' in how: cmd = fcntl.F_SETLKW
159 elif '?' in how: cmd = fcntl.F_GETLK
160 else: cmd = fcntl.F_SETLK
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000161
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000162 l_whence = 0
163 l_start = 0
164 l_len = 0
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000165
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000166 if len(args) == 1:
167 l_len = args[0]
168 elif len(args) == 2:
169 l_len, l_start = args
170 elif len(args) == 3:
171 l_len, l_start, l_whence = args
172 elif len(args) > 3:
173 raise TypeError, 'too many arguments'
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000174
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000175 # Hack by davem@magnet.com to get locking to go on freebsd;
176 # additions for AIX by Vladimir.Marangozov@imag.fr
Guido van Rossum7698d121996-07-30 16:28:45 +0000177 import sys, os
Guido van Rossum027188a1999-02-23 04:14:32 +0000178 if sys.platform in ('netbsd1',
Guido van Rossum5274c331999-12-06 14:51:05 +0000179 'openbsd2',
Guido van Rossum2d218632000-08-29 14:57:27 +0000180 'freebsd2', 'freebsd3', 'freebsd4', 'freebsd5',
Guido van Rossum027188a1999-02-23 04:14:32 +0000181 'bsdos2', 'bsdos3', 'bsdos4'):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000182 flock = struct.pack('lxxxxlxxxxlhh', \
Tim Peters2344fae2001-01-15 00:50:52 +0000183 l_start, l_len, os.getpid(), l_type, l_whence)
Guido van Rossum0f6a3bf1996-08-20 20:23:34 +0000184 elif sys.platform in ['aix3', 'aix4']:
185 flock = struct.pack('hhlllii', \
186 l_type, l_whence, l_start, l_len, 0, 0, 0)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000187 else:
188 flock = struct.pack('hhllhh', \
189 l_type, l_whence, l_start, l_len, 0, 0)
Guido van Rossum7698d121996-07-30 16:28:45 +0000190
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000191 flock = fcntl.fcntl(self._file_.fileno(), cmd, flock)
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000192
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000193 if '?' in how:
Guido van Rossum027188a1999-02-23 04:14:32 +0000194 if sys.platform in ('netbsd1',
Guido van Rossum5274c331999-12-06 14:51:05 +0000195 'openbsd2',
Guido van Rossum2d218632000-08-29 14:57:27 +0000196 'freebsd2', 'freebsd3', 'freebsd4', 'freebsd5',
Guido van Rossum027188a1999-02-23 04:14:32 +0000197 'bsdos2', 'bsdos3', 'bsdos4'):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000198 l_start, l_len, l_pid, l_type, l_whence = \
199 struct.unpack('lxxxxlxxxxlhh', flock)
Guido van Rossum0f6a3bf1996-08-20 20:23:34 +0000200 elif sys.platform in ['aix3', 'aix4']:
201 l_type, l_whence, l_start, l_len, l_sysid, l_pid, l_vfs = \
202 struct.unpack('hhlllii', flock)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000203 elif sys.platform == "linux2":
204 l_type, l_whence, l_start, l_len, l_pid, l_sysid = \
205 struct.unpack('hhllhh', flock)
206 else:
207 l_type, l_whence, l_start, l_len, l_sysid, l_pid = \
208 struct.unpack('hhllhh', flock)
Guido van Rossum7698d121996-07-30 16:28:45 +0000209
Fred Drakea94414a2001-05-10 15:33:31 +0000210 if l_type != fcntl.F_UNLCK:
211 if l_type == fcntl.F_RDLCK:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000212 return 'r', l_len, l_start, l_whence, l_pid
213 else:
214 return 'w', l_len, l_start, l_whence, l_pid
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000215
Guido van Rossum28aa2291995-03-23 10:39:49 +0000216def open(name, mode='r', bufsize=-1):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000217 """Public routine to open a file as a posixfile object."""
Guido van Rossum28aa2291995-03-23 10:39:49 +0000218 return _posixfile_().open(name, mode, bufsize)
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000219
Guido van Rossumc762bec1994-05-18 11:08:10 +0000220def fileopen(file):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000221 """Public routine to get a posixfile object from a Python file object."""
Guido van Rossumc762bec1994-05-18 11:08:10 +0000222 return _posixfile_().fileopen(file)
223
224#
225# Constants
226#
227SEEK_SET = 0
228SEEK_CUR = 1
229SEEK_END = 2
230
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000231#
232# End of posixfile.py
233#