public inbox for libstdc++-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/users/aoliva/heads/testme)] libstdc++: retry removal of dir entries if dir removal fails
@ 2022-06-27 13:35 Alexandre Oliva
0 siblings, 0 replies; 12+ messages in thread
From: Alexandre Oliva @ 2022-06-27 13:35 UTC (permalink / raw)
To: gcc-cvs, libstdc++-cvs
https://gcc.gnu.org/g:b48f65918a6797ce8024d19412762b742d875405
commit b48f65918a6797ce8024d19412762b742d875405
Author: Alexandre Oliva <oliva@adacore.com>
Date: Mon Jun 27 05:30:54 2022 -0300
libstdc++: retry removal of dir entries if dir removal fails
On some target systems (e.g. rtems6.0), removing directory components
while iterating over directory entries may cause some of the directory
entries to be skipped, which prevents the removal of the parent
directory from succeeding.
Advancing the iterator before removing a member proved not to be
enough, so I've instead arranged for remove_all to retry the removal
of components if the removal of the parent dir fails after removing at
least one entry. The fail will be permanent only if no components got
removed in the current try.
for libstdc++-v3/ChangeLog
* src/c++17/fs_ops.cc (remove_all): Retry removal of
directory entries.
Diff:
---
libstdc++-v3/src/c++17/fs_ops.cc | 40 ++++++++++++++++++++++++++++++++++++----
1 file changed, 36 insertions(+), 4 deletions(-)
diff --git a/libstdc++-v3/src/c++17/fs_ops.cc b/libstdc++-v3/src/c++17/fs_ops.cc
index 435368fa5c5..de99e02af4c 100644
--- a/libstdc++-v3/src/c++17/fs_ops.cc
+++ b/libstdc++-v3/src/c++17/fs_ops.cc
@@ -1286,6 +1286,8 @@ fs::remove_all(const path& p)
{
error_code ec;
uintmax_t count = 0;
+ retry:
+ uintmax_t init_count = count;
recursive_directory_iterator dir(p, directory_options{64|128}, ec);
switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
{
@@ -1295,7 +1297,16 @@ fs::remove_all(const path& p)
const recursive_directory_iterator end;
while (dir != end)
{
- dir.__erase(); // throws on error
+ /* Avoid exceptions if we may retry on fail on systems that
+ miss dir entries when removing while iterating. */
+ if (count > init_count)
+ {
+ dir.__erase(&ec);
+ if (ec)
+ goto retry;
+ }
+ else
+ dir.__erase(); // throws on error
++count;
}
}
@@ -1303,7 +1314,7 @@ fs::remove_all(const path& p)
break;
case ENOENT:
// Our work here is done.
- return 0;
+ return count;
case ENOTDIR:
case ELOOP:
// Not a directory, will remove below.
@@ -1313,6 +1324,18 @@ fs::remove_all(const path& p)
_GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot remove all", p, ec));
}
+ if (count > init_count)
+ {
+ if (int last = fs::remove(p, ec); !ec)
+ return count + last;
+ else
+ // Some systems seem to skip entries in the dir iteration if
+ // you remove dir entries while iterating, so if we removed
+ // anything in the dir in this round, and failed to remove
+ // the dir (presumably because it wasn't empty), retry.
+ goto retry;
+ }
+
// Remove p itself, which is either a non-directory or is now empty.
return count + fs::remove(p);
}
@@ -1321,6 +1344,8 @@ std::uintmax_t
fs::remove_all(const path& p, error_code& ec)
{
uintmax_t count = 0;
+ retry:
+ uintmax_t init_count = count;
recursive_directory_iterator dir(p, directory_options{64|128}, ec);
switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
{
@@ -1332,7 +1357,12 @@ fs::remove_all(const path& p, error_code& ec)
{
dir.__erase(&ec);
if (ec)
- return -1;
+ {
+ if (count > init_count)
+ goto retry;
+ else
+ return -1;
+ }
++count;
}
}
@@ -1341,7 +1371,7 @@ fs::remove_all(const path& p, error_code& ec)
case ENOENT:
// Our work here is done.
ec.clear();
- return 0;
+ return count;
case ENOTDIR:
case ELOOP:
// Not a directory, will remove below.
@@ -1354,6 +1384,8 @@ fs::remove_all(const path& p, error_code& ec)
// Remove p itself, which is either a non-directory or is now empty.
if (int last = fs::remove(p, ec); !ec)
return count + last;
+ if (count > init_count)
+ goto retry;
return -1;
}
^ permalink raw reply [flat|nested] 12+ messages in thread
* [gcc(refs/users/aoliva/heads/testme)] libstdc++: retry removal of dir entries if dir removal fails
@ 2022-06-27 15:45 Alexandre Oliva
0 siblings, 0 replies; 12+ messages in thread
From: Alexandre Oliva @ 2022-06-27 15:45 UTC (permalink / raw)
To: gcc-cvs, libstdc++-cvs
https://gcc.gnu.org/g:537383dad7f2115821ab9a12059a4840089bd855
commit 537383dad7f2115821ab9a12059a4840089bd855
Author: Alexandre Oliva <oliva@adacore.com>
Date: Mon Jun 27 12:07:19 2022 -0300
libstdc++: retry removal of dir entries if dir removal fails
On some target systems (e.g. rtems6.0), removing directory components
while iterating over directory entries may cause some of the directory
entries to be skipped, which prevents the removal of the parent
directory from succeeding.
Advancing the iterator before removing a member proved not to be
enough, so I've instead arranged for remove_all to retry the removal
of components if the removal of the parent dir fails after removing at
least one entry. The fail will be permanent only if no components got
removed in the current try.
for libstdc++-v3/ChangeLog
* src/c++17/fs_ops.cc (remove_all): Retry removal of
directory entries.
Diff:
---
libstdc++-v3/src/c++17/fs_ops.cc | 40 ++++++++++++++++++++++++++++++++++++----
1 file changed, 36 insertions(+), 4 deletions(-)
diff --git a/libstdc++-v3/src/c++17/fs_ops.cc b/libstdc++-v3/src/c++17/fs_ops.cc
index 435368fa5c5..de99e02af4c 100644
--- a/libstdc++-v3/src/c++17/fs_ops.cc
+++ b/libstdc++-v3/src/c++17/fs_ops.cc
@@ -1286,6 +1286,8 @@ fs::remove_all(const path& p)
{
error_code ec;
uintmax_t count = 0;
+ retry:
+ uintmax_t init_count = count;
recursive_directory_iterator dir(p, directory_options{64|128}, ec);
switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
{
@@ -1295,7 +1297,16 @@ fs::remove_all(const path& p)
const recursive_directory_iterator end;
while (dir != end)
{
- dir.__erase(); // throws on error
+ /* Avoid exceptions if we may retry on fail on systems that
+ miss dir entries when removing while iterating. */
+ if (count > init_count)
+ {
+ dir.__erase(&ec);
+ if (ec)
+ goto retry;
+ }
+ else
+ dir.__erase(); // throws on error
++count;
}
}
@@ -1303,7 +1314,7 @@ fs::remove_all(const path& p)
break;
case ENOENT:
// Our work here is done.
- return 0;
+ return count;
case ENOTDIR:
case ELOOP:
// Not a directory, will remove below.
@@ -1313,6 +1324,18 @@ fs::remove_all(const path& p)
_GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot remove all", p, ec));
}
+ if (count > init_count)
+ {
+ if (int last = fs::remove(p, ec); !ec)
+ return count + last;
+ else
+ // Some systems seem to skip entries in the dir iteration if
+ // you remove dir entries while iterating, so if we removed
+ // anything in the dir in this round, and failed to remove
+ // the dir (presumably because it wasn't empty), retry.
+ goto retry;
+ }
+
// Remove p itself, which is either a non-directory or is now empty.
return count + fs::remove(p);
}
@@ -1321,6 +1344,8 @@ std::uintmax_t
fs::remove_all(const path& p, error_code& ec)
{
uintmax_t count = 0;
+ retry:
+ uintmax_t init_count = count;
recursive_directory_iterator dir(p, directory_options{64|128}, ec);
switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
{
@@ -1332,7 +1357,12 @@ fs::remove_all(const path& p, error_code& ec)
{
dir.__erase(&ec);
if (ec)
- return -1;
+ {
+ if (count > init_count)
+ goto retry;
+ else
+ return -1;
+ }
++count;
}
}
@@ -1341,7 +1371,7 @@ fs::remove_all(const path& p, error_code& ec)
case ENOENT:
// Our work here is done.
ec.clear();
- return 0;
+ return count;
case ENOTDIR:
case ELOOP:
// Not a directory, will remove below.
@@ -1354,6 +1384,8 @@ fs::remove_all(const path& p, error_code& ec)
// Remove p itself, which is either a non-directory or is now empty.
if (int last = fs::remove(p, ec); !ec)
return count + last;
+ if (count > init_count)
+ goto retry;
return -1;
}
^ permalink raw reply [flat|nested] 12+ messages in thread
* [gcc(refs/users/aoliva/heads/testme)] libstdc++: retry removal of dir entries if dir removal fails
@ 2022-06-27 10:51 Alexandre Oliva
0 siblings, 0 replies; 12+ messages in thread
From: Alexandre Oliva @ 2022-06-27 10:51 UTC (permalink / raw)
To: gcc-cvs, libstdc++-cvs
https://gcc.gnu.org/g:28bd1631e2cd6c26f2de966e96d54b46fe2dc296
commit 28bd1631e2cd6c26f2de966e96d54b46fe2dc296
Author: Alexandre Oliva <oliva@adacore.com>
Date: Mon Jun 27 05:30:54 2022 -0300
libstdc++: retry removal of dir entries if dir removal fails
On some target systems (e.g. rtems6.0), removing directory components
while iterating over directory entries may cause some of the directory
entries to be skipped, which prevents the removal of the parent
directory from succeeding.
Advancing the iterator before removing a member proved not to be
enough, so I've instead arranged for remove_all to retry the removal
of components if the removal of the parent dir fails after removing at
least one entry. The fail will be permanent only if no components got
removed in the current try.
for libstdc++-v3/ChangeLog
* src/c++17/fs_ops.cc (remove_all): Retry removal of
directory entries.
Diff:
---
libstdc++-v3/src/c++17/fs_ops.cc | 40 ++++++++++++++++++++++++++++++++++++----
1 file changed, 36 insertions(+), 4 deletions(-)
diff --git a/libstdc++-v3/src/c++17/fs_ops.cc b/libstdc++-v3/src/c++17/fs_ops.cc
index 435368fa5c5..de99e02af4c 100644
--- a/libstdc++-v3/src/c++17/fs_ops.cc
+++ b/libstdc++-v3/src/c++17/fs_ops.cc
@@ -1286,6 +1286,8 @@ fs::remove_all(const path& p)
{
error_code ec;
uintmax_t count = 0;
+ retry:
+ uintmax_t init_count = count;
recursive_directory_iterator dir(p, directory_options{64|128}, ec);
switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
{
@@ -1295,7 +1297,16 @@ fs::remove_all(const path& p)
const recursive_directory_iterator end;
while (dir != end)
{
- dir.__erase(); // throws on error
+ /* Avoid exceptions if we may retry on fail on systems that
+ miss dir entries when removing while iterating. */
+ if (count > init_count)
+ {
+ dir.__erase(&ec);
+ if (ec)
+ goto retry;
+ }
+ else
+ dir.__erase(); // throws on error
++count;
}
}
@@ -1303,7 +1314,7 @@ fs::remove_all(const path& p)
break;
case ENOENT:
// Our work here is done.
- return 0;
+ return count;
case ENOTDIR:
case ELOOP:
// Not a directory, will remove below.
@@ -1313,6 +1324,18 @@ fs::remove_all(const path& p)
_GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot remove all", p, ec));
}
+ if (count > init_count)
+ {
+ if (int last = fs::remove(p, ec); !ec)
+ return count + last;
+ else
+ // Some systems seem to skip entries in the dir iteration if
+ // you remove dir entries while iterating, so if we removed
+ // anything in the dir in this round, and failed to remove
+ // the dir (presumably because it wasn't empty), retry.
+ goto retry;
+ }
+
// Remove p itself, which is either a non-directory or is now empty.
return count + fs::remove(p);
}
@@ -1321,6 +1344,8 @@ std::uintmax_t
fs::remove_all(const path& p, error_code& ec)
{
uintmax_t count = 0;
+ retry:
+ uintmax_t init_count = count;
recursive_directory_iterator dir(p, directory_options{64|128}, ec);
switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
{
@@ -1332,7 +1357,12 @@ fs::remove_all(const path& p, error_code& ec)
{
dir.__erase(&ec);
if (ec)
- return -1;
+ {
+ if (count > init_count)
+ goto retry;
+ else
+ return -1;
+ }
++count;
}
}
@@ -1341,7 +1371,7 @@ fs::remove_all(const path& p, error_code& ec)
case ENOENT:
// Our work here is done.
ec.clear();
- return 0;
+ return count;
case ENOTDIR:
case ELOOP:
// Not a directory, will remove below.
@@ -1354,6 +1384,8 @@ fs::remove_all(const path& p, error_code& ec)
// Remove p itself, which is either a non-directory or is now empty.
if (int last = fs::remove(p, ec); !ec)
return count + last;
+ if (count > init_count)
+ goto retry;
return -1;
}
^ permalink raw reply [flat|nested] 12+ messages in thread
* [gcc(refs/users/aoliva/heads/testme)] libstdc++: retry removal of dir entries if dir removal fails
@ 2022-06-27 9:33 Alexandre Oliva
0 siblings, 0 replies; 12+ messages in thread
From: Alexandre Oliva @ 2022-06-27 9:33 UTC (permalink / raw)
To: gcc-cvs, libstdc++-cvs
https://gcc.gnu.org/g:10fb66615f12363596b5246d7de05d8993941e60
commit 10fb66615f12363596b5246d7de05d8993941e60
Author: Alexandre Oliva <oliva@adacore.com>
Date: Mon Jun 27 05:30:54 2022 -0300
libstdc++: retry removal of dir entries if dir removal fails
On some target systems (e.g. rtems6.0), removing directory components
while iterating over directory entries may cause some of the directory
entries to be skipped, which prevents the removal of the parent
directory from succeeding.
Advancing the iterator before removing a member proved not to be
enough, so I've instead arranged for remove_all to retry the removal
of components if the removal of the parent dir fails after removing at
least one entry. The fail will be permanent only if no components got
removed in the current try.
for libstdc++-v3/ChangeLog
* src/c++17/fs_ops.cc (remove_all): Retry removal of
directory entries.
Diff:
---
libstdc++-v3/src/c++17/fs_ops.cc | 22 ++++++++++++++++++++--
1 file changed, 20 insertions(+), 2 deletions(-)
diff --git a/libstdc++-v3/src/c++17/fs_ops.cc b/libstdc++-v3/src/c++17/fs_ops.cc
index 435368fa5c5..b3390310132 100644
--- a/libstdc++-v3/src/c++17/fs_ops.cc
+++ b/libstdc++-v3/src/c++17/fs_ops.cc
@@ -1286,6 +1286,8 @@ fs::remove_all(const path& p)
{
error_code ec;
uintmax_t count = 0;
+ retry:
+ uintmax_t init_count = count;
recursive_directory_iterator dir(p, directory_options{64|128}, ec);
switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
{
@@ -1303,7 +1305,7 @@ fs::remove_all(const path& p)
break;
case ENOENT:
// Our work here is done.
- return 0;
+ return count;
case ENOTDIR:
case ELOOP:
// Not a directory, will remove below.
@@ -1313,6 +1315,18 @@ fs::remove_all(const path& p)
_GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot remove all", p, ec));
}
+ if (count > init_count)
+ {
+ if (int last = fs::remove(p, ec); !ec)
+ return count + last;
+ else
+ // Some systems seem to skip entries in the dir iteration if
+ // you remove dir entries while iterating, so if we removed
+ // anything in the dir in this round, and failed to remove
+ // the dir (presumably because it wasn't empty), retry.
+ goto retry;
+ }
+
// Remove p itself, which is either a non-directory or is now empty.
return count + fs::remove(p);
}
@@ -1321,6 +1335,8 @@ std::uintmax_t
fs::remove_all(const path& p, error_code& ec)
{
uintmax_t count = 0;
+ retry:
+ uintmax_t init_count = count;
recursive_directory_iterator dir(p, directory_options{64|128}, ec);
switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
{
@@ -1341,7 +1357,7 @@ fs::remove_all(const path& p, error_code& ec)
case ENOENT:
// Our work here is done.
ec.clear();
- return 0;
+ return count;
case ENOTDIR:
case ELOOP:
// Not a directory, will remove below.
@@ -1354,6 +1370,8 @@ fs::remove_all(const path& p, error_code& ec)
// Remove p itself, which is either a non-directory or is now empty.
if (int last = fs::remove(p, ec); !ec)
return count + last;
+ if (count > init_count)
+ goto retry;
return -1;
}
^ permalink raw reply [flat|nested] 12+ messages in thread
* [gcc(refs/users/aoliva/heads/testme)] libstdc++: retry removal of dir entries if dir removal fails
@ 2022-06-23 12:44 Alexandre Oliva
0 siblings, 0 replies; 12+ messages in thread
From: Alexandre Oliva @ 2022-06-23 12:44 UTC (permalink / raw)
To: gcc-cvs, libstdc++-cvs
https://gcc.gnu.org/g:74873e320fab4b7c39f7fc10276a6452da6ce763
commit 74873e320fab4b7c39f7fc10276a6452da6ce763
Author: Alexandre Oliva <oliva@adacore.com>
Date: Mon Jun 20 20:19:55 2022 -0300
libstdc++: retry removal of dir entries if dir removal fails
On some target systems (e.g. rtems6.0), removing directory components
while iterating over directory entries may cause some of the directory
entries to be skipped, which prevents the removal of the parent
directory from succeeding.
Advancing the iterator before removing a member proved not to be
enough, so I've instead arranged for remove_all to retry the removal
of components if the removal of the parent dir fails after removing at
least one entry. The fail will be permanent only if no components got
removed in the current try.
for libstdc++-v3/ChangeLog
* src/c++17/fs_ops.cc (remove_all): Retry removal of
directory entries.
Diff:
---
libstdc++-v3/src/c++17/fs_ops.cc | 22 ++++++++++++++++++++--
1 file changed, 20 insertions(+), 2 deletions(-)
diff --git a/libstdc++-v3/src/c++17/fs_ops.cc b/libstdc++-v3/src/c++17/fs_ops.cc
index 435368fa5c5..b3390310132 100644
--- a/libstdc++-v3/src/c++17/fs_ops.cc
+++ b/libstdc++-v3/src/c++17/fs_ops.cc
@@ -1286,6 +1286,8 @@ fs::remove_all(const path& p)
{
error_code ec;
uintmax_t count = 0;
+ retry:
+ uintmax_t init_count = count;
recursive_directory_iterator dir(p, directory_options{64|128}, ec);
switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
{
@@ -1303,7 +1305,7 @@ fs::remove_all(const path& p)
break;
case ENOENT:
// Our work here is done.
- return 0;
+ return count;
case ENOTDIR:
case ELOOP:
// Not a directory, will remove below.
@@ -1313,6 +1315,18 @@ fs::remove_all(const path& p)
_GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot remove all", p, ec));
}
+ if (count > init_count)
+ {
+ if (int last = fs::remove(p, ec); !ec)
+ return count + last;
+ else
+ // Some systems seem to skip entries in the dir iteration if
+ // you remove dir entries while iterating, so if we removed
+ // anything in the dir in this round, and failed to remove
+ // the dir (presumably because it wasn't empty), retry.
+ goto retry;
+ }
+
// Remove p itself, which is either a non-directory or is now empty.
return count + fs::remove(p);
}
@@ -1321,6 +1335,8 @@ std::uintmax_t
fs::remove_all(const path& p, error_code& ec)
{
uintmax_t count = 0;
+ retry:
+ uintmax_t init_count = count;
recursive_directory_iterator dir(p, directory_options{64|128}, ec);
switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
{
@@ -1341,7 +1357,7 @@ fs::remove_all(const path& p, error_code& ec)
case ENOENT:
// Our work here is done.
ec.clear();
- return 0;
+ return count;
case ENOTDIR:
case ELOOP:
// Not a directory, will remove below.
@@ -1354,6 +1370,8 @@ fs::remove_all(const path& p, error_code& ec)
// Remove p itself, which is either a non-directory or is now empty.
if (int last = fs::remove(p, ec); !ec)
return count + last;
+ if (count > init_count)
+ goto retry;
return -1;
}
^ permalink raw reply [flat|nested] 12+ messages in thread
* [gcc(refs/users/aoliva/heads/testme)] libstdc++: retry removal of dir entries if dir removal fails
@ 2022-06-23 12:30 Alexandre Oliva
0 siblings, 0 replies; 12+ messages in thread
From: Alexandre Oliva @ 2022-06-23 12:30 UTC (permalink / raw)
To: gcc-cvs, libstdc++-cvs
https://gcc.gnu.org/g:b4199c73cec70cc8d4cac659aa84068b6257ec1c
commit b4199c73cec70cc8d4cac659aa84068b6257ec1c
Author: Alexandre Oliva <oliva@adacore.com>
Date: Mon Jun 20 20:19:55 2022 -0300
libstdc++: retry removal of dir entries if dir removal fails
On some target systems (e.g. rtems6.0), removing directory components
while iterating over directory entries may cause some of the directory
entries to be skipped, which prevents the removal of the parent
directory from succeeding.
Advancing the iterator before removing a member proved not to be
enough, so I've instead arranged for remove_all to retry the removal
of components if the removal of the parent dir fails after removing at
least one entry. The fail will be permanent only if no components got
removed in the current try.
for libstdc++-v3/ChangeLog
* src/c++17/fs_ops.cc (remove_all): Retry removal of
directory entries.
Diff:
---
libstdc++-v3/src/c++17/fs_ops.cc | 22 ++++++++++++++++++++--
1 file changed, 20 insertions(+), 2 deletions(-)
diff --git a/libstdc++-v3/src/c++17/fs_ops.cc b/libstdc++-v3/src/c++17/fs_ops.cc
index 435368fa5c5..b3390310132 100644
--- a/libstdc++-v3/src/c++17/fs_ops.cc
+++ b/libstdc++-v3/src/c++17/fs_ops.cc
@@ -1286,6 +1286,8 @@ fs::remove_all(const path& p)
{
error_code ec;
uintmax_t count = 0;
+ retry:
+ uintmax_t init_count = count;
recursive_directory_iterator dir(p, directory_options{64|128}, ec);
switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
{
@@ -1303,7 +1305,7 @@ fs::remove_all(const path& p)
break;
case ENOENT:
// Our work here is done.
- return 0;
+ return count;
case ENOTDIR:
case ELOOP:
// Not a directory, will remove below.
@@ -1313,6 +1315,18 @@ fs::remove_all(const path& p)
_GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot remove all", p, ec));
}
+ if (count > init_count)
+ {
+ if (int last = fs::remove(p, ec); !ec)
+ return count + last;
+ else
+ // Some systems seem to skip entries in the dir iteration if
+ // you remove dir entries while iterating, so if we removed
+ // anything in the dir in this round, and failed to remove
+ // the dir (presumably because it wasn't empty), retry.
+ goto retry;
+ }
+
// Remove p itself, which is either a non-directory or is now empty.
return count + fs::remove(p);
}
@@ -1321,6 +1335,8 @@ std::uintmax_t
fs::remove_all(const path& p, error_code& ec)
{
uintmax_t count = 0;
+ retry:
+ uintmax_t init_count = count;
recursive_directory_iterator dir(p, directory_options{64|128}, ec);
switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
{
@@ -1341,7 +1357,7 @@ fs::remove_all(const path& p, error_code& ec)
case ENOENT:
// Our work here is done.
ec.clear();
- return 0;
+ return count;
case ENOTDIR:
case ELOOP:
// Not a directory, will remove below.
@@ -1354,6 +1370,8 @@ fs::remove_all(const path& p, error_code& ec)
// Remove p itself, which is either a non-directory or is now empty.
if (int last = fs::remove(p, ec); !ec)
return count + last;
+ if (count > init_count)
+ goto retry;
return -1;
}
^ permalink raw reply [flat|nested] 12+ messages in thread
* [gcc(refs/users/aoliva/heads/testme)] libstdc++: retry removal of dir entries if dir removal fails
@ 2022-06-23 12:22 Alexandre Oliva
0 siblings, 0 replies; 12+ messages in thread
From: Alexandre Oliva @ 2022-06-23 12:22 UTC (permalink / raw)
To: gcc-cvs, libstdc++-cvs
https://gcc.gnu.org/g:ec9a4b4b3adb65186f6cd1c8b3950f8b49db02b0
commit ec9a4b4b3adb65186f6cd1c8b3950f8b49db02b0
Author: Alexandre Oliva <oliva@adacore.com>
Date: Mon Jun 20 20:19:55 2022 -0300
libstdc++: retry removal of dir entries if dir removal fails
On some target systems (e.g. rtems6.0), removing directory components
while iterating over directory entries may cause some of the directory
entries to be skipped, which prevents the removal of the parent
directory from succeeding.
Advancing the iterator before removing a member proved not to be
enough, so I've instead arranged for remove_all to retry the removal
of components if the removal of the parent dir fails after removing at
least one entry. The fail will be permanent only if no components got
removed in the current try.
for libstdc++-v3/ChangeLog
* src/c++17/fs_ops.cc (remove_all): Retry removal of
directory entries.
Diff:
---
libstdc++-v3/src/c++17/fs_ops.cc | 22 ++++++++++++++++++++--
1 file changed, 20 insertions(+), 2 deletions(-)
diff --git a/libstdc++-v3/src/c++17/fs_ops.cc b/libstdc++-v3/src/c++17/fs_ops.cc
index 435368fa5c5..b3390310132 100644
--- a/libstdc++-v3/src/c++17/fs_ops.cc
+++ b/libstdc++-v3/src/c++17/fs_ops.cc
@@ -1286,6 +1286,8 @@ fs::remove_all(const path& p)
{
error_code ec;
uintmax_t count = 0;
+ retry:
+ uintmax_t init_count = count;
recursive_directory_iterator dir(p, directory_options{64|128}, ec);
switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
{
@@ -1303,7 +1305,7 @@ fs::remove_all(const path& p)
break;
case ENOENT:
// Our work here is done.
- return 0;
+ return count;
case ENOTDIR:
case ELOOP:
// Not a directory, will remove below.
@@ -1313,6 +1315,18 @@ fs::remove_all(const path& p)
_GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot remove all", p, ec));
}
+ if (count > init_count)
+ {
+ if (int last = fs::remove(p, ec); !ec)
+ return count + last;
+ else
+ // Some systems seem to skip entries in the dir iteration if
+ // you remove dir entries while iterating, so if we removed
+ // anything in the dir in this round, and failed to remove
+ // the dir (presumably because it wasn't empty), retry.
+ goto retry;
+ }
+
// Remove p itself, which is either a non-directory or is now empty.
return count + fs::remove(p);
}
@@ -1321,6 +1335,8 @@ std::uintmax_t
fs::remove_all(const path& p, error_code& ec)
{
uintmax_t count = 0;
+ retry:
+ uintmax_t init_count = count;
recursive_directory_iterator dir(p, directory_options{64|128}, ec);
switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
{
@@ -1341,7 +1357,7 @@ fs::remove_all(const path& p, error_code& ec)
case ENOENT:
// Our work here is done.
ec.clear();
- return 0;
+ return count;
case ENOTDIR:
case ELOOP:
// Not a directory, will remove below.
@@ -1354,6 +1370,8 @@ fs::remove_all(const path& p, error_code& ec)
// Remove p itself, which is either a non-directory or is now empty.
if (int last = fs::remove(p, ec); !ec)
return count + last;
+ if (count > init_count)
+ goto retry;
return -1;
}
^ permalink raw reply [flat|nested] 12+ messages in thread
* [gcc(refs/users/aoliva/heads/testme)] libstdc++: retry removal of dir entries if dir removal fails
@ 2022-06-23 10:05 Alexandre Oliva
0 siblings, 0 replies; 12+ messages in thread
From: Alexandre Oliva @ 2022-06-23 10:05 UTC (permalink / raw)
To: gcc-cvs, libstdc++-cvs
https://gcc.gnu.org/g:6c9d89a9095d5271954d2d4660a3448b29febfd4
commit 6c9d89a9095d5271954d2d4660a3448b29febfd4
Author: Alexandre Oliva <oliva@adacore.com>
Date: Mon Jun 20 20:19:55 2022 -0300
libstdc++: retry removal of dir entries if dir removal fails
On some target systems (e.g. rtems6.0), removing directory components
while iterating over directory entries may cause some of the directory
entries to be skipped, which prevents the removal of the parent
directory from succeeding.
Advancing the iterator before removing a member proved not to be
enough, so I've instead arranged for remove_all to retry the removal
of components if the removal of the parent dir fails after removing at
least one entry. The fail will be permanent only if no components got
removed in the current try.
for libstdc++-v3/ChangeLog
* src/c++17/fs_ops.cc (remove_all): Retry removal of
directory entries.
Diff:
---
libstdc++-v3/src/c++17/fs_ops.cc | 22 ++++++++++++++++++++--
1 file changed, 20 insertions(+), 2 deletions(-)
diff --git a/libstdc++-v3/src/c++17/fs_ops.cc b/libstdc++-v3/src/c++17/fs_ops.cc
index 435368fa5c5..b3390310132 100644
--- a/libstdc++-v3/src/c++17/fs_ops.cc
+++ b/libstdc++-v3/src/c++17/fs_ops.cc
@@ -1286,6 +1286,8 @@ fs::remove_all(const path& p)
{
error_code ec;
uintmax_t count = 0;
+ retry:
+ uintmax_t init_count = count;
recursive_directory_iterator dir(p, directory_options{64|128}, ec);
switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
{
@@ -1303,7 +1305,7 @@ fs::remove_all(const path& p)
break;
case ENOENT:
// Our work here is done.
- return 0;
+ return count;
case ENOTDIR:
case ELOOP:
// Not a directory, will remove below.
@@ -1313,6 +1315,18 @@ fs::remove_all(const path& p)
_GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot remove all", p, ec));
}
+ if (count > init_count)
+ {
+ if (int last = fs::remove(p, ec); !ec)
+ return count + last;
+ else
+ // Some systems seem to skip entries in the dir iteration if
+ // you remove dir entries while iterating, so if we removed
+ // anything in the dir in this round, and failed to remove
+ // the dir (presumably because it wasn't empty), retry.
+ goto retry;
+ }
+
// Remove p itself, which is either a non-directory or is now empty.
return count + fs::remove(p);
}
@@ -1321,6 +1335,8 @@ std::uintmax_t
fs::remove_all(const path& p, error_code& ec)
{
uintmax_t count = 0;
+ retry:
+ uintmax_t init_count = count;
recursive_directory_iterator dir(p, directory_options{64|128}, ec);
switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
{
@@ -1341,7 +1357,7 @@ fs::remove_all(const path& p, error_code& ec)
case ENOENT:
// Our work here is done.
ec.clear();
- return 0;
+ return count;
case ENOTDIR:
case ELOOP:
// Not a directory, will remove below.
@@ -1354,6 +1370,8 @@ fs::remove_all(const path& p, error_code& ec)
// Remove p itself, which is either a non-directory or is now empty.
if (int last = fs::remove(p, ec); !ec)
return count + last;
+ if (count > init_count)
+ goto retry;
return -1;
}
^ permalink raw reply [flat|nested] 12+ messages in thread
* [gcc(refs/users/aoliva/heads/testme)] libstdc++: retry removal of dir entries if dir removal fails
@ 2022-06-23 7:15 Alexandre Oliva
0 siblings, 0 replies; 12+ messages in thread
From: Alexandre Oliva @ 2022-06-23 7:15 UTC (permalink / raw)
To: gcc-cvs, libstdc++-cvs
https://gcc.gnu.org/g:ae6e31b9ce7e733c3e12c1363990490873935577
commit ae6e31b9ce7e733c3e12c1363990490873935577
Author: Alexandre Oliva <oliva@adacore.com>
Date: Mon Jun 20 20:19:55 2022 -0300
libstdc++: retry removal of dir entries if dir removal fails
On some target systems (e.g. rtems6.0), removing directory components
while iterating over directory entries may cause some of the directory
entries to be skipped, which prevents the removal of the parent
directory from succeeding.
Advancing the iterator before removing a member proved not to be
enough, so I've instead arranged for remove_all to retry the removal
of components if the removal of the parent dir fails after removing at
least one entry. The fail will be permanent only if no components got
removed in the current try.
for libstdc++-v3/ChangeLog
* src/c++17/fs_ops.cc (remove_all): Retry removal of
directory entries.
Diff:
---
libstdc++-v3/src/c++17/fs_ops.cc | 22 ++++++++++++++++++++--
1 file changed, 20 insertions(+), 2 deletions(-)
diff --git a/libstdc++-v3/src/c++17/fs_ops.cc b/libstdc++-v3/src/c++17/fs_ops.cc
index 435368fa5c5..b3390310132 100644
--- a/libstdc++-v3/src/c++17/fs_ops.cc
+++ b/libstdc++-v3/src/c++17/fs_ops.cc
@@ -1286,6 +1286,8 @@ fs::remove_all(const path& p)
{
error_code ec;
uintmax_t count = 0;
+ retry:
+ uintmax_t init_count = count;
recursive_directory_iterator dir(p, directory_options{64|128}, ec);
switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
{
@@ -1303,7 +1305,7 @@ fs::remove_all(const path& p)
break;
case ENOENT:
// Our work here is done.
- return 0;
+ return count;
case ENOTDIR:
case ELOOP:
// Not a directory, will remove below.
@@ -1313,6 +1315,18 @@ fs::remove_all(const path& p)
_GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot remove all", p, ec));
}
+ if (count > init_count)
+ {
+ if (int last = fs::remove(p, ec); !ec)
+ return count + last;
+ else
+ // Some systems seem to skip entries in the dir iteration if
+ // you remove dir entries while iterating, so if we removed
+ // anything in the dir in this round, and failed to remove
+ // the dir (presumably because it wasn't empty), retry.
+ goto retry;
+ }
+
// Remove p itself, which is either a non-directory or is now empty.
return count + fs::remove(p);
}
@@ -1321,6 +1335,8 @@ std::uintmax_t
fs::remove_all(const path& p, error_code& ec)
{
uintmax_t count = 0;
+ retry:
+ uintmax_t init_count = count;
recursive_directory_iterator dir(p, directory_options{64|128}, ec);
switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
{
@@ -1341,7 +1357,7 @@ fs::remove_all(const path& p, error_code& ec)
case ENOENT:
// Our work here is done.
ec.clear();
- return 0;
+ return count;
case ENOTDIR:
case ELOOP:
// Not a directory, will remove below.
@@ -1354,6 +1370,8 @@ fs::remove_all(const path& p, error_code& ec)
// Remove p itself, which is either a non-directory or is now empty.
if (int last = fs::remove(p, ec); !ec)
return count + last;
+ if (count > init_count)
+ goto retry;
return -1;
}
^ permalink raw reply [flat|nested] 12+ messages in thread
* [gcc(refs/users/aoliva/heads/testme)] libstdc++: retry removal of dir entries if dir removal fails
@ 2022-06-22 5:23 Alexandre Oliva
0 siblings, 0 replies; 12+ messages in thread
From: Alexandre Oliva @ 2022-06-22 5:23 UTC (permalink / raw)
To: gcc-cvs, libstdc++-cvs
https://gcc.gnu.org/g:e4e2717691e13559d3db3e82e25d32d9b95ce5c6
commit e4e2717691e13559d3db3e82e25d32d9b95ce5c6
Author: Alexandre Oliva <oliva@adacore.com>
Date: Mon Jun 20 20:19:55 2022 -0300
libstdc++: retry removal of dir entries if dir removal fails
On some target systems (e.g. rtems6.0), removing directory components
while iterating over directory entries may cause some of the directory
entries to be skipped, which prevents the removal of the parent
directory from succeeding.
Advancing the iterator before removing a member proved not to be
enough, so I've instead arranged for remove_all to retry the removal
of components if the removal of the parent dir fails after removing at
least one entry. The fail will be permanent only if no components got
removed in the current try.
for libstdc++-v3/ChangeLog
* src/c++17/fs_ops.cc (remove_all): Retry removal of
directory entries.
Diff:
---
libstdc++-v3/src/c++17/fs_ops.cc | 22 ++++++++++++++++++++--
1 file changed, 20 insertions(+), 2 deletions(-)
diff --git a/libstdc++-v3/src/c++17/fs_ops.cc b/libstdc++-v3/src/c++17/fs_ops.cc
index 435368fa5c5..b3390310132 100644
--- a/libstdc++-v3/src/c++17/fs_ops.cc
+++ b/libstdc++-v3/src/c++17/fs_ops.cc
@@ -1286,6 +1286,8 @@ fs::remove_all(const path& p)
{
error_code ec;
uintmax_t count = 0;
+ retry:
+ uintmax_t init_count = count;
recursive_directory_iterator dir(p, directory_options{64|128}, ec);
switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
{
@@ -1303,7 +1305,7 @@ fs::remove_all(const path& p)
break;
case ENOENT:
// Our work here is done.
- return 0;
+ return count;
case ENOTDIR:
case ELOOP:
// Not a directory, will remove below.
@@ -1313,6 +1315,18 @@ fs::remove_all(const path& p)
_GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot remove all", p, ec));
}
+ if (count > init_count)
+ {
+ if (int last = fs::remove(p, ec); !ec)
+ return count + last;
+ else
+ // Some systems seem to skip entries in the dir iteration if
+ // you remove dir entries while iterating, so if we removed
+ // anything in the dir in this round, and failed to remove
+ // the dir (presumably because it wasn't empty), retry.
+ goto retry;
+ }
+
// Remove p itself, which is either a non-directory or is now empty.
return count + fs::remove(p);
}
@@ -1321,6 +1335,8 @@ std::uintmax_t
fs::remove_all(const path& p, error_code& ec)
{
uintmax_t count = 0;
+ retry:
+ uintmax_t init_count = count;
recursive_directory_iterator dir(p, directory_options{64|128}, ec);
switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
{
@@ -1341,7 +1357,7 @@ fs::remove_all(const path& p, error_code& ec)
case ENOENT:
// Our work here is done.
ec.clear();
- return 0;
+ return count;
case ENOTDIR:
case ELOOP:
// Not a directory, will remove below.
@@ -1354,6 +1370,8 @@ fs::remove_all(const path& p, error_code& ec)
// Remove p itself, which is either a non-directory or is now empty.
if (int last = fs::remove(p, ec); !ec)
return count + last;
+ if (count > init_count)
+ goto retry;
return -1;
}
^ permalink raw reply [flat|nested] 12+ messages in thread
* [gcc(refs/users/aoliva/heads/testme)] libstdc++: retry removal of dir entries if dir removal fails
@ 2022-06-21 0:16 Alexandre Oliva
0 siblings, 0 replies; 12+ messages in thread
From: Alexandre Oliva @ 2022-06-21 0:16 UTC (permalink / raw)
To: gcc-cvs, libstdc++-cvs
https://gcc.gnu.org/g:75ca2e120aa78abf67b51c47db48ac3dc626a136
commit 75ca2e120aa78abf67b51c47db48ac3dc626a136
Author: Alexandre Oliva <oliva@adacore.com>
Date: Mon Jun 20 20:19:55 2022 -0300
libstdc++: retry removal of dir entries if dir removal fails
On some target systems (e.g. rtems6.0), removing directory components
while iterating over directory entries may cause some of the directory
entries to be skipped, which prevents the removal of the parent
directory from succeeding.
Advancing the iterator before removing a member proved not to be
enough, so I've instead arranged for remove_all to retry the removal
of components if the removal of the parent dir fails after removing at
least one entry. The fail will be permanent only if no components got
removed in the current try.
for libstdc++-v3/ChangeLog
* src/c++17/fs_ops.cc (remove_all): Retry removal of
directory entries.
Diff:
---
libstdc++-v3/src/c++17/fs_ops.cc | 22 ++++++++++++++++++++--
1 file changed, 20 insertions(+), 2 deletions(-)
diff --git a/libstdc++-v3/src/c++17/fs_ops.cc b/libstdc++-v3/src/c++17/fs_ops.cc
index 435368fa5c5..b3390310132 100644
--- a/libstdc++-v3/src/c++17/fs_ops.cc
+++ b/libstdc++-v3/src/c++17/fs_ops.cc
@@ -1286,6 +1286,8 @@ fs::remove_all(const path& p)
{
error_code ec;
uintmax_t count = 0;
+ retry:
+ uintmax_t init_count = count;
recursive_directory_iterator dir(p, directory_options{64|128}, ec);
switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
{
@@ -1303,7 +1305,7 @@ fs::remove_all(const path& p)
break;
case ENOENT:
// Our work here is done.
- return 0;
+ return count;
case ENOTDIR:
case ELOOP:
// Not a directory, will remove below.
@@ -1313,6 +1315,18 @@ fs::remove_all(const path& p)
_GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot remove all", p, ec));
}
+ if (count > init_count)
+ {
+ if (int last = fs::remove(p, ec); !ec)
+ return count + last;
+ else
+ // Some systems seem to skip entries in the dir iteration if
+ // you remove dir entries while iterating, so if we removed
+ // anything in the dir in this round, and failed to remove
+ // the dir (presumably because it wasn't empty), retry.
+ goto retry;
+ }
+
// Remove p itself, which is either a non-directory or is now empty.
return count + fs::remove(p);
}
@@ -1321,6 +1335,8 @@ std::uintmax_t
fs::remove_all(const path& p, error_code& ec)
{
uintmax_t count = 0;
+ retry:
+ uintmax_t init_count = count;
recursive_directory_iterator dir(p, directory_options{64|128}, ec);
switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
{
@@ -1341,7 +1357,7 @@ fs::remove_all(const path& p, error_code& ec)
case ENOENT:
// Our work here is done.
ec.clear();
- return 0;
+ return count;
case ENOTDIR:
case ELOOP:
// Not a directory, will remove below.
@@ -1354,6 +1370,8 @@ fs::remove_all(const path& p, error_code& ec)
// Remove p itself, which is either a non-directory or is now empty.
if (int last = fs::remove(p, ec); !ec)
return count + last;
+ if (count > init_count)
+ goto retry;
return -1;
}
^ permalink raw reply [flat|nested] 12+ messages in thread
* [gcc(refs/users/aoliva/heads/testme)] libstdc++: retry removal of dir entries if dir removal fails
@ 2022-06-21 0:08 Alexandre Oliva
0 siblings, 0 replies; 12+ messages in thread
From: Alexandre Oliva @ 2022-06-21 0:08 UTC (permalink / raw)
To: gcc-cvs, libstdc++-cvs
https://gcc.gnu.org/g:8aada61fdc69b41c361bd6d533cb25322e0c7cd5
commit 8aada61fdc69b41c361bd6d533cb25322e0c7cd5
Author: Alexandre Oliva <oliva@adacore.com>
Date: Mon Jun 20 20:19:55 2022 -0300
libstdc++: retry removal of dir entries if dir removal fails
On some target systems (e.g. rtems6.0), removing directory components
while iterating over directory entries may cause some of the directory
entries to be skipped, which prevents the removal of the parent
directory from succeeding.
Advancing the iterator before removing a member proved not to be
enough, so I've instead arranged for remove_all to retry the removal
of components if the removal of the parent dir fails after removing at
least one entry. The fail will be permanent only if no components got
removed in the current try.
for libstdc++-v3/ChangeLog
* src/c++17/fs_ops.cc (remove_all): Retry removal of
directory entries.
TN: V527-033
Diff:
---
libstdc++-v3/src/c++17/fs_ops.cc | 22 ++++++++++++++++++++--
1 file changed, 20 insertions(+), 2 deletions(-)
diff --git a/libstdc++-v3/src/c++17/fs_ops.cc b/libstdc++-v3/src/c++17/fs_ops.cc
index 435368fa5c5..b3390310132 100644
--- a/libstdc++-v3/src/c++17/fs_ops.cc
+++ b/libstdc++-v3/src/c++17/fs_ops.cc
@@ -1286,6 +1286,8 @@ fs::remove_all(const path& p)
{
error_code ec;
uintmax_t count = 0;
+ retry:
+ uintmax_t init_count = count;
recursive_directory_iterator dir(p, directory_options{64|128}, ec);
switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
{
@@ -1303,7 +1305,7 @@ fs::remove_all(const path& p)
break;
case ENOENT:
// Our work here is done.
- return 0;
+ return count;
case ENOTDIR:
case ELOOP:
// Not a directory, will remove below.
@@ -1313,6 +1315,18 @@ fs::remove_all(const path& p)
_GLIBCXX_THROW_OR_ABORT(filesystem_error("cannot remove all", p, ec));
}
+ if (count > init_count)
+ {
+ if (int last = fs::remove(p, ec); !ec)
+ return count + last;
+ else
+ // Some systems seem to skip entries in the dir iteration if
+ // you remove dir entries while iterating, so if we removed
+ // anything in the dir in this round, and failed to remove
+ // the dir (presumably because it wasn't empty), retry.
+ goto retry;
+ }
+
// Remove p itself, which is either a non-directory or is now empty.
return count + fs::remove(p);
}
@@ -1321,6 +1335,8 @@ std::uintmax_t
fs::remove_all(const path& p, error_code& ec)
{
uintmax_t count = 0;
+ retry:
+ uintmax_t init_count = count;
recursive_directory_iterator dir(p, directory_options{64|128}, ec);
switch (ec.value()) // N.B. assumes ec.category() == std::generic_category()
{
@@ -1341,7 +1357,7 @@ fs::remove_all(const path& p, error_code& ec)
case ENOENT:
// Our work here is done.
ec.clear();
- return 0;
+ return count;
case ENOTDIR:
case ELOOP:
// Not a directory, will remove below.
@@ -1354,6 +1370,8 @@ fs::remove_all(const path& p, error_code& ec)
// Remove p itself, which is either a non-directory or is now empty.
if (int last = fs::remove(p, ec); !ec)
return count + last;
+ if (count > init_count)
+ goto retry;
return -1;
}
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2022-06-27 15:45 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-27 13:35 [gcc(refs/users/aoliva/heads/testme)] libstdc++: retry removal of dir entries if dir removal fails Alexandre Oliva
-- strict thread matches above, loose matches on Subject: below --
2022-06-27 15:45 Alexandre Oliva
2022-06-27 10:51 Alexandre Oliva
2022-06-27 9:33 Alexandre Oliva
2022-06-23 12:44 Alexandre Oliva
2022-06-23 12:30 Alexandre Oliva
2022-06-23 12:22 Alexandre Oliva
2022-06-23 10:05 Alexandre Oliva
2022-06-23 7:15 Alexandre Oliva
2022-06-22 5:23 Alexandre Oliva
2022-06-21 0:16 Alexandre Oliva
2022-06-21 0:08 Alexandre Oliva
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).