blob: cc5ecd2ce64236fdbc57d90b9e12121d33ebe085 [file] [log] [blame]
Guido van Rossum78f8dea1994-05-18 11:07:44 +00001#
2# Start of posixfile.py
3#
4
5#
6# Extended file operations
7#
8# f = posixfile.open(filename, mode)
9#
10# f.file()
11# will return the original builtin file object
12#
13# f.dup()
14# will return a new file object based on a new filedescriptor
15#
16# f.dup2(fd)
17# will return a new file object based on the given filedescriptor
18#
19# f.flags(mode)
20# will turn on the associated flag (merge)
21# mode can contain the following characters:
22#
23# (character representing a flag)
24# a append only flag
25# c close on exec flag
26# n no delay flag
27# s synchronization flag
28# (modifiers)
29# ! turn flags 'off' instead of default 'on'
30# = copy flags 'as is' instead of default 'merge'
31# ? return a string in which the characters represent the flags
32# that are set
33#
34# note: - the '!' and '=' modifiers are mutually exclusive.
35# - the '?' modifier will return the status of the flags after they
36# have been changed by other characters in the mode string
37#
38# f.lock(mode [, len [, start [, whence]]])
39# will (un)lock a region
40# mode can contain the following characters:
41#
42# (character representing type of lock)
43# u unlock
44# r read lock
45# w write lock
46# (modifiers)
47# | wait until the lock can be granted
48# ? return the first lock conflicting with the requested lock
49# or 'None' if there is no conflict. The lock returned is in the
50# format (mode, len, start, whence, pid) where mode is a
51# character representing the type of lock ('r' or 'w')
52#
53# note: - the '?' modifier prevents a region from being locked; it is
54# query only
55#
56
57class _posixfile_:
58 #
59 # Internal routines
60 #
61 def __repr__(self):
62 return repr(self._file_)
63
64 def __del__(self):
65 self._file_.close()
66
67 #
68 # Initialization routines
69 #
70 def open(self, name, mode):
71 import __builtin__
72
73 self._name_ = name
74 self._mode_ = mode
75 self._file_ = __builtin__.open(name, mode)
76 # Copy basic file methods
77 for method in self._file_.__methods__:
78 setattr(self, method, getattr(self._file_, method))
79 return self
80
81 #
82 # New methods
83 #
84 def file(self):
85 return self._file_
86
87 def dup(self):
88 import posix
89
90 try: ignore = posix.fdopen
91 except: raise AttributeError, 'dup() method unavailable'
92
93 return posix.fdopen(posix.dup(self._file_.fileno()), self._mode_)
94
95 def dup2(self, fd):
96 import posix
97
98 try: ignore = posix.fdopen
99 except: raise AttributeError, 'dup() method unavailable'
100
101 posix.dup2(self._file_.fileno(), fd)
102 return posix.fdopen(fd, self._mode_)
103
104 def flags(self, which):
105 import fcntl, FCNTL
106
107 l_flags = 0
108 if 'n' in which: l_flags = l_flags | FCNTL.O_NDELAY
109 if 'a' in which: l_flags = l_flags | FCNTL.O_APPEND
110 if 's' in which: l_flags = l_flags | FCNTL.O_SYNC
111
112 if '=' not in which:
113 cur_fl = fcntl.fcntl(self._file_.fileno(), FCNTL.F_GETFL, 0)
114 if '!' in which: l_flags = cur_fl & ~ l_flags
115 else: l_flags = cur_fl | l_flags
116
117 l_flags = fcntl.fcntl(self._file_.fileno(), FCNTL.F_SETFL, l_flags)
118
119 if 'c' in which:
120 arg = ('!' not in which) # 1 is close
121 l_flags = fcntl.fcntl(self._file_.fileno(), FCNTL.F_SETFD, arg)
122
123 if '?' in which:
124 which = ''
125 l_flags = fcntl.fcntl(self._file_.fileno(), FCNTL.F_GETFL, 0)
126 if FCNTL.O_APPEND & l_flags: which = which + 'a'
127 if fcntl.fcntl(self._file_.fileno(), FCNTL.F_GETFD, 0) & 1:
128 which = which + 'c'
129 if FCNTL.O_NDELAY & l_flags: which = which + 'n'
130 if FCNTL.O_SYNC & l_flags: which = which + 's'
131 return which
132
133 def lock(self, how, *args):
134 import struct, fcntl, FCNTL
135
136 if 'w' in how: l_type = FCNTL.F_WRLCK
137 elif 'r' in how: l_type = FCNTL.F_WRLCK
138 elif 'u' in how: l_type = FCNTL.F_UNLCK
139 else: raise TypeError, 'no type of lock specified'
140
141 if '|' in how: cmd = FCNTL.F_SETLKW
142 elif '?' in how: cmd = FCNTL.F_GETLK
143 else: cmd = FCNTL.F_SETLK
144
145 l_whence = 0
146 l_start = 0
147 l_len = 0
148
149 if len(args) == 1:
150 l_len = args[0]
151 elif len(args) == 2:
152 l_len, l_start = args
153 elif len(args) == 3:
154 l_len, l_start, l_whence = args
155 elif len(args) > 3:
156 raise TypeError, 'too many arguments'
157
158 flock = struct.pack('hhllhh', l_type, l_whence, l_start, l_len, 0, 0)
159 flock = fcntl.fcntl(self._file_.fileno(), cmd, flock)
160
161 if '?' in how:
162 l_type, l_whence, l_start, l_len, l_sysid, l_pid = \
163 struct.unpack('hhllhh', flock)
164 if l_type != FCNTL.F_UNLCK:
165 if l_type == FCNTL.F_RDLCK:
166 return 'r', l_len, l_start, l_whence, l_pid
167 else:
168 return 'w', l_len, l_start, l_whence, l_pid
169
170#
171# Public routine to obtain a posixfile object
172#
173def open(name, mode):
174 return _posixfile_().open(name, mode)
175
176#
177# End of posixfile.py
178#