diff --git a/Userland/Utilities/CMakeLists.txt b/Userland/Utilities/CMakeLists.txt index 81b5d61b9e..f6c490f644 100644 --- a/Userland/Utilities/CMakeLists.txt +++ b/Userland/Utilities/CMakeLists.txt @@ -116,6 +116,7 @@ target_link_libraries(man PRIVATE LibMarkdown LibManual) target_link_libraries(markdown-check PRIVATE LibFileSystem LibMarkdown) target_link_libraries(matroska PRIVATE LibVideo) target_link_libraries(md PRIVATE LibMarkdown) +target_link_libraries(mktemp PRIVATE LibFileSystem) target_link_libraries(mv PRIVATE LibFileSystem) target_link_libraries(network-settings PRIVATE LibCore LibMain) target_link_libraries(notify PRIVATE LibGfx LibGUI) diff --git a/Userland/Utilities/mktemp.cpp b/Userland/Utilities/mktemp.cpp index 27facf93c7..9d3d17252f 100644 --- a/Userland/Utilities/mktemp.cpp +++ b/Userland/Utilities/mktemp.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2021, Idan Horowitz + * Copyright (c) 2023, Cameron Youell * * SPDX-License-Identifier: BSD-2-Clause */ @@ -8,13 +9,12 @@ #include #include #include +#include #include #include #include #include -constexpr StringView default_template = "tmp.XXXXXXXXXX"sv; - static DeprecatedString generate_random_filename(DeprecatedString const& pattern) { StringBuilder new_filename { pattern.length() }; @@ -71,28 +71,33 @@ ErrorOr serenity_main(Main::Arguments arguments) args_parser.add_option(target_directory, "Create TEMPLATE relative to DIR", "tmpdir", 'p', "DIR"); args_parser.parse(arguments); + Optional final_file_template; + Optional final_target_directory; + if (target_directory.is_empty()) { - if (!file_template.is_empty()) { // If a custom template is specified we assume the target directory is the current directory - // FIXME: Get rid of this minor memory leak. - auto const* cwd_ptr = getcwd(nullptr, 0); - target_directory = StringView { cwd_ptr, strlen(cwd_ptr) }; + if (!file_template.is_empty()) { + auto resolved_path = LexicalPath(TRY(FileSystem::absolute_path(file_template)).to_deprecated_string()); + final_target_directory = TRY(String::from_utf8(resolved_path.dirname())); + final_file_template = TRY(String::from_utf8(resolved_path.basename())); } else { - char const* env_directory = getenv("TMPDIR"); - target_directory = env_directory && *env_directory ? StringView { env_directory, strlen(env_directory) } : "/tmp"sv; + final_target_directory = "/tmp"_short_string; + auto const* env_directory = getenv("TMPDIR"); + if (env_directory != nullptr && *env_directory != 0) + final_target_directory = TRY(String::from_utf8({ env_directory, strlen(env_directory) })); } } - if (file_template.is_empty()) { - file_template = default_template; + if (!final_file_template.has_value()) { + final_file_template = TRY("tmp.XXXXXXXXXX"_string); } - if (!file_template.find("XXX"sv).has_value()) { + if (!final_file_template->find_byte_offset("XXX"sv).has_value()) { if (!quiet) - warnln("Too few X's in template {}", file_template); + warnln("Too few X's in template {}", final_file_template); return 1; } - auto target_path = LexicalPath::join(target_directory, file_template).string(); + auto target_path = LexicalPath::join(final_target_directory->to_deprecated_string(), final_file_template->to_deprecated_string()).string(); auto final_path = TRY(make_temp(target_path, create_directory, dry_run)); if (final_path.is_null()) {