File 3251-file-implement-del_dir_r-1-for-recursive-deletes.patch of Package erlang

From 51269f062091dabd58631822d3145a573ea2d2f8 Mon Sep 17 00:00:00 2001
From: Mikael Pettersson <mikpelinux@gmail.com>
Date: Mon, 23 Mar 2020 18:16:10 +0100
Subject: [PATCH] file: implement del_dir_r/1 for recursive deletes file_SUITE:
 add basic tests of file:del_dir_r/1 file_SUITE: use file:del_dir_r/1 instead
 of local rm_rf/2 file.xml: add documentation for file:del_dir_r/1

---
 lib/kernel/doc/src/file.xml    | 22 +++++++++++++++++
 lib/kernel/src/file.erl        | 21 +++++++++++++++-
 lib/kernel/test/file_SUITE.erl | 56 ++++++++++++++++++++++++++++--------------
 3 files changed, 80 insertions(+), 19 deletions(-)

diff --git a/lib/kernel/doc/src/file.xml b/lib/kernel/doc/src/file.xml
index c4073f13a2..e1191ced52 100644
--- a/lib/kernel/doc/src/file.xml
+++ b/lib/kernel/doc/src/file.xml
@@ -401,6 +401,28 @@ f.txt:  {person, "kalle", 25}.
         </taglist>
       </desc>
     </func>
+    <func>
+      <name name="del_dir_r" arity="1"/>
+      <fsummary>Delete a file or directory.</fsummary>
+      <desc>
+        <p>Deletes file or directory <c><anno>File</anno></c>.
+          If <c><anno>File</anno></c> is a directory, its contents
+          is first recursively deleted.  Returns:</p>
+        <taglist>
+          <tag><c>ok</c></tag>
+          <item>
+            <p>The operation completed without errors.</p>
+          </item>
+          <tag><c>{error, posix()}</c></tag>
+          <item>
+            <p>An error occurred when accessing or deleting <c><anno>File</anno></c>.
+             If some file or directory under <c><anno>File</anno></c> could not be
+             deleted, <c><anno>File</anno></c> cannot be deleted as it is non-empty,
+             and <c>{error, eexist}</c> is returned.</p>
+          </item>
+        </taglist>
+      </desc>
+    </func>
     <func>
       <name name="delete" arity="1"/>
       <fsummary>Delete a file.</fsummary>
