diff options
author | dkf <donal.k.fellows@manchester.ac.uk> | 2012-11-14 13:01:46 (GMT) |
---|---|---|
committer | dkf <donal.k.fellows@manchester.ac.uk> | 2012-11-14 13:01:46 (GMT) |
commit | 7ecabf83c6ffcd212364b2b0b35ef18e98ee7ecd (patch) | |
tree | 50025dfed29a1aad376792dac26c592de41f9d6a /unix | |
parent | 47871a70f2f72a07a20bcf8ab3826068bf227392 (diff) | |
download | tcl-7ecabf83c6ffcd212364b2b0b35ef18e98ee7ecd.zip tcl-7ecabf83c6ffcd212364b2b0b35ef18e98ee7ecd.tar.gz tcl-7ecabf83c6ffcd212364b2b0b35ef18e98ee7ecd.tar.bz2 |
* unix/tclUnixFCmd.c (TclUnixOpenTemporaryFile): [Bug 2933003]: Factor
out all the code to do temporary file creation so that it is possible
to make it correct in one place. Allow overriding of the back-stop
default temporary file location at compile time by setting the
TCL_TEMPORARY_FILE_DIRECTORY #def to a string containing the directory
name (defaults to "/tmp" as that is the most common default).
Diffstat (limited to 'unix')
-rw-r--r-- | unix/tclUnixFCmd.c | 54 | ||||
-rw-r--r-- | unix/tclUnixPipe.c | 43 |
2 files changed, 56 insertions, 41 deletions
diff --git a/unix/tclUnixFCmd.c b/unix/tclUnixFCmd.c index d3cc6bf..559992f 100644 --- a/unix/tclUnixFCmd.c +++ b/unix/tclUnixFCmd.c @@ -62,6 +62,16 @@ #define DOTREE_F 3 /* regular file */ /* + * Fallback temporary file location the temporary file generation code. Can be + * overridden at compile time for when it is known that temp files can't be + * written to /tmp (hello, iOS!). + */ + +#ifndef TCL_TEMPORARY_FILE_DIRECTORY +#define TCL_TEMPORARY_FILE_DIRECTORY "/tmp" +#endif + +/* * Callbacks for file attributes code. */ @@ -2093,7 +2103,7 @@ TclpObjNormalizePath( /* *---------------------------------------------------------------------- * - * TclpOpenTemporaryFile -- + * TclpOpenTemporaryFile, TclUnixOpenTemporaryFile -- * * Creates a temporary file, possibly based on the supplied bits and * pieces of template supplied in the first three arguments. If the @@ -2103,7 +2113,12 @@ TclpObjNormalizePath( * file to go away once it is no longer needed. * * Results: - * A read-write Tcl Channel open on the file. + * A read-write Tcl Channel open on the file for TclpOpenTemporaryFile, + * or a file descriptor (or -1 on failure) for TclUnixOpenTemporaryFile. + * + * Side effects: + * Accesses the filesystem. Will set the contents of the Tcl_Obj fourth + * argument (if that is non-NULL). * *---------------------------------------------------------------------- */ @@ -2115,11 +2130,30 @@ TclpOpenTemporaryFile( Tcl_Obj *extensionObj, Tcl_Obj *resultingNameObj) { - Tcl_Channel chan; + int fd = TclUnixOpenTemporaryFile(dirObj, basenameObj, extensionObj, + resultingNameObj); + + if (fd == -1) { + return NULL; + } + return Tcl_MakeFileChannel(INT2PTR(fd), TCL_READABLE|TCL_WRITABLE); +} + +int +TclUnixOpenTemporaryFile( + Tcl_Obj *dirObj, + Tcl_Obj *basenameObj, + Tcl_Obj *extensionObj, + Tcl_Obj *resultingNameObj) +{ Tcl_DString template, tmp; const char *string; int len, fd; + /* + * We should also check against making more then TMP_MAX of these. + */ + if (dirObj) { string = Tcl_GetStringFromObj(dirObj, &len); Tcl_UtfToExternalDString(NULL, string, len, &template); @@ -2155,9 +2189,10 @@ TclpOpenTemporaryFile( } if (fd == -1) { - return NULL; + Tcl_DStringFree(&template); + return -1; } - chan = Tcl_MakeFileChannel(INT2PTR(fd), TCL_READABLE|TCL_WRITABLE); + if (resultingNameObj) { Tcl_ExternalToUtfDString(NULL, Tcl_DStringValue(&template), Tcl_DStringLength(&template), &tmp); @@ -2176,7 +2211,7 @@ TclpOpenTemporaryFile( } Tcl_DStringFree(&template); - return chan; + return fd; } /* @@ -2203,11 +2238,12 @@ DefaultTempDir(void) #endif /* - * Assume that "/tmp" is always an existing writable directory; we've no - * recovery mechanism if it isn't. + * Assume that the default location ("/tmp" if not overridden) is always + * an existing writable directory; we've no recovery mechanism if it + * isn't. */ - return "/tmp"; + return TCL_TEMPORARY_FILE_DIRECTORY; } #if defined(HAVE_CHFLAGS) && defined(UF_IMMUTABLE) diff --git a/unix/tclUnixPipe.c b/unix/tclUnixPipe.c index 654c9d8..9c21b28 100644 --- a/unix/tclUnixPipe.c +++ b/unix/tclUnixPipe.c @@ -188,28 +188,16 @@ TclFile TclpCreateTempFile( const char *contents) /* String to write into temp file, or NULL. */ { - char fileName[L_tmpnam + 9]; - const char *native; - Tcl_DString dstring; - int fd; + int fd = TclUnixOpenTemporaryFile(NULL, NULL, NULL, NULL); - /* - * We should also check against making more then TMP_MAX of these. - */ - - strcpy(fileName, P_tmpdir); /* INTL: Native. */ - if (fileName[strlen(fileName) - 1] != '/') { - strcat(fileName, "/"); /* INTL: Native. */ - } - strcat(fileName, "tclXXXXXX"); - fd = mkstemp(fileName); /* INTL: Native. */ if (fd == -1) { return NULL; } fcntl(fd, F_SETFD, FD_CLOEXEC); - unlink(fileName); /* INTL: Native. */ - if (contents != NULL) { + Tcl_DString dstring; + char *native; + native = Tcl_UtfToExternalDString(NULL, contents, -1, &dstring); if (write(fd, native, Tcl_DStringLength(&dstring)) == -1) { close(fd); @@ -241,29 +229,20 @@ TclpCreateTempFile( Tcl_Obj * TclpTempFileName(void) { - char fileName[L_tmpnam + 9]; - Tcl_Obj *result = NULL; + Tcl_Obj *nameObj = Tcl_NewObj(); int fd; - /* - * We should also check against making more then TMP_MAX of these. - */ - - strcpy(fileName, P_tmpdir); /* INTL: Native. */ - if (fileName[strlen(fileName) - 1] != '/') { - strcat(fileName, "/"); /* INTL: Native. */ - } - strcat(fileName, "tclXXXXXX"); - fd = mkstemp(fileName); /* INTL: Native. */ + Tcl_IncrRefCount(nameObj); + fd = TclUnixOpenTemporaryFile(NULL, NULL, NULL, nameObj); if (fd == -1) { + Tcl_DecrRefCount(nameObj); return NULL; } - fcntl(fd, F_SETFD, FD_CLOEXEC); - unlink(fileName); /* INTL: Native. */ - result = TclpNativeToNormalized(fileName); + fcntl(fd, F_SETFD, FD_CLOEXEC); + TclpObjDeleteFile(nameObj); close(fd); - return result; + return nameObj; } /* |