Moved functions mc_mkstemp() and mc_tempdir() to VFS module.

Signed-off-by: Slava Zanko <slavazanko@gmail.com>
This commit is contained in:
Slava Zanko 2012-01-04 11:44:35 +03:00
parent 4945d0f9a6
commit 53c500f58c
5 changed files with 200 additions and 197 deletions

View File

@ -181,7 +181,7 @@ resolve_symlinks (const char *path)
else if (*(r - 1) == PATH_SEP && r != buf + 1)
*(r - 1) = 0;
ret:
ret:
g_free (buf2);
vfs_path_free (vpath);
return buf;
@ -1181,88 +1181,6 @@ list_append_unique (GList * list, char *text)
return list;
}
/* --------------------------------------------------------------------------------------------- */
/* Following code heavily borrows from libiberty, mkstemps.c */
/*
* Arguments:
* pname (output) - pointer to the name of the temp file (needs g_free).
* NULL if the function fails.
* prefix - part of the filename before the random part.
* Prepend $TMPDIR or /tmp if there are no path separators.
* suffix - if not NULL, part of the filename after the random part.
*
* Result:
* handle of the open file or -1 if couldn't open any.
*/
int
mc_mkstemps (char **pname, const char *prefix, const char *suffix)
{
static const char letters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
static unsigned long value;
struct timeval tv;
char *tmpbase;
char *tmpname;
char *XXXXXX;
int count;
if (strchr (prefix, PATH_SEP) == NULL)
{
/* Add prefix first to find the position of XXXXXX */
tmpbase = concat_dir_and_file (mc_tmpdir (), prefix);
}
else
{
tmpbase = g_strdup (prefix);
}
tmpname = g_strconcat (tmpbase, "XXXXXX", suffix, (char *) NULL);
*pname = tmpname;
XXXXXX = &tmpname[strlen (tmpbase)];
g_free (tmpbase);
/* Get some more or less random data. */
gettimeofday (&tv, NULL);
value += (tv.tv_usec << 16) ^ tv.tv_sec ^ getpid ();
for (count = 0; count < TMP_MAX; ++count)
{
unsigned long v = value;
int fd;
/* Fill in the random bits. */
XXXXXX[0] = letters[v % 62];
v /= 62;
XXXXXX[1] = letters[v % 62];
v /= 62;
XXXXXX[2] = letters[v % 62];
v /= 62;
XXXXXX[3] = letters[v % 62];
v /= 62;
XXXXXX[4] = letters[v % 62];
v /= 62;
XXXXXX[5] = letters[v % 62];
fd = open (tmpname, O_RDWR | O_CREAT | O_TRUNC | O_EXCL, S_IRUSR | S_IWUSR);
if (fd >= 0)
{
/* Successfully created. */
return fd;
}
/* This is a random value. It is only necessary that the next
TMP_MAX values generated by adding 7777 to VALUE are different
with (module 2^32). */
value += 7777;
}
/* Unsuccessful. Free the filename. */
g_free (tmpname);
*pname = NULL;
return -1;
}
/* --------------------------------------------------------------------------------------------- */
/**
* Read and restore position for the given filename.

View File

@ -166,10 +166,6 @@ void canonicalize_pathname (char *);
int my_mkdir (const char *s, mode_t mode);
int my_rmdir (const char *s);
/* Creating temporary files safely */
const char *mc_tmpdir (void);
int mc_mkstemps (char **pname, const char *prefix, const char *suffix);
#ifdef HAVE_REALPATH
#define mc_realpath realpath
#else

View File

