On 16Feb2016 19:24, Alan Bawden <a...@csail.mit.edu> wrote:
Ben Finney <ben+pyt...@benfinney.id.au> writes:
Cameron Simpson <c...@zip.com.au> writes:
I've been watching this for a few days, and am struggling to
understand your use case.
Yes, you're not alone. This surprises me, which is why I'm persisting.
Can you elaborate with a concrete example and its purpose which would
work with a mktemp-ish official function?
An example::
Let me present another example that might strike some as more
straightforward.
If I want to create a temporary file, I can call mkstemp().
If I want to create a temporary directory, I can call mkdtemp().
Suppose that instead of a file or a directory, I want a FIFO or a
socket.
A FIFO is created by passing a pathname to os.mkfifo(). A socket is
created by passing a pathname to an AF_UNIX socket's bind() method. In
both cases, the pathname must not name anything yet (not even a symbolic
link), otherwise the call will fail.
So in the FIFO case, I might write something like the following:
def make_temp_fifo(mode=0o600):
while True:
path = tempfile.mktemp()
try:
os.mkfifo(path, mode=mode)
except FileExistsError:
pass
else:
return path
mktemp() is convenient here, because I don't have to worry about whether
I should be using "/tmp" or "/var/tmp" or "c:\temp", or whether the
TMPDIR environment variable is set, or whether I have permission to
create entries in those directories. It just gives me a pathname
without making me think about the rest of that stuff.
Yes, that is highly desirable.
Yes, I have to
defend against the possibility that somebody else creates something with
the same name first, but as you can see, I did that, and it wasn't
rocket science.
So is there something wrong with the above code? Other than the fact
that the documentation says something scary about mktemp()?
Well, it has a few shortcomings.
It relies on mkfifo reliably failing if the name exists. It shounds like mkfifo
is reliable this way, but I can imagine analogous use cases without such a
convenient core action, and your code only avoids mktemp's security issue
_because_ mkfifo has that fortuitous aspect.
It looks to me like mktemp() provides some real utility, packaged up in
a way that is orthogonal to the type of file system entry I want to
create, the permissions I want to give to that entry, and the mode I
want use to open it. It looks like a useful, albeit low-level,
primitive that it is perfectly reasonable for the tempfile module to
supply.
Secondly, why is your example better than::
os.mkfifo(os.path.join(mkdtemp(), 'myfifo'))
On that basis, this example doesn't present a use case what can't be addressed
by mkstemp or mkdtemp.
By contrast, Ben's example does look like it needs something like mktemp.
And yet the documentation condemns it as "deprecated", and tells me I
should use mkstemp() instead.
You _do_ understand the security issue, yes? I sure looked like you did, until
here.
(As if that would be of any use in the
situation above!) It looks like anxiety that some people might use
mktemp() in a stupid way has caused an over-reaction.
No, it is anxiety that mktemp's _normal_ use is inherently unsafe.
Let the
documentation warn about the problem and point to prepackaged solutions
in the common cases of making files and directories, but I see no good
reason to deprecate this useful utility.
I think it is like C's gets() function (albeit not as dangerous). It really
shouldn't be used.
One of the things about mktemp() is its raciness, which is the core of the
security issue. People look at the term "security issue" and think "Ah, it can
be attacked." But the flipside is that it is simply unreliable. Its normal use
was to make an ordinary temp file. Consider the case where two instances of the
same task are running at the same time, doing that. They can easily, by
accident, end us using the same scratch file!
This is by no means unlikely; any shell script running tasks in parallel can
arrange it, any procmail script filing a message with a "copy" rule (which
causes procmail simply to fork and proceed), etc.
This is neither weird nor even unlikely which is why kmtemp is strongly
discouraged - naive (and standard) use is not safe.
That you have contrived a use case where you can _carefully_ use mktemp in
safety in no way makes mktemp recommendable. In fact your use case isn't safe,
because _another_ task using mktemp in conflict as a plain old temporary file
may grab your fifo.
Cheers,
Cameron Simpson <c...@zip.com.au>
--
https://mail.python.org/mailman/listinfo/python-list