1 // Copyright 2020 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #pragma once
16 
17 #include "aemu/base/Compiler.h"
18 
19 #include <errno.h>
20 #ifdef _MSC_VER
21 #include "aemu/base/msvc.h"
22 #else
23 #include <unistd.h>
24 #endif
25 
26 namespace android {
27 namespace base {
28 
29 // Helper class to hold an integer file descriptor, and have the 'close'
30 // function called automatically on scope exit, unless the 'release'
31 // method was called previously.
32 class ScopedFd {
33 public:
34     // Default constructor will hold an invalid descriptor.
ScopedFd()35     ScopedFd() : fd_(-1) {}
36 
37     // Constructor takes ownership of |fd|.
ScopedFd(int fd)38     explicit ScopedFd(int fd) : fd_(fd) {}
39 
40     // Make it movable.
ScopedFd(ScopedFd && other)41     ScopedFd(ScopedFd&& other) : fd_(other.fd_) {
42         other.fd_ = -1;
43     }
44 
45     ScopedFd& operator=(ScopedFd&& other) {
46         swap(&other);
47         return *this;
48     }
49 
50     // Destructor calls close().
~ScopedFd()51     ~ScopedFd() { close(); }
52 
53     // Return the file descriptor value, does _not_ transfer ownership.
get()54     int get() const { return fd_; }
55 
56     // Return the file descriptor value, transfers ownership to the caller.
release()57     int release() {
58         int fd = fd_;
59         fd_ = -1;
60         return fd;
61     }
62 
63     // Return true iff the file descriptor is valid.
valid()64     bool valid() const { return fd_ >= 0; }
65 
66     // Close the file descriptor (and make the wrapped value invalid).
close()67     void close() {
68         if (fd_ != -1) {
69             int save_errno = errno;
70             ::close(fd_);
71             fd_ = -1;
72             errno = save_errno;
73         }
74     }
75 
76     // Swap two ScopedFd instances.
swap(ScopedFd * other)77     void swap(ScopedFd* other) {
78         int fd = fd_;
79         fd_ = other->fd_;
80         other->fd_ = fd;
81     }
82 
83 private:
84     DISALLOW_COPY_AND_ASSIGN(ScopedFd);
85 
86     int fd_;
87 };
88 
89 }  // namespace base
90 }  // namespace android
91