source: trunk/essentials/dev-lang/python/Lib/posixfile.py

Last change on this file was 3225, checked in by bird, 18 years ago

Python 2.5

File size: 7.7 KB
Line 
1"""Extended file operations available in POSIX.
2
3f = 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"""
55
56
57class _posixfile_:
58 """File wrapper class that provides extra POSIX file routines."""
59
60 states = ['open', 'closed']
61
62 #
63 # Internal routines
64 #
65 def __repr__(self):
66 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:])
70
71 #
72 # Initialization routines
73 #
74 def open(self, name, mode='r', bufsize=-1):
75 import __builtin__
76 return self.fileopen(__builtin__.open(name, mode, bufsize))
77
78 def fileopen(self, file):
79 import types
80 if repr(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 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)
89 return self
90
91 #
92 # New methods
93 #
94 def file(self):
95 return self._file_
96
97 def dup(self):
98 import posix
99
100 if not hasattr(posix, 'fdopen'):
101 raise AttributeError, 'dup() method unavailable'
102
103 return posix.fdopen(posix.dup(self._file_.fileno()), self._file_.mode)
104
105 def dup2(self, fd):
106 import posix
107
108 if not hasattr(posix, 'fdopen'):
109 raise AttributeError, 'dup() method unavailable'
110
111 posix.dup2(self._file_.fileno(), fd)
112 return posix.fdopen(fd, self._file_.mode)
113
114 def flags(self, *which):
115 import fcntl, os
116
117 if which:
118 if len(which) > 1:
119 raise TypeError, 'Too many arguments'
120 which = which[0]
121 else: which = '?'
122
123 l_flags = 0
124 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
127
128 file = self._file_
129
130 if '=' not in which:
131 cur_fl = fcntl.fcntl(file.fileno(), fcntl.F_GETFL, 0)
132 if '!' in which: l_flags = cur_fl & ~ l_flags
133 else: l_flags = cur_fl | l_flags
134
135 l_flags = fcntl.fcntl(file.fileno(), fcntl.F_SETFL, l_flags)
136
137 if 'c' in which:
138 arg = ('!' not in which) # 0 is don't, 1 is do close on exec
139 l_flags = fcntl.fcntl(file.fileno(), fcntl.F_SETFD, arg)
140
141 if '?' in which:
142 which = '' # Return current flags
143 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:
146 which = which + 'c'
147 if os.O_NDELAY & l_flags: which = which + 'n'
148 if os.O_SYNC & l_flags: which = which + 's'
149 return which
150
151 def lock(self, how, *args):
152 import struct, fcntl
153
154 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
157 else: raise TypeError, 'no type of lock specified'
158
159 if '|' in how: cmd = fcntl.F_SETLKW
160 elif '?' in how: cmd = fcntl.F_GETLK
161 else: cmd = fcntl.F_SETLK
162
163 l_whence = 0
164 l_start = 0
165 l_len = 0
166
167 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'
175
176 # Hack by davem@magnet.com to get locking to go on freebsd;
177 # additions for AIX by Vladimir.Marangozov@imag.fr
178 import sys, os
179 if sys.platform in ('netbsd1',
180 'openbsd2',
181 'freebsd2', 'freebsd3', 'freebsd4', 'freebsd5',
182 'freebsd6', 'freebsd7',
183 'bsdos2', 'bsdos3', 'bsdos4'):
184 flock = struct.pack('lxxxxlxxxxlhh', \
185 l_start, l_len, os.getpid(), l_type, l_whence)
186 elif sys.platform in ('aix3', 'aix4'):
187 flock = struct.pack('hhlllii', \
188 l_type, l_whence, l_start, l_len, 0, 0, 0)
189 else:
190 flock = struct.pack('hhllhh', \
191 l_type, l_whence, l_start, l_len, 0, 0)
192
193 flock = fcntl.fcntl(self._file_.fileno(), cmd, flock)
194
195 if '?' in how:
196 if sys.platform in ('netbsd1',
197 'openbsd2',
198 'freebsd2', 'freebsd3', 'freebsd4', 'freebsd5',
199 'bsdos2', 'bsdos3', 'bsdos4'):
200 l_start, l_len, l_pid, l_type, l_whence = \
201 struct.unpack('lxxxxlxxxxlhh', flock)
202 elif sys.platform in ('aix3', 'aix4'):
203 l_type, l_whence, l_start, l_len, l_sysid, l_pid, l_vfs = \
204 struct.unpack('hhlllii', flock)
205 elif sys.platform == "linux2":
206 l_type, l_whence, l_start, l_len, l_pid, l_sysid = \
207 struct.unpack('hhllhh', flock)
208 else:
209 l_type, l_whence, l_start, l_len, l_sysid, l_pid = \
210 struct.unpack('hhllhh', flock)
211
212 if l_type != fcntl.F_UNLCK:
213 if l_type == fcntl.F_RDLCK:
214 return 'r', l_len, l_start, l_whence, l_pid
215 else:
216 return 'w', l_len, l_start, l_whence, l_pid
217
218def open(name, mode='r', bufsize=-1):
219 """Public routine to open a file as a posixfile object."""
220 return _posixfile_().open(name, mode, bufsize)
221
222def fileopen(file):
223 """Public routine to get a posixfile object from a Python file object."""
224 return _posixfile_().fileopen(file)
225
226#
227# Constants
228#
229SEEK_SET = 0
230SEEK_CUR = 1
231SEEK_END = 2
232
233#
234# End of posixfile.py
235#
Note: See TracBrowser for help on using the repository browser.