You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
225 lines
9.9 KiB
225 lines
9.9 KiB
// Copyright 2014 The Chromium OS Authors. All rights reserved. |
|
// Use of this source code is governed by a BSD-style license that can be |
|
// found in the LICENSE file. |
|
|
|
#include <brillo/errors/error_codes.h> |
|
|
|
#include <base/posix/safe_strerror.h> |
|
|
|
namespace brillo { |
|
namespace errors { |
|
|
|
namespace dbus { |
|
const char kDomain[] = "dbus"; |
|
} // namespace dbus |
|
|
|
namespace json { |
|
const char kDomain[] = "json_parser"; |
|
const char kParseError[] = "json_parse_error"; |
|
const char kObjectExpected[] = "json_object_expected"; |
|
} // namespace json |
|
|
|
namespace http { |
|
const char kDomain[] = "http"; |
|
} // namespace http |
|
|
|
namespace system { |
|
const char kDomain[] = "system"; |
|
|
|
namespace { |
|
const struct ErrorMapEntry { |
|
const char* error_code; |
|
int errnum; |
|
} error_map[] = { |
|
#define ERROR_ENTRY(err) { #err, err } |
|
ERROR_ENTRY(EPERM), // Operation not permitted |
|
ERROR_ENTRY(ENOENT), // No such file or directory |
|
ERROR_ENTRY(ESRCH), // No such process |
|
ERROR_ENTRY(EINTR), // Interrupted system call |
|
ERROR_ENTRY(EIO), // I/O error |
|
ERROR_ENTRY(ENXIO), // No such device or address |
|
ERROR_ENTRY(E2BIG), // Argument list too long |
|
ERROR_ENTRY(ENOEXEC), // Exec format error |
|
ERROR_ENTRY(EBADF), // Bad file number |
|
ERROR_ENTRY(ECHILD), // No child processes |
|
ERROR_ENTRY(EAGAIN), // Try again |
|
ERROR_ENTRY(ENOMEM), // Out of memory |
|
ERROR_ENTRY(EACCES), // Permission denied |
|
ERROR_ENTRY(EFAULT), // Bad address |
|
ERROR_ENTRY(ENOTBLK), // Block device required |
|
ERROR_ENTRY(EBUSY), // Device or resource busy |
|
ERROR_ENTRY(EEXIST), // File exists |
|
ERROR_ENTRY(EXDEV), // Cross-device link |
|
ERROR_ENTRY(ENODEV), // No such device |
|
ERROR_ENTRY(ENOTDIR), // Not a directory |
|
ERROR_ENTRY(EISDIR), // Is a directory |
|
ERROR_ENTRY(EINVAL), // Invalid argument |
|
ERROR_ENTRY(ENFILE), // File table overflow |
|
ERROR_ENTRY(EMFILE), // Too many open files |
|
ERROR_ENTRY(ENOTTY), // Not a typewriter |
|
ERROR_ENTRY(ETXTBSY), // Text file busy |
|
ERROR_ENTRY(EFBIG), // File too large |
|
ERROR_ENTRY(ENOSPC), // No space left on device |
|
ERROR_ENTRY(ESPIPE), // Illegal seek |
|
ERROR_ENTRY(EROFS), // Read-only file system |
|
ERROR_ENTRY(EMLINK), // Too many links |
|
ERROR_ENTRY(EPIPE), // Broken pipe |
|
ERROR_ENTRY(EDOM), // Math argument out of domain of func |
|
ERROR_ENTRY(ERANGE), // Math result not representable |
|
ERROR_ENTRY(EDEADLK), // Resource deadlock would occur |
|
ERROR_ENTRY(ENAMETOOLONG), // File name too long |
|
ERROR_ENTRY(ENOLCK), // No record locks available |
|
ERROR_ENTRY(ENOSYS), // Function not implemented |
|
ERROR_ENTRY(ENOTEMPTY), // Directory not empty |
|
ERROR_ENTRY(ELOOP), // Too many symbolic links encountered |
|
ERROR_ENTRY(ENOMSG), // No message of desired type |
|
ERROR_ENTRY(EIDRM), // Identifier removed |
|
#ifdef __linux__ |
|
ERROR_ENTRY(ECHRNG), // Channel number out of range |
|
ERROR_ENTRY(EL2NSYNC), // Level 2 not synchronized |
|
ERROR_ENTRY(EL3HLT), // Level 3 halted |
|
ERROR_ENTRY(EL3RST), // Level 3 reset |
|
ERROR_ENTRY(ELNRNG), // Link number out of range |
|
ERROR_ENTRY(EUNATCH), // Protocol driver not attached |
|
ERROR_ENTRY(ENOCSI), // No CSI structure available |
|
ERROR_ENTRY(EL2HLT), // Level 2 halted |
|
ERROR_ENTRY(EBADE), // Invalid exchange |
|
ERROR_ENTRY(EBADR), // Invalid request descriptor |
|
ERROR_ENTRY(EXFULL), // Exchange full |
|
ERROR_ENTRY(ENOANO), // No anode |
|
ERROR_ENTRY(EBADRQC), // Invalid request code |
|
ERROR_ENTRY(EBADSLT), // Invalid slot |
|
ERROR_ENTRY(EBFONT), // Bad font file format |
|
#endif // __linux__ |
|
ERROR_ENTRY(ENOSTR), // Device not a stream |
|
ERROR_ENTRY(ENODATA), // No data available |
|
ERROR_ENTRY(ETIME), // Timer expired |
|
ERROR_ENTRY(ENOSR), // Out of streams resources |
|
#ifdef __linux__ |
|
ERROR_ENTRY(ENONET), // Machine is not on the network |
|
ERROR_ENTRY(ENOPKG), // Package not installed |
|
#endif // __linux__ |
|
ERROR_ENTRY(EREMOTE), // Object is remote |
|
ERROR_ENTRY(ENOLINK), // Link has been severed |
|
#ifdef __linux__ |
|
ERROR_ENTRY(EADV), // Advertise error |
|
ERROR_ENTRY(ESRMNT), // Srmount error |
|
ERROR_ENTRY(ECOMM), // Communication error on send |
|
#endif // __linux__ |
|
ERROR_ENTRY(EPROTO), // Protocol error |
|
ERROR_ENTRY(EMULTIHOP), // Multihop attempted |
|
#ifdef __linux__ |
|
ERROR_ENTRY(EDOTDOT), // RFS specific error |
|
#endif // __linux__ |
|
ERROR_ENTRY(EBADMSG), // Not a data message |
|
ERROR_ENTRY(EOVERFLOW), // Value too large for defined data type |
|
#ifdef __linux__ |
|
ERROR_ENTRY(ENOTUNIQ), // Name not unique on network |
|
ERROR_ENTRY(EBADFD), // File descriptor in bad state |
|
ERROR_ENTRY(EREMCHG), // Remote address changed |
|
ERROR_ENTRY(ELIBACC), // Can not access a needed shared library |
|
ERROR_ENTRY(ELIBBAD), // Accessing a corrupted shared library |
|
ERROR_ENTRY(ELIBSCN), // .lib section in a.out corrupted |
|
ERROR_ENTRY(ELIBMAX), // Attempting to link in too many shared libs. |
|
ERROR_ENTRY(ELIBEXEC), // Cannot exec a shared library directly |
|
#endif // __linux__ |
|
ERROR_ENTRY(EILSEQ), // Illegal byte sequence |
|
#ifdef __linux__ |
|
ERROR_ENTRY(ERESTART), // Interrupted system call should be restarted |
|
ERROR_ENTRY(ESTRPIPE), // Streams pipe error |
|
#endif // __linux__ |
|
ERROR_ENTRY(EUSERS), // Too many users |
|
ERROR_ENTRY(ENOTSOCK), // Socket operation on non-socket |
|
ERROR_ENTRY(EDESTADDRREQ), // Destination address required |
|
ERROR_ENTRY(EMSGSIZE), // Message too long |
|
ERROR_ENTRY(EPROTOTYPE), // Protocol wrong type for socket |
|
ERROR_ENTRY(ENOPROTOOPT), // Protocol not available |
|
ERROR_ENTRY(EPROTONOSUPPORT), // Protocol not supported |
|
ERROR_ENTRY(ESOCKTNOSUPPORT), // Socket type not supported |
|
ERROR_ENTRY(EOPNOTSUPP), // Operation not supported o/transport endpoint |
|
ERROR_ENTRY(EPFNOSUPPORT), // Protocol family not supported |
|
ERROR_ENTRY(EAFNOSUPPORT), // Address family not supported by protocol |
|
ERROR_ENTRY(EADDRINUSE), // Address already in use |
|
ERROR_ENTRY(EADDRNOTAVAIL), // Cannot assign requested address |
|
ERROR_ENTRY(ENETDOWN), // Network is down |
|
ERROR_ENTRY(ENETUNREACH), // Network is unreachable |
|
ERROR_ENTRY(ENETRESET), // Network dropped connection because of reset |
|
ERROR_ENTRY(ECONNABORTED), // Software caused connection abort |
|
ERROR_ENTRY(ECONNRESET), // Connection reset by peer |
|
ERROR_ENTRY(ENOBUFS), // No buffer space available |
|
ERROR_ENTRY(EISCONN), // Transport endpoint is already connected |
|
ERROR_ENTRY(ENOTCONN), // Transport endpoint is not connected |
|
ERROR_ENTRY(ESHUTDOWN), // Cannot send after transp. endpoint shutdown |
|
ERROR_ENTRY(ETOOMANYREFS), // Too many references: cannot splice |
|
ERROR_ENTRY(ETIMEDOUT), // Connection timed out |
|
ERROR_ENTRY(ECONNREFUSED), // Connection refused |
|
ERROR_ENTRY(EHOSTDOWN), // Host is down |
|
ERROR_ENTRY(EHOSTUNREACH), // No route to host |
|
ERROR_ENTRY(EALREADY), // Operation already in progress |
|
ERROR_ENTRY(EINPROGRESS), // Operation now in progress |
|
ERROR_ENTRY(ESTALE), // Stale file handle |
|
#ifdef __linux__ |
|
ERROR_ENTRY(EUCLEAN), // Structure needs cleaning |
|
ERROR_ENTRY(ENOTNAM), // Not a XENIX named type file |
|
ERROR_ENTRY(ENAVAIL), // No XENIX semaphores available |
|
ERROR_ENTRY(EISNAM), // Is a named type file |
|
ERROR_ENTRY(EREMOTEIO), // Remote I/O error |
|
#endif // __linux__ |
|
ERROR_ENTRY(EDQUOT), // Quota exceeded |
|
#ifdef __linux__ |
|
ERROR_ENTRY(ENOMEDIUM), // No medium found |
|
ERROR_ENTRY(EMEDIUMTYPE), // Wrong medium type |
|
#endif // __linux__ |
|
ERROR_ENTRY(ECANCELED), // Operation Canceled |
|
#ifdef __linux__ |
|
ERROR_ENTRY(ENOKEY), // Required key not available |
|
ERROR_ENTRY(EKEYEXPIRED), // Key has expired |
|
ERROR_ENTRY(EKEYREVOKED), // Key has been revoked |
|
ERROR_ENTRY(EKEYREJECTED), // Key was rejected by service |
|
#endif // __linux__ |
|
ERROR_ENTRY(EOWNERDEAD), // Owner died |
|
ERROR_ENTRY(ENOTRECOVERABLE), // State not recoverable |
|
#ifdef __linux__ |
|
ERROR_ENTRY(ERFKILL), // Operation not possible due to RF-kill |
|
ERROR_ENTRY(EHWPOISON), // Memory page has hardware error |
|
#endif // __linux__ |
|
#undef ERROR_ENTRY |
|
// This list comes from <errno.h> system header. The elements are ordered |
|
// by increasing errnum values which is the same order used in the header |
|
// file. So, when new error codes are added to glibc, it should be relatively |
|
// easy to identify them and add them to this list. |
|
}; |
|
|
|
// Gets the error code string from system error code. If unknown system error |
|
// number is provided, returns an empty string. |
|
std::string ErrorCodeFromSystemError(int errnum) { |
|
std::string error_code; |
|
for (const ErrorMapEntry& entry : error_map) { |
|
if (entry.errnum == errnum) { |
|
error_code = entry.error_code; |
|
break; |
|
} |
|
} |
|
return error_code; |
|
} |
|
|
|
} // anonymous namespace |
|
|
|
void AddSystemError(ErrorPtr* error, |
|
const tracked_objects::Location& location, |
|
int errnum) { |
|
std::string message = base::safe_strerror(errnum); |
|
std::string code = ErrorCodeFromSystemError(errnum); |
|
if (message.empty()) |
|
message = "Unknown error " + std::to_string(errnum); |
|
|
|
if (code.empty()) |
|
code = "error_" + std::to_string(errnum); |
|
|
|
Error::AddTo(error, location, kDomain, code, message); |
|
} |
|
|
|
} // namespace system |
|
|
|
} // namespace errors |
|
} // namespace brillo
|
|
|