blob: afffb66e490fc1d160c87c977940f6fd74b337a5 [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
Fred Drake9242a4a2001-10-24 22:03:35 +000056
Guido van Rossum78f8dea1994-05-18 11:07:44 +000057class _posixfile_:
Guido van Rossum54f22ed2000-02-04 15:10:34 +000058 """File wrapper class that provides extra POSIX file routines."""
59
Guido van Rossumc762bec1994-05-18 11:08:10 +000060 states = ['open', 'closed']
61
Guido van Rossum78f8dea1994-05-18 11:07:44 +000062 #
63 # Internal routines
64 #
65 def __repr__(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000066 file = self._file_
67 return "<%s posixfile '%s', mode '%s' at %s>" % \
68 (self.states[file.closed], file.name, file.mode, \
69 hex(id(self))[2:])
Guido van Rossum78f8dea1994-05-18 11:07:44 +000070
Guido van Rossum78f8dea1994-05-18 11:07:44 +000071 #
72 # Initialization routines
73 #
Guido van Rossum13c503e1995-03-16 15:58:12 +000074 def open(self, name, mode='r', bufsize=-1):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000075 import __builtin__
76 return self.fileopen(__builtin__.open(name, mode, bufsize))
Guido van Rossum78f8dea1994-05-18 11:07:44 +000077
Guido van Rossumc762bec1994-05-18 11:08:10 +000078 def fileopen(self, file):
Tim Peters22cd7682001-09-18 05:40:24 +000079 import types
Walter Dörwald70a6b492004-02-12 17:35:32 +000080 if repr(type(file)) != "<type 'file'>":
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000081 raise TypeError, 'posixfile.fileopen() arg must be file object'
82 self._file_ = file
83 # Copy basic file methods
Tim Peters22cd7682001-09-18 05:40:24 +000084 for maybemethod in dir(file):
85 if not maybemethod.startswith('_'):
86 attr = getattr(file, maybemethod)
87 if isinstance(attr, types.BuiltinMethodType):
88 setattr(self, maybemethod, attr)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000089 return self
Guido van Rossum78f8dea1994-05-18 11:07:44 +000090
91 #
92 # New methods
93 #
94 def file(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000095 return self._file_
Guido van Rossum78f8dea1994-05-18 11:07:44 +000096
97 def dup(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000098 import posix
Guido van Rossum78f8dea1994-05-18 11:07:44 +000099
Guido van Rossume9901f32001-04-10 15:44:33 +0000100 if not hasattr(posix, 'fdopen'):
101 raise AttributeError, 'dup() method unavailable'
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000102
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000103 return posix.fdopen(posix.dup(self._file_.fileno()), self._file_.mode)
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000104
105 def dup2(self, fd):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000106 import posix
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000107
Guido van Rossume9901f32001-04-10 15:44:33 +0000108 if not hasattr(posix, 'fdopen'):
109 raise AttributeError, 'dup() method unavailable'
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000110
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000111 posix.dup2(self._file_.fileno(), fd)
112 return posix.fdopen(fd, self._file_.mode)
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000113
Guido van Rossumc762bec1994-05-18 11:08:10 +0000114 def flags(self, *which):
Andrew M. Kuchling86c7e222001-08-13 14:47:12 +0000115 import fcntl, os
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000116
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000117 if which:
118 if len(which) > 1:
119 raise TypeError, 'Too many arguments'
120 which = which[0]
121 else: which = '?'
Guido van Rossumc762bec1994-05-18 11:08:10 +0000122
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000123 l_flags = 0
Fred Drakea94414a2001-05-10 15:33:31 +0000124 if 'n' in which: l_flags = l_flags | os.O_NDELAY
125 if 'a' in which: l_flags = l_flags | os.O_APPEND
126 if 's' in which: l_flags = l_flags | os.O_SYNC
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000127
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000128 file = self._file_
Guido van Rossumc762bec1994-05-18 11:08:10 +0000129
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000130 if '=' not in which:
Fred Drakea94414a2001-05-10 15:33:31 +0000131 cur_fl = fcntl.fcntl(file.fileno(), fcntl.F_GETFL, 0)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000132 if '!' in which: l_flags = cur_fl & ~ l_flags
133 else: l_flags = cur_fl | l_flags
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000134
Fred Drakea94414a2001-05-10 15:33:31 +0000135 l_flags = fcntl.fcntl(file.fileno(), fcntl.F_SETFL, l_flags)
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000136
Tim Peters2344fae2001-01-15 00:50:52 +0000137 if 'c' in which:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000138 arg = ('!' not in which) # 0 is don't, 1 is do close on exec
Fred Drakea94414a2001-05-10 15:33:31 +0000139 l_flags = fcntl.fcntl(file.fileno(), fcntl.F_SETFD, arg)
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000140
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000141 if '?' in which:
142 which = '' # Return current flags
Fred Drakea94414a2001-05-10 15:33:31 +0000143 l_flags = fcntl.fcntl(file.fileno(), fcntl.F_GETFL, 0)
144 if os.O_APPEND & l_flags: which = which + 'a'
145 if fcntl.fcntl(file.fileno(), fcntl.F_GETFD, 0) & 1:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000146 which = which + 'c'
Fred Drakea94414a2001-05-10 15:33:31 +0000147 if os.O_NDELAY & l_flags: which = which + 'n'
148 if os.O_SYNC & l_flags: which = which + 's'
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000149 return which
Tim Peters2344fae2001-01-15 00:50:52 +0000150
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000151 def lock(self, how, *args):
Fred Drakea94414a2001-05-10 15:33:31 +0000152 import struct, fcntl
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000153
Fred Drakea94414a2001-05-10 15:33:31 +0000154 if 'w' in how: l_type = fcntl.F_WRLCK
155 elif 'r' in how: l_type = fcntl.F_RDLCK
156 elif 'u' in how: l_type = fcntl.F_UNLCK
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000157 else: raise TypeError, 'no type of lock specified'
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000158
Fred Drakea94414a2001-05-10 15:33:31 +0000159 if '|' in how: cmd = fcntl.F_SETLKW
160 elif '?' in how: cmd = fcntl.F_GETLK
161 else: cmd = fcntl.F_SETLK
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000162
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000163 l_whence = 0
164 l_start = 0
165 l_len = 0
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000166
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000167 if len(args) == 1:
168 l_len = args[0]
169 elif len(args) == 2:
170 l_len, l_start = args
171 elif len(args) == 3:
172 l_len, l_start, l_whence = args
173 elif len(args) > 3:
174 raise TypeError, 'too many arguments'
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000175
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000176 # Hack by davem@magnet.com to get locking to go on freebsd;
177 # additions for AIX by Vladimir.Marangozov@imag.fr
Guido van Rossum7698d121996-07-30 16:28:45 +0000178 import sys, os
Guido van Rossum027188a1999-02-23 04:14:32 +0000179 if sys.platform in ('netbsd1',
Guido van Rossum5274c331999-12-06 14:51:05 +0000180 'openbsd2',
Guido van Rossum2d218632000-08-29 14:57:27 +0000181 'freebsd2', 'freebsd3', 'freebsd4', 'freebsd5',
Hye-Shik Changf64700a2004-08-18 15:13:41 +0000182 'freebsd6', 'bsdos2', 'bsdos3', 'bsdos4'):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000183 flock = struct.pack('lxxxxlxxxxlhh', \
Tim Peters2344fae2001-01-15 00:50:52 +0000184 l_start, l_len, os.getpid(), l_type, l_whence)
Raymond Hettingerdbecd932005-02-06 06:57:08 +0000185 elif sys.platform in ('aix3', 'aix4'):
Guido van Rossum0f6a3bf1996-08-20 20:23:34 +0000186 flock = struct.pack('hhlllii', \
187 l_type, l_whence, l_start, l_len, 0, 0, 0)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000188 else:
189 flock = struct.pack('hhllhh', \
190 l_type, l_whence, l_start, l_len, 0, 0)
Guido van Rossum7698d121996-07-30 16:28:45 +0000191
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000192 flock = fcntl.fcntl(self._file_.fileno(), cmd, flock)
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000193
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000194 if '?' in how:
Guido van Rossum027188a1999-02-23 04:14:32 +0000195 if sys.platform in ('netbsd1',
Guido van Rossum5274c331999-12-06 14:51:05 +0000196 'openbsd2',
Guido van Rossum2d218632000-08-29 14:57:27 +0000197 'freebsd2', 'freebsd3', 'freebsd4', 'freebsd5',
Guido van Rossum027188a1999-02-23 04:14:32 +0000198 'bsdos2', 'bsdos3', 'bsdos4'):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000199 l_start, l_len, l_pid, l_type, l_whence = \
200 struct.unpack('lxxxxlxxxxlhh', flock)
Raymond Hettingerdbecd932005-02-06 06:57:08 +0000201 elif sys.platform in ('aix3', 'aix4'):
Guido van Rossum0f6a3bf1996-08-20 20:23:34 +0000202 l_type, l_whence, l_start, l_len, l_sysid, l_pid, l_vfs = \
203 struct.unpack('hhlllii', flock)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000204 elif sys.platform == "linux2":
205 l_type, l_whence, l_start, l_len, l_pid, l_sysid = \
206 struct.unpack('hhllhh', flock)
207 else:
208 l_type, l_whence, l_start, l_len, l_sysid, l_pid = \
209 struct.unpack('hhllhh', flock)
Guido van Rossum7698d121996-07-30 16:28:45 +0000210
Fred Drakea94414a2001-05-10 15:33:31 +0000211 if l_type != fcntl.F_UNLCK:
212 if l_type == fcntl.F_RDLCK:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000213 return 'r', l_len, l_start, l_whence, l_pid
214 else:
215 return 'w', l_len, l_start, l_whence, l_pid
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000216
Guido van Rossum28aa2291995-03-23 10:39:49 +0000217def open(name, mode='r', bufsize=-1):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000218 """Public routine to open a file as a posixfile object."""
Guido van Rossum28aa2291995-03-23 10:39:49 +0000219 return _posixfile_().open(name, mode, bufsize)
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000220
Guido van Rossumc762bec1994-05-18 11:08:10 +0000221def fileopen(file):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000222 """Public routine to get a posixfile object from a Python file object."""
Guido van Rossumc762bec1994-05-18 11:08:10 +0000223 return _posixfile_().fileopen(file)
224
225#
226# Constants
227#
228SEEK_SET = 0
229SEEK_CUR = 1
230SEEK_END = 2
231
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000232#
233# End of posixfile.py
234#