folly/folly/lang/SafeAssert.cpp

/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <folly/lang/SafeAssert.h>

#include <algorithm>
#include <cerrno>
#include <cstdarg>

#include <folly/detail/FileUtilDetail.h>
#include <folly/lang/ToAscii.h>
#include <folly/portability/SysTypes.h>
#include <folly/portability/Windows.h>

#if defined(_WIN32)

#include <fileapi.h> // @manual

#else

// @lint-ignore CLANGTIDY
#include <unistd.h>

#endif

//  This header takes care to have minimal dependencies.

namespace folly {
namespace detail {

namespace {

//  script (centos):
//
//  for e in $(
//      cat /usr/include/asm*/errno*.h | awk '{print $2}' | grep -P '^E' | sort
//  ) ; do
//    echo "#if defined($e)"
//    echo "    FOLLY_DETAIL_ERROR($e),"
//    echo "#endif"
//  done

#define FOLLY_DETAIL_ERROR
constexpr std::pair<int, const char*> errors[] =;
#undef FOLLY_DETAIL_ERROR

#if defined(_WIN32)

constexpr int stderr_fileno = 2;

ssize_t write(int fh, void const* buf, size_t count) {
  auto r = _write(fh, buf, static_cast<unsigned int>(count));
  if ((r > 0 && size_t(r) != count) || (r == -1 && errno == ENOSPC)) {
    // Writing to a pipe with a full buffer doesn't generate
    // any error type, unless it caused us to write exactly 0
    // bytes, so we have to see if we have a pipe first. We
    // don't touch the errno for anything else.
    HANDLE h = (HANDLE)_get_osfhandle(fh);
    if (GetFileType(h) == FILE_TYPE_PIPE) {
      DWORD state = 0;
      if (GetNamedPipeHandleState(
              h, &state, nullptr, nullptr, nullptr, nullptr, 0)) {
        if ((state & PIPE_NOWAIT) == PIPE_NOWAIT) {
          errno = EAGAIN;
          return -1;
        }
      }
    }
  }
  return r;
}

int fsync(int fh) {
  HANDLE h = (HANDLE)_get_osfhandle(fh);
  if (!FlushFileBuffers(h)) {
    return -1;
  }
  return 0;
}

#else

constexpr int stderr_fileno =;

#endif

#if !defined(_WIN32) && !defined(_POSIX_FSYNC)

int fsync(int fh) {
  return 0;
}

#endif

void writeStderr(const char* s, size_t len) {}
void writeStderr(const char* s) {}
void flushStderr() {}

[[noreturn, FOLLY_ATTR_GNU_COLD]] void safe_assert_terminate_v(
    safe_assert_arg const* arg_, int const error, va_list msg) noexcept {}

} // namespace

template <>
void safe_assert_terminate<0>(safe_assert_arg const* arg, ...) noexcept {}

template <>
void safe_assert_terminate<1>(safe_assert_arg const* arg, ...) noexcept {}

} // namespace detail
} // namespace folly