blob: 43de57b1605289901ee6a3b0bd67c5ec314ba93f [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Common helper functions/classes used both in the host and device forwarder.
#ifndef TOOLS_ANDROID_FORWARDER2_COMMON_H_
#define TOOLS_ANDROID_FORWARDER2_COMMON_H_
#include <stdarg.h>
#include <stdio.h>
#include <errno.h>
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/posix/eintr_wrapper.h"
// Preserving errno for Close() is important because the function is very often
// used in cleanup code, after an error occurred, and it is very easy to pass an
// invalid file descriptor to close() in this context, or more rarely, a
// spurious signal might make close() return -1 + setting errno to EINTR,
// masking the real reason for the original error. This leads to very unpleasant
// debugging sessions.
#define PRESERVE_ERRNO_HANDLE_EINTR(Func) \
do { \
int local_errno = errno; \
(void) HANDLE_EINTR(Func); \
errno = local_errno; \
} while (false);
// Wrapper around RAW_LOG() which is signal-safe. The only purpose of this macro
// is to avoid documenting uses of RawLog().
#define SIGNAL_SAFE_LOG(Level, Msg) \
RAW_LOG(Level, Msg);
namespace forwarder2 {
// Note that the two following functions are not signal-safe.
// Chromium logging-aware implementation of libc's perror().
void PError(const char* msg);
// Closes the provided file descriptor and logs an error if it failed.
void CloseFD(int fd);
// Helps build a formatted C-string allocated in a fixed-size array. This is
// useful in signal handlers where base::StringPrintf() can't be used safely
// (due to its use of LOG()).
template <int BufferSize>
class FixedSizeStringBuilder {
public:
FixedSizeStringBuilder() {
Reset();
}
const char* buffer() const { return buffer_; }
void Reset() {
buffer_[0] = 0;
write_ptr_ = buffer_;
}
// Returns the number of bytes appended to the underlying buffer or -1 if it
// failed.
int Append(const char* format, ...) PRINTF_FORMAT(/* + 1 for 'this' */ 2, 3) {
if (write_ptr_ >= buffer_ + BufferSize)
return -1;
va_list ap;
va_start(ap, format);
const int bytes_written = vsnprintf(
write_ptr_, BufferSize - (write_ptr_ - buffer_), format, ap);
va_end(ap);
if (bytes_written > 0)
write_ptr_ += bytes_written;
return bytes_written;
}
private:
char* write_ptr_;
char buffer_[BufferSize];
COMPILE_ASSERT(BufferSize >= 1, Size_of_buffer_must_be_at_least_one);
DISALLOW_COPY_AND_ASSIGN(FixedSizeStringBuilder);
};
} // namespace forwarder2
#endif // TOOLS_ANDROID_FORWARDER2_COMMON_H_