tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

status.cc (13142B)


      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 
     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 
     90 std::ostream& operator<<(std::ostream& os, StatusCode code) {
     91  return os << StatusCodeToString(code);
     92 }
     93 
     94 absl::Nonnull<const std::string*> Status::EmptyString() {
     95  static const absl::NoDestructor<std::string> kEmpty;
     96  return kEmpty.get();
     97 }
     98 
     99 absl::Nonnull<const std::string*> Status::MovedFromString() {
    100  static const absl::NoDestructor<std::string> kMovedFrom(kMovedFromString);
    101  return kMovedFrom.get();
    102 }
    103 
    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 
    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 
    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 
    127 std::ostream& operator<<(std::ostream& os, const Status& x) {
    128  os << x.ToString(StatusToStringMode::kWithEverything);
    129  return os;
    130 }
    131 
    132 Status AbortedError(absl::string_view message) {
    133  return Status(absl::StatusCode::kAborted, message);
    134 }
    135 
    136 Status AlreadyExistsError(absl::string_view message) {
    137  return Status(absl::StatusCode::kAlreadyExists, message);
    138 }
    139 
    140 Status CancelledError(absl::string_view message) {
    141  return Status(absl::StatusCode::kCancelled, message);
    142 }
    143 
    144 Status DataLossError(absl::string_view message) {
    145  return Status(absl::StatusCode::kDataLoss, message);
    146 }
    147 
    148 Status DeadlineExceededError(absl::string_view message) {
    149  return Status(absl::StatusCode::kDeadlineExceeded, message);
    150 }
    151 
    152 Status FailedPreconditionError(absl::string_view message) {
    153  return Status(absl::StatusCode::kFailedPrecondition, message);
    154 }
    155 
    156 Status InternalError(absl::string_view message) {
    157  return Status(absl::StatusCode::kInternal, message);
    158 }
    159 
    160 Status InvalidArgumentError(absl::string_view message) {
    161  return Status(absl::StatusCode::kInvalidArgument, message);
    162 }
    163 
    164 Status NotFoundError(absl::string_view message) {
    165  return Status(absl::StatusCode::kNotFound, message);
    166 }
    167 
    168 Status OutOfRangeError(absl::string_view message) {
    169  return Status(absl::StatusCode::kOutOfRange, message);
    170 }
    171 
    172 Status PermissionDeniedError(absl::string_view message) {
    173  return Status(absl::StatusCode::kPermissionDenied, message);
    174 }
    175 
    176 Status ResourceExhaustedError(absl::string_view message) {
    177  return Status(absl::StatusCode::kResourceExhausted, message);
    178 }
    179 
    180 Status UnauthenticatedError(absl::string_view message) {
    181  return Status(absl::StatusCode::kUnauthenticated, message);
    182 }
    183 
    184 Status UnavailableError(absl::string_view message) {
    185  return Status(absl::StatusCode::kUnavailable, message);
    186 }
    187 
    188 Status UnimplementedError(absl::string_view message) {
    189  return Status(absl::StatusCode::kUnimplemented, message);
    190 }
    191 
    192 Status UnknownError(absl::string_view message) {
    193  return Status(absl::StatusCode::kUnknown, message);
    194 }
    195 
    196 bool IsAborted(const Status& status) {
    197  return status.code() == absl::StatusCode::kAborted;
    198 }
    199 
    200 bool IsAlreadyExists(const Status& status) {
    201  return status.code() == absl::StatusCode::kAlreadyExists;
    202 }
    203 
    204 bool IsCancelled(const Status& status) {
    205  return status.code() == absl::StatusCode::kCancelled;
    206 }
    207 
    208 bool IsDataLoss(const Status& status) {
    209  return status.code() == absl::StatusCode::kDataLoss;
    210 }
    211 
    212 bool IsDeadlineExceeded(const Status& status) {
    213  return status.code() == absl::StatusCode::kDeadlineExceeded;
    214 }
    215 
    216 bool IsFailedPrecondition(const Status& status) {
    217  return status.code() == absl::StatusCode::kFailedPrecondition;
    218 }
    219 
    220 bool IsInternal(const Status& status) {
    221  return status.code() == absl::StatusCode::kInternal;
    222 }
    223 
    224 bool IsInvalidArgument(const Status& status) {
    225  return status.code() == absl::StatusCode::kInvalidArgument;
    226 }
    227 
    228 bool IsNotFound(const Status& status) {
    229  return status.code() == absl::StatusCode::kNotFound;
    230 }
    231 
    232 bool IsOutOfRange(const Status& status) {
    233  return status.code() == absl::StatusCode::kOutOfRange;
    234 }
    235 
    236 bool IsPermissionDenied(const Status& status) {
    237  return status.code() == absl::StatusCode::kPermissionDenied;
    238 }
    239 
    240 bool IsResourceExhausted(const Status& status) {
    241  return status.code() == absl::StatusCode::kResourceExhausted;
    242 }
    243 
    244 bool IsUnauthenticated(const Status& status) {
    245  return status.code() == absl::StatusCode::kUnauthenticated;
    246 }
    247 
    248 bool IsUnavailable(const Status& status) {
    249  return status.code() == absl::StatusCode::kUnavailable;
    250 }
    251 
    252 bool IsUnimplemented(const Status& status) {
    253  return status.code() == absl::StatusCode::kUnimplemented;
    254 }
    255 
    256 bool IsUnknown(const Status& status) {
    257  return status.code() == absl::StatusCode::kUnknown;
    258 }
    259 
    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 {
    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 
    404 Status ErrnoToStatus(int error_number, absl::string_view message) {
    405  return Status(ErrnoToStatusCode(error_number),
    406                MessageForErrnoToStatus(error_number, message));
    407 }
    408 
    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