blob: 5fdd2473a850a8a4f07bc5d47f049979bfcda15c [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#pragma once
#include <cstdint>
#include <cstdlib>
#include <utility>
#include <memory>
#include <fbl/string_buffer.h>
#include <fs/trace.h>
#include <zircon/device/vfs.h>
// fs-internal header defining utility functions for logging flags and paths.
namespace fs {
// Marker type for pretty-printing flags
struct ZxFlags {
public:
explicit ZxFlags(uint32_t flags) : value(flags) {}
uint32_t value;
};
struct Path {
Path(const char* path, size_t size) : str(path), size(size) {}
const char* str;
size_t size;
};
namespace debug_internal {
constexpr const char* FlagToString(uint32_t flag) {
switch (flag) {
case ZX_FS_RIGHT_ADMIN:
return "RIGHT_ADMIN";
case ZX_FS_RIGHT_READABLE:
return "RIGHT_READABLE";
case ZX_FS_RIGHT_WRITABLE:
return "RIGHT_WRITABLE";
case ZX_FS_RIGHTS:
return "RIGHTS";
case ZX_FS_FLAG_CREATE:
return "FLAG_CREATE";
case ZX_FS_FLAG_EXCLUSIVE:
return "FLAG_EXCLUSIVE";
case ZX_FS_FLAG_TRUNCATE:
return "FLAG_TRUNCATE";
case ZX_FS_FLAG_DIRECTORY:
return "FLAG_DIRECTORY";
case ZX_FS_FLAG_APPEND:
return "FLAG_APPEND";
case ZX_FS_FLAG_NOREMOTE:
return "FLAG_NOREMOTE";
case ZX_FS_FLAG_VNODE_REF_ONLY:
return "FLAG_VNODE_REF_ONLY";
case ZX_FS_FLAG_DESCRIBE:
return "FLAG_DESCRIBE";
case ZX_FS_FLAG_POSIX:
return "FLAG_POSIX";
case ZX_FS_FLAG_NOT_DIRECTORY:
return "FLAG_NOT_DIRECTORY";
case ZX_FS_FLAG_CLONE_SAME_RIGHTS:
return "FLAG_CLONE_SAME_RIGHTS";
default:
return "(Unknown flag)";
}
}
template <size_t N>
void PrintIntoStringBuffer(fbl::StringBuffer<N>* sb, ZxFlags flags) {
bool first = true;
uint32_t bit = 1;
for (int i = 0; i < 32; i++) {
const uint32_t flag = flags.value & bit;
if (flag) {
const char* desc = FlagToString(flag);
if (!first) {
sb->Append(" | ");
}
first = false;
sb->Append(desc);
}
bit = bit << 1U;
}
}
template <size_t N>
void PrintIntoStringBuffer(fbl::StringBuffer<N>* sb, const char* str) {
sb->Append(str);
}
template <size_t N>
void PrintIntoStringBuffer(fbl::StringBuffer<N>* sb, Path path) {
sb->Append(path.str, path.size);
}
template <size_t N>
void PrintEach(fbl::StringBuffer<N>* sb) {
}
template <size_t N, typename T, typename... Args>
void PrintEach(fbl::StringBuffer<N>* sb, T val, Args... args) {
PrintIntoStringBuffer(sb, val);
PrintEach(sb, args...);
}
template <typename... Args>
void ConnectionTraceDebug(Args... args) {
constexpr size_t kMaxSize = 2000;
auto str = std::make_unique<fbl::StringBuffer<kMaxSize>>();
PrintEach(str.get(), args...);
FS_TRACE_DEBUG("%s\n", str->c_str());
}
} // namespace debug_internal
} // namespace fs
#if FS_TRACE_DEBUG_ENABLED
#define FS_PRETTY_TRACE_DEBUG(args...) fs::debug_internal::ConnectionTraceDebug(args)
#else
// Explicitly expand FS_PRETTY_TRACE_DEBUG into nothing when not debugging, to ensure zero overhead.
#define FS_PRETTY_TRACE_DEBUG(args...)
#endif