|
1 """Extended file operations available in POSIX. |
|
2 |
|
3 f = posixfile.open(filename, [mode, [bufsize]]) |
|
4 will create a new posixfile object |
|
5 |
|
6 f = posixfile.fileopen(fileobject) |
|
7 will create a posixfile object from a builtin file object |
|
8 |
|
9 f.file() |
|
10 will return the original builtin file object |
|
11 |
|
12 f.dup() |
|
13 will return a new file object based on a new filedescriptor |
|
14 |
|
15 f.dup2(fd) |
|
16 will return a new file object based on the given filedescriptor |
|
17 |
|
18 f.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 |
|
37 f.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 import warnings |
|
56 warnings.warn("The posixfile module is deprecated; " |
|
57 "fcntl.lockf() provides better locking", DeprecationWarning, 2) |
|
58 |
|
59 class _posixfile_: |
|
60 """File wrapper class that provides extra POSIX file routines.""" |
|
61 |
|
62 states = ['open', 'closed'] |
|
63 |
|
64 # |
|
65 # Internal routines |
|
66 # |
|
67 def __repr__(self): |
|
68 file = self._file_ |
|
69 return "<%s posixfile '%s', mode '%s' at %s>" % \ |
|
70 (self.states[file.closed], file.name, file.mode, \ |
|
71 hex(id(self))[2:]) |
|
72 |
|
73 # |
|
74 # Initialization routines |
|
75 # |
|
76 def open(self, name, mode='r', bufsize=-1): |
|
77 import __builtin__ |
|
78 return self.fileopen(__builtin__.open(name, mode, bufsize)) |
|
79 |
|
80 def fileopen(self, file): |
|
81 import types |
|
82 if repr(type(file)) != "<type 'file'>": |
|
83 raise TypeError, 'posixfile.fileopen() arg must be file object' |
|
84 self._file_ = file |
|
85 # Copy basic file methods |
|
86 for maybemethod in dir(file): |
|
87 if not maybemethod.startswith('_'): |
|
88 attr = getattr(file, maybemethod) |
|
89 if isinstance(attr, types.BuiltinMethodType): |
|
90 setattr(self, maybemethod, attr) |
|
91 return self |
|
92 |
|
93 # |
|
94 # New methods |
|
95 # |
|
96 def file(self): |
|
97 return self._file_ |
|
98 |
|
99 def dup(self): |
|
100 import posix |
|
101 |
|
102 if not hasattr(posix, 'fdopen'): |
|
103 raise AttributeError, 'dup() method unavailable' |
|
104 |
|
105 return posix.fdopen(posix.dup(self._file_.fileno()), self._file_.mode) |
|
106 |
|
107 def dup2(self, fd): |
|
108 import posix |
|
109 |
|
110 if not hasattr(posix, 'fdopen'): |
|
111 raise AttributeError, 'dup() method unavailable' |
|
112 |
|
113 posix.dup2(self._file_.fileno(), fd) |
|
114 return posix.fdopen(fd, self._file_.mode) |
|
115 |
|
116 def flags(self, *which): |
|
117 import fcntl, os |
|
118 |
|
119 if which: |
|
120 if len(which) > 1: |
|
121 raise TypeError, 'Too many arguments' |
|
122 which = which[0] |
|
123 else: which = '?' |
|
124 |
|
125 l_flags = 0 |
|
126 if 'n' in which: l_flags = l_flags | os.O_NDELAY |
|
127 if 'a' in which: l_flags = l_flags | os.O_APPEND |
|
128 if 's' in which: l_flags = l_flags | os.O_SYNC |
|
129 |
|
130 file = self._file_ |
|
131 |
|
132 if '=' not in which: |
|
133 cur_fl = fcntl.fcntl(file.fileno(), fcntl.F_GETFL, 0) |
|
134 if '!' in which: l_flags = cur_fl & ~ l_flags |
|
135 else: l_flags = cur_fl | l_flags |
|
136 |
|
137 l_flags = fcntl.fcntl(file.fileno(), fcntl.F_SETFL, l_flags) |
|
138 |
|
139 if 'c' in which: |
|
140 arg = ('!' not in which) # 0 is don't, 1 is do close on exec |
|
141 l_flags = fcntl.fcntl(file.fileno(), fcntl.F_SETFD, arg) |
|
142 |
|
143 if '?' in which: |
|
144 which = '' # Return current flags |
|
145 l_flags = fcntl.fcntl(file.fileno(), fcntl.F_GETFL, 0) |
|
146 if os.O_APPEND & l_flags: which = which + 'a' |
|
147 if fcntl.fcntl(file.fileno(), fcntl.F_GETFD, 0) & 1: |
|
148 which = which + 'c' |
|
149 if os.O_NDELAY & l_flags: which = which + 'n' |
|
150 if os.O_SYNC & l_flags: which = which + 's' |
|
151 return which |
|
152 |
|
153 def lock(self, how, *args): |
|
154 import struct, fcntl |
|
155 |
|
156 if 'w' in how: l_type = fcntl.F_WRLCK |
|
157 elif 'r' in how: l_type = fcntl.F_RDLCK |
|
158 elif 'u' in how: l_type = fcntl.F_UNLCK |
|
159 else: raise TypeError, 'no type of lock specified' |
|
160 |
|
161 if '|' in how: cmd = fcntl.F_SETLKW |
|
162 elif '?' in how: cmd = fcntl.F_GETLK |
|
163 else: cmd = fcntl.F_SETLK |
|
164 |
|
165 l_whence = 0 |
|
166 l_start = 0 |
|
167 l_len = 0 |
|
168 |
|
169 if len(args) == 1: |
|
170 l_len = args[0] |
|
171 elif len(args) == 2: |
|
172 l_len, l_start = args |
|
173 elif len(args) == 3: |
|
174 l_len, l_start, l_whence = args |
|
175 elif len(args) > 3: |
|
176 raise TypeError, 'too many arguments' |
|
177 |
|
178 # Hack by davem@magnet.com to get locking to go on freebsd; |
|
179 # additions for AIX by Vladimir.Marangozov@imag.fr |
|
180 import sys, os |
|
181 if sys.platform in ('netbsd1', |
|
182 'openbsd2', |
|
183 'freebsd2', 'freebsd3', 'freebsd4', 'freebsd5', |
|
184 'freebsd6', 'freebsd7', 'freebsd8', |
|
185 'bsdos2', 'bsdos3', 'bsdos4'): |
|
186 flock = struct.pack('lxxxxlxxxxlhh', \ |
|
187 l_start, l_len, os.getpid(), l_type, l_whence) |
|
188 elif sys.platform in ('aix3', 'aix4'): |
|
189 flock = struct.pack('hhlllii', \ |
|
190 l_type, l_whence, l_start, l_len, 0, 0, 0) |
|
191 else: |
|
192 flock = struct.pack('hhllhh', \ |
|
193 l_type, l_whence, l_start, l_len, 0, 0) |
|
194 |
|
195 flock = fcntl.fcntl(self._file_.fileno(), cmd, flock) |
|
196 |
|
197 if '?' in how: |
|
198 if sys.platform in ('netbsd1', |
|
199 'openbsd2', |
|
200 'freebsd2', 'freebsd3', 'freebsd4', 'freebsd5', |
|
201 'bsdos2', 'bsdos3', 'bsdos4'): |
|
202 l_start, l_len, l_pid, l_type, l_whence = \ |
|
203 struct.unpack('lxxxxlxxxxlhh', flock) |
|
204 elif sys.platform in ('aix3', 'aix4'): |
|
205 l_type, l_whence, l_start, l_len, l_sysid, l_pid, l_vfs = \ |
|
206 struct.unpack('hhlllii', flock) |
|
207 elif sys.platform == "linux2": |
|
208 l_type, l_whence, l_start, l_len, l_pid, l_sysid = \ |
|
209 struct.unpack('hhllhh', flock) |
|
210 else: |
|
211 l_type, l_whence, l_start, l_len, l_sysid, l_pid = \ |
|
212 struct.unpack('hhllhh', flock) |
|
213 |
|
214 if l_type != fcntl.F_UNLCK: |
|
215 if l_type == fcntl.F_RDLCK: |
|
216 return 'r', l_len, l_start, l_whence, l_pid |
|
217 else: |
|
218 return 'w', l_len, l_start, l_whence, l_pid |
|
219 |
|
220 def open(name, mode='r', bufsize=-1): |
|
221 """Public routine to open a file as a posixfile object.""" |
|
222 return _posixfile_().open(name, mode, bufsize) |
|
223 |
|
224 def fileopen(file): |
|
225 """Public routine to get a posixfile object from a Python file object.""" |
|
226 return _posixfile_().fileopen(file) |
|
227 |
|
228 # |
|
229 # Constants |
|
230 # |
|
231 SEEK_SET = 0 |
|
232 SEEK_CUR = 1 |
|
233 SEEK_END = 2 |
|
234 |
|
235 # |
|
236 # End of posixfile.py |
|
237 # |