diff --git a/lib/kernel/src/file.erl b/lib/kernel/src/file.erl
index cde03ce1c4..8abfb3ef35 100644
--- a/lib/kernel/src/file.erl
+++ b/lib/kernel/src/file.erl
@@ -28,7 +28,7 @@
 -export([format_error/1]).
 %% File system and metadata.
 -export([get_cwd/0, get_cwd/1, set_cwd/1, delete/1, rename/2,
-	 make_dir/1, del_dir/1, list_dir/1, list_dir_all/1,
+	 make_dir/1, del_dir/1, del_dir_r/1, list_dir/1, list_dir_all/1,
 	 read_file_info/1, read_file_info/2,
 	 write_file_info/2, write_file_info/3,
 	 altname/1,
@@ -239,6 +239,25 @@ make_dir(Name) ->
 del_dir(Name) ->
     check_and_call(del_dir, [file_name(Name)]).
 
+-spec del_dir_r(File) -> ok | {error, Reason} when
+      File :: name_all(),
+      Reason :: posix() | badarg.
+
+del_dir_r(File) -> % rm -rf File
+    case read_link_info(File) of
+	{ok, #file_info{type = directory}} ->
+	    case list_dir_all(File) of
+		{ok, Names} ->
+		    lists:foreach(fun(Name) ->
+				      del_dir_r(filename:join(File, Name))
+				  end, Names);
+		{error, _Reason} -> ok
+	    end,
+	    del_dir(File);
+	{ok, _FileInfo} -> delete(File);
+	{error, _Reason} = Error -> Error
+    end.
+
 -spec read_file_info(Filename) -> {ok, FileInfo} | {error, Reason} when
       Filename :: name_all(),
       FileInfo :: file_info(),
diff --git a/lib/kernel/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl
index a73c5e9753..52ef711008 100644
--- a/lib/kernel/test/file_SUITE.erl
+++ b/lib/kernel/test/file_SUITE.erl
@@ -47,7 +47,7 @@
 	 init_per_group/2,end_per_group/2,
 	 init_per_testcase/2, end_per_testcase/2,
 	 read_write_file/1, names/1]).
--export([cur_dir_0/1, cur_dir_1/1, make_del_dir/1,
+-export([cur_dir_0/1, cur_dir_1/1, make_del_dir/1, make_del_dir_r/1,
 	 list_dir/1,list_dir_error/1,
 	 untranslatable_names/1, untranslatable_names_error/1,
 	 pos1/1, pos2/1, pos3/1]).
@@ -143,7 +143,7 @@ all() ->
     ].
 
 groups() -> 
-    [{dirs, [], [make_del_dir, cur_dir_0, cur_dir_1,
+    [{dirs, [], [make_del_dir, make_del_dir_r, cur_dir_0, cur_dir_1,
 		 list_dir, list_dir_error, untranslatable_names,
 		 untranslatable_names_error]},
      {files, [],
@@ -637,6 +637,41 @@ make_del_dir(Config) when is_list(Config) ->
     end,
     ok.
 
+make_del_dir_r(Config) when is_list(Config) ->
+    RootDir = proplists:get_value(priv_dir, Config),
+    NewDir = filename:join(RootDir, ?MODULE_STRING ++ "_make_del_dir_r"),
+    ok = ?FILE_MODULE:make_dir(NewDir),
+
+    %% Create:
+    %% newdir/
+    %%     file1
+    %%     dir/
+    %%         file2
+    %%         link -> /newdir/file1
+    File1 = test_server:temp_name(filename:join(NewDir, "file1")),
+    ok = ?FILE_MODULE:write_file(File1, <<"file1">>),
+    Dir = test_server:temp_name(filename:join(NewDir, "dir")),
+    ok = ?FILE_MODULE:make_dir(Dir),
+    File2 = test_server:temp_name(filename:join(Dir, "file2")),
+    ok = ?FILE_MODULE:write_file(File2, <<"file2">>),
+    Link = test_server:temp_name(filename:join(Dir, "link")),
+    case ?FILE_MODULE:make_symlink(File1, Link) of
+        {error, enotsup} -> ok; % symlinks not supported
+        {error, eperm} -> {win32, _} = os:type(), ok; % not allowed to make symlinks
+        ok -> ok
+    end,
+
+    %% check that del_dir_r/1 succeeds on non-empty dir
+    ok = ?FILE_MODULE:del_dir_r(Dir),
+    {error, enoent} = ?FILE_MODULE:read_file_info(Dir),
+    %% check that the symlink wasn't followed
+    {ok, _} = ?FILE_MODULE:read_file_info(File1),
+
+    %% clean up
+    ?FILE_MODULE:del_dir_r(NewDir),
+    [] = flush(),
+    ok.
+
 cur_dir_0(Config) when is_list(Config) ->
     %% Find out the current dir, and cd to it ;-)
     {ok,BaseDir} = ?FILE_MODULE:get_cwd(),
@@ -3093,7 +3128,7 @@ symlinks(Config) when is_list(Config) ->
 		{ok, Name} = ?FILE_MODULE:read_link(Alias),
 		{ok, Name} = ?FILE_MODULE:read_link_all(Alias),
 		%% If all is good, delete dir again (avoid hanging dir on windows)
-		rm_rf(?FILE_MODULE,NewDir),
+		file:del_dir_r(NewDir),
 		ok
 	end,
 
@@ -4799,18 +4834,3 @@ disc_free(Path) ->
 memsize() ->
     {Tot,_Used,_}  = memsup:get_memory_data(),
     Tot.
-
-%%%-----------------------------------------------------------------
-%%% Utilities
-rm_rf(Mod,Dir) ->
-    case  Mod:read_link_info(Dir) of
-	{ok, #file_info{type = directory}} ->
-	    {ok, Content} = Mod:list_dir_all(Dir),
-	    [ rm_rf(Mod,filename:join(Dir,C)) || C <- Content ],
-	    Mod:del_dir(Dir),
-	    ok;
-	{ok, #file_info{}} ->
-	    Mod:delete(Dir);
-	_ ->
-	    ok
-    end.
-- 
2.16.4

openSUSE Build Service is sponsored by