From 1d9f410810de6fbb9c974735e5e14dbebe1c0718 Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Fri, 22 Jul 2016 12:43:22 +0300 Subject: Adapt to fdstream extension --- bpkg/archive.cxx | 7 ++-- bpkg/auth.cxx | 110 ++++++++++++++++++++-------------------------------- bpkg/cfg-create.cxx | 32 +++++++-------- bpkg/checksum | 2 +- bpkg/checksum.cxx | 89 +++++++++++++++++++++++++++--------------- bpkg/fetch.cxx | 95 ++++++++++++++++++++++++++++----------------- bpkg/help.cxx | 8 +++- bpkg/pkg-verify.cxx | 26 ++----------- bpkg/rep-create.cxx | 17 ++++---- bpkg/rep-fetch.cxx | 2 - 10 files changed, 196 insertions(+), 192 deletions(-) diff --git a/bpkg/archive.cxx b/bpkg/archive.cxx index 0edf09d..f0596bf 100644 --- a/bpkg/archive.cxx +++ b/bpkg/archive.cxx @@ -93,15 +93,14 @@ namespace bpkg try { - ifdstream is (pr.in_ofd); - // Do not throw when eofbit is set (end of stream reached), and // when failbit is set (getline() failed to extract any character). // - is.exceptions (ifdstream::badbit); + ifdstream is (pr.in_ofd, ifdstream::badbit); string s; getline (is, s, '\0'); + is.close (); if (pr.wait ()) return s; @@ -113,7 +112,7 @@ namespace bpkg // Child exit status doesn't matter. Just wait for the process // completion and fall through. // - pr.wait (); + pr.wait (); // Check throw. } // While it is reasonable to assuming the child process issued diagnostics diff --git a/bpkg/auth.cxx b/bpkg/auth.cxx index c152834..a9eaa76 100644 --- a/bpkg/auth.cxx +++ b/bpkg/auth.cxx @@ -4,9 +4,9 @@ #include +#include #include #include // numeric_limits -#include #include // strlen(), strcmp() #include // ostreambuf_iterator, istreambuf_iterator @@ -118,21 +118,20 @@ namespace bpkg process pr (start_openssl ( co, "x509", {"-sha256", "-noout", "-fingerprint"}, true, true)); - ifdstream is (pr.in_ofd); - is.exceptions (ifdstream::badbit); - try { + ifdstream is (pr.in_ofd, fdstream_mode::skip); ofdstream os (pr.out_fd); - os.exceptions (ofdstream::badbit); os << pem; os.close (); string s; + getline (is, s); + is.close (); + const size_t n (19); - if (!(getline (is, s) && s.size () > n && - s.compare (0, n, "SHA256 Fingerprint=") == 0)) - throw istream::failure (""); + if (!(s.size () > n && s.compare (0, n, "SHA256 Fingerprint=") == 0)) + throw ifdstream::failure (""); string fp; @@ -142,27 +141,21 @@ namespace bpkg } catch (const invalid_argument&) { - throw istream::failure (""); + throw ifdstream::failure (""); } - is.close (); - if (pr.wait ()) return fp; // Fall through. // } - catch (const istream::failure&) + catch (const ios_base::failure&) { - // Child input writing or output reading error. - // - is.close (); - // Child exit status doesn't matter. Just wait for the process // completion and fall through. // - pr.wait (); + pr.wait (); // Check throw. } error << "unable to calculate certificate fingerprint for " @@ -267,13 +260,14 @@ namespace bpkg true, true)); - ifdstream is (pr.in_ofd); - is.exceptions (ifdstream::badbit); - try { + // We unset failbit to provide the detailed error description (which + // certificate field is missed) on failure. + // + ifdstream is (pr.in_ofd, fdstream_mode::skip, ifdstream::badbit); + ofdstream os (pr.out_fd); - os.exceptions (ofdstream::badbit); // Reading from and writing to the child process standard streams from // the same thread is generally a bad idea. Depending on the program @@ -413,27 +407,15 @@ namespace bpkg // Fall through. // } - catch (const istream::failure&) + catch (const ios_base::failure&) { - // Child input writing or output reading error. - // - is.close (); - // Child exit status doesn't matter. Just wait for the process // completion and fall through. // - pr.wait (); + pr.wait (); // Check throw. } catch (const invalid_argument& e) { - // Certificate parsing error. Skip until the end, not to offend the - // child with the broken pipe. Never knows how it will take it. - // - if (!is.eof ()) - is.ignore (numeric_limits::max ()); - - is.close (); - // If the child exited with an error status, then omit any output // parsing diagnostics since we were probably parsing garbage. // @@ -570,14 +552,13 @@ namespace bpkg try { - ofstream ofs; - ofs.exceptions (ofstream::badbit | ofstream::failbit); - ofs.open (f.string ()); + ofdstream ofs (f); ofs << *pem; + ofs.close (); } - catch (const ofstream::failure&) + catch (const ofdstream::failure& e) { - fail << "unable to write certificate to " << f; + fail << "unable to write certificate to " << f << ": " << e.what (); } } @@ -656,15 +637,15 @@ namespace bpkg { f = path::temp_path ("bpkg"); - ofstream ofs; - ofs.exceptions (ofstream::badbit | ofstream::failbit); - ofs.open (f.string ()); + ofdstream ofs (f); rm = auto_rmfile (f); ofs << *cert_pem; + ofs.close (); } - catch (const ofstream::failure&) + catch (const ofdstream::failure& e) { - fail << "unable to save certificate to temporary file " << f; + fail << "unable to save certificate to temporary file " << f + << ": " << e.what (); } catch (const system_error& e) { @@ -702,15 +683,13 @@ namespace bpkg true, true)); - ifdstream is (pr.in_ofd); - is.exceptions (ifdstream::badbit); - try { + ifdstream is (pr.in_ofd, fdstream_mode::skip); + // Write the signature to the openssl process input in the binary mode. // - ofdstream os (pr.out_fd, fdtranslate::binary); - os.exceptions (ofdstream::badbit); + ofdstream os (pr.out_fd, fdstream_mode::binary); for (const auto& c: sm.signature) os.put (c); // Sets badbit on failure. @@ -718,7 +697,9 @@ namespace bpkg os.close (); string s; - bool v (getline (is, s) && is.eof ()); + getline (is, s); + + bool v (is.eof ()); is.close (); if (pr.wait () && v) @@ -733,16 +714,12 @@ namespace bpkg // Fall through. // } - catch (const istream::failure&) + catch (const ios_base::failure&) { - // Child input writing or output reading error. - // - is.close (); - // Child exit status doesn't matter. Just wait for the process // completion and fall through. // - pr.wait (); + pr.wait (); // Check throw. } error << "unable to authenticate repository " << rl.canonical_name (); @@ -793,15 +770,14 @@ namespace bpkg process pr (start_openssl ( co, "pkeyutl", {"-sign", "-inkey", key_name.c_str ()}, true, true)); - // Read the signature from the openssl process output in the binary mode. - // - ifdstream is (pr.in_ofd, fdtranslate::binary); - is.exceptions (ifdstream::badbit); - try { + // Read the signature from the openssl process output in the binary + // mode. + // + ifdstream is (pr.in_ofd, fdstream_mode::binary | fdstream_mode::skip); + ofdstream os (pr.out_fd); - os.exceptions (ofdstream::badbit); os << sha256sum; os.close (); @@ -819,16 +795,12 @@ namespace bpkg // Fall through. // } - catch (const istream::failure&) + catch (const iostream::failure&) { - // Child input writing or output reading error. - // - is.close (); - // Child exit status doesn't matter. Just wait for the process // completion and fall through. // - pr.wait (); + pr.wait (); // Check throw. } error << "unable to sign repository " << r; diff --git a/bpkg/cfg-create.cxx b/bpkg/cfg-create.cxx index 3d2121e..b5b1f41 100644 --- a/bpkg/cfg-create.cxx +++ b/bpkg/cfg-create.cxx @@ -4,7 +4,7 @@ #include -#include +#include #include #include @@ -72,9 +72,7 @@ namespace bpkg path f (b / path ("bootstrap.build")); try { - ofstream ofs; - ofs.exceptions (ofstream::badbit | ofstream::failbit); - ofs.open (f.string ()); + ofdstream ofs (f); ofs << "# Maintained automatically by bpkg. Edit if you know what " << "you are doing." << endl @@ -85,10 +83,12 @@ namespace bpkg << "using config" << endl << "using test" << endl << "using install" << endl; + + ofs.close (); } - catch (const ofstream::failure&) + catch (const ofdstream::failure& e) { - fail << "unable to write to " << f; + fail << "unable to write to " << f << ": " << e.what (); } // Write build/root.build. @@ -96,9 +96,7 @@ namespace bpkg f = b / path ("root.build"); try { - ofstream ofs; - ofs.exceptions (ofstream::badbit | ofstream::failbit); - ofs.open (f.string ()); + ofdstream ofs (f); ofs << "# Maintained automatically by bpkg. Edit if you know what " << "you are doing." << endl @@ -109,10 +107,12 @@ namespace bpkg // for (const string& m: mods) ofs << "using " << m << endl; + + ofs.close (); } - catch (const ofstream::failure&) + catch (const ofdstream::failure& e) { - fail << "unable to write to " << f; + fail << "unable to write to " << f << ": " << e.what (); } // Write root buildfile. @@ -120,18 +120,18 @@ namespace bpkg f = c / path ("buildfile"); try { - ofstream ofs; - ofs.exceptions (ofstream::badbit | ofstream::failbit); - ofs.open (f.string ()); + ofdstream ofs (f); ofs << "# Maintained automatically by bpkg. Edit if you know what " << "you are doing." << endl << "#" << endl << "./:" << endl; + + ofs.close (); } - catch (const ofstream::failure&) + catch (const ofdstream::failure& e) { - fail << "unable to write to " << f; + fail << "unable to write to " << f << ": " << e.what (); } // Configure. diff --git a/bpkg/checksum b/bpkg/checksum index 3ef35cc..c0dbb6b 100644 --- a/bpkg/checksum +++ b/bpkg/checksum @@ -18,7 +18,7 @@ namespace bpkg string sha256 (const common_options&, const char* buf, size_t n); - // The same but for a stream (if ifstream, open in binary mode). + // The same but for a stream (if ifdstream, open in binary mode). // string sha256 (const common_options&, istream&); diff --git a/bpkg/checksum.cxx b/bpkg/checksum.cxx index 3c9c4e5..023e641 100644 --- a/bpkg/checksum.cxx +++ b/bpkg/checksum.cxx @@ -4,7 +4,6 @@ #include -#include #include #include @@ -36,21 +35,33 @@ namespace bpkg { process pr (args, 0, -1, 1); // Redirect STDOUT and STDERR to a pipe. - ifdstream is (pr.in_ofd); - string l; - getline (is, l); + try + { + ifdstream is (pr.in_ofd); + + string l; + getline (is, l); + is.close (); - return - l == "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" - && pr.wait (); + return + pr.wait () && + l == + "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"; + } + catch (const ifdstream::failure&) + { + // Fall through. + } } catch (const process_error& e) { if (e.child ()) exit (1); - return false; + // Fall through. } + + return false; } static process @@ -89,19 +100,30 @@ namespace bpkg { process pr (args, 0, -1); // Redirect STDOUT to a pipe. - ifdstream is (pr.in_ofd); - string l; - getline (is, l); + try + { + ifdstream is (pr.in_ofd, fdstream_mode::skip); + + string l; + getline (is, l); + is.close (); - return l.compare (0, 9, "sha256sum") == 0 && pr.wait (); + return pr.wait () && l.compare (0, 9, "sha256sum") == 0; + } + catch (const ifdstream::failure&) + { + // Fall through. + } } catch (const process_error& e) { if (e.child ()) exit (1); - return false; + // Fall through. } + + return false; } static process @@ -140,19 +162,30 @@ namespace bpkg { process pr (args, 0, -1); // Redirect STDOUT to a pipe. - ifdstream is (pr.in_ofd); - string l; - getline (is, l); + try + { + ifdstream is (pr.in_ofd); + + string l; + getline (is, l); + is.close (); - return l.size () != 0 && l[0] >= '0' && l[0] <= '9' && pr.wait (); + return pr.wait () && l.size () != 0 && l[0] >= '0' && l[0] <= '9'; + } + catch (const ifdstream::failure&) + { + // Fall through. + } } catch (const process_error& e) { if (e.child ()) exit (1); - return false; + // Fall through. } + + return false; } static process @@ -273,7 +306,7 @@ namespace bpkg // Prevent any data modifications on the way to the hashing program. // - fdmode (pr.out_fd, fdtranslate::binary); + fdmode (pr.out_fd, fdstream_mode::binary); return pr; } catch (const process_error& e) @@ -294,11 +327,8 @@ namespace bpkg try { + ifdstream is (pr.in_ofd, fdstream_mode::skip); ofdstream os (pr.out_fd); - os.exceptions (ofdstream::badbit | ofdstream::failbit); - - ifdstream is (pr.in_ofd); - is.exceptions (ifdstream::badbit | ifdstream::failbit); os << &sb; os.close (); @@ -319,7 +349,7 @@ namespace bpkg return s; } - // Child existed with an error, fall through. + // Child exited with an error, fall through. } // Ignore these exceptions if the child process exited with an error status // since that's the source of the failure. @@ -373,17 +403,12 @@ namespace bpkg try { - ifstream ifs (f.string (), ios::binary); - if (!ifs.is_open ()) - fail << "unable to open " << f << " in read mode"; - - ifs.exceptions (ofstream::badbit | ofstream::failbit); - + ifdstream ifs (f, ios::binary); return sha256 (o, ifs); } - catch (const iostream::failure&) + catch (const iostream::failure& e) { - error << "unable read " << f; + error << "unable read " << f << ": " << e.what (); throw failed (); } } diff --git a/bpkg/fetch.cxx b/bpkg/fetch.cxx index c4e441a..e095785 100644 --- a/bpkg/fetch.cxx +++ b/bpkg/fetch.cxx @@ -4,7 +4,6 @@ #include -#include #include #include @@ -44,12 +43,22 @@ namespace bpkg { process pr (args, 0, -1); // Redirect STDOUT to a pipe. - ifdstream is (pr.in_ofd); string l; - getline (is, l); - if (l.compare (0, 9, "GNU Wget ") != 0) + try + { + ifdstream is (pr.in_ofd, fdstream_mode::skip); + + getline (is, l); + is.close (); + + if (!(pr.wait () && l.compare (0, 9, "GNU Wget ") == 0)) + return false; + } + catch (const ifdstream::failure&) + { return false; + } // Extract the version. If something goes wrong, set the version // to 0 so that we treat it as a really old wget. @@ -74,7 +83,7 @@ namespace bpkg l4 ([&]{trace << "unable to extract version from '" << l << "'";}); } - return pr.wait (); + return true; } catch (const process_error& e) { @@ -176,19 +185,30 @@ namespace bpkg { process pr (args, 0, -1); // Redirect STDOUT to a pipe. - ifdstream is (pr.in_ofd); - string l; - getline (is, l); + try + { + ifdstream is (pr.in_ofd, fdstream_mode::skip); - return l.compare (0, 5, "curl ") == 0 && pr.wait (); + string l; + getline (is, l); + is.close (); + + return pr.wait () && l.compare (0, 5, "curl ") == 0; + } + catch (const ifdstream::failure&) + { + // Fall through. + } } catch (const process_error& e) { if (e.child ()) exit (1); - return false; + // Fall through. } + + return false; } static process @@ -276,19 +296,30 @@ namespace bpkg { process pr (args, 0, -1, 1); // Redirect STDOUT and STDERR to a pipe. - ifdstream is (pr.in_ofd); - string l; - getline (is, l); + try + { + ifdstream is (pr.in_ofd, fdstream_mode::skip); - return l.compare (0, 13, "usage: fetch ") == 0; + string l; + getline (is, l); + is.close (); + + return pr.wait () && l.compare (0, 13, "usage: fetch ") == 0; + } + catch (const ifdstream::failure&) + { + // Fall through. + } } catch (const process_error& e) { if (e.child ()) exit (1); - return false; + // Fall through. } + + return false; } static process @@ -546,8 +577,7 @@ namespace bpkg // calculation, then use the binary data to create the text stream for // the manifest parsing. // - ifdstream is (pr.in_ofd, fdtranslate::binary); - is.exceptions (ifdstream::badbit | ifdstream::failbit); + ifdstream is (pr.in_ofd, fdstream_mode::binary); stringstream bs (ios::in | ios::out | ios::binary); bs << is.rdbuf (); @@ -604,18 +634,15 @@ namespace bpkg try { - ifstream ifs (f.string (), ios::binary); - if (!ifs.is_open ()) - fail << "unable to open " << f << " in read mode"; - - auto_rm arm (r); - - ofstream ofs (r.string (), ios::binary); - if (!ofs.is_open ()) - fail << "unable to open " << r << " in write mode"; + // @@ Shouldn't we use cpfile() instead? + // + // @@ Yes, definitely. + // + ifdstream ifs (f, ios::binary); - ifs.exceptions (ofstream::badbit | ofstream::failbit); - ofs.exceptions (ofstream::badbit | ofstream::failbit); + auto_rm arm; + ofdstream ofs (r, ios::binary); + arm = auto_rm (r); ofs << ifs.rdbuf (); @@ -626,9 +653,9 @@ namespace bpkg arm.cancel (); } - catch (const iostream::failure&) + catch (const ifdstream::failure& e) { - fail << "unable to copy " << f << " to " << r << ": io error"; + fail << "unable to copy " << f << " to " << r << ": " << e.what (); } return r; @@ -655,9 +682,7 @@ namespace bpkg if (o != nullptr) sha256sum = sha256 (*o, f); // Read file in the binary mode. - ifstream ifs; - ifs.exceptions (ofstream::badbit | ofstream::failbit); - ifs.open (f.string ()); // Open file in the text mode. + ifdstream ifs (f); // Open file in the text mode. manifest_parser mp (ifs, f.string ()); return make_pair (M (mp, ignore_unknown), move (sha256sum)); @@ -666,9 +691,9 @@ namespace bpkg { error (e.name, e.line, e.column) << e.description; } - catch (const ifstream::failure&) + catch (const ifdstream::failure& e) { - error << "unable to read from " << f; + error << "unable to read from " << f << ": " << e.what (); } throw failed (); diff --git a/bpkg/help.cxx b/bpkg/help.cxx index cf496ca..3d5efb8 100644 --- a/bpkg/help.cxx +++ b/bpkg/help.cxx @@ -50,10 +50,16 @@ namespace bpkg // return p.wait () ? 0 : 1; } + // Catch ios_base::failure as std::system_error together with the + // pager-specific exceptions. + // catch (const system_error& e) { error << "pager failed: " << e.what (); - throw failed (); + + // Fall through. } + + throw failed (); } } diff --git a/bpkg/pkg-verify.cxx b/bpkg/pkg-verify.cxx index 3c79cbd..ea072d9 100644 --- a/bpkg/pkg-verify.cxx +++ b/bpkg/pkg-verify.cxx @@ -4,8 +4,6 @@ #include -#include - #include #include @@ -38,11 +36,9 @@ namespace bpkg // process pr (start_extract (co, af, mf, diag)); - ifdstream is (pr.in_ofd); - is.exceptions (ifdstream::badbit | ifdstream::failbit); - try { + ifdstream is (pr.in_ofd, fdstream_mode::skip); manifest_parser mp (is, mf.string ()); package_manifest m (mp, iu); is.close (); @@ -73,15 +69,6 @@ namespace bpkg // catch (const manifest_parsing& e) { - // Before we used to just close the file descriptor to signal to the - // other end that we are not interested in the rest. But tar doesn't - // take this very well (SIGPIPE). So now we are going to skip until - // the end. - // - if (!is.eof ()) - is.ignore (numeric_limits::max ()); - is.close (); - if (pr.wait ()) { if (diag) @@ -93,8 +80,6 @@ namespace bpkg } catch (const ifdstream::failure&) { - is.close (); - if (pr.wait ()) { if (diag) @@ -144,10 +129,7 @@ namespace bpkg try { - ifstream ifs; - ifs.exceptions (ifstream::badbit | ifstream::failbit); - ifs.open (mf.string ()); - + ifdstream ifs (mf); manifest_parser mp (ifs, mf.string ()); package_manifest m (mp, iu); @@ -175,10 +157,10 @@ namespace bpkg throw failed (); } - catch (const ifstream::failure&) + catch (const ifdstream::failure& e) { if (diag) - error << "unable to read from " << mf; + error << "unable to read from " << mf << ": " << e.what (); throw failed (); } diff --git a/bpkg/rep-create.cxx b/bpkg/rep-create.cxx index 61e3f81..16da164 100644 --- a/bpkg/rep-create.cxx +++ b/bpkg/rep-create.cxx @@ -5,9 +5,9 @@ #include #include -#include #include +#include #include // dir_iterator #include @@ -217,17 +217,15 @@ namespace bpkg try { { - ofstream ofs; - ofs.exceptions (ofstream::badbit | ofstream::failbit); - // While we can do nothing about repositories files edited on Windows // and littered with the carriage return characters, there is no // reason to litter the auto-generated packages and signature files. // - ofs.open (p.string (), ofstream::out | ofstream::binary); + ofdstream ofs (p, ios::binary); manifest_serializer s (ofs, p.string ()); manifests.serialize (s); + ofs.close (); } const optional& cert (rms.back ().certificate); @@ -245,12 +243,11 @@ namespace bpkg p = path (d / signature); - ofstream ofs; - ofs.exceptions (ofstream::badbit | ofstream::failbit); - ofs.open (p.string (), ofstream::out | ofstream::binary); + ofdstream ofs (p, ios::binary); manifest_serializer s (ofs, p.string ()); m.serialize (s); + ofs.close (); } else { @@ -266,9 +263,9 @@ namespace bpkg { fail << "unable to save manifest: " << e.description; } - catch (const ofstream::failure&) + catch (const ofdstream::failure& e) { - fail << "unable to write to " << p; + fail << "unable to write to " << p << ": " << e.what (); } if (verb) diff --git a/bpkg/rep-fetch.cxx b/bpkg/rep-fetch.cxx index fb22986..d42ae6c 100644 --- a/bpkg/rep-fetch.cxx +++ b/bpkg/rep-fetch.cxx @@ -4,8 +4,6 @@ #include -#include - #include #include -- cgit v1.1