|
@@ -861,35 +861,42 @@ int bdrv_probe_geometry(BlockDriverState *bs, HDGeometry *geo)
|
|
|
|
|
|
/*
|
|
|
* Create a uniquely-named empty temporary file.
|
|
|
- * Return 0 upon success, otherwise a negative errno value.
|
|
|
+ * Return the actual file name used upon success, otherwise NULL.
|
|
|
+ * This string should be freed with g_free() when not needed any longer.
|
|
|
+ *
|
|
|
+ * Note: creating a temporary file for the caller to (re)open is
|
|
|
+ * inherently racy. Use g_file_open_tmp() instead whenever practical.
|
|
|
*/
|
|
|
-int get_tmp_filename(char *filename, int size)
|
|
|
+char *create_tmp_file(Error **errp)
|
|
|
{
|
|
|
-#ifdef _WIN32
|
|
|
- char temp_dir[MAX_PATH];
|
|
|
- /* GetTempFileName requires that its output buffer (4th param)
|
|
|
- have length MAX_PATH or greater. */
|
|
|
- assert(size >= MAX_PATH);
|
|
|
- return (GetTempPath(MAX_PATH, temp_dir)
|
|
|
- && GetTempFileName(temp_dir, "qem", 0, filename)
|
|
|
- ? 0 : -GetLastError());
|
|
|
-#else
|
|
|
int fd;
|
|
|
const char *tmpdir;
|
|
|
- tmpdir = getenv("TMPDIR");
|
|
|
- if (!tmpdir) {
|
|
|
+ g_autofree char *filename = NULL;
|
|
|
+
|
|
|
+ tmpdir = g_get_tmp_dir();
|
|
|
+#ifndef _WIN32
|
|
|
+ /*
|
|
|
+ * See commit 69bef79 ("block: use /var/tmp instead of /tmp for -snapshot")
|
|
|
+ *
|
|
|
+ * This function is used to create temporary disk images (like -snapshot),
|
|
|
+ * so the files can become very large. /tmp is often a tmpfs where as
|
|
|
+ * /var/tmp is usually on a disk, so more appropriate for disk images.
|
|
|
+ */
|
|
|
+ if (!g_strcmp0(tmpdir, "/tmp")) {
|
|
|
tmpdir = "/var/tmp";
|
|
|
}
|
|
|
- if (snprintf(filename, size, "%s/vl.XXXXXX", tmpdir) >= size) {
|
|
|
- return -EOVERFLOW;
|
|
|
- }
|
|
|
- fd = mkstemp(filename);
|
|
|
+#endif
|
|
|
+
|
|
|
+ filename = g_strdup_printf("%s/vl.XXXXXX", tmpdir);
|
|
|
+ fd = g_mkstemp(filename);
|
|
|
if (fd < 0) {
|
|
|
- return -errno;
|
|
|
+ error_setg_errno(errp, errno, "Could not open temporary file '%s'",
|
|
|
+ filename);
|
|
|
+ return NULL;
|
|
|
}
|
|
|
close(fd);
|
|
|
- return 0;
|
|
|
-#endif
|
|
|
+
|
|
|
+ return g_steal_pointer(&filename);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -3715,8 +3722,7 @@ static BlockDriverState *bdrv_append_temp_snapshot(BlockDriverState *bs,
|
|
|
QDict *snapshot_options,
|
|
|
Error **errp)
|
|
|
{
|
|
|
- /* TODO: extra byte is a hack to ensure MAX_PATH space on Windows. */
|
|
|
- char *tmp_filename = g_malloc0(PATH_MAX + 1);
|
|
|
+ g_autofree char *tmp_filename = NULL;
|
|
|
int64_t total_size;
|
|
|
QemuOpts *opts = NULL;
|
|
|
BlockDriverState *bs_snapshot = NULL;
|
|
@@ -3735,9 +3741,8 @@ static BlockDriverState *bdrv_append_temp_snapshot(BlockDriverState *bs,
|
|
|
}
|
|
|
|
|
|
/* Create the temporary image */
|
|
|
- ret = get_tmp_filename(tmp_filename, PATH_MAX + 1);
|
|
|
- if (ret < 0) {
|
|
|
- error_setg_errno(errp, -ret, "Could not get temporary filename");
|
|
|
+ tmp_filename = create_tmp_file(errp);
|
|
|
+ if (!tmp_filename) {
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
@@ -3771,7 +3776,6 @@ static BlockDriverState *bdrv_append_temp_snapshot(BlockDriverState *bs,
|
|
|
|
|
|
out:
|
|
|
qobject_unref(snapshot_options);
|
|
|
- g_free(tmp_filename);
|
|
|
return bs_snapshot;
|
|
|
}
|
|
|
|