Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / devtools / amd64 / lib / python2.4 / tempfile.py
CommitLineData
920dae64
AT
1"""Temporary files.
2
3This module provides generic, low- and high-level interfaces for
4creating temporary files and directories. The interfaces listed
5as "safe" just below can be used without fear of race conditions.
6Those listed as "unsafe" cannot, and are provided for backward
7compatibility only.
8
9This module also provides some data items to the user:
10
11 TMP_MAX - maximum number of names that will be tried before
12 giving up.
13 template - the default prefix for all temporary names.
14 You may change this to control the default prefix.
15 tempdir - If this is set to a string before the first use of
16 any routine from this module, it will be considered as
17 another candidate location to store temporary files.
18"""
19
20__all__ = [
21 "NamedTemporaryFile", "TemporaryFile", # high level safe interfaces
22 "mkstemp", "mkdtemp", # low level safe interfaces
23 "mktemp", # deprecated unsafe interface
24 "TMP_MAX", "gettempprefix", # constants
25 "tempdir", "gettempdir"
26 ]
27
28
29# Imports.
30
31import os as _os
32import errno as _errno
33from random import Random as _Random
34
35if _os.name == 'mac':
36 import Carbon.Folder as _Folder
37 import Carbon.Folders as _Folders
38
39try:
40 import fcntl as _fcntl
41except ImportError:
42 def _set_cloexec(fd):
43 pass
44else:
45 def _set_cloexec(fd):
46 try:
47 flags = _fcntl.fcntl(fd, _fcntl.F_GETFD, 0)
48 except IOError:
49 pass
50 else:
51 # flags read successfully, modify
52 flags |= _fcntl.FD_CLOEXEC
53 _fcntl.fcntl(fd, _fcntl.F_SETFD, flags)
54
55
56try:
57 import thread as _thread
58except ImportError:
59 import dummy_thread as _thread
60_allocate_lock = _thread.allocate_lock
61
62_text_openflags = _os.O_RDWR | _os.O_CREAT | _os.O_EXCL
63if hasattr(_os, 'O_NOINHERIT'):
64 _text_openflags |= _os.O_NOINHERIT
65if hasattr(_os, 'O_NOFOLLOW'):
66 _text_openflags |= _os.O_NOFOLLOW
67
68_bin_openflags = _text_openflags
69if hasattr(_os, 'O_BINARY'):
70 _bin_openflags |= _os.O_BINARY
71
72if hasattr(_os, 'TMP_MAX'):
73 TMP_MAX = _os.TMP_MAX
74else:
75 TMP_MAX = 10000
76
77template = "tmp"
78
79tempdir = None
80
81# Internal routines.
82
83_once_lock = _allocate_lock()
84
85if hasattr(_os, "lstat"):
86 _stat = _os.lstat
87elif hasattr(_os, "stat"):
88 _stat = _os.stat
89else:
90 # Fallback. All we need is something that raises os.error if the
91 # file doesn't exist.
92 def _stat(fn):
93 try:
94 f = open(fn)
95 except IOError:
96 raise _os.error
97 f.close()
98
99def _exists(fn):
100 try:
101 _stat(fn)
102 except _os.error:
103 return False
104 else:
105 return True
106
107class _RandomNameSequence:
108 """An instance of _RandomNameSequence generates an endless
109 sequence of unpredictable strings which can safely be incorporated
110 into file names. Each string is six characters long. Multiple
111 threads can safely use the same instance at the same time.
112
113 _RandomNameSequence is an iterator."""
114
115 characters = ("abcdefghijklmnopqrstuvwxyz" +
116 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
117 "0123456789-_")
118
119 def __init__(self):
120 self.mutex = _allocate_lock()
121 self.rng = _Random()
122 self.normcase = _os.path.normcase
123
124 def __iter__(self):
125 return self
126
127 def next(self):
128 m = self.mutex
129 c = self.characters
130 choose = self.rng.choice
131
132 m.acquire()
133 try:
134 letters = [choose(c) for dummy in "123456"]
135 finally:
136 m.release()
137
138 return self.normcase(''.join(letters))
139
140def _candidate_tempdir_list():
141 """Generate a list of candidate temporary directories which
142 _get_default_tempdir will try."""
143
144 dirlist = []
145
146 # First, try the environment.
147 for envname in 'TMPDIR', 'TEMP', 'TMP':
148 dirname = _os.getenv(envname)
149 if dirname: dirlist.append(dirname)
150
151 # Failing that, try OS-specific locations.
152 if _os.name == 'mac':
153 try:
154 fsr = _Folder.FSFindFolder(_Folders.kOnSystemDisk,
155 _Folders.kTemporaryFolderType, 1)
156 dirname = fsr.as_pathname()
157 dirlist.append(dirname)
158 except _Folder.error:
159 pass
160 elif _os.name == 'riscos':
161 dirname = _os.getenv('Wimp$ScrapDir')
162 if dirname: dirlist.append(dirname)
163 elif _os.name == 'nt':
164 dirlist.extend([ r'c:\temp', r'c:\tmp', r'\temp', r'\tmp' ])
165 else:
166 dirlist.extend([ '/tmp', '/var/tmp', '/usr/tmp' ])
167
168 # As a last resort, the current directory.
169 try:
170 dirlist.append(_os.getcwd())
171 except (AttributeError, _os.error):
172 dirlist.append(_os.curdir)
173
174 return dirlist
175
176def _get_default_tempdir():
177 """Calculate the default directory to use for temporary files.
178 This routine should be called exactly once.
179
180 We determine whether or not a candidate temp dir is usable by
181 trying to create and write to a file in that directory. If this
182 is successful, the test file is deleted. To prevent denial of
183 service, the name of the test file must be randomized."""
184
185 namer = _RandomNameSequence()
186 dirlist = _candidate_tempdir_list()
187 flags = _text_openflags
188
189 for dir in dirlist:
190 if dir != _os.curdir:
191 dir = _os.path.normcase(_os.path.abspath(dir))
192 # Try only a few names per directory.
193 for seq in xrange(100):
194 name = namer.next()
195 filename = _os.path.join(dir, name)
196 try:
197 fd = _os.open(filename, flags, 0600)
198 fp = _os.fdopen(fd, 'w')
199 fp.write('blat')
200 fp.close()
201 _os.unlink(filename)
202 del fp, fd
203 return dir
204 except (OSError, IOError), e:
205 if e[0] != _errno.EEXIST:
206 break # no point trying more names in this directory
207 pass
208 raise IOError, (_errno.ENOENT,
209 ("No usable temporary directory found in %s" % dirlist))
210
211_name_sequence = None
212
213def _get_candidate_names():
214 """Common setup sequence for all user-callable interfaces."""
215
216 global _name_sequence
217 if _name_sequence is None:
218 _once_lock.acquire()
219 try:
220 if _name_sequence is None:
221 _name_sequence = _RandomNameSequence()
222 finally:
223 _once_lock.release()
224 return _name_sequence
225
226
227def _mkstemp_inner(dir, pre, suf, flags):
228 """Code common to mkstemp, TemporaryFile, and NamedTemporaryFile."""
229
230 names = _get_candidate_names()
231
232 for seq in xrange(TMP_MAX):
233 name = names.next()
234 file = _os.path.join(dir, pre + name + suf)
235 try:
236 fd = _os.open(file, flags, 0600)
237 _set_cloexec(fd)
238 return (fd, _os.path.abspath(file))
239 except OSError, e:
240 if e.errno == _errno.EEXIST:
241 continue # try again
242 raise
243
244 raise IOError, (_errno.EEXIST, "No usable temporary file name found")
245
246
247# User visible interfaces.
248
249def gettempprefix():
250 """Accessor for tempdir.template."""
251 return template
252
253tempdir = None
254
255def gettempdir():
256 """Accessor for tempdir.tempdir."""
257 global tempdir
258 if tempdir is None:
259 _once_lock.acquire()
260 try:
261 if tempdir is None:
262 tempdir = _get_default_tempdir()
263 finally:
264 _once_lock.release()
265 return tempdir
266
267def mkstemp(suffix="", prefix=template, dir=None, text=False):
268 """mkstemp([suffix, [prefix, [dir, [text]]]])
269 User-callable function to create and return a unique temporary
270 file. The return value is a pair (fd, name) where fd is the
271 file descriptor returned by os.open, and name is the filename.
272
273 If 'suffix' is specified, the file name will end with that suffix,
274 otherwise there will be no suffix.
275
276 If 'prefix' is specified, the file name will begin with that prefix,
277 otherwise a default prefix is used.
278
279 If 'dir' is specified, the file will be created in that directory,
280 otherwise a default directory is used.
281
282 If 'text' is specified and true, the file is opened in text
283 mode. Else (the default) the file is opened in binary mode. On
284 some operating systems, this makes no difference.
285
286 The file is readable and writable only by the creating user ID.
287 If the operating system uses permission bits to indicate whether a
288 file is executable, the file is executable by no one. The file
289 descriptor is not inherited by children of this process.
290
291 Caller is responsible for deleting the file when done with it.
292 """
293
294 if dir is None:
295 dir = gettempdir()
296
297 if text:
298 flags = _text_openflags
299 else:
300 flags = _bin_openflags
301
302 return _mkstemp_inner(dir, prefix, suffix, flags)
303
304
305def mkdtemp(suffix="", prefix=template, dir=None):
306 """mkdtemp([suffix, [prefix, [dir]]])
307 User-callable function to create and return a unique temporary
308 directory. The return value is the pathname of the directory.
309
310 Arguments are as for mkstemp, except that the 'text' argument is
311 not accepted.
312
313 The directory is readable, writable, and searchable only by the
314 creating user.
315
316 Caller is responsible for deleting the directory when done with it.
317 """
318
319 if dir is None:
320 dir = gettempdir()
321
322 names = _get_candidate_names()
323
324 for seq in xrange(TMP_MAX):
325 name = names.next()
326 file = _os.path.join(dir, prefix + name + suffix)
327 try:
328 _os.mkdir(file, 0700)
329 return file
330 except OSError, e:
331 if e.errno == _errno.EEXIST:
332 continue # try again
333 raise
334
335 raise IOError, (_errno.EEXIST, "No usable temporary directory name found")
336
337def mktemp(suffix="", prefix=template, dir=None):
338 """mktemp([suffix, [prefix, [dir]]])
339 User-callable function to return a unique temporary file name. The
340 file is not created.
341
342 Arguments are as for mkstemp, except that the 'text' argument is
343 not accepted.
344
345 This function is unsafe and should not be used. The file name
346 refers to a file that did not exist at some point, but by the time
347 you get around to creating it, someone else may have beaten you to
348 the punch.
349 """
350
351## from warnings import warn as _warn
352## _warn("mktemp is a potential security risk to your program",
353## RuntimeWarning, stacklevel=2)
354
355 if dir is None:
356 dir = gettempdir()
357
358 names = _get_candidate_names()
359 for seq in xrange(TMP_MAX):
360 name = names.next()
361 file = _os.path.join(dir, prefix + name + suffix)
362 if not _exists(file):
363 return file
364
365 raise IOError, (_errno.EEXIST, "No usable temporary filename found")
366
367class _TemporaryFileWrapper:
368 """Temporary file wrapper
369
370 This class provides a wrapper around files opened for
371 temporary use. In particular, it seeks to automatically
372 remove the file when it is no longer needed.
373 """
374
375 def __init__(self, file, name):
376 self.file = file
377 self.name = name
378 self.close_called = False
379
380 def __getattr__(self, name):
381 file = self.__dict__['file']
382 a = getattr(file, name)
383 if type(a) != type(0):
384 setattr(self, name, a)
385 return a
386
387 # NT provides delete-on-close as a primitive, so we don't need
388 # the wrapper to do anything special. We still use it so that
389 # file.name is useful (i.e. not "(fdopen)") with NamedTemporaryFile.
390 if _os.name != 'nt':
391
392 # Cache the unlinker so we don't get spurious errors at
393 # shutdown when the module-level "os" is None'd out. Note
394 # that this must be referenced as self.unlink, because the
395 # name TemporaryFileWrapper may also get None'd out before
396 # __del__ is called.
397 unlink = _os.unlink
398
399 def close(self):
400 if not self.close_called:
401 self.close_called = True
402 self.file.close()
403 self.unlink(self.name)
404
405 def __del__(self):
406 self.close()
407
408def NamedTemporaryFile(mode='w+b', bufsize=-1, suffix="",
409 prefix=template, dir=None):
410 """Create and return a temporary file.
411 Arguments:
412 'prefix', 'suffix', 'dir' -- as for mkstemp.
413 'mode' -- the mode argument to os.fdopen (default "w+b").
414 'bufsize' -- the buffer size argument to os.fdopen (default -1).
415 The file is created as mkstemp() would do it.
416
417 Returns an object with a file-like interface; the name of the file
418 is accessible as file.name. The file will be automatically deleted
419 when it is closed.
420 """
421
422 if dir is None:
423 dir = gettempdir()
424
425 if 'b' in mode:
426 flags = _bin_openflags
427 else:
428 flags = _text_openflags
429
430 # Setting O_TEMPORARY in the flags causes the OS to delete
431 # the file when it is closed. This is only supported by Windows.
432 if _os.name == 'nt':
433 flags |= _os.O_TEMPORARY
434
435 (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags)
436 file = _os.fdopen(fd, mode, bufsize)
437 return _TemporaryFileWrapper(file, name)
438
439if _os.name != 'posix' or _os.sys.platform == 'cygwin':
440 # On non-POSIX and Cygwin systems, assume that we cannot unlink a file
441 # while it is open.
442 TemporaryFile = NamedTemporaryFile
443
444else:
445 def TemporaryFile(mode='w+b', bufsize=-1, suffix="",
446 prefix=template, dir=None):
447 """Create and return a temporary file.
448 Arguments:
449 'prefix', 'suffix', 'directory' -- as for mkstemp.
450 'mode' -- the mode argument to os.fdopen (default "w+b").
451 'bufsize' -- the buffer size argument to os.fdopen (default -1).
452 The file is created as mkstemp() would do it.
453
454 Returns an object with a file-like interface. The file has no
455 name, and will cease to exist when it is closed.
456 """
457
458 if dir is None:
459 dir = gettempdir()
460
461 if 'b' in mode:
462 flags = _bin_openflags
463 else:
464 flags = _text_openflags
465
466 (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags)
467 try:
468 _os.unlink(name)
469 return _os.fdopen(fd, mode, bufsize)
470 except:
471 _os.close(fd)
472 raise