1 // Copyright 2014 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <brillo/errors/error_codes.h>
6 
7 #include <base/posix/safe_strerror.h>
8 
9 namespace brillo {
10 namespace errors {
11 
12 namespace dbus {
13 const char kDomain[] = "dbus";
14 }  // namespace dbus
15 
16 namespace json {
17 const char kDomain[] = "json_parser";
18 const char kParseError[] = "json_parse_error";
19 const char kObjectExpected[] = "json_object_expected";
20 }  // namespace json
21 
22 namespace http {
23 const char kDomain[] = "http";
24 }  // namespace http
25 
26 namespace system {
27 const char kDomain[] = "system";
28 
29 namespace {
30 const struct ErrorMapEntry {
31   const char* error_code;
32   int errnum;
33 } error_map[] = {
34 #define ERROR_ENTRY(err) { #err, err }
35   ERROR_ENTRY(EPERM),            // Operation not permitted
36   ERROR_ENTRY(ENOENT),           // No such file or directory
37   ERROR_ENTRY(ESRCH),            // No such process
38   ERROR_ENTRY(EINTR),            // Interrupted system call
39   ERROR_ENTRY(EIO),              // I/O error
40   ERROR_ENTRY(ENXIO),            // No such device or address
41   ERROR_ENTRY(E2BIG),            // Argument list too long
42   ERROR_ENTRY(ENOEXEC),          // Exec format error
43   ERROR_ENTRY(EBADF),            // Bad file number
44   ERROR_ENTRY(ECHILD),           // No child processes
45   ERROR_ENTRY(EAGAIN),           // Try again
46   ERROR_ENTRY(ENOMEM),           // Out of memory
47   ERROR_ENTRY(EACCES),           // Permission denied
48   ERROR_ENTRY(EFAULT),           // Bad address
49   ERROR_ENTRY(ENOTBLK),          // Block device required
50   ERROR_ENTRY(EBUSY),            // Device or resource busy
51   ERROR_ENTRY(EEXIST),           // File exists
52   ERROR_ENTRY(EXDEV),            // Cross-device link
53   ERROR_ENTRY(ENODEV),           // No such device
54   ERROR_ENTRY(ENOTDIR),          // Not a directory
55   ERROR_ENTRY(EISDIR),           // Is a directory
56   ERROR_ENTRY(EINVAL),           // Invalid argument
57   ERROR_ENTRY(ENFILE),           // File table overflow
58   ERROR_ENTRY(EMFILE),           // Too many open files
59   ERROR_ENTRY(ENOTTY),           // Not a typewriter
60   ERROR_ENTRY(ETXTBSY),          // Text file busy
61   ERROR_ENTRY(EFBIG),            // File too large
62   ERROR_ENTRY(ENOSPC),           // No space left on device
63   ERROR_ENTRY(ESPIPE),           // Illegal seek
64   ERROR_ENTRY(EROFS),            // Read-only file system
65   ERROR_ENTRY(EMLINK),           // Too many links
66   ERROR_ENTRY(EPIPE),            // Broken pipe
67   ERROR_ENTRY(EDOM),             // Math argument out of domain of func
68   ERROR_ENTRY(ERANGE),           // Math result not representable
69   ERROR_ENTRY(EDEADLK),          // Resource deadlock would occur
70   ERROR_ENTRY(ENAMETOOLONG),     // File name too long
71   ERROR_ENTRY(ENOLCK),           // No record locks available
72   ERROR_ENTRY(ENOSYS),           // Function not implemented
73   ERROR_ENTRY(ENOTEMPTY),        // Directory not empty
74   ERROR_ENTRY(ELOOP),            // Too many symbolic links encountered
75   ERROR_ENTRY(ENOMSG),           // No message of desired type
76   ERROR_ENTRY(EIDRM),            // Identifier removed
77 #ifdef __linux__
78   ERROR_ENTRY(ECHRNG),           // Channel number out of range
79   ERROR_ENTRY(EL2NSYNC),         // Level 2 not synchronized
80   ERROR_ENTRY(EL3HLT),           // Level 3 halted
81   ERROR_ENTRY(EL3RST),           // Level 3 reset
82   ERROR_ENTRY(ELNRNG),           // Link number out of range
83   ERROR_ENTRY(EUNATCH),          // Protocol driver not attached
84   ERROR_ENTRY(ENOCSI),           // No CSI structure available
85   ERROR_ENTRY(EL2HLT),           // Level 2 halted
86   ERROR_ENTRY(EBADE),            // Invalid exchange
87   ERROR_ENTRY(EBADR),            // Invalid request descriptor
88   ERROR_ENTRY(EXFULL),           // Exchange full
89   ERROR_ENTRY(ENOANO),           // No anode
90   ERROR_ENTRY(EBADRQC),          // Invalid request code
91   ERROR_ENTRY(EBADSLT),          // Invalid slot
92   ERROR_ENTRY(EBFONT),           // Bad font file format
93 #endif  // __linux__
94   ERROR_ENTRY(ENOSTR),           // Device not a stream
95   ERROR_ENTRY(ENODATA),          // No data available
96   ERROR_ENTRY(ETIME),            // Timer expired
97   ERROR_ENTRY(ENOSR),            // Out of streams resources
98 #ifdef __linux__
99   ERROR_ENTRY(ENONET),           // Machine is not on the network
100   ERROR_ENTRY(ENOPKG),           // Package not installed
101 #endif  // __linux__
102   ERROR_ENTRY(EREMOTE),          // Object is remote
103   ERROR_ENTRY(ENOLINK),          // Link has been severed
104 #ifdef __linux__
105   ERROR_ENTRY(EADV),             // Advertise error
106   ERROR_ENTRY(ESRMNT),           // Srmount error
107   ERROR_ENTRY(ECOMM),            // Communication error on send
108 #endif  // __linux__
109   ERROR_ENTRY(EPROTO),           // Protocol error
110   ERROR_ENTRY(EMULTIHOP),        // Multihop attempted
111 #ifdef __linux__
112   ERROR_ENTRY(EDOTDOT),          // RFS specific error
113 #endif  // __linux__
114   ERROR_ENTRY(EBADMSG),          // Not a data message
115   ERROR_ENTRY(EOVERFLOW),        // Value too large for defined data type
116 #ifdef __linux__
117   ERROR_ENTRY(ENOTUNIQ),         // Name not unique on network
118   ERROR_ENTRY(EBADFD),           // File descriptor in bad state
119   ERROR_ENTRY(EREMCHG),          // Remote address changed
120   ERROR_ENTRY(ELIBACC),          // Can not access a needed shared library
121   ERROR_ENTRY(ELIBBAD),          // Accessing a corrupted shared library
122   ERROR_ENTRY(ELIBSCN),          // .lib section in a.out corrupted
123   ERROR_ENTRY(ELIBMAX),          // Attempting to link in too many shared libs.
124   ERROR_ENTRY(ELIBEXEC),         // Cannot exec a shared library directly
125 #endif  // __linux__
126   ERROR_ENTRY(EILSEQ),           // Illegal byte sequence
127 #ifdef __linux__
128   ERROR_ENTRY(ERESTART),         // Interrupted system call should be restarted
129   ERROR_ENTRY(ESTRPIPE),         // Streams pipe error
130 #endif  // __linux__
131   ERROR_ENTRY(EUSERS),           // Too many users
132   ERROR_ENTRY(ENOTSOCK),         // Socket operation on non-socket
133   ERROR_ENTRY(EDESTADDRREQ),     // Destination address required
134   ERROR_ENTRY(EMSGSIZE),         // Message too long
135   ERROR_ENTRY(EPROTOTYPE),       // Protocol wrong type for socket
136   ERROR_ENTRY(ENOPROTOOPT),      // Protocol not available
137   ERROR_ENTRY(EPROTONOSUPPORT),  // Protocol not supported
138   ERROR_ENTRY(ESOCKTNOSUPPORT),  // Socket type not supported
139   ERROR_ENTRY(EOPNOTSUPP),       // Operation not supported o/transport endpoint
140   ERROR_ENTRY(EPFNOSUPPORT),     // Protocol family not supported
141   ERROR_ENTRY(EAFNOSUPPORT),     // Address family not supported by protocol
142   ERROR_ENTRY(EADDRINUSE),       // Address already in use
143   ERROR_ENTRY(EADDRNOTAVAIL),    // Cannot assign requested address
144   ERROR_ENTRY(ENETDOWN),         // Network is down
145   ERROR_ENTRY(ENETUNREACH),      // Network is unreachable
146   ERROR_ENTRY(ENETRESET),        // Network dropped connection because of reset
147   ERROR_ENTRY(ECONNABORTED),     // Software caused connection abort
148   ERROR_ENTRY(ECONNRESET),       // Connection reset by peer
149   ERROR_ENTRY(ENOBUFS),          // No buffer space available
150   ERROR_ENTRY(EISCONN),          // Transport endpoint is already connected
151   ERROR_ENTRY(ENOTCONN),         // Transport endpoint is not connected
152   ERROR_ENTRY(ESHUTDOWN),        // Cannot send after transp. endpoint shutdown
153   ERROR_ENTRY(ETOOMANYREFS),     // Too many references: cannot splice
154   ERROR_ENTRY(ETIMEDOUT),        // Connection timed out
155   ERROR_ENTRY(ECONNREFUSED),     // Connection refused
156   ERROR_ENTRY(EHOSTDOWN),        // Host is down
157   ERROR_ENTRY(EHOSTUNREACH),     // No route to host
158   ERROR_ENTRY(EALREADY),         // Operation already in progress
159   ERROR_ENTRY(EINPROGRESS),      // Operation now in progress
160   ERROR_ENTRY(ESTALE),           // Stale file handle
161 #ifdef __linux__
162   ERROR_ENTRY(EUCLEAN),          // Structure needs cleaning
163   ERROR_ENTRY(ENOTNAM),          // Not a XENIX named type file
164   ERROR_ENTRY(ENAVAIL),          // No XENIX semaphores available
165   ERROR_ENTRY(EISNAM),           // Is a named type file
166   ERROR_ENTRY(EREMOTEIO),        // Remote I/O error
167 #endif  // __linux__
168   ERROR_ENTRY(EDQUOT),           // Quota exceeded
169 #ifdef __linux__
170   ERROR_ENTRY(ENOMEDIUM),        // No medium found
171   ERROR_ENTRY(EMEDIUMTYPE),      // Wrong medium type
172 #endif  // __linux__
173   ERROR_ENTRY(ECANCELED),        // Operation Canceled
174 #ifdef __linux__
175   ERROR_ENTRY(ENOKEY),           // Required key not available
176   ERROR_ENTRY(EKEYEXPIRED),      // Key has expired
177   ERROR_ENTRY(EKEYREVOKED),      // Key has been revoked
178   ERROR_ENTRY(EKEYREJECTED),     // Key was rejected by service
179 #endif  // __linux__
180   ERROR_ENTRY(EOWNERDEAD),       // Owner died
181   ERROR_ENTRY(ENOTRECOVERABLE),  // State not recoverable
182 #ifdef __linux__
183   ERROR_ENTRY(ERFKILL),          // Operation not possible due to RF-kill
184   ERROR_ENTRY(EHWPOISON),        // Memory page has hardware error
185 #endif  // __linux__
186 #undef ERROR_ENTRY
187   // This list comes from <errno.h> system header. The elements are ordered
188   // by increasing errnum values which is the same order used in the header
189   // file. So, when new error codes are added to glibc, it should be relatively
190   // easy to identify them and add them to this list.
191 };
192 
193 // Gets the error code string from system error code. If unknown system error
194 // number is provided, returns an empty string.
ErrorCodeFromSystemError(int errnum)195 std::string ErrorCodeFromSystemError(int errnum) {
196   std::string error_code;
197   for (const ErrorMapEntry& entry : error_map) {
198     if (entry.errnum == errnum) {
199       error_code = entry.error_code;
200       break;
201     }
202   }
203   return error_code;
204 }
205 
206 }  // anonymous namespace
207 
AddSystemError(ErrorPtr * error,const tracked_objects::Location & location,int errnum)208 void AddSystemError(ErrorPtr* error,
209                     const tracked_objects::Location& location,
210                     int errnum) {
211   std::string message = base::safe_strerror(errnum);
212   std::string code = ErrorCodeFromSystemError(errnum);
213   if (message.empty())
214     message = "Unknown error " + std::to_string(errnum);
215 
216   if (code.empty())
217     code = "error_" + std::to_string(errnum);
218 
219   Error::AddTo(error, location, kDomain, code, message);
220 }
221 
222 }  // namespace system
223 
224 }  // namespace errors
225 }  // namespace brillo
226