aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2020-08-28 19:40:52 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2020-08-31 12:07:10 +0300
commitab080add26815ceef754c6ebaa2f2512e1f954cf (patch)
treecd93483b330d114e3427632290f368226e726996
parent584e8fce074286cbf1a5bf0c79265f789c050c59 (diff)
Fix assertion failure in path_search() on Windows
Also fix the similar potential assertion failure in fdstream.
-rw-r--r--libbutl/fdstream.cxx14
-rw-r--r--libbutl/filesystem.cxx11
-rw-r--r--libbutl/utility.cxx24
3 files changed, 35 insertions, 14 deletions
diff --git a/libbutl/fdstream.cxx b/libbutl/fdstream.cxx
index 0a5525c..377681e 100644
--- a/libbutl/fdstream.cxx
+++ b/libbutl/fdstream.cxx
@@ -1567,11 +1567,19 @@ namespace butl
}
catch (const system_error& e)
{
- // Make sure that the error denotes errno portable code.
+ // Re-throw system_error as ios::failure, preserving the error category
+ // and description.
//
- assert (e.code ().category () == generic_category ());
+ int v (e.code ().value ());
+ const error_category& c (e.code ().category ());
- throw_generic_ios_failure (e.code ().value ());
+ if (c == generic_category ())
+ throw_generic_ios_failure (v);
+ else
+ {
+ assert (c == system_category ());
+ throw_system_ios_failure (v, e.what ());
+ }
}
}
diff --git a/libbutl/filesystem.cxx b/libbutl/filesystem.cxx
index 7db26a5..9e8a232 100644
--- a/libbutl/filesystem.cxx
+++ b/libbutl/filesystem.cxx
@@ -2573,11 +2573,14 @@ namespace butl
//
// Make sure that the error denotes errno portable code.
//
- assert (e.code ().category () == generic_category ());
+ if (e.code ().category () == generic_category ())
+ {
+ int ec (e.code ().value ());
+ if (ec == ENOENT || ec == ENOTDIR)
+ return;
+ }
- int ec (e.code ().value ());
- if (ec != ENOENT && ec != ENOTDIR)
- throw;
+ throw;
}
}
diff --git a/libbutl/utility.cxx b/libbutl/utility.cxx
index c23d3f5..bbeafd2 100644
--- a/libbutl/utility.cxx
+++ b/libbutl/utility.cxx
@@ -388,7 +388,7 @@ namespace std
// Invalid data.\r\n
//
size_t n (string::traits_type::length (s));
- for (; n > 0; --n)
+ for (; n != 0; --n)
{
switch (s[n-1])
{
@@ -411,7 +411,7 @@ namespace std
// Check if the string ends with the specified suffix and return its
// length if that's the case. So can be used as bool.
//
- auto suffix = [s, n] (const char* v) -> size_t
+ auto suffix = [s, &n] (const char* v) -> size_t
{
size_t nv (string::traits_type::length (v));
return (n >= nv && string::traits_type::compare (s + n - nv, v, nv) == 0
@@ -419,17 +419,27 @@ namespace std
: 0);
};
+ // Note that in some cases we need to re-throw exception using a different
+ // type, for example system_error as ios::failure. In such cases these
+ // suffixed may accumulate, for example:
+ //
+ // Access denied. : Success.: Success.
+ //
+ // Thus, we will strip them in a loop.
+ //
size_t ns;
- if ((ns = suffix (". : Success")) ||
- (ns = suffix (". : No error")) ||
- (ns = suffix (". : The operation completed successfully")))
- n -= ns;
+ while ((ns = suffix (": Success")) ||
+ (ns = suffix (": No error")) ||
+ (ns = suffix (": The operation completed successfully")))
+ {
+ for (n -= ns; n != 0 && (s[n-1] == '.' || s[n-1] == ' '); --n) ;
+ }
// Lower-case the first letter if the beginning looks like a word (the
// second character is the lower-case letter or space).
//
char c;
- bool lc (n > 0 && alpha (c = s[0]) && c == ucase (c) &&
+ bool lc (n != 0 && alpha (c = s[0]) && c == ucase (c) &&
(n == 1 || (alpha (c = s[1]) && c == lcase (c)) || c == ' '));
// Print the description as is if no adjustment is required.