unofficial mirror of guile-user@gnu.org 
 help / color / mirror / Atom feed
* request tmpfile(3) wrapping in Guile 1.9 libguile
@ 2010-02-07 18:48 Thien-Thi Nguyen
  2010-02-08 11:11 ` Andy Wingo
  0 siblings, 1 reply; 6+ messages in thread
From: Thien-Thi Nguyen @ 2010-02-07 18:48 UTC (permalink / raw)
  To: guile-user

I'm writing to request that tmpfile(3) be added to Guile 1.9 libguile.

Background info: I'm in the process of cleaning up ttn-do dependency on Guile
1.4.x-isms[0].  One of these is the module (database tmpfile), which provides
tmpfile(3) wrapping.  In Guile 1.4.1.119, this will be provided by libguile
directly.[1]

According to tmpfile(3), this function is:

CONFORMING TO
       SVr4, 4.3BSD, C89, C99, SUSv2, POSIX.1-2001.

What do you think?

thi

_________________________________________________________________
[0] http://www.gnuvola.org/software/ttn-do/frisk.out.html

[1] libguile/posix.c excerpt:

SCM_SYMBOL (sym_tmpfile, "tmpfile");

SCM_DEFINE
(scm_tmpfile, "tmpfile", 0, 0, 0,
 (void),
 doc: /***********
Return an input/output port to a unique temporary file
named using the path prefix @code{P_tmpdir} defined in
@file{stdio.h}.
The file is automatically deleted when the port is closed
or the program terminates.

The name of the temporary file associated with the returned
port is not available to Scheme programs;
@code{(port-filename (tmpfile))} always returns the
symbol @code{tmpfile}.  */)
{
#define FUNC_NAME s_scm_tmpfile
  FILE *rv;

  rv = tmpfile ();
  if (! rv)
    SCM_SYSERROR;
  return scm_fdes_to_port (fileno (rv), "w+", sym_tmpfile);
#undef FUNC_NAME
}





^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: request tmpfile(3) wrapping in Guile 1.9 libguile
  2010-02-07 18:48 request tmpfile(3) wrapping in Guile 1.9 libguile Thien-Thi Nguyen
@ 2010-02-08 11:11 ` Andy Wingo
  2010-02-08 15:34   ` Ken Raeburn
  2010-02-09  9:07   ` Thien-Thi Nguyen
  0 siblings, 2 replies; 6+ messages in thread
From: Andy Wingo @ 2010-02-08 11:11 UTC (permalink / raw)
  To: Thien-Thi Nguyen; +Cc: guile-user

Hi Thien-Thi,

On Sun 07 Feb 2010 19:48, Thien-Thi Nguyen <ttn@gnuvola.org> writes:

> I'm writing to request that tmpfile(3) be added to Guile 1.9 libguile.

I think this sounds like a good idea. I have a few concerns, though if
none of them can be nicely addressed I'd still be happy adding tmpfile.

1. tmpfile(3) returns a FILE*, whereas Guile's fports normally deal in
file descriptors. Will this be a problem? What about buffering? Do we
have to fclose() the FILE* to get deletion working?

2. Why return 'tmpfile as the name, and not whatever filename one can
get from the FILE* ?

3. Is tmpfile(3) really needed, if you have mkstemp! and dynamic
extents? Here's what I use, for example:

(define-macro (unwind-protect form . cleanups)
  `(dynamic-wind (lambda () #t)
       (lambda () ,form)
       (lambda () ,@cleanups)))

(define (call-with-temp-file contents proc)
  (let* ((template (string-copy "/tmp/tekutiXXXXXX"))
         (tmp (mkstemp! template)))
    (display contents tmp)
    (close tmp)
    (unwind-protect
     (proc template)
     (delete-file template))))

Granted, one has to consider what to do on rewind... Regarding that, I
enjoyed Taylor Campbell's entry from
http://mumble.net/~campbell/blag.txt about unwind-protect.

Anyway, I digress. Anyone have thoughts about these?

Andy
-- 
http://wingolog.org/




^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: request tmpfile(3) wrapping in Guile 1.9 libguile
  2010-02-08 11:11 ` Andy Wingo
@ 2010-02-08 15:34   ` Ken Raeburn
  2010-02-08 17:06     ` Andy Wingo
  2010-02-09  9:07   ` Thien-Thi Nguyen
  1 sibling, 1 reply; 6+ messages in thread
From: Ken Raeburn @ 2010-02-08 15:34 UTC (permalink / raw)
  To: Andy Wingo; +Cc: guile-user, Thien-Thi Nguyen

On Feb 8, 2010, at 06:11, Andy Wingo wrote:
> 1. tmpfile(3) returns a FILE*, whereas Guile's fports normally deal in
> file descriptors. Will this be a problem? What about buffering? Do we
> have to fclose() the FILE* to get deletion working?

On POSIX systems you can use fileno().  The automatic deletion is probably handled by unlinking the file before returning the file handle.  But you probably can't get rid of the FILE* without calling fclose(), which would throw away the file and file descriptor.  On most UNIX systems you could probably dup() the file descriptor indicated by fileno() and then fclose() the FILE* handle, without losing the on-disk temporary file storage.

I don't know if you can use fileno on Windows.  It's also not clear to me from a quick look at the MSDN docs on tmpfile() whether the temporary file gets deleted if your program changes directories while running.

> 2. Why return 'tmpfile as the name, and not whatever filename one can
> get from the FILE* ?

If the file has been unlinked, the file name isn't going to be useful.  In fact, the tmpfile() interface doesn't give you a filename.

> 3. Is tmpfile(3) really needed, if you have mkstemp! and dynamic
> extents? Here's what I use, for example:

But mkstemp doesn't guarantee that no one else will grab the file name in between the time mkstemp checks that the file doesn't exist, and when you actually open(O_CREAT) it.  Using it can leave you with a race condition such that you need to loop generating and then trying filenames; tmpfile hides that away from the implementation, at least, or maybe uses more randomness in its filenames than mkstemp supports.  (And if you don't use O_EXCL, you may have a security problem, too.)

>    (unwind-protect
>     (proc template)
>     (delete-file template))))

Interesting...  A temp-file port type could probably be created that either uses tmpfile or unlinks on close or destruction of the port object, couldn't it?  I don't know if that would be better or worse than using tmpfile directly.  Does the unwind-protect here catch any cases that that would miss?

Ken



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: request tmpfile(3) wrapping in Guile 1.9 libguile
  2010-02-08 15:34   ` Ken Raeburn
@ 2010-02-08 17:06     ` Andy Wingo
  2010-02-09  4:36       ` Ken Raeburn
  0 siblings, 1 reply; 6+ messages in thread
From: Andy Wingo @ 2010-02-08 17:06 UTC (permalink / raw)
  To: Ken Raeburn; +Cc: guile-user, Thien-Thi Nguyen

Hi,

On Mon 08 Feb 2010 16:34, Ken Raeburn <raeburn@raeburn.org> writes:

> On Feb 8, 2010, at 06:11, Andy Wingo wrote:
>
>> 3. Is tmpfile(3) really needed, if you have mkstemp! and dynamic
>> extents? Here's what I use, for example:
>
> But mkstemp doesn't guarantee that no one else will grab the file name
> in between the time mkstemp checks that the file doesn't exist, and when
> you actually open(O_CREAT) it.

It does. The return value from mkstemp! is a port, and it mutates the
template to give you a file name. See mkstemp(3).

Andy
-- 
http://wingolog.org/




^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: request tmpfile(3) wrapping in Guile 1.9 libguile
  2010-02-08 17:06     ` Andy Wingo
@ 2010-02-09  4:36       ` Ken Raeburn
  0 siblings, 0 replies; 6+ messages in thread
From: Ken Raeburn @ 2010-02-09  4:36 UTC (permalink / raw)
  To: Andy Wingo; +Cc: guile-user, Thien-Thi Nguyen

On Feb 8, 2010, at 12:06, Andy Wingo wrote:
>> But mkstemp doesn't guarantee that no one else will grab the file name
>> in between the time mkstemp checks that the file doesn't exist, and when
>> you actually open(O_CREAT) it.
> 
> It does. The return value from mkstemp! is a port, and it mutates the
> template to give you a file name. See mkstemp(3).

Ah, yes, I was looking at mktemp(3)... *sigh*  Too many similarly-named functions.

It looks to me like tmpfile still has the advantage that (at least on a POSIX system with local file systems) the file will automatically go away even in the event of ungraceful process termination.  You could call unlink from Scheme code, but then you're coding the Scheme application to be dependent on POSIX behavior, versus letting the Windows version of tmpfile help you out.

Ken



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: request tmpfile(3) wrapping in Guile 1.9 libguile
  2010-02-08 11:11 ` Andy Wingo
  2010-02-08 15:34   ` Ken Raeburn
@ 2010-02-09  9:07   ` Thien-Thi Nguyen
  1 sibling, 0 replies; 6+ messages in thread
From: Thien-Thi Nguyen @ 2010-02-09  9:07 UTC (permalink / raw)
  To: guile-user

() Andy Wingo <wingo@pobox.com>
() Mon, 08 Feb 2010 12:11:17 +0100

   I think this sounds like a good idea. I have a few concerns, though if
   none of them can be nicely addressed I'd still be happy adding tmpfile.

I'm happy to see Ken Raeburn answer these concerns.  Personally, i find it
very nice to have an anonymous seekable chunk of filesystem to play with.

BTW (veering off-topic, but you started it!)... i dislike `mkstemp!'.
Its safe use requires `string-copy'.  Why not have all that handled
automatically, including the "XXXXXX" suffixing?  That's what i do
in Guile 1.4.x `mkstemp' (note, no "!").

thi

__________________________________________________
SCM_DEFINE
(scm_mkstemp, "mkstemp", 1, 0, 0,
 (SCM base),
 doc: /***********
Return a new port open on a temporary file named using string @var{base}.
The actual assigned filename, available via procedure @code{port-filename},
is @var{base} appended with six random characters.  For example:

@lisp
(define p (mkstemp "/tmp/foo-"))
(port-filename p)
@result{} "/tmp/foo-hoQtxh"
@end lisp  */)
{
#define FUNC_NAME s_scm_mkstemp
  char *s;
  size_t len;
  int fd;

  SCM_VALIDATE_STRING (1, base);
  len = SCM_ROLENGTH (base) + 6 + 1;
  s = alloca (len);
  snprintf (s, len, "%sXXXXXX", SCM_ROCHARS (base));

  if (PROB (fd = mkstemp (s)))
    SCM_SYSERROR;

  return scm_fdes_to_port (fd, "w+", STRFROM (s, len - 1));
#undef FUNC_NAME
}





^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2010-02-09  9:07 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-02-07 18:48 request tmpfile(3) wrapping in Guile 1.9 libguile Thien-Thi Nguyen
2010-02-08 11:11 ` Andy Wingo
2010-02-08 15:34   ` Ken Raeburn
2010-02-08 17:06     ` Andy Wingo
2010-02-09  4:36       ` Ken Raeburn
2010-02-09  9:07   ` Thien-Thi Nguyen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).