1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 use super::{
18     BorrowedParcel, Deserialize, DeserializeArray, DeserializeOption, Serialize, SerializeArray,
19     SerializeOption,
20 };
21 use crate::binder::AsNative;
22 use crate::error::{status_result, Result, StatusCode};
23 use crate::sys;
24 
25 use std::os::fd::{AsRawFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
26 
27 /// Rust version of the Java class android.os.ParcelFileDescriptor
28 #[derive(Debug)]
29 pub struct ParcelFileDescriptor(OwnedFd);
30 
31 impl ParcelFileDescriptor {
32     /// Create a new `ParcelFileDescriptor`
new<F: Into<OwnedFd>>(fd: F) -> Self33     pub fn new<F: Into<OwnedFd>>(fd: F) -> Self {
34         Self(fd.into())
35     }
36 }
37 
38 impl AsRef<OwnedFd> for ParcelFileDescriptor {
as_ref(&self) -> &OwnedFd39     fn as_ref(&self) -> &OwnedFd {
40         &self.0
41     }
42 }
43 
44 impl From<ParcelFileDescriptor> for OwnedFd {
from(fd: ParcelFileDescriptor) -> OwnedFd45     fn from(fd: ParcelFileDescriptor) -> OwnedFd {
46         fd.0
47     }
48 }
49 
50 impl AsRawFd for ParcelFileDescriptor {
as_raw_fd(&self) -> RawFd51     fn as_raw_fd(&self) -> RawFd {
52         self.0.as_raw_fd()
53     }
54 }
55 
56 impl IntoRawFd for ParcelFileDescriptor {
into_raw_fd(self) -> RawFd57     fn into_raw_fd(self) -> RawFd {
58         self.0.into_raw_fd()
59     }
60 }
61 
62 impl PartialEq for ParcelFileDescriptor {
63     // Since ParcelFileDescriptors own the FD, if this function ever returns true (and it is used to
64     // compare two different objects), then it would imply that an FD is double-owned.
eq(&self, other: &Self) -> bool65     fn eq(&self, other: &Self) -> bool {
66         self.as_raw_fd() == other.as_raw_fd()
67     }
68 }
69 
70 impl Eq for ParcelFileDescriptor {}
71 
72 impl Serialize for ParcelFileDescriptor {
serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()>73     fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
74         let fd = self.0.as_raw_fd();
75         // Safety: `Parcel` always contains a valid pointer to an
76         // `AParcel`. Likewise, `ParcelFileDescriptor` always contains a
77         // valid file, so we can borrow a valid file
78         // descriptor. `AParcel_writeParcelFileDescriptor` does NOT take
79         // ownership of the fd, so we need not duplicate it first.
80         let status = unsafe { sys::AParcel_writeParcelFileDescriptor(parcel.as_native_mut(), fd) };
81         status_result(status)
82     }
83 }
84 
85 impl SerializeArray for ParcelFileDescriptor {}
86 
87 impl SerializeOption for ParcelFileDescriptor {
serialize_option(this: Option<&Self>, parcel: &mut BorrowedParcel<'_>) -> Result<()>88     fn serialize_option(this: Option<&Self>, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
89         if let Some(f) = this {
90             f.serialize(parcel)
91         } else {
92             let status =
93             // Safety: `Parcel` always contains a valid pointer to an
94             // `AParcel`. `AParcel_writeParcelFileDescriptor` accepts the
95             // value `-1` as the file descriptor to signify serializing a
96             // null file descriptor.
97                 unsafe { sys::AParcel_writeParcelFileDescriptor(parcel.as_native_mut(), -1i32) };
98             status_result(status)
99         }
100     }
101 }
102 
103 impl DeserializeOption for ParcelFileDescriptor {
deserialize_option(parcel: &BorrowedParcel<'_>) -> Result<Option<Self>>104     fn deserialize_option(parcel: &BorrowedParcel<'_>) -> Result<Option<Self>> {
105         let mut fd = -1i32;
106         // Safety: `Parcel` always contains a valid pointer to an
107         // `AParcel`. We pass a valid mutable pointer to an i32, which
108         // `AParcel_readParcelFileDescriptor` assigns the valid file
109         // descriptor into, or `-1` if deserializing a null file
110         // descriptor. The read function passes ownership of the file
111         // descriptor to its caller if it was non-null, so we must take
112         // ownership of the file and ensure that it is eventually closed.
113         unsafe {
114             status_result(sys::AParcel_readParcelFileDescriptor(parcel.as_native(), &mut fd))?;
115         }
116         if fd < 0 {
117             Ok(None)
118         } else {
119             // Safety: At this point, we know that the file descriptor was
120             // not -1, so must be a valid, owned file descriptor which we
121             // can safely turn into a `File`.
122             let file = unsafe { OwnedFd::from_raw_fd(fd) };
123             Ok(Some(ParcelFileDescriptor::new(file)))
124         }
125     }
126 }
127 
128 impl Deserialize for ParcelFileDescriptor {
129     type UninitType = Option<Self>;
uninit() -> Self::UninitType130     fn uninit() -> Self::UninitType {
131         Self::UninitType::default()
132     }
from_init(value: Self) -> Self::UninitType133     fn from_init(value: Self) -> Self::UninitType {
134         Some(value)
135     }
136 
deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self>137     fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> {
138         Deserialize::deserialize(parcel).transpose().unwrap_or(Err(StatusCode::UNEXPECTED_NULL))
139     }
140 }
141 
142 impl DeserializeArray for ParcelFileDescriptor {}
143