blob: da374ad9a998d26046b52d1d0ef873b9adf1e76f [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
Skip Montanaroc62c81e2001-02-12 02:00:42 +000056__all__ = ["open","fileopen","SEEK_SET","SEEK_CUR","SEEK_END"]
57
Guido van Rossum78f8dea1994-05-18 11:07:44 +000058class _posixfile_:
Guido van Rossum54f22ed2000-02-04 15:10:34 +000059 """File wrapper class that provides extra POSIX file routines."""
60
Guido van Rossumc762bec1994-05-18 11:08:10 +000061 states = ['open', 'closed']
62
Guido van Rossum78f8dea1994-05-18 11:07:44 +000063 #
64 # Internal routines
65 #
66 def __repr__(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000067 file = self._file_
68 return "<%s posixfile '%s', mode '%s' at %s>" % \
69 (self.states[file.closed], file.name, file.mode, \
70 hex(id(self))[2:])
Guido van Rossum78f8dea1994-05-18 11:07:44 +000071
Guido van Rossum78f8dea1994-05-18 11:07:44 +000072 #
73 # Initialization routines
74 #
Guido van Rossum13c503e1995-03-16 15:58:12 +000075 def open(self, name, mode='r', bufsize=-1):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000076 import __builtin__
77 return self.fileopen(__builtin__.open(name, mode, bufsize))
Guido van Rossum78f8dea1994-05-18 11:07:44 +000078
Guido van Rossumc762bec1994-05-18 11:08:10 +000079 def fileopen(self, file):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000080 if `type(file)` != "<type 'file'>":
81 raise TypeError, 'posixfile.fileopen() arg must be file object'
82 self._file_ = file
83 # Copy basic file methods
84 for method in file.__methods__:
85 setattr(self, method, getattr(file, method))
86 return self
Guido van Rossum78f8dea1994-05-18 11:07:44 +000087
88 #
89 # New methods
90 #
91 def file(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000092 return self._file_
Guido van Rossum78f8dea1994-05-18 11:07:44 +000093
94 def dup(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000095 import posix
Guido van Rossum78f8dea1994-05-18 11:07:44 +000096
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000097 try: ignore = posix.fdopen
98 except: raise AttributeError, 'dup() method unavailable'
Guido van Rossum78f8dea1994-05-18 11:07:44 +000099
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000100 return posix.fdopen(posix.dup(self._file_.fileno()), self._file_.mode)
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000101
102 def dup2(self, fd):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000103 import posix
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000104
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000105 try: ignore = posix.fdopen
106 except: raise AttributeError, 'dup() method unavailable'
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000107
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000108 posix.dup2(self._file_.fileno(), fd)
109 return posix.fdopen(fd, self._file_.mode)
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000110
Guido van Rossumc762bec1994-05-18 11:08:10 +0000111 def flags(self, *which):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000112 import fcntl, FCNTL
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000113
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000114 if which:
115 if len(which) > 1:
116 raise TypeError, 'Too many arguments'
117 which = which[0]
118 else: which = '?'
Guido van Rossumc762bec1994-05-18 11:08:10 +0000119
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000120 l_flags = 0
121 if 'n' in which: l_flags = l_flags | FCNTL.O_NDELAY
122 if 'a' in which: l_flags = l_flags | FCNTL.O_APPEND
123 if 's' in which: l_flags = l_flags | FCNTL.O_SYNC
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000124
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000125 file = self._file_
Guido van Rossumc762bec1994-05-18 11:08:10 +0000126
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000127 if '=' not in which:
128 cur_fl = fcntl.fcntl(file.fileno(), FCNTL.F_GETFL, 0)
129 if '!' in which: l_flags = cur_fl & ~ l_flags
130 else: l_flags = cur_fl | l_flags
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000131
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000132 l_flags = fcntl.fcntl(file.fileno(), FCNTL.F_SETFL, l_flags)
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000133
Tim Peters2344fae2001-01-15 00:50:52 +0000134 if 'c' in which:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000135 arg = ('!' not in which) # 0 is don't, 1 is do close on exec
136 l_flags = fcntl.fcntl(file.fileno(), FCNTL.F_SETFD, arg)
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000137
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000138 if '?' in which:
139 which = '' # Return current flags
140 l_flags = fcntl.fcntl(file.fileno(), FCNTL.F_GETFL, 0)
141 if FCNTL.O_APPEND & l_flags: which = which + 'a'
142 if fcntl.fcntl(file.fileno(), FCNTL.F_GETFD, 0) & 1:
143 which = which + 'c'
144 if FCNTL.O_NDELAY & l_flags: which = which + 'n'
145 if FCNTL.O_SYNC & l_flags: which = which + 's'
146 return which
Tim Peters2344fae2001-01-15 00:50:52 +0000147
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000148 def lock(self, how, *args):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000149 import struct, fcntl, FCNTL
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000150
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000151 if 'w' in how: l_type = FCNTL.F_WRLCK
152 elif 'r' in how: l_type = FCNTL.F_RDLCK
153 elif 'u' in how: l_type = FCNTL.F_UNLCK
154 else: raise TypeError, 'no type of lock specified'
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000155
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000156 if '|' in how: cmd = FCNTL.F_SETLKW
157 elif '?' in how: cmd = FCNTL.F_GETLK
158 else: cmd = FCNTL.F_SETLK
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000159
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000160 l_whence = 0
161 l_start = 0
162 l_len = 0
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000163
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000164 if len(args) == 1:
165 l_len = args[0]
166 elif len(args) == 2:
167 l_len, l_start = args
168 elif len(args) == 3:
169 l_len, l_start, l_whence = args
170 elif len(args) > 3:
171 raise TypeError, 'too many arguments'
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000172
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000173 # Hack by davem@magnet.com to get locking to go on freebsd;
174 # additions for AIX by Vladimir.Marangozov@imag.fr
Guido van Rossum7698d121996-07-30 16:28:45 +0000175 import sys, os
Guido van Rossum027188a1999-02-23 04:14:32 +0000176 if sys.platform in ('netbsd1',
Guido van Rossum5274c331999-12-06 14:51:05 +0000177 'openbsd2',
Guido van Rossum2d218632000-08-29 14:57:27 +0000178 'freebsd2', 'freebsd3', 'freebsd4', 'freebsd5',
Guido van Rossum027188a1999-02-23 04:14:32 +0000179 'bsdos2', 'bsdos3', 'bsdos4'):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000180 flock = struct.pack('lxxxxlxxxxlhh', \
Tim Peters2344fae2001-01-15 00:50:52 +0000181 l_start, l_len, os.getpid(), l_type, l_whence)
Guido van Rossum0f6a3bf1996-08-20 20:23:34 +0000182 elif sys.platform in ['aix3', 'aix4']:
183 flock = struct.pack('hhlllii', \
184 l_type, l_whence, l_start, l_len, 0, 0, 0)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000185 else:
186 flock = struct.pack('hhllhh', \
187 l_type, l_whence, l_start, l_len, 0, 0)
Guido van Rossum7698d121996-07-30 16:28:45 +0000188
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000189 flock = fcntl.fcntl(self._file_.fileno(), cmd, flock)
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000190
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000191 if '?' in how:
Guido van Rossum027188a1999-02-23 04:14:32 +0000192 if sys.platform in ('netbsd1',
Guido van Rossum5274c331999-12-06 14:51:05 +0000193 'openbsd2',
Guido van Rossum2d218632000-08-29 14:57:27 +0000194 'freebsd2', 'freebsd3', 'freebsd4', 'freebsd5',
Guido van Rossum027188a1999-02-23 04:14:32 +0000195 'bsdos2', 'bsdos3', 'bsdos4'):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000196 l_start, l_len, l_pid, l_type, l_whence = \
197 struct.unpack('lxxxxlxxxxlhh', flock)
Guido van Rossum0f6a3bf1996-08-20 20:23:34 +0000198 elif sys.platform in ['aix3', 'aix4']:
199 l_type, l_whence, l_start, l_len, l_sysid, l_pid, l_vfs = \
200 struct.unpack('hhlllii', flock)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000201 elif sys.platform == "linux2":
202 l_type, l_whence, l_start, l_len, l_pid, l_sysid = \
203 struct.unpack('hhllhh', flock)
204 else:
205 l_type, l_whence, l_start, l_len, l_sysid, l_pid = \
206 struct.unpack('hhllhh', flock)
Guido van Rossum7698d121996-07-30 16:28:45 +0000207
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000208 if l_type != FCNTL.F_UNLCK:
209 if l_type == FCNTL.F_RDLCK:
210 return 'r', l_len, l_start, l_whence, l_pid
211 else:
212 return 'w', l_len, l_start, l_whence, l_pid
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000213
Guido van Rossum28aa2291995-03-23 10:39:49 +0000214def open(name, mode='r', bufsize=-1):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000215 """Public routine to open a file as a posixfile object."""
Guido van Rossum28aa2291995-03-23 10:39:49 +0000216 return _posixfile_().open(name, mode, bufsize)
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000217
Guido van Rossumc762bec1994-05-18 11:08:10 +0000218def fileopen(file):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000219 """Public routine to get a posixfile object from a Python file object."""
Guido van Rossumc762bec1994-05-18 11:08:10 +0000220 return _posixfile_().fileopen(file)
221
222#
223# Constants
224#
225SEEK_SET = 0
226SEEK_CUR = 1
227SEEK_END = 2
228
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000229#
230# End of posixfile.py
231#