blob: eb5d8cd75f8a8dc758efbb16925a6e96b9a8c892 [file] [log] [blame]
// Copyright 2017 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.
#ifndef FBL_UNIQUE_FD_H_
#define FBL_UNIQUE_FD_H_
#include <stdlib.h>
#include <unistd.h>
#include <fbl/macros.h>
namespace fbl {
// A scoped file descriptor that automatically closes when it goes
// out of scope.
class unique_fd {
public:
constexpr unique_fd() : fd_(InvalidValue()) {}
explicit unique_fd(int fd) : fd_(fd) {}
static constexpr int InvalidValue() { return -1; }
~unique_fd() { reset(); }
unique_fd(unique_fd&& o) : fd_(o.release()) {}
unique_fd& operator=(unique_fd&& o) {
reset(o.release());
return *this;
}
// Comparison against raw file descriptors (of the form fd == unique_fd)
bool operator==(int fd) const { return (fd_ == fd); }
bool operator!=(int fd) const { return (fd_ != fd); }
// Comparison against other unique_fd's.
bool operator==(const unique_fd& o) const { return fd_ == o.fd_; }
bool operator!=(const unique_fd& o) const { return fd_ != o.fd_; }
// move semantics only
DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(unique_fd);
fbl::unique_fd duplicate() const { return fbl::unique_fd(dup(fd_)); }
int release() {
int t = fd_;
fd_ = InvalidValue();
return t;
}
// Reset the underlying fd.
//
// Optionally takes a value to reset the underlying fd to. If no
// value is passed, underlying fd will be set to an invalid value.
//
// If the fd_ is not set to InvalidValue(), calls close(2) on the fd and
// returns any error value. Otherwise, returns -1.
int reset(int t = InvalidValue()) {
int error;
if (fd_ == InvalidValue()) {
error = -1;
} else {
error = close(fd_);
}
fd_ = t;
return error;
}
// Reset the underlying fd, and then get the address of the underlying internal fd storage.
//
// Note: The intended purpose is to facilitate interactions with C APIs which expect to be
// provided a pointer to a handle used as an out parameter.
int* reset_and_get_address() {
reset();
return &fd_;
}
void swap(unique_fd& other) {
int t = fd_;
fd_ = other.fd_;
other.fd_ = t;
}
int get() const { return fd_; }
bool is_valid() const { return fd_ != InvalidValue(); }
explicit operator bool() const { return is_valid(); }
explicit operator int() const { return fd_; }
private:
int fd_;
};
} // namespace fbl
#endif // FBL_UNIQUE_FD_H_