forwarded message from Stephen Weeks

Stephen Weeks MLton@sourcelight.com
Thu, 21 Jun 2001 14:54:33 -0700


Return-Path: <sweeks@eponym.epr.com>
Received: (from sweeks@localhost)
	by eponym.epr.com (8.11.2/8.11.2) id f5LLs3e27613;
	Thu, 21 Jun 2001 14:54:03 -0700
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Message-ID: <15154.27899.351541.970585@eponym.epr.com>
In-Reply-To: <200106212127.f5LLRHJ29946@syzygy.sourcelight.com>
References: <200106212127.f5LLRHJ29946@syzygy.sourcelight.com>
X-Mailer: VM 6.89 under 21.1 (patch 14) "Cuyahoga Valley" XEmacs Lucid
From: Stephen Weeks <sweeks@intertrust.com>
To: Henry Cejtin <henry@sourcelight.com>
Subject: mkstemp
Date: Thu, 21 Jun 2001 14:54:03 -0700


> As  to  directories,  only the mdir system call can meke them, and it doesn't
> have the fancy options that open has.  On the other hand, mkdir will fail  if
> the  file  already  exists, even if it is a symlink to something that doesn't
> exist.  Thus there are no race conditions.

OK.

> As you say, mkstemp is all just using the correct open options,  so  I  would
> definitely  do  it  using the posix stuff.  If you need files with particular
> suffixes, then you can't use mkstemp(), but you can, of course, get the  same
> effect  using  the  correct open modes by hand.  The key point is O_CREAT and
> O_EXCL.  They indicate that you want to create the file, and  that  you  want
> the  call  to fail if the file exists, even if it is a symlink to a file that
> does not exist.  You also have to supply the mode argument, which  should  be
> octal  666  (any  one can read and write, no execute), which is automatically
> adjusted by the umask removing some of these bits.  If the file is  going  to
> be executable you should use octal 777 instead.

Linux mkstemp does 0600, not 0666.

How do you propose allowing flexibility for the mode?  I think having the simple
function with the hardwired mode is nice.  Should we have a separate function
mkstemp' that takes an extra argument of type Posix.FileSys.S.mode?  Or leave
that for hackers who know what's going on to do themselves, since it can be done
as pure SML code.

I am hesitating about putting mkstemp in MLton.TextIO instead of my libraries.
What's pushing me to is the fact that OS.FileSys.tmpName causes that link time
warning, and I want a ready answer for questions, like "oh, just use
MLton.TextIO.mkstemp".

Anyways, here is the latest sig ...

      val MLton.TextIO.mkstemp: 
             {prefix: string, suffix: string} -> string * TextIO.outstream

and implementation ...

      local
	 val chars =
	    "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
	 val n = Word.fromInt (String.size chars)
	 val r: word ref = ref 0w0
      in
	 fun tempName {prefix, suffix} =
	    let
	       val _ = r := Random.seed ()
	       val unique =
		  String.tabulate
		  (6, fn _ =>
		   let
		      val w = !r
		      val c = String.sub (chars,
					  Word.toInt (Word.mod (w, n)))
		      val _ = r := Word.div (w, n)
		   in c
		   end)
	    in
	       concat [prefix, unique, suffix]
	    end
      end

      fun mkstemp arg: string * outstream =
	 let
	    fun loop (i: int) =
	       if i = 0
		  then raise Fail "MLton.TextIO.temp"
	       else
		  let
		     val name = tempName arg
		     open Posix.FileSys
		  in
		     (name,
		      newOut (createf (name, O_WRONLY, O.flags [O.excl],
				       let open S
				       in flags [irusr, iwusr]
				       end)))
		  end handle PosixError.SysErr _ => loop (i - 1)
	 in
	    loop 100 (* max num trials *)
	 end