/*
* 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);
}
/*
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;
}
/* 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;
}
out:
qobject_unref(snapshot_options);
- g_free(tmp_filename);
return bs_snapshot;
}
read 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
Testing: -drive driver=null-co,snapshot=on
-QEMU_PROG: -drive driver=null-co,snapshot=on: Could not get temporary filename: No such file or directory
+QEMU_PROG: -drive driver=null-co,snapshot=on: Could not open temporary file SNAPSHOT_PATH: No such file or directory
Testing: -drive file=TEST_DIR/t.qcow2,snapshot=on,read-only=on,if=none,id=drive0
QEMU X.Y.Z monitor - type 'help' for more information
read 4096/4096 bytes at offset 0
4 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
Testing: -drive driver=null-co,snapshot=on
-QEMU_PROG: -drive driver=null-co,snapshot=on: Could not get temporary filename: No such file or directory
+QEMU_PROG: -drive driver=null-co,snapshot=on: Could not open temporary file SNAPSHOT_PATH: No such file or directory
Testing: -drive file=TEST_DIR/t.qcow2,snapshot=on,read-only=on,if=none,id=drive0
QEMU X.Y.Z monitor - type 'help' for more information