• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 The Abseil Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 #include "absl/status/status.h"
15 
16 #include <errno.h>
17 
18 #include <atomic>
19 #include <cstddef>
20 #include <cstdint>
21 #include <cstring>
22 #include <memory>
23 #include <ostream>
24 #include <string>
25 
26 #include "absl/base/attributes.h"
27 #include "absl/base/config.h"
28 #include "absl/base/internal/raw_logging.h"
29 #include "absl/base/internal/strerror.h"
30 #include "absl/base/macros.h"
31 #include "absl/base/no_destructor.h"
32 #include "absl/base/nullability.h"
33 #include "absl/debugging/stacktrace.h"
34 #include "absl/debugging/symbolize.h"
35 #include "absl/status/internal/status_internal.h"
36 #include "absl/strings/str_cat.h"
37 #include "absl/strings/str_format.h"
38 #include "absl/strings/str_split.h"
39 #include "absl/strings/string_view.h"
40 #include "absl/types/optional.h"
41 
42 namespace absl {
43 ABSL_NAMESPACE_BEGIN
44 
45 static_assert(
46     alignof(status_internal::StatusRep) >= 4,
47     "absl::Status assumes it can use the bottom 2 bits of a StatusRep*.");
48 
StatusCodeToString(StatusCode code)49 std::string StatusCodeToString(StatusCode code) {
50   switch (code) {
51     case StatusCode::kOk:
52       return "OK";
53     case StatusCode::kCancelled:
54       return "CANCELLED";
55     case StatusCode::kUnknown:
56       return "UNKNOWN";
57     case StatusCode::kInvalidArgument:
58       return "INVALID_ARGUMENT";
59     case StatusCode::kDeadlineExceeded:
60       return "DEADLINE_EXCEEDED";
61     case StatusCode::kNotFound:
62       return "NOT_FOUND";
63     case StatusCode::kAlreadyExists:
64       return "ALREADY_EXISTS";
65     case StatusCode::kPermissionDenied:
66       return "PERMISSION_DENIED";
67     case StatusCode::kUnauthenticated:
68       return "UNAUTHENTICATED";
69     case StatusCode::kResourceExhausted:
70       return "RESOURCE_EXHAUSTED";
71     case StatusCode::kFailedPrecondition:
72       return "FAILED_PRECONDITION";
73     case StatusCode::kAborted:
74       return "ABORTED";
75     case StatusCode::kOutOfRange:
76       return "OUT_OF_RANGE";
77     case StatusCode::kUnimplemented:
78       return "UNIMPLEMENTED";
79     case StatusCode::kInternal:
80       return "INTERNAL";
81     case StatusCode::kUnavailable:
82       return "UNAVAILABLE";
83     case StatusCode::kDataLoss:
84       return "DATA_LOSS";
85     default:
86       return "";
87   }
88 }
89 
operator <<(std::ostream & os,StatusCode code)90 std::ostream& operator<<(std::ostream& os, StatusCode code) {
91   return os << StatusCodeToString(code);
92 }
93 
EmptyString()94 absl::Nonnull<const std::string*> Status::EmptyString() {
95   static const absl::NoDestructor<std::string> kEmpty;
96   return kEmpty.get();
97 }
98 
MovedFromString()99 absl::Nonnull<const std::string*> Status::MovedFromString() {
100   static const absl::NoDestructor<std::string> kMovedFrom(kMovedFromString);
101   return kMovedFrom.get();
102 }
103 
Status(absl::StatusCode code,absl::string_view msg)104 Status::Status(absl::StatusCode code, absl::string_view msg)
105     : rep_(CodeToInlinedRep(code)) {
106   if (code != absl::StatusCode::kOk && !msg.empty()) {
107     rep_ = PointerToRep(new status_internal::StatusRep(code, msg, nullptr));
108   }
109 }
110 
PrepareToModify(uintptr_t rep)111 absl::Nonnull<status_internal::StatusRep*> Status::PrepareToModify(
112     uintptr_t rep) {
113   if (IsInlined(rep)) {
114     return new status_internal::StatusRep(InlinedRepToCode(rep),
115                                           absl::string_view(), nullptr);
116   }
117   return RepToPointer(rep)->CloneAndUnref();
118 }
119 
ToStringSlow(uintptr_t rep,StatusToStringMode mode)120 std::string Status::ToStringSlow(uintptr_t rep, StatusToStringMode mode) {
121   if (IsInlined(rep)) {
122     return absl::StrCat(absl::StatusCodeToString(InlinedRepToCode(rep)), ": ");
123   }
124   return RepToPointer(rep)->ToString(mode);
125 }
126 
operator <<(std::ostream & os,const Status & x)127 std::ostream& operator<<(std::ostream& os, const Status& x) {
128   os << x.ToString(StatusToStringMode::kWithEverything);
129   return os;
130 }
131 
AbortedError(absl::string_view message)132 Status AbortedError(absl::string_view message) {
133   return Status(absl::StatusCode::kAborted, message);
134 }
135 
AlreadyExistsError(absl::string_view message)136 Status AlreadyExistsError(absl::string_view message) {
137   return Status(absl::StatusCode::kAlreadyExists, message);
138 }
139 
CancelledError(absl::string_view message)140 Status CancelledError(absl::string_view message) {
141   return Status(absl::StatusCode::kCancelled, message);
142 }
143 
DataLossError(absl::string_view message)144 Status DataLossError(absl::string_view message) {
145   return Status(absl::StatusCode::kDataLoss, message);
146 }
147 
DeadlineExceededError(absl::string_view message)148 Status DeadlineExceededError(absl::string_view message) {
149   return Status(absl::StatusCode::kDeadlineExceeded, message);
150 }
151 
FailedPreconditionError(absl::string_view message)152 Status FailedPreconditionError(absl::string_view message) {
153   return Status(absl::StatusCode::kFailedPrecondition, message);
154 }
155 
InternalError(absl::string_view message)156 Status InternalError(absl::string_view message) {
157   return Status(absl::StatusCode::kInternal, message);
158 }
159 
InvalidArgumentError(absl::string_view message)160 Status InvalidArgumentError(absl::string_view message) {
161   return Status(absl::StatusCode::kInvalidArgument, message);
162 }
163 
NotFoundError(absl::string_view message)164 Status NotFoundError(absl::string_view message) {
165   return Status(absl::StatusCode::kNotFound, message);
166 }
167 
OutOfRangeError(absl::string_view message)168 Status OutOfRangeError(absl::string_view message) {
169   return Status(absl::StatusCode::kOutOfRange, message);
170 }
171 
PermissionDeniedError(absl::string_view message)172 Status PermissionDeniedError(absl::string_view message) {
173   return Status(absl::StatusCode::kPermissionDenied, message);
174 }
175 
ResourceExhaustedError(absl::string_view message)176 Status ResourceExhaustedError(absl::string_view message) {
177   return Status(absl::StatusCode::kResourceExhausted, message);
178 }
179 
UnauthenticatedError(absl::string_view message)180 Status UnauthenticatedError(absl::string_view message) {
181   return Status(absl::StatusCode::kUnauthenticated, message);
182 }
183 
UnavailableError(absl::string_view message)184 Status UnavailableError(absl::string_view message) {
185   return Status(absl::StatusCode::kUnavailable, message);
186 }
187 
UnimplementedError(absl::string_view message)188 Status UnimplementedError(absl::string_view message) {
189   return Status(absl::StatusCode::kUnimplemented, message);
190 }
191 
UnknownError(absl::string_view message)192 Status UnknownError(absl::string_view message) {
193   return Status(absl::StatusCode::kUnknown, message);
194 }
195 
IsAborted(const Status & status)196 bool IsAborted(const Status& status) {
197   return status.code() == absl::StatusCode::kAborted;
198 }
199 
IsAlreadyExists(const Status & status)200 bool IsAlreadyExists(const Status& status) {
201   return status.code() == absl::StatusCode::kAlreadyExists;
202 }
203 
IsCancelled(const Status & status)204 bool IsCancelled(const Status& status) {
205   return status.code() == absl::StatusCode::kCancelled;
206 }
207 
IsDataLoss(const Status & status)208 bool IsDataLoss(const Status& status) {
209   return status.code() == absl::StatusCode::kDataLoss;
210 }
211 
IsDeadlineExceeded(const Status & status)212 bool IsDeadlineExceeded(const Status& status) {
213   return status.code() == absl::StatusCode::kDeadlineExceeded;
214 }
215 
IsFailedPrecondition(const Status & status)216 bool IsFailedPrecondition(const Status& status) {
217   return status.code() == absl::StatusCode::kFailedPrecondition;
218 }
219 
IsInternal(const Status & status)220 bool IsInternal(const Status& status) {
221   return status.code() == absl::StatusCode::kInternal;
222 }
223 
IsInvalidArgument(const Status & status)224 bool IsInvalidArgument(const Status& status) {
225   return status.code() == absl::StatusCode::kInvalidArgument;
226 }
227 
IsNotFound(const Status & status)228 bool IsNotFound(const Status& status) {
229   return status.code() == absl::StatusCode::kNotFound;
230 }
231 
IsOutOfRange(const Status & status)232 bool IsOutOfRange(const Status& status) {
233   return status.code() == absl::StatusCode::kOutOfRange;
234 }
235 
IsPermissionDenied(const Status & status)236 bool IsPermissionDenied(const Status& status) {
237   return status.code() == absl::StatusCode::kPermissionDenied;
238 }
239 
IsResourceExhausted(const Status & status)240 bool IsResourceExhausted(const Status& status) {
241   return status.code() == absl::StatusCode::kResourceExhausted;
242 }
243 
IsUnauthenticated(const Status & status)244 bool IsUnauthenticated(const Status& status) {
245   return status.code() == absl::StatusCode::kUnauthenticated;
246 }
247 
IsUnavailable(const Status & status)248 bool IsUnavailable(const Status& status) {
249   return status.code() == absl::StatusCode::kUnavailable;
250 }
251 
IsUnimplemented(const Status & status)252 bool IsUnimplemented(const Status& status) {
253   return status.code() == absl::StatusCode::kUnimplemented;
254 }
255 
IsUnknown(const Status & status)256 bool IsUnknown(const Status& status) {
257   return status.code() == absl::StatusCode::kUnknown;
258 }
259 
ErrnoToStatusCode(int error_number)260 StatusCode ErrnoToStatusCode(int error_number) {
261   switch (error_number) {
262     case 0:
263       return StatusCode::kOk;
264     case EINVAL:        // Invalid argument
265     case ENAMETOOLONG:  // Filename too long
266     case E2BIG:         // Argument list too long
267     case EDESTADDRREQ:  // Destination address required
268     case EDOM:          // Mathematics argument out of domain of function
269     case EFAULT:        // Bad address
270     case EILSEQ:        // Illegal byte sequence
271     case ENOPROTOOPT:   // Protocol not available
272     case ENOTSOCK:      // Not a socket
273     case ENOTTY:        // Inappropriate I/O control operation
274     case EPROTOTYPE:    // Protocol wrong type for socket
275     case ESPIPE:        // Invalid seek
276       return StatusCode::kInvalidArgument;
277     case ETIMEDOUT:  // Connection timed out
278       return StatusCode::kDeadlineExceeded;
279     case ENODEV:  // No such device
280     case ENOENT:  // No such file or directory
281 #ifdef ENOMEDIUM
282     case ENOMEDIUM:  // No medium found
283 #endif
284     case ENXIO:  // No such device or address
285     case ESRCH:  // No such process
286       return StatusCode::kNotFound;
287     case EEXIST:         // File exists
288     case EADDRNOTAVAIL:  // Address not available
289     case EALREADY:       // Connection already in progress
290 #ifdef ENOTUNIQ
291     case ENOTUNIQ:  // Name not unique on network
292 #endif
293       return StatusCode::kAlreadyExists;
294     case EPERM:   // Operation not permitted
295     case EACCES:  // Permission denied
296 #ifdef ENOKEY
297     case ENOKEY:  // Required key not available
298 #endif
299     case EROFS:  // Read only file system
300       return StatusCode::kPermissionDenied;
301     case ENOTEMPTY:   // Directory not empty
302     case EISDIR:      // Is a directory
303     case ENOTDIR:     // Not a directory
304     case EADDRINUSE:  // Address already in use
305     case EBADF:       // Invalid file descriptor
306 #ifdef EBADFD
307     case EBADFD:  // File descriptor in bad state
308 #endif
309     case EBUSY:    // Device or resource busy
310     case ECHILD:   // No child processes
311     case EISCONN:  // Socket is connected
312 #ifdef EISNAM
313     case EISNAM:  // Is a named type file
314 #endif
315 #ifdef ENOTBLK
316     case ENOTBLK:  // Block device required
317 #endif
318     case ENOTCONN:  // The socket is not connected
319     case EPIPE:     // Broken pipe
320 #ifdef ESHUTDOWN
321     case ESHUTDOWN:  // Cannot send after transport endpoint shutdown
322 #endif
323     case ETXTBSY:  // Text file busy
324 #ifdef EUNATCH
325     case EUNATCH:  // Protocol driver not attached
326 #endif
327       return StatusCode::kFailedPrecondition;
328     case ENOSPC:  // No space left on device
329 #ifdef EDQUOT
330     case EDQUOT:  // Disk quota exceeded
331 #endif
332     case EMFILE:   // Too many open files
333     case EMLINK:   // Too many links
334     case ENFILE:   // Too many open files in system
335     case ENOBUFS:  // No buffer space available
336     case ENOMEM:   // Not enough space
337 #ifdef EUSERS
338     case EUSERS:  // Too many users
339 #endif
340       return StatusCode::kResourceExhausted;
341 #ifdef ECHRNG
342     case ECHRNG:  // Channel number out of range
343 #endif
344     case EFBIG:      // File too large
345     case EOVERFLOW:  // Value too large to be stored in data type
346     case ERANGE:     // Result too large
347       return StatusCode::kOutOfRange;
348 #ifdef ENOPKG
349     case ENOPKG:  // Package not installed
350 #endif
351     case ENOSYS:        // Function not implemented
352     case ENOTSUP:       // Operation not supported
353     case EAFNOSUPPORT:  // Address family not supported
354 #ifdef EPFNOSUPPORT
355     case EPFNOSUPPORT:  // Protocol family not supported
356 #endif
357     case EPROTONOSUPPORT:  // Protocol not supported
358 #ifdef ESOCKTNOSUPPORT
359     case ESOCKTNOSUPPORT:  // Socket type not supported
360 #endif
361     case EXDEV:  // Improper link
362       return StatusCode::kUnimplemented;
363     case EAGAIN:  // Resource temporarily unavailable
364 #ifdef ECOMM
365     case ECOMM:  // Communication error on send
366 #endif
367     case ECONNREFUSED:  // Connection refused
368     case ECONNABORTED:  // Connection aborted
369     case ECONNRESET:    // Connection reset
370     case EINTR:         // Interrupted function call
371 #ifdef EHOSTDOWN
372     case EHOSTDOWN:  // Host is down
373 #endif
374     case EHOSTUNREACH:  // Host is unreachable
375     case ENETDOWN:      // Network is down
376     case ENETRESET:     // Connection aborted by network
377     case ENETUNREACH:   // Network unreachable
378     case ENOLCK:        // No locks available
379     case ENOLINK:       // Link has been severed
380 #ifdef ENONET
381     case ENONET:  // Machine is not on the network
382 #endif
383       return StatusCode::kUnavailable;
384     case EDEADLK:  // Resource deadlock avoided
385 #ifdef ESTALE
386     case ESTALE:  // Stale file handle
387 #endif
388       return StatusCode::kAborted;
389     case ECANCELED:  // Operation cancelled
390       return StatusCode::kCancelled;
391     default:
392       return StatusCode::kUnknown;
393   }
394 }
395 
396 namespace {
MessageForErrnoToStatus(int error_number,absl::string_view message)397 std::string MessageForErrnoToStatus(int error_number,
398                                     absl::string_view message) {
399   return absl::StrCat(message, ": ",
400                       absl::base_internal::StrError(error_number));
401 }
402 }  // namespace
403 
ErrnoToStatus(int error_number,absl::string_view message)404 Status ErrnoToStatus(int error_number, absl::string_view message) {
405   return Status(ErrnoToStatusCode(error_number),
406                 MessageForErrnoToStatus(error_number, message));
407 }
408 
StatusMessageAsCStr(const Status & status)409 absl::Nonnull<const char*> StatusMessageAsCStr(const Status& status) {
410   // As an internal implementation detail, we guarantee that if status.message()
411   // is non-empty, then the resulting string_view is null terminated.
412   auto sv_message = status.message();
413   return sv_message.empty() ? "" : sv_message.data();
414 }
415 
416 ABSL_NAMESPACE_END
417 }  // namespace absl
418