blob: 2db37e04ee20b0c3f17dd75eb3b8b4d5eed30741 [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
70 def __del__(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000071 self._file_.close()
Guido van Rossum78f8dea1994-05-18 11:07:44 +000072
73 #
74 # Initialization routines
75 #
Guido van Rossum13c503e1995-03-16 15:58:12 +000076 def open(self, name, mode='r', bufsize=-1):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000077 import __builtin__
78 return self.fileopen(__builtin__.open(name, mode, bufsize))
Guido van Rossum78f8dea1994-05-18 11:07:44 +000079
Guido van Rossumc762bec1994-05-18 11:08:10 +000080 def fileopen(self, file):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000081 if `type(file)` != "<type 'file'>":
82 raise TypeError, 'posixfile.fileopen() arg must be file object'
83 self._file_ = file
84 # Copy basic file methods
85 for method in file.__methods__:
86 setattr(self, method, getattr(file, method))
87 return self
Guido van Rossum78f8dea1994-05-18 11:07:44 +000088
89 #
90 # New methods
91 #
92 def file(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000093 return self._file_
Guido van Rossum78f8dea1994-05-18 11:07:44 +000094
95 def dup(self):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000096 import posix
Guido van Rossum78f8dea1994-05-18 11:07:44 +000097
Guido van Rossum45e2fbc1998-03-26 21:13:24 +000098 try: ignore = posix.fdopen
99 except: raise AttributeError, 'dup() method unavailable'
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000100
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000101 return posix.fdopen(posix.dup(self._file_.fileno()), self._file_.mode)
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000102
103 def dup2(self, fd):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000104 import posix
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000105
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000106 try: ignore = posix.fdopen
107 except: raise AttributeError, 'dup() method unavailable'
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000108
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000109 posix.dup2(self._file_.fileno(), fd)
110 return posix.fdopen(fd, self._file_.mode)
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000111
Guido van Rossumc762bec1994-05-18 11:08:10 +0000112 def flags(self, *which):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000113 import fcntl, FCNTL
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000114
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000115 if which:
116 if len(which) > 1:
117 raise TypeError, 'Too many arguments'
118 which = which[0]
119 else: which = '?'
Guido van Rossumc762bec1994-05-18 11:08:10 +0000120
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000121 l_flags = 0
122 if 'n' in which: l_flags = l_flags | FCNTL.O_NDELAY
123 if 'a' in which: l_flags = l_flags | FCNTL.O_APPEND
124 if 's' in which: l_flags = l_flags | FCNTL.O_SYNC
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000125
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000126 file = self._file_
Guido van Rossumc762bec1994-05-18 11:08:10 +0000127
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000128 if '=' not in which:
129 cur_fl = fcntl.fcntl(file.fileno(), FCNTL.F_GETFL, 0)
130 if '!' in which: l_flags = cur_fl & ~ l_flags
131 else: l_flags = cur_fl | l_flags
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000132
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000133 l_flags = fcntl.fcntl(file.fileno(), FCNTL.F_SETFL, l_flags)
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000134
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000135 if 'c' in which:
136 arg = ('!' not in which) # 0 is don't, 1 is do close on exec
137 l_flags = fcntl.fcntl(file.fileno(), FCNTL.F_SETFD, arg)
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000138
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000139 if '?' in which:
140 which = '' # Return current flags
141 l_flags = fcntl.fcntl(file.fileno(), FCNTL.F_GETFL, 0)
142 if FCNTL.O_APPEND & l_flags: which = which + 'a'
143 if fcntl.fcntl(file.fileno(), FCNTL.F_GETFD, 0) & 1:
144 which = which + 'c'
145 if FCNTL.O_NDELAY & l_flags: which = which + 'n'
146 if FCNTL.O_SYNC & l_flags: which = which + 's'
147 return which
148
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000149 def lock(self, how, *args):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000150 import struct, fcntl, FCNTL
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000151
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000152 if 'w' in how: l_type = FCNTL.F_WRLCK
153 elif 'r' in how: l_type = FCNTL.F_RDLCK
154 elif 'u' in how: l_type = FCNTL.F_UNLCK
155 else: raise TypeError, 'no type of lock specified'
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000156
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000157 if '|' in how: cmd = FCNTL.F_SETLKW
158 elif '?' in how: cmd = FCNTL.F_GETLK
159 else: cmd = FCNTL.F_SETLK
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000160
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000161 l_whence = 0
162 l_start = 0
163 l_len = 0
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000164
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000165 if len(args) == 1:
166 l_len = args[0]
167 elif len(args) == 2:
168 l_len, l_start = args
169 elif len(args) == 3:
170 l_len, l_start, l_whence = args
171 elif len(args) > 3:
172 raise TypeError, 'too many arguments'
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000173
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000174 # Hack by davem@magnet.com to get locking to go on freebsd;
175 # additions for AIX by Vladimir.Marangozov@imag.fr
Guido van Rossum7698d121996-07-30 16:28:45 +0000176 import sys, os
Guido van Rossum027188a1999-02-23 04:14:32 +0000177 if sys.platform in ('netbsd1',
Guido van Rossum5274c331999-12-06 14:51:05 +0000178 'openbsd2',
Guido van Rossum027188a1999-02-23 04:14:32 +0000179 'freebsd2', 'freebsd3',
180 'bsdos2', 'bsdos3', 'bsdos4'):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000181 flock = struct.pack('lxxxxlxxxxlhh', \
182 l_start, l_len, os.getpid(), l_type, l_whence)
Guido van Rossum0f6a3bf1996-08-20 20:23:34 +0000183 elif sys.platform in ['aix3', 'aix4']:
184 flock = struct.pack('hhlllii', \
185 l_type, l_whence, l_start, l_len, 0, 0, 0)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000186 else:
187 flock = struct.pack('hhllhh', \
188 l_type, l_whence, l_start, l_len, 0, 0)
Guido van Rossum7698d121996-07-30 16:28:45 +0000189
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000190 flock = fcntl.fcntl(self._file_.fileno(), cmd, flock)
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000191
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000192 if '?' in how:
Guido van Rossum027188a1999-02-23 04:14:32 +0000193 if sys.platform in ('netbsd1',
Guido van Rossum5274c331999-12-06 14:51:05 +0000194 'openbsd2',
Guido van Rossum027188a1999-02-23 04:14:32 +0000195 'freebsd2', 'freebsd3',
196 'bsdos2', 'bsdos3', 'bsdos4'):
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000197 l_start, l_len, l_pid, l_type, l_whence = \
198 struct.unpack('lxxxxlxxxxlhh', flock)
Guido van Rossum0f6a3bf1996-08-20 20:23:34 +0000199 elif sys.platform in ['aix3', 'aix4']:
200 l_type, l_whence, l_start, l_len, l_sysid, l_pid, l_vfs = \
201 struct.unpack('hhlllii', flock)
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000202 elif sys.platform == "linux2":
203 l_type, l_whence, l_start, l_len, l_pid, l_sysid = \
204 struct.unpack('hhllhh', flock)
205 else:
206 l_type, l_whence, l_start, l_len, l_sysid, l_pid = \
207 struct.unpack('hhllhh', flock)
Guido van Rossum7698d121996-07-30 16:28:45 +0000208
Guido van Rossum45e2fbc1998-03-26 21:13:24 +0000209 if l_type != FCNTL.F_UNLCK:
210 if l_type == FCNTL.F_RDLCK:
211 return 'r', l_len, l_start, l_whence, l_pid
212 else:
213 return 'w', l_len, l_start, l_whence, l_pid
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000214
Guido van Rossum28aa2291995-03-23 10:39:49 +0000215def open(name, mode='r', bufsize=-1):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000216 """Public routine to open a file as a posixfile object."""
Guido van Rossum28aa2291995-03-23 10:39:49 +0000217 return _posixfile_().open(name, mode, bufsize)
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000218
Guido van Rossumc762bec1994-05-18 11:08:10 +0000219def fileopen(file):
Guido van Rossum54f22ed2000-02-04 15:10:34 +0000220 """Public routine to get a posixfile object from a Python file object."""
Guido van Rossumc762bec1994-05-18 11:08:10 +0000221 return _posixfile_().fileopen(file)
222
223#
224# Constants
225#
226SEEK_SET = 0
227SEEK_CUR = 1
228SEEK_END = 2
229
Guido van Rossum78f8dea1994-05-18 11:07:44 +0000230#
231# End of posixfile.py
232#