blob: 58c4b4f5f890c37c55c83c63011501d8d8490e03 [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):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000078 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
Guido van Rossum78f8dea1994-05-18 11:07:44 +000085
86 #
87 # New methods
88 #
89 def file(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000090 return self._file_
Guido van Rossum78f8dea1994-05-18 11:07:44 +000091
92 def dup(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000093 import posix
Guido van Rossum78f8dea1994-05-18 11:07:44 +000094
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000095 try: ignore = posix.fdopen
96 except: raise AttributeError, 'dup() method unavailable'
Guido van Rossum78f8dea1994-05-18 11:07:44 +000097
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000098 return posix.fdopen(posix.dup(self._file_.fileno()), self._file_.mode)
Guido van Rossum78f8dea1994-05-18 11:07:44 +000099
100 def dup2(self, fd):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000101 import posix
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000102
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000103 try: ignore = posix.fdopen
104 except: raise AttributeError, 'dup() method unavailable'
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000105
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000106 posix.dup2(self._file_.fileno(), fd)
107 return posix.fdopen(fd, self._file_.mode)
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000108
Guido van Rossumc762bec1994-05-18 11:08:10 +0000109 def flags(self, *which):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000110 import fcntl, FCNTL
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000111
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000112 if which:
113 if len(which) > 1:
114 raise TypeError, 'Too many arguments'
115 which = which[0]
116 else: which = '?'
Guido van Rossumc762bec1994-05-18 11:08:10 +0000117
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000118 l_flags = 0
119 if 'n' in which: l_flags = l_flags | FCNTL.O_NDELAY
120 if 'a' in which: l_flags = l_flags | FCNTL.O_APPEND
121 if 's' in which: l_flags = l_flags | FCNTL.O_SYNC
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000122
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000123 file = self._file_
Guido van Rossumc762bec1994-05-18 11:08:10 +0000124
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000125 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
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000129
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000130 l_flags = fcntl.fcntl(file.fileno(), FCNTL.F_SETFL, l_flags)
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000131
Tim Peters2344fae2001-01-15 00:50:52 +0000132 if 'c' in which:
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000133 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)
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000135
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000136 if '?' in which:
137 which = '' # Return current flags
138 l_flags = fcntl.fcntl(file.fileno(), FCNTL.F_GETFL, 0)
139 if FCNTL.O_APPEND & l_flags: which = which + 'a'
140 if fcntl.fcntl(file.fileno(), FCNTL.F_GETFD, 0) & 1:
141 which = which + 'c'
142 if FCNTL.O_NDELAY & l_flags: which = which + 'n'
143 if FCNTL.O_SYNC & l_flags: which = which + 's'
144 return which
Tim Peters2344fae2001-01-15 00:50:52 +0000145
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000146 def lock(self, how, *args):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000147 import struct, fcntl, FCNTL
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000148
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000149 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'
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000153
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000154 if '|' in how: cmd = FCNTL.F_SETLKW
155 elif '?' in how: cmd = FCNTL.F_GETLK
156 else: cmd = FCNTL.F_SETLK
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000157
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000158 l_whence = 0
159 l_start = 0
160 l_len = 0
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000161
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000162 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'
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000170
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000171 # Hack by davem@magnet.com to get locking to go on freebsd;
172 # additions for AIX by Vladimir.Marangozov@imag.fr
Guido van Rossum7698d121996-07-30 16:28:45 +0000173 import sys, os
Guido van Rossum027188a1999-02-23 04:14:32 +0000174 if sys.platform in ('netbsd1',
Guido van Rossum5274c331999-12-06 14:51:05 +0000175 'openbsd2',
Guido van Rossum2d218632000-08-29 14:57:27 +0000176 'freebsd2', 'freebsd3', 'freebsd4', 'freebsd5',
Guido van Rossum027188a1999-02-23 04:14:32 +0000177 'bsdos2', 'bsdos3', 'bsdos4'):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000178 flock = struct.pack('lxxxxlxxxxlhh', \
Tim Peters2344fae2001-01-15 00:50:52 +0000179 l_start, l_len, os.getpid(), l_type, l_whence)
Guido van Rossum0f6a3bf1996-08-20 20:23:34 +0000180 elif sys.platform in ['aix3', 'aix4']:
181 flock = struct.pack('hhlllii', \
182 l_type, l_whence, l_start, l_len, 0, 0, 0)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000183 else:
184 flock = struct.pack('hhllhh', \
185 l_type, l_whence, l_start, l_len, 0, 0)
Guido van Rossum7698d121996-07-30 16:28:45 +0000186
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000187 flock = fcntl.fcntl(self._file_.fileno(), cmd, flock)
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000188
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000189 if '?' in how:
Guido van Rossum027188a1999-02-23 04:14:32 +0000190 if sys.platform in ('netbsd1',
Guido van Rossum5274c331999-12-06 14:51:05 +0000191 'openbsd2',
Guido van Rossum2d218632000-08-29 14:57:27 +0000192 'freebsd2', 'freebsd3', 'freebsd4', 'freebsd5',
Guido van Rossum027188a1999-02-23 04:14:32 +0000193 'bsdos2', 'bsdos3', 'bsdos4'):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000194 l_start, l_len, l_pid, l_type, l_whence = \
195 struct.unpack('lxxxxlxxxxlhh', flock)
Guido van Rossum0f6a3bf1996-08-20 20:23:34 +0000196 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)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000199 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)
Guido van Rossum7698d121996-07-30 16:28:45 +0000205
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000206 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
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000211
Guido van Rossum28aa2291995-03-23 10:39:49 +0000212def open(name, mode='r', bufsize=-1):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000213 """Public routine to open a file as a posixfile object."""
Guido van Rossum28aa2291995-03-23 10:39:49 +0000214 return _posixfile_().open(name, mode, bufsize)
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000215
Guido van Rossumc762bec1994-05-18 11:08:10 +0000216def fileopen(file):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000217 """Public routine to get a posixfile object from a Python file object."""
Guido van Rossumc762bec1994-05-18 11:08:10 +0000218 return _posixfile_().fileopen(file)
219
220#
221# Constants
222#
223SEEK_SET = 0
224SEEK_CUR = 1
225SEEK_END = 2
226
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000227#
228# End of posixfile.py
229#