On 17 March 2003, I said: > Yuck. So here's another crack at patching this: Oops, stupid error in that one. Third and final attempt -- this time I actually tested the code on Linux, and it Works For Me (TM). Gonna check it in shortly. --- upload.py (revision 21160) +++ upload.py (working copy) @@ -11,6 +11,8 @@ __revision__ = "$Id$" import os, string +import errno +from random import random from cgi import parse_header from rfc822 import Message from time import time, strftime, localtime @@ -149,13 +151,46 @@ def __repr__ (self): return "<%s at %x: %s>" % (self.__class__.__name__, id(self), self) + def _open (self, dir): + """ + Generate a unique filename in 'dir'. Open and return a + writeable file object from it. + """ + while 1: + now = time() + tstamp = strftime("%Y%m%d.%H%M%S", localtime(now)) + + # Get 32 bits of fuzz -- don't use sys.maxint in case this + # is a 64-bit machine -- 32 bits is plenty. + # XXX random() not threadsafe! + fuzz = "%08x" % (random() * 2147483647) + filename = "upload.%s.%s.%s" % (tstamp, os.getpid(), fuzz) + filename = os.path.join(dir, filename) + flags = os.O_WRONLY|os.O_CREAT|os.O_EXCL + try: + flags |= os.O_BINARY # for Windows + except AttributeError: + pass + try: + fd = os.open(filename, flags) + except OSError, err: + if err.strerror == errno.EAGAIN: + # Filename collision -- try again on the + # next time through the loop. + pass + else: + # Bomb on any other error. + raise + else: + # Opened the file just fine; it now exists so no other + # process or thread will be able to grab that filename. + break + + # Wrap a file object around the file descriptor. + return (os.fdopen(fd, "wb"), filename) + def receive (self, file, boundary, dir): - now = time() - tstamp = (strftime("%Y%m%d.%H%M%S", localtime(now)) + - ("%.3f" % (now % 1))[1:]) - filename = "upload.%s.%s" % (tstamp, os.getpid()) - filename = os.path.join(dir, filename) - ofile = open(filename, "wb") + (ofile, filename) = self._open(dir) done = read_mime_part(file, boundary, ofile=ofile) ofile.close() self.tmp_filename = filename -- Greg Ward - software developer gward@mems-exchange.org MEMS Exchange http://www.mems-exchange.org