197502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner// Copyright 2014 The Android Open Source Project
297502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner//
397502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner// This software is licensed under the terms of the GNU General Public
497502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner// License version 2, as published by the Free Software Foundation, and
597502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner// may be copied, distributed, and modified under those terms.
697502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner//
797502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner// This program is distributed in the hope that it will be useful,
897502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner// but WITHOUT ANY WARRANTY; without even the implied warranty of
997502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1097502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner// GNU General Public License for more details.
1197502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner
1297502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner#ifndef ANDROID_BASE_SCOPED_FD_H
1397502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner#define ANDROID_BASE_SCOPED_FD_H
1497502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner
1597502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner#include "android/base/Compiler.h"
1697502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner
1797502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner#include <errno.h>
1897502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner#include <unistd.h>
1997502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner
2097502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turnernamespace android {
2197502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turnernamespace base {
2297502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner
2397502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner// Helper class to hold an integer file descriptor, and have the 'close'
2497502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner// function called automatically on scope exit, unless the 'release'
2597502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner// method was called previously.
2697502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turnerclass ScopedFd {
2797502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turnerpublic:
2897502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner    // Default constructor will hold an invalid descriptor.
2997502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner    ScopedFd() : fd_(-1) {}
3097502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner
3197502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner    // Constructor takes ownership of |fd|.
3297502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner    explicit ScopedFd(int fd) : fd_(fd) {}
3397502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner
3497502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner    // Destructor calls close().
3597502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner    ~ScopedFd() { close(); }
3697502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner
3797502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner    // Return the file descriptor value, does _not_ transfer ownership.
3897502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner    int get() const { return fd_; }
3997502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner
4097502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner    // Return the file descriptor value, transfers ownership to the caller.
4197502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner    int release() {
4297502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner        int fd = fd_;
4397502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner        fd_ = -1;
4497502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner        return fd;
4597502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner    }
4697502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner
4797502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner    // Return true iff the file descriptor is valid.
4897502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner    bool valid() const { return fd_ >= 0; }
4997502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner
5097502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner    // Close the file descriptor (and make the wrapped value invalid).
5197502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner    void close() {
5297502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner        if (fd_ != -1) {
5397502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner            int save_errno = errno;
5497502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner            ::close(fd_);
5597502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner            fd_ = -1;
5697502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner            errno = save_errno;
5797502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner        }
5897502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner    }
5997502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner
6097502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner    // Swap two ScopedFd instances.
6197502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner    void swap(ScopedFd* other) {
6297502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner        int fd = fd_;
6397502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner        fd_ = other->fd_;
6497502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner        other->fd_ = fd;
6597502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner    }
6697502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner
6797502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turnerprivate:
6897502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner    DISALLOW_COPY_AND_ASSIGN(ScopedFd);
6997502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner
7097502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner    int fd_;
7197502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner};
7297502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner
7397502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner}  // namespace base
7497502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner}  // namespace android
7597502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner
7697502faffa2e99bf717749a2d249ba3e57d7da4dDavid 'Digit' Turner#endif  // ANDROID_BASE_SCOPED_FD_H
77