//------------------------------------------------------------------------------ intrusive_ptr<sink_base> console() { if(con) return con; n_throw(logic_error) << ei_msg_c("Call init_console() first!"); }
//------------------------------------------------------------------------------ void init_console() { if(con) n_throw(logic_error) << ei_msg_c("init_console() has already been called."); con = new console_(); }
//------------------------------------------------------------------------------ protocol_type protocol_server::get(const char *name) const { const ::protoent *pe = ::getprotobyname(name); if(!pe) { n_throw(network_error) << ei_msg(fmt::to_string("getprotobyname() failed. name: ", name)); } return pe->p_proto; }
//------------------------------------------------------------------------------ void cout_impl_::write(const char *x, streamsize n) { while(n > 0) { const size_t r = fwrite(x, 1, n, stdout); if(ferror(stdout)) n_throw(io_error) << ei_msg_c("fwrite() failed."); x += r; n -= r; } }
//------------------------------------------------------------------------------ void create_directory(const path &p, file_permission_type fp) { const int r = ::mkdir(p.c_str(), fp); if(r != 0) { n_throw(system::system_error) << ei_msg_c("mkdir() failed.") << ei_path(p) << system::ei_error_code(system::error_code( errno, system::system_category())); } }
//------------------------------------------------------------------------------ void rename(const path &op, const path &np) { const int r = ::rename(op.c_str(), np.c_str()); if(r != 0) { n_throw(system::system_error) << ei_msg_c("rename() failed.") << ei_path(op) << system::ei_error_code(system::error_code( errno, system::system_category())); } }
//------------------------------------------------------------------------------ path read_symlink(const path &p) { string buf; buf.resize(4096); const ::ssize_t r = ::readlink(p.c_str(), buf.data(), buf.size()); if(r == -1) { n_throw(system::system_error) << ei_msg_c("readlink() failed.") << ei_path(p) << system::ei_error_code(system::error_code( errno, system::system_category())); } buf.resize(r); return path(foundation::move(buf)); }
//------------------------------------------------------------------------------ void cout_impl_::flush() { if(fflush(stdout)) n_throw(io_error) << ei_msg_c("fflush() failed."); }
//------------------------------------------------------------------------------ void cout_impl_::put(char x) { if(EOF == fputc(x, stdout)) n_throw(io_error) << ei_msg_c("fputc() failed."); }
//------------------------------------------------------------------------------ int main(int argc, char **argv) { init_log(); try { fnd::vector<fnd::const_cstring> opt_paths; unsigned opt_type_mask = regular_f; size_t opt_max_depth = math::maximum<size_t>(); bool opt_canonical = false; bool opt_newline = false; fnd::const_cstring opt_interpolate; fnd::const_cstring opt_rx; regex::regex_option_type opt_rx_type = regex::ecma; bool opt_rx_search = true; int quit = -1; auto opts_ctx = fnd::opts::context( [&] (fnd::const_cstring id, fnd::const_cstring val, const size_t i) { gl->error("Unknown parameter: '-", id, "'."); quit = EXIT_FAILURE; }, [&] (fnd::const_cstring val, const size_t i) { if(i > 0) opt_paths.push_back(val); return true; }, fnd::opts::argument( [&] (fnd::const_cstring id, fnd::const_cstring val, size_t i) { if(!val.empty()) gl->warning("Value ignored. '-", id, "' is a flag."); print_help(argv[0]); quit = EXIT_SUCCESS; return false; }, "help", "h"), fnd::opts::argument( [&] (fnd::const_cstring id, fnd::const_cstring val, size_t i) { if(!val.empty()) gl->warning("Value ignored. '-", id, "' is a flag."); print_license(); quit = EXIT_SUCCESS; return false; }, "license"), fnd::opts::argument( [&] (fnd::const_cstring id, fnd::const_cstring val, size_t i) { if(!val.empty()) gl->warning("Value ignored. '-", id, "' is a flag."); print_version(); quit = EXIT_SUCCESS; return false; }, "version"), fnd::opts::argument( [&] (fnd::const_cstring id, fnd::const_cstring val, size_t i) { if(!val.empty()) gl->warning("Value ignored. '-", id, "' is a flag."); if(1 != i) gl->warning("'-", id, "' should be the first argument!"); gl->threshold(fnd::qlog::level::debug); return true; }, "verbose", "v"), fnd::opts::argument( [&] (fnd::const_cstring id, fnd::const_cstring val, size_t i) { if(val.empty()) { quit = EXIT_FAILURE; gl->error("Missing value. '-", id, "=?'."); return false; } unsigned mask = 0; for(const char c : val) { switch(c) { case 'f': mask |= regular_f; break; case 's': mask |= symlink_f; break; case 'd': mask |= directory_f; break; case 'b': mask |= block_f; break; case 'i': mask |= fifo_f; break; case 'k': mask |= socket_f; break; case 'c': mask |= character_device_f; break; case 'a': mask = all_f; default: quit = EXIT_FAILURE; gl->error("Invalid value. '-", id, "=#ERROR'"); return false; } } opt_type_mask = mask; return true; }, "type", "t"), fnd::opts::argument( [&] (fnd::const_cstring id, fnd::const_cstring val, size_t i) { if(val.empty()) { quit = EXIT_FAILURE; gl->error("Missing value. '-", id, "=?'."); return false; } auto r = fmt::to_integer<size_t>( val, 10, fnd::nothrow_tag()); if(!r.valid()) { quit = EXIT_FAILURE; gl->error("Expected a positive number. ", "--", id, "=#ERROR"); return false; } opt_max_depth = r.get(); return true; }, "depth", "d"), fnd::opts::argument( [&] (fnd::const_cstring id, fnd::const_cstring val, size_t i) { if(!val.empty()) gl->warning("Value ignored. '-", id, "' is a flag."); opt_canonical = true; return true; }, "canonical", "c"), fnd::opts::argument( [&] (fnd::const_cstring id, fnd::const_cstring val, size_t i) { if(!val.empty()) gl->warning("Value ignored. '-", id, "' is a flag."); opt_newline = true; return true; }, "newline", "n"), fnd::opts::argument( [&] (fnd::const_cstring id, fnd::const_cstring val, size_t i) { if(val.empty()) { quit = EXIT_FAILURE; gl->error("Missing value. '-", id, "=?'."); return false; } opt_interpolate = val; return true; }, "interpolate", "i"), fnd::opts::argument( [&] (fnd::const_cstring id, fnd::const_cstring val, size_t i) { if(val.empty()) { quit = EXIT_FAILURE; gl->error("Missing value. '-", id, "=?'."); return false; } opt_rx = val; return true; }, "regex", "r"), fnd::opts::argument( [&] (fnd::const_cstring id, fnd::const_cstring val, size_t i) { if(val.empty()) { quit = EXIT_FAILURE; gl->error("Missing value. '-", id, "=?'."); return false; } if(val == "grep") opt_rx_type = regex::grep; else if(val == "egrep") opt_rx_type = regex::egrep; else if(val == "ecma") opt_rx_type = regex::ecma; else if(val == "posix") opt_rx_type = regex::basic_posix; else if(val == "eposix") opt_rx_type = regex::extended_posix; else { quit = EXIT_FAILURE; gl->error("Invalid value. '-", id, "=#ERROR'"); return false; } return true; }, "regex-type", "rt"), fnd::opts::argument( [&] (fnd::const_cstring id, fnd::const_cstring val, size_t i) { if(!val.empty()) gl->warning("Value ignored. '-", id, "' is a flag."); opt_rx_search = false; return true; }, "regex-match", "rm")); fnd::opts::parse_command_line(opts_ctx, argc, argv); if(quit != -1) return quit; regex::default_regex *rx = nullptr; n_scope_exit(&) { if(rx) delete rx; }; if(!opt_rx.empty() && opt_rx != ".*") { try { rx = new regex::default_regex( opt_rx, regex::optimize | opt_rx_type); } catch(const regex::regex_error &e) { gl->error("Compiling a regular expression failed."); gl->debug(fnd::diagnostic_information(e)); return EXIT_FAILURE; } } auto f = [&](fs::path p, size_t level) -> bool { const fs::file_status stat = fs::status(p); switch(fs::type(stat)) { case fs::file_type::regular: if((opt_type_mask & regular_f) == 0u) return true; break; case fs::file_type::symlink: if((opt_type_mask & symlink_f) == 0u) return true; break; case fs::file_type::directory: if((opt_type_mask & directory_f) == 0u) return true; break; case fs::file_type::block: if((opt_type_mask & block_f) == 0u) return true; break; case fs::file_type::fifo: if((opt_type_mask & fifo_f) == 0u) return true; break; case fs::file_type::socket: if((opt_type_mask & socket_f) == 0u) return true; break; case fs::file_type::character_device: if((opt_type_mask & character_device_f) == 0u) return true; break; default: n_throw(logic_error); } if(rx) { if(opt_rx_search) { if(!regex::search(p.str(), *rx)) return true; } else { if(!regex::match(p.str(), *rx)) return true; } } if(opt_interpolate.empty()) { fmt::fwrite(io::cout, p); } else { try { fmt::interp( io::cout, opt_interpolate, p, fs::to_cstr(fs::type(stat)), fs::size(stat), fs::last_access(stat), fs::last_modification(stat), fs::last_status_change(stat), fs::pretty_permissions(stat), level); } catch(...) { n_throw(runtime_error) << fnd::ei_msg_c("String interpolation failed.") << fnd::ei_exc(fnd::current_exception()) << fs::ei_path(p); } } if(opt_newline) io::put(io::cout, '\n'); else io::put(io::cout, ' '); return true; }; if(opt_paths.empty()) opt_paths.emplace_back("."); for(fnd::const_cstring x : opt_paths) { const fs::path path = opt_canonical ? fs::canonical(x) : x; fs::recursive_scan(path, opt_max_depth, f); } } catch(const fnd::exception &e) { const fs::ei_path *p = fnd::get_error_info<fs::ei_path>(e); gl->fatal("Internal Error"); if(p) gl->fatal("Path: ", p->value()); gl->debug(fnd::diagnostic_information(e)); return EXIT_FAILURE; } catch(...) { gl->fatal("Internal Error"); gl->debug(fnd::diagnostic_information(fnd::current_exception())); return EXIT_FAILURE; } return EXIT_SUCCESS; }