File 1083-Test-option-root_dir.patch of Package erlang

From 2479feddd1fcc5270c3af109ebbd817350f8f493 Mon Sep 17 00:00:00 2001
From: Raimo Niskanen <raimo@erlang.org>
Date: Wed, 11 Feb 2026 18:38:20 +0100
Subject: [PATCH 3/5] Test option root_dir

---
 lib/tftp/test/tftp_SUITE.erl    | 109 +++++++++++++++++++++++++++-----
 lib/tftp/test/tftp_test_lib.hrl |   5 +-
 2 files changed, 95 insertions(+), 19 deletions(-)

diff --git a/lib/tftp/test/tftp_SUITE.erl b/lib/tftp/test/tftp_SUITE.erl
index 35582a4388..a84d608bd7 100644
--- a/lib/tftp/test/tftp_SUITE.erl
+++ b/lib/tftp/test/tftp_SUITE.erl
@@ -20,7 +20,7 @@
 
 -module(tftp_SUITE).
 
--compile(export_all).
+-compile([export_all, nowarn_export_all]).
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %% Includes and defines
@@ -29,18 +29,13 @@
 -include_lib("common_test/include/ct.hrl").
 -include("tftp_test_lib.hrl").
 
--define(START_DAEMON(Port, Options),
+-define(START_DAEMON(Options),
         begin
-            {ok, Pid} = ?VERIFY({ok, _Pid}, tftp:start([{port, Port} | Options])),
-            if
-                Port == 0 ->
-                    {ok, ActualOptions} = ?IGNORE(tftp:info(Pid)),
-                    {value, {port, ActualPort}} =
-                        lists:keysearch(port, 1, ActualOptions),
-                    {ActualPort, Pid};
-                true ->
-                    {Port, Pid}
-            end
+            {ok, Pid} = ?VERIFY({ok, _Pid}, tftp:start([{port, 0} | Options])),
+            {ok, ActualOptions} = ?IGNORE(tftp:info(Pid)),
+            {value, {port, ActualPort}} =
+                lists:keysearch(port, 1, ActualOptions),
+            {ActualPort, Pid}
         end).
 
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -78,6 +73,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
 all() ->
     [
      simple,
+     root_dir,
      extra,
      reuse_connection,
      resend_client,
@@ -157,7 +153,7 @@ simple(suite) ->
 simple(Config) when is_list(Config) ->
     ?VERIFY(ok, application:start(tftp)),
 
-    {Port, DaemonPid} = ?IGNORE(?START_DAEMON(0, [{debug, brief}])),
+    {Port, DaemonPid} = ?IGNORE(?START_DAEMON([{debug, brief}])),
 
     %% Read fail
     RemoteFilename = "tftp_temporary_remote_test_file.txt",
@@ -183,6 +179,73 @@ simple(Config) when is_list(Config) ->
     ?VERIFY(ok, application:stop(tftp)),
     ok.
 
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% root_dir
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+root_dir(doc) ->
+    ["Start the daemon and check the root_dir option."];
+root_dir(suite) ->
+    [];
+root_dir(Config) when is_list(Config) ->
+    ?VERIFY(ok, application:start(tftp)),
+    PrivDir = get_conf(priv_dir, Config),
+    Root    = hd(filename:split(PrivDir)),
+    Up      = "..",
+    Remote  = "remote.txt",
+    Local   = "tftp_temporary_local_test_file.txt",
+    SideDir = fn_jn(PrivDir,tftp_side),
+    RootDir = fn_jn(PrivDir,tftp_root),
+    ?IGNORE(file:del_dir_r(RootDir)),
+    ?IGNORE(file:del_dir_r(SideDir)),
+    ok = filelib:ensure_path(fn_jn(RootDir,sub)),
+    ok = filelib:ensure_path(SideDir),
+    Blob = binary:copy(<<$1>>, 2000),
+    Size = byte_size(Blob),
+    ok = file:write_file(fn_jn(SideDir,Remote), Blob),
+    {Port, DaemonPid} =
+        ?IGNORE(?START_DAEMON([{debug, brief},
+                               {callback,
+                                {"", tftp_file, [{root_dir, RootDir}]}}])),
+    try
+        %% Outside root_dir
+        ?VERIFY({error, {client_open, badop, _}},
+                 tftp:read_file(
+                   fn_jn([Up,tftp_side,Remote]), binary, [{port, Port}])),
+        ?VERIFY({error, {client_open, badop, _}},
+                tftp:write_file(
+                  fn_jn([Up,tftp_side,Remote]), Blob, [{port, Port}])),
+        %% Nonexistent
+        ?VERIFY({error, {client_open, enoent, _}},
+                 tftp:read_file(
+                   fn_jn(sub,Remote), binary, [{port, Port}])),
+        ?VERIFY({error, {client_open, enoent, _}},
+                tftp:write_file(
+                  fn_jn(nonexistent,Remote), Blob, [{port, Port}])),
+        %% Write and read
+        ?VERIFY({ok, Size},
+                tftp:write_file(
+                  fn_jn(sub,Remote), Blob, [{port, Port}])),
+        ?VERIFY({ok, Blob},
+                tftp:read_file(
+                  fn_jn([Root,sub,Remote]), binary, [{port, Port}])),
+        ?VERIFY({ok, Size},
+                tftp:read_file(
+                  fn_jn(sub,Remote), Local, [{port, Port}])),
+        ?VERIFY({ok, Blob}, file:read_file(Local)),
+        ?VERIFY(ok, file:delete(Local)),
+        ?VERIFY(ok, application:stop(tftp))
+    after
+        %% Cleanup
+        unlink(DaemonPid),
+        exit(DaemonPid, kill),
+        ?IGNORE(file:del_dir_r(SideDir)),
+        ?IGNORE(file:del_dir_r(RootDir)),
+        ?IGNORE(application:stop(tftp))
+    end,
+    ok.
+
+
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %% Extra
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -195,7 +258,7 @@ extra(Config) when is_list(Config) ->
     ?VERIFY({'EXIT', {badarg,{fake_key, fake_flag}}},
             tftp:start([{port, 0}, {fake_key, fake_flag}])),
 
-    {Port, DaemonPid} = ?IGNORE(?START_DAEMON(0, [{debug, brief}])),
+    {Port, DaemonPid} = ?IGNORE(?START_DAEMON([{debug, brief}])),
     
     RemoteFilename = "tftp_extra_temporary_remote_test_file.txt",
     LocalFilename = "tftp_extra_temporary_local_test_file.txt",
@@ -329,7 +392,7 @@ resend_client(suite) ->
     [];
 resend_client(Config) when is_list(Config) ->
     Host = {127, 0, 0, 1},
-    {Port, DaemonPid} = ?IGNORE(?START_DAEMON(0, [{debug, all}])),
+    {Port, DaemonPid} = ?IGNORE(?START_DAEMON([{debug, all}])),
 
     ?VERIFY(ok, resend_read_client(Host, Port, 10)),
     ?VERIFY(ok, resend_read_client(Host, Port, 512)),
@@ -890,7 +953,7 @@ reuse_connection(suite) ->
     [];
 reuse_connection(Config) when is_list(Config) ->
     Host = {127, 0, 0, 1},
-    {Port, DaemonPid} = ?IGNORE(?START_DAEMON(0, [{debug, all}])),
+    {Port, DaemonPid} = ?IGNORE(?START_DAEMON([{debug, all}])),
 
     RemoteFilename = "reuse_connection.tmp",
     BlkSize = 512,
@@ -964,7 +1027,7 @@ large_file(suite) ->
 large_file(Config) when is_list(Config) ->
     ?VERIFY(ok, application:start(tftp)),
 
-    {Port, DaemonPid} = ?IGNORE(?START_DAEMON(0, [{debug, brief}])),
+    {Port, DaemonPid} = ?IGNORE(?START_DAEMON([{debug, brief}])),
 
     %% Read fail
     RemoteFilename = "tftp_temporary_large_file_remote_test_file.txt",
@@ -999,3 +1062,15 @@ recv(Timeout) ->
     after Timeout ->
             timeout
     end.
+
+get_conf(Key, Config) ->
+    Default = make_ref(),
+    case proplists:get_value(Key, Config, Default) of
+        Default ->
+            erlang:error({no_key, Key});
+        Value ->
+            Value
+    end.
+
+fn_jn(A, B) -> filename:join(A, B).
+fn_jn(P) -> filename:join(P).
diff --git a/lib/tftp/test/tftp_test_lib.hrl b/lib/tftp/test/tftp_test_lib.hrl
index eb8ed77fc1..9c07a53280 100644
--- a/lib/tftp/test/tftp_test_lib.hrl
+++ b/lib/tftp/test/tftp_test_lib.hrl
@@ -1,7 +1,7 @@
 %%
 %% %CopyrightBegin%
 %% 
-%% Copyright Ericsson AB 2007-2018. All Rights Reserved.
+%% Copyright Ericsson AB 2007-2025. All Rights Reserved.
 %% 
 %% Licensed under the Apache License, Version 2.0 (the "License");
 %% you may not use this file except in compliance with the License.
@@ -24,7 +24,8 @@
 	tftp_test_lib:log(Format, Args, ?MODULE, ?LINE)).
 
 -define(ERROR(Reason),
-	tftp_test_lib:error(Reason, ?MODULE, ?LINE)).
+        erlang:error({?MODULE,?LINE,?FUNCTION_NAME,(Reason)})).
+	%% tftp_test_lib:error(Reason, ?MODULE, ?LINE)).
 
 -define(VERIFY(Expected, Expr),
 	fun() ->
-- 
2.51.0

openSUSE Build Service is sponsored by