Index: uspace/lib/cpp/Makefile
===================================================================
--- uspace/lib/cpp/Makefile	(revision 6fa83f01510d51902aaa3ba7f8f7e1e8d6643fab)
+++ uspace/lib/cpp/Makefile	(revision 68cfab1fd355ca0e57b9ce60ccb8f4fcc6909771)
@@ -47,4 +47,5 @@
 	src/new.cpp \
 	src/string.cpp \
+	src/system_error.cpp \
 	src/thread.cpp \
 	src/typeindex.cpp \
Index: uspace/lib/cpp/include/impl/system_error.hpp
===================================================================
--- uspace/lib/cpp/include/impl/system_error.hpp	(revision 6fa83f01510d51902aaa3ba7f8f7e1e8d6643fab)
+++ uspace/lib/cpp/include/impl/system_error.hpp	(revision 68cfab1fd355ca0e57b9ce60ccb8f4fcc6909771)
@@ -1,4 +1,4 @@
 /*
- * Copyright (c) 2017 Jaroslav Jindrak
+ * Copyright (c) 2018 Jaroslav Jindrak
  * All rights reserved.
  *
@@ -30,9 +30,338 @@
 #define LIBCPP_SYSTEM_ERROR
 
+#include <internal/aux.hpp>
+#include <stdexcept>
+
 namespace std
 {
-    class system_error
-    {
-        // TODO: implement
+    class error_condition;
+    class error_code;
+
+    enum class errc
+    { // TODO: add matching values
+        address_family_not_supported,
+        address_in_use,
+        address_not_available,
+        already_connected,
+        argument_list_too_long,
+        argument_out_of_domain,
+        bad_address,
+        bad_file_descriptor,
+        bad_message,
+        broken_pipe,
+        connection_aborted,
+        connection_already_in_progress,
+        connection_refused,
+        connection_reset,
+        cross_device_link,
+        destination_address_required,
+        device_or_resource_busy,
+        directory_not_empty,
+        executable_format_error,
+        file_exists,
+        file_too_large,
+        filename_too_long,
+        function_not_supported,
+        host_unreachable,
+        identifier_removed,
+        illegal_byte_sequence,
+        inappropriate_io_control_operation,
+        interrupted,
+        invalid_argument,
+        invalid_seek,
+        io_error,
+        is_a_directory,
+        message_size,
+        network_down,
+        network_reset,
+        network_unreachable,
+        no_buffer_space,
+        no_child_process,
+        no_link,
+        no_lock_available,
+        no_message_available,
+        no_message,
+        no_protocol_option,
+        no_space_on_device,
+        no_stream_resources,
+        no_such_device_or_address,
+        no_such_device,
+        no_such_file_or_directory,
+        no_such_process,
+        not_a_directory,
+        not_a_socket,
+        not_a_stream,
+        not_connected,
+        not_enough_memory,
+        not_supported,
+        operation_canceled,
+        operation_in_progress,
+        operation_not_permitted,
+        operation_not_supported,
+        operation_would_block,
+        owner_dead,
+        permission_denied,
+        protocol_error,
+        protocol_not_supported,
+        read_only_file_system,
+        resource_deadlock_would_occur,
+        resource_unavailable_try_again,
+        result_out_of_range,
+        state_not_recoverable,
+        stream_timeout,
+        text_file_busy,
+        timed_out,
+        too_many_files_open_in_system,
+        too_many_files_open,
+        too_many_links,
+        too_many_symbolic_link_levels,
+        value_too_large,
+        wrong_protocol_type
+    };
+
+    template<class>
+    struct is_error_code_enum: false_type
+    { /* DUMMY BODY */ };
+
+    template<>
+    struct is_error_code_enum<errc>: true_type
+    { /* DUMMY BODY */ };
+
+    template<class T>
+    inline constexpr bool is_error_code_enum_v = is_error_code_enum<T>::value;
+
+    template<class>
+    struct is_error_condition_enum: false_type
+    { /* DUMMY BODY */ };
+
+    template<>
+    struct is_error_condition_enum<errc>: true_type
+    { /* DUMMY BODY */ };
+
+    template<class T>
+    inline constexpr bool is_error_condition_enum_v = is_error_condition_enum<T>::value;
+
+    /**
+     * 19.5.1, class error_category:
+     */
+
+    class error_category
+    {
+        public:
+            constexpr error_category() noexcept = default;
+            virtual ~error_category();
+
+            error_category(const error_category&) = delete;
+            error_category& operator=(const error_category&) = delete;
+
+            virtual const char* name() const noexcept = 0;
+            virtual error_condition default_error_condition(int) const noexcept;
+            virtual bool equivalent(int, const error_condition&) const noexcept;
+            virtual bool equivalent(const error_code&, int) const noexcept;
+            virtual string message(int) const = 0;
+
+            bool operator==(const error_category&) const noexcept;
+            bool operator!=(const error_category&) const noexcept;
+            bool operator<(const error_category&) const noexcept;
+    };
+
+    const error_category& generic_category() noexcept;
+    const error_category& system_category() noexcept;
+
+    /**
+     * 19.5.2, class error_code:
+     */
+
+    class error_code
+    {
+        public:
+            /**
+             * 19.5.2.2, constructors:
+             */
+
+            error_code() noexcept;
+            error_code(int, const error_category&) noexcept;
+
+            template<class ErrorCodeEnum>
+            error_code(
+                enable_if_t<is_error_code_enum_v<ErrorCodeEnum>, ErrorCodeEnum> e
+            ) noexcept
+            {
+                val_ = static_cast<int>(e);
+                cat_ = &generic_category();
+            }
+
+            /**
+             * 19.5.2.3, modifiers:
+             */
+
+            void assign(int, const error_category&) noexcept;
+
+            template<class ErrorCodeEnum>
+            error_code& operator=(
+                enable_if_t<is_error_code_enum_v<ErrorCodeEnum>, ErrorCodeEnum> e
+            ) noexcept
+            {
+                val_ = static_cast<int>(e);
+                cat_ = &generic_category();
+
+                return *this;
+            }
+
+            void clear() noexcept;
+
+            /**
+             * 19.5.2.4, observers:
+             */
+
+            int value() const noexcept;
+            const error_category& category() const noexcept;
+            error_condition default_error_condition() const noexcept;
+            string message() const;
+
+            explicit operator bool() const noexcept
+            {
+                return val_ != 0;
+            }
+
+        private:
+            int val_;
+            const error_category* cat_;
+    };
+
+    /**
+     * 19.5.2.5, non-member functions:
+     */
+
+    error_code make_error_code(errc e) noexcept;
+    bool operator<(const error_code&, const error_code&) noexcept;
+
+    template<class Char, class Traits>
+    basic_ostream<Char, Traits>& operator<<(basic_ostream<Char, Traits>& os,
+                                            const error_code& ec)
+    {
+        return os << ec.category().name() << ": " << ec.value();
+    }
+
+    /**
+     * 19.5.3, class error_condition:
+     */
+
+    class error_condition
+    {
+        public:
+            /**
+             * 19.5.3.2, constructors:
+             */
+
+            error_condition() noexcept;
+            error_condition(int, const error_category&) noexcept;
+
+            template<class ErrorCodeEnum>
+            error_condition(
+                enable_if_t<is_error_code_enum_v<ErrorCodeEnum>, ErrorCodeEnum> e
+            ) noexcept
+            {
+                val_ = static_cast<int>(e);
+                cat_ = &generic_category();
+            }
+
+            /**
+             * 19.5.3.3, modifiers:
+             */
+
+            void assign(int, const error_category&) noexcept;
+
+            template<class ErrorCodeEnum>
+            error_condition& operator=(
+                enable_if_t<is_error_code_enum_v<ErrorCodeEnum>, ErrorCodeEnum> e
+            ) noexcept
+            {
+                val_ = static_cast<int>(e);
+                cat_ = &generic_category();
+
+                return *this;
+            }
+
+            void clear() noexcept;
+
+            /**
+             * 19.5.3.4, observers:
+             */
+
+            int value() const noexcept;
+            const error_category& category() const noexcept;
+            string message() const;
+
+            explicit operator bool() const noexcept
+            {
+                return val_ != 0;
+            }
+
+        private:
+            int val_;
+            const error_category* cat_;
+    };
+
+    /**
+     * 19.5.3.4, non-member functions:
+     */
+
+    error_condition make_error_condition(errc e) noexcept;
+    bool operator<(const error_condition&, const error_condition&) noexcept;
+
+    /**
+     * 19.5.4, comparison operators:
+     */
+
+    bool operator==(const error_code&, const error_code&) noexcept;
+    bool operator==(const error_code&, const error_condition&) noexcept;
+    bool operator==(const error_condition&, const error_code&) noexcept;
+    bool operator==(const error_condition&, const error_condition&) noexcept;
+    bool operator!=(const error_code&, const error_code&) noexcept;
+    bool operator!=(const error_code&, const error_condition&) noexcept;
+    bool operator!=(const error_condition&, const error_code&) noexcept;
+    bool operator!=(const error_condition&, const error_condition&) noexcept;
+
+    /**
+     * 19.5.6, class system_error:
+     */
+
+    class system_error: public runtime_error
+    {
+        public:
+            system_error(error_code, const string&);
+            system_error(error_code, const char*);
+            system_error(error_code);
+            system_error(int, const error_category&, const string&);
+            system_error(int, const error_category&, const char*);
+            system_error(int, const error_category&);
+
+            const error_code& code() const noexcept;
+
+            const char* what() const noexcept override;
+
+        private:
+            error_code code_;
+            string what_;
+    };
+
+    /**
+     * 19.5.5, hash support:
+     */
+
+    template<class>
+    struct hash;
+
+    template<>
+    struct hash<error_code>
+    {
+        size_t operator()(const error_code& ec) const noexcept
+        {
+            return static_cast<size_t>(ec.value());
+        }
+
+        using result_type   = size_t;
+        using argument_type = error_code;
     };
 }
Index: uspace/lib/cpp/src/system_error.cpp
===================================================================
--- uspace/lib/cpp/src/system_error.cpp	(revision 68cfab1fd355ca0e57b9ce60ccb8f4fcc6909771)
+++ uspace/lib/cpp/src/system_error.cpp	(revision 68cfab1fd355ca0e57b9ce60ccb8f4fcc6909771)
@@ -0,0 +1,299 @@
+/*
+ * Copyright (c) 2018 Jaroslav Jindrak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <functional>
+#include <string>
+#include <system_error>
+
+namespace std
+{
+    error_category::~error_category()
+    { /* DUMMY BODY */ }
+
+    error_condition error_category::default_error_condition(int code) const noexcept
+    {
+        return error_condition{code, *this};
+    }
+
+    bool error_category::equivalent(int code, const error_condition& cond) const noexcept
+    {
+        return default_error_condition(code) == cond;
+    }
+
+    bool error_category::equivalent(const error_code& ec, int cond) const noexcept
+    {
+        return *this == ec.category() && ec.value() == cond;
+    }
+
+    bool error_category::operator==(const error_category& rhs) const noexcept
+    {
+        return this == &rhs;
+    }
+
+    bool error_category::operator!=(const error_category& rhs) const noexcept
+    {
+        return !(*this == rhs);
+    }
+
+    bool error_category::operator<(const error_category& rhs) const noexcept
+    {
+        return less<const error_category*>{}(this, &rhs);
+    }
+
+    namespace aux
+    {
+        class generic_category_t: public error_category
+        {
+            public:
+                generic_category_t()
+                    : error_category{}
+                { /* DUMMY BODY */ }
+
+                ~generic_category_t() = default;
+
+                const char* name() const noexcept override
+                {
+                    return "generic";
+                }
+
+                string message(int ev) const override
+                {
+                    return "ev: " + std::to_string(ev);
+                }
+        };
+
+        class system_category_t: public error_category
+        {
+            public:
+                system_category_t()
+                    : error_category{}
+                { /* DUMMY BODY */ }
+
+                ~system_category_t() = default;
+
+                const char* name() const noexcept override
+                {
+                    return "system";
+                }
+
+                string message(int ev) const override
+                {
+                    return "ev: " + std::to_string(ev);
+                }
+        };
+    }
+
+    const error_category& generic_category() noexcept
+    {
+        static aux::generic_category_t instance{};
+
+        return instance;
+    }
+
+    const error_category& system_category() noexcept
+    {
+        static aux::system_category_t instance{};
+
+        return instance;
+    }
+
+    error_code::error_code() noexcept
+        : val_{}, cat_{&system_category()}
+    { /* DUMMY BODY */ }
+
+    error_code::error_code(int val, const error_category& cat) noexcept
+        : val_{val}, cat_{&cat}
+    { /* DUMMY BODY */ }
+
+    void error_code::assign(int val, const error_category& cat) noexcept
+    {
+        val_ = val;
+        cat_ = &cat;
+    }
+
+    void error_code::clear() noexcept
+    {
+        val_ = 0;
+        cat_ = &system_category();
+    }
+
+    int error_code::value() const noexcept
+    {
+        return val_;
+    }
+
+    const error_category& error_code::category() const noexcept
+    {
+        return *cat_;
+    }
+
+    error_condition error_code::default_error_condition() const noexcept
+    {
+        return cat_->default_error_condition(val_);
+    }
+
+    string error_code::message() const
+    {
+        return cat_->message(val_);
+    }
+
+    error_code make_error_code(errc e) noexcept
+    {
+        return error_code{static_cast<int>(e), generic_category()};
+    }
+
+    bool operator<(const error_code& lhs, const error_code& rhs) noexcept
+    {
+        return lhs.category() < rhs.category() ||
+            (lhs.category() == rhs.category() && lhs.value() < rhs.value());
+    }
+
+    error_condition::error_condition() noexcept
+        : val_{}, cat_{&generic_category()}
+    { /* DUMMY BODY */ }
+
+    error_condition::error_condition(int val, const error_category& cat) noexcept
+        : val_{val}, cat_{&cat}
+    { /* DUMMY BODY */ }
+
+    void error_condition::assign(int val, const error_category& cat) noexcept
+    {
+        val_ = val;
+        cat_ = &cat;
+    }
+
+    void error_condition::clear() noexcept
+    {
+        val_ = 0;
+        cat_ = &generic_category();
+    }
+
+    int error_condition::value() const noexcept
+    {
+        return val_;
+    }
+
+    const error_category& error_condition::category() const noexcept
+    {
+        return *cat_;
+    }
+
+    string error_condition::message() const
+    {
+        return cat_->message(val_);
+    }
+
+    error_condition make_error_condition(errc e) noexcept
+    {
+        return error_condition{static_cast<int>(e), generic_category()};
+    }
+
+    bool operator<(const error_condition& lhs, const error_condition& rhs) noexcept
+    {
+        return lhs.category() < rhs.category() ||
+            (lhs.category() == rhs.category() && lhs.value() < rhs.value());
+    }
+
+    bool operator==(const error_code& lhs, const error_code& rhs) noexcept
+    {
+        return lhs.category() == rhs.category() && lhs.value() == rhs.value();
+    }
+
+    bool operator==(const error_code& lhs, const error_condition& rhs) noexcept
+    {
+        return lhs.category().equivalent(lhs.value(), rhs)
+            || rhs.category().equivalent(lhs, rhs.value());
+    }
+
+    bool operator==(const error_condition& lhs, const error_code& rhs) noexcept
+    {
+        return rhs.category().equivalent(rhs.value(), lhs)
+            || lhs.category().equivalent(rhs, lhs.value());
+    }
+
+    bool operator==(const error_condition& lhs, const error_condition& rhs) noexcept
+    {
+        return lhs.category() == rhs.category() && lhs.value() == rhs.value();
+    }
+
+    bool operator!=(const error_code& lhs, const error_code& rhs) noexcept
+    {
+        return !(lhs == rhs);
+    }
+
+    bool operator!=(const error_code& lhs, const error_condition& rhs) noexcept
+    {
+        return !(lhs == rhs);
+    }
+
+    bool operator!=(const error_condition& lhs, const error_code& rhs) noexcept
+    {
+        return !(lhs == rhs);
+    }
+
+    bool operator!=(const error_condition& lhs, const error_condition& rhs) noexcept
+    {
+        return !(lhs == rhs);
+    }
+
+    system_error::system_error(error_code ec, const string& what_arg)
+        : code_{ec}, what_{what_arg}
+    { /* DUMMY BODY */ }
+
+    system_error::system_error(error_code ec, const char* what_arg)
+        : code_{ec}, what_{what_arg}
+    { /* DUMMY BODY */ }
+
+    system_error::system_error(error_code ec)
+        : code_{ec}, what_{}
+    { /* DUMMY BODY */ }
+
+    system_error::system_error(int code, const error_category& cat,
+                               const string& what_arg)
+        : code_{code, cat}, what_{what_arg}
+    { /* DUMMY BODY */ }
+
+    system_error::system_error(int code, const error_category& cat,
+                               const char* what_arg)
+        : code_{code, cat}, what_{what_arg}
+    { /* DUMMY BODY */ }
+
+    system_error::system_error(int code, const error_category& cat)
+        : code_{code, cat}, what_{}
+    { /* DUMMY BODY */ }
+
+    const error_code& system_error::code() const noexcept
+    {
+        return code_;
+    }
+
+    const char* system_error::what() const noexcept
+    {
+        return what_.c_str();
+    }
+}