@ -324,116 +324,6 @@ tilde_expand (const char *directory)
return g_strconcat (passwd->pw_dir, PATH_SEP_STR, q, (char *) NULL);
}
/* --------------------------------------------------------------------------------------------- */
/**
* Return the directory where mc should keep its temporary files.
* This directory is (in Bourne shell terms) "${TMPDIR=/tmp}/mc-$USER"
* When called the first time, the directory is created if needed.
* The first call should be done early, since we are using fprintf()
* and not message() to report possible problems.
*/
const char *
mc_tmpdir (void)
{
static char buffer[64];
static const char *tmpdir;
const char *sys_tmp;
struct passwd *pwd;
struct stat st;
const char *error = NULL;
/* Check if already correctly initialized */
if (tmpdir && lstat (tmpdir, &st) == 0 && S_ISDIR (st.st_mode) &&
st.st_uid == getuid () && (st.st_mode & 0777) == 0700)
return tmpdir;
sys_tmp = getenv ("TMPDIR");
if (!sys_tmp || sys_tmp[0] != '/')
{
sys_tmp = TMPDIR_DEFAULT;
}
pwd = getpwuid (getuid ());
if (pwd)
g_snprintf (buffer, sizeof (buffer), "%s/mc-%s", sys_tmp, pwd->pw_name);
else
g_snprintf (buffer, sizeof (buffer), "%s/mc-%lu", sys_tmp, (unsigned long) getuid ());
canonicalize_pathname (buffer);
if (lstat (buffer, &st) == 0)
{
/* Sanity check for existing directory */
if (!S_ISDIR (st.st_mode))
error = _("%s is not a directory\n");
else if (st.st_uid != getuid ())
error = _("Directory %s is not owned by you\n");
else if (((st.st_mode & 0777) != 0700) && (chmod (buffer, 0700) != 0))
error = _("Cannot set correct permissions for directory %s\n");
}
else
{
/* Need to create directory */
if (mkdir (buffer, S_IRWXU) != 0)
{
fprintf (stderr,
_("Cannot create temporary directory %s: %s\n"),
buffer, unix_error_string (errno));
error = "";
}
}
if (error != NULL)
{
int test_fd;
char *test_fn, *fallback_prefix;
int fallback_ok = 0;
if (*error)
fprintf (stderr, error, buffer);
/* Test if sys_tmp is suitable for temporary files */
fallback_prefix = g_strdup_printf ("%s/mctest", sys_tmp);
test_fd = mc_mkstemps (&test_fn, fallback_prefix, NULL);
g_free (fallback_prefix);
if (test_fd != -1)
{
close (test_fd);
test_fd = open (test_fn, O_RDONLY);
if (test_fd != -1)
{
close (test_fd);
unlink (test_fn);
fallback_ok = 1;
}
}
if (fallback_ok)
{
fprintf (stderr, _("Temporary files will be created in %s\n"), sys_tmp);
g_snprintf (buffer, sizeof (buffer), "%s", sys_tmp);
error = NULL;
}
else
{
fprintf (stderr, _("Temporary files will not be created\n"));
g_snprintf (buffer, sizeof (buffer), "%s", "/dev/null/");
}
fprintf (stderr, "%s\n", _("Press any key to continue..."));
getc (stdin);
}
tmpdir = buffer;
if (!error)
g_setenv ("MC_TMPDIR", tmpdir, TRUE);
return tmpdir;
}
/* --------------------------------------------------------------------------------------------- */
/**
* Creates a pipe to hold standard error for a later analysis.

View File

@ -45,11 +45,14 @@
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <pwd.h>
#include <grp.h>
#include "lib/global.h"
#include "lib/widget.h" /* message() */
#include "lib/strutil.h" /* str_crt_conv_from() */
#include "lib/util.h"
#include "vfs.h"
#include "utilvfs.h"
@ -746,3 +749,195 @@ mc_lseek (int fd, off_t offset, int whence)
}
/* --------------------------------------------------------------------------------------------- */
/* Following code heavily borrows from libiberty, mkstemps.c */
/*
* Arguments:
* pname (output) - pointer to the name of the temp file (needs g_free).
* NULL if the function fails.
* prefix - part of the filename before the random part.
* Prepend $TMPDIR or /tmp if there are no path separators.
* suffix - if not NULL, part of the filename after the random part.
*
* Result:
* handle of the open file or -1 if couldn't open any.
*/
int
mc_mkstemps (char **pname, const char *prefix, const char *suffix)
{
static const char letters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
static unsigned long value;
struct timeval tv;
char *tmpbase;
char *tmpname;
char *XXXXXX;
int count;
if (strchr (prefix, PATH_SEP) == NULL)
{
/* Add prefix first to find the position of XXXXXX */
tmpbase = g_build_filename (mc_tmpdir (), prefix, NULL);
}
else
{
tmpbase = g_strdup (prefix);
}
tmpname = g_strconcat (tmpbase, "XXXXXX", suffix, (char *) NULL);
*pname = tmpname;
XXXXXX = &tmpname[strlen (tmpbase)];
g_free (tmpbase);
/* Get some more or less random data. */
gettimeofday (&tv, NULL);
value += (tv.tv_usec << 16) ^ tv.tv_sec ^ getpid ();
for (count = 0; count < TMP_MAX; ++count)
{
unsigned long v = value;
int fd;
/* Fill in the random bits. */
XXXXXX[0] = letters[v % 62];
v /= 62;
XXXXXX[1] = letters[v % 62];
v /= 62;
XXXXXX[2] = letters[v % 62];
v /= 62;
XXXXXX[3] = letters[v % 62];
v /= 62;
XXXXXX[4] = letters[v % 62];
v /= 62;
XXXXXX[5] = letters[v % 62];
fd = open (tmpname, O_RDWR | O_CREAT | O_TRUNC | O_EXCL, S_IRUSR | S_IWUSR);
if (fd >= 0)
{
/* Successfully created. */
return fd;
}
/* This is a random value. It is only necessary that the next
TMP_MAX values generated by adding 7777 to VALUE are different
with (module 2^32). */
value += 7777;
}
/* Unsuccessful. Free the filename. */
g_free (tmpname);
*pname = NULL;
return -1;
}
/* --------------------------------------------------------------------------------------------- */
/**
* Return the directory where mc should keep its temporary files.
* This directory is (in Bourne shell terms) "${TMPDIR=/tmp}/mc-$USER"
* When called the first time, the directory is created if needed.
* The first call should be done early, since we are using fprintf()
* and not message() to report possible problems.
*/
const char *
mc_tmpdir (void)
{
static char buffer[64];
static const char *tmpdir;
const char *sys_tmp;
struct passwd *pwd;
struct stat st;
const char *error = NULL;
/* Check if already correctly initialized */
if (tmpdir && lstat (tmpdir, &st) == 0 && S_ISDIR (st.st_mode) &&
st.st_uid == getuid () && (st.st_mode & 0777) == 0700)
return tmpdir;
sys_tmp = getenv ("TMPDIR");
if (!sys_tmp || sys_tmp[0] != '/')
{
sys_tmp = TMPDIR_DEFAULT;
}
pwd = getpwuid (getuid ());
if (pwd)
g_snprintf (buffer, sizeof (buffer), "%s/mc-%s", sys_tmp, pwd->pw_name);
else
g_snprintf (buffer, sizeof (buffer), "%s/mc-%lu", sys_tmp, (unsigned long) getuid ());
canonicalize_pathname (buffer);
if (lstat (buffer, &st) == 0)
{
/* Sanity check for existing directory */
if (!S_ISDIR (st.st_mode))
error = _("%s is not a directory\n");
else if (st.st_uid != getuid ())
error = _("Directory %s is not owned by you\n");
else if (((st.st_mode & 0777) != 0700) && (chmod (buffer, 0700) != 0))
error = _("Cannot set correct permissions for directory %s\n");
}
else
{
/* Need to create directory */
if (mkdir (buffer, S_IRWXU) != 0)
{
fprintf (stderr,
_("Cannot create temporary directory %s: %s\n"),
buffer, unix_error_string (errno));
error = "";
}
}
if (error != NULL)
{
int test_fd;
char *test_fn, *fallback_prefix;
int fallback_ok = 0;
if (*error)
fprintf (stderr, error, buffer);
/* Test if sys_tmp is suitable for temporary files */
fallback_prefix = g_strdup_printf ("%s/mctest", sys_tmp);
test_fd = mc_mkstemps (&test_fn, fallback_prefix, NULL);
g_free (fallback_prefix);
if (test_fd != -1)
{
close (test_fd);
test_fd = open (test_fn, O_RDONLY);
if (test_fd != -1)
{
close (test_fd);
unlink (test_fn);
fallback_ok = 1;
}
}
if (fallback_ok)
{
fprintf (stderr, _("Temporary files will be created in %s\n"), sys_tmp);
g_snprintf (buffer, sizeof (buffer), "%s", sys_tmp);
error = NULL;
}
else
{
fprintf (stderr, _("Temporary files will not be created\n"));
g_snprintf (buffer, sizeof (buffer), "%s", "/dev/null/");
}
fprintf (stderr, "%s\n", _("Press any key to continue..."));
getc (stdin);
}
tmpdir = buffer;
if (!error)
g_setenv ("MC_TMPDIR", tmpdir, TRUE);
return tmpdir;
}
/* --------------------------------------------------------------------------------------------- */

View File

@ -301,6 +301,10 @@ int mc_open (const vfs_path_t * vpath, int flags, ...);
char *mc_get_current_wd (char *buffer, size_t bufsize);
char *mc_getlocalcopy (const char *pathname);
int mc_ungetlocalcopy (const char *pathname, const char *local, int has_changed);
int mc_mkstemps (char **pname, const char *prefix, const char *suffix);
/* Creating temporary files safely */
const char *mc_tmpdir (void);
/*** inline functions ****************************************************************************/