1 // Copyright 2017 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #pragma once
6 
7 #include <stdlib.h>
8 #include <unistd.h>
9 
10 #include <fbl/macros.h>
11 #include <fbl/type_support.h>
12 
13 namespace fbl {
14 
15 // A scoped file descriptor that automatically closes when it goes
16 // out of scope.
17 class unique_fd {
18 public:
unique_fd()19     constexpr unique_fd() : fd_(InvalidValue()) {}
unique_fd(int fd)20     explicit unique_fd(int fd) : fd_(fd) { }
21 
InvalidValue()22     static constexpr int InvalidValue() { return -1; }
23 
~unique_fd()24     ~unique_fd() {
25         reset();
26     }
27 
unique_fd(unique_fd && o)28     unique_fd(unique_fd&& o) : fd_(o.release()) {}
29     unique_fd& operator=(unique_fd&& o) {
30         reset(o.release());
31         return *this;
32     }
33 
34     // Comparison against raw file descriptors (of the form fd == unique_fd)
35     bool operator==(int fd) const { return (fd_ == fd); }
36     bool operator!=(int fd) const { return (fd_ != fd); }
37 
38     // Comparison against other unique_fd's.
39     bool operator==(const unique_fd& o) const { return fd_ == o.fd_; }
40     bool operator!=(const unique_fd& o) const { return fd_ != o.fd_; }
41 
42     // move semantics only
43     DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(unique_fd);
44 
duplicate()45     fbl::unique_fd duplicate() {
46         return fbl::unique_fd(dup(fd_));
47     }
48 
release()49     int release() {
50         int t = fd_;
51         fd_ = InvalidValue();
52         return t;
53     }
54 
55     void reset(int t = InvalidValue()) {
56         if (fd_ != InvalidValue()) {
57             close(fd_);
58         }
59         fd_ = t;
60     }
61 
swap(unique_fd & other)62     void swap(unique_fd& other) {
63         int t = fd_;
64         fd_ = other.fd_;
65         other.fd_ = t;
66     }
67 
get()68     int get() const {
69         return fd_;
70     }
71 
is_valid()72     bool is_valid() const  {
73         return fd_ != InvalidValue();
74     }
75 
76     explicit operator bool() const {
77         return is_valid();
78     }
79 
80     explicit operator int() const {
81         return fd_;
82     }
83 
84 private:
85     int fd_;
86 };
87 
88 }  // namespace fbl
89