• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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     Deserialize, DeserializeArray, DeserializeOption, BorrowedParcel, 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::fs::File;
26 use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
27 
28 /// Rust version of the Java class android.os.ParcelFileDescriptor
29 #[derive(Debug)]
30 pub struct ParcelFileDescriptor(File);
31 
32 impl ParcelFileDescriptor {
33     /// Create a new `ParcelFileDescriptor`
new(file: File) -> Self34     pub fn new(file: File) -> Self {
35         Self(file)
36     }
37 }
38 
39 impl AsRef<File> for ParcelFileDescriptor {
as_ref(&self) -> &File40     fn as_ref(&self) -> &File {
41         &self.0
42     }
43 }
44 
45 impl From<ParcelFileDescriptor> for File {
from(file: ParcelFileDescriptor) -> File46     fn from(file: ParcelFileDescriptor) -> File {
47         file.0
48     }
49 }
50 
51 impl AsRawFd for ParcelFileDescriptor {
as_raw_fd(&self) -> RawFd52     fn as_raw_fd(&self) -> RawFd {
53         self.0.as_raw_fd()
54     }
55 }
56 
57 impl IntoRawFd for ParcelFileDescriptor {
into_raw_fd(self) -> RawFd58     fn into_raw_fd(self) -> RawFd {
59         self.0.into_raw_fd()
60     }
61 }
62 
63 impl PartialEq for ParcelFileDescriptor {
64     // Since ParcelFileDescriptors own the FD, if this function ever returns true (and it is used to
65     // compare two different objects), then it would imply that an FD is double-owned.
eq(&self, other: &Self) -> bool66     fn eq(&self, other: &Self) -> bool {
67         self.as_raw_fd() == other.as_raw_fd()
68     }
69 }
70 
71 impl Eq for ParcelFileDescriptor {}
72 
73 impl Serialize for ParcelFileDescriptor {
serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()>74     fn serialize(&self, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
75         let fd = self.0.as_raw_fd();
76         let status = unsafe {
77             // Safety: `Parcel` always contains a valid pointer to an
78             // `AParcel`. Likewise, `ParcelFileDescriptor` always contains a
79             // valid file, so we can borrow a valid file
80             // descriptor. `AParcel_writeParcelFileDescriptor` does NOT take
81             // ownership of the fd, so we need not duplicate it first.
82             sys::AParcel_writeParcelFileDescriptor(parcel.as_native_mut(), fd)
83         };
84         status_result(status)
85     }
86 }
87 
88 impl SerializeArray for ParcelFileDescriptor {}
89 
90 impl SerializeOption for ParcelFileDescriptor {
serialize_option(this: Option<&Self>, parcel: &mut BorrowedParcel<'_>) -> Result<()>91     fn serialize_option(this: Option<&Self>, parcel: &mut BorrowedParcel<'_>) -> Result<()> {
92         if let Some(f) = this {
93             f.serialize(parcel)
94         } else {
95             let status = unsafe {
96                 // Safety: `Parcel` always contains a valid pointer to an
97                 // `AParcel`. `AParcel_writeParcelFileDescriptor` accepts the
98                 // value `-1` as the file descriptor to signify serializing a
99                 // null file descriptor.
100                 sys::AParcel_writeParcelFileDescriptor(parcel.as_native_mut(), -1i32)
101             };
102             status_result(status)
103         }
104     }
105 }
106 
107 impl DeserializeOption for ParcelFileDescriptor {
deserialize_option(parcel: &BorrowedParcel<'_>) -> Result<Option<Self>>108     fn deserialize_option(parcel: &BorrowedParcel<'_>) -> Result<Option<Self>> {
109         let mut fd = -1i32;
110         unsafe {
111             // Safety: `Parcel` always contains a valid pointer to an
112             // `AParcel`. We pass a valid mutable pointer to an i32, which
113             // `AParcel_readParcelFileDescriptor` assigns the valid file
114             // descriptor into, or `-1` if deserializing a null file
115             // descriptor. The read function passes ownership of the file
116             // descriptor to its caller if it was non-null, so we must take
117             // ownership of the file and ensure that it is eventually closed.
118             status_result(sys::AParcel_readParcelFileDescriptor(
119                 parcel.as_native(),
120                 &mut fd,
121             ))?;
122         }
123         if fd < 0 {
124             Ok(None)
125         } else {
126             let file = unsafe {
127                 // Safety: At this point, we know that the file descriptor was
128                 // not -1, so must be a valid, owned file descriptor which we
129                 // can safely turn into a `File`.
130                 File::from_raw_fd(fd)
131             };
132             Ok(Some(ParcelFileDescriptor::new(file)))
133         }
134     }
135 }
136 
137 impl Deserialize for ParcelFileDescriptor {
deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self>138     fn deserialize(parcel: &BorrowedParcel<'_>) -> Result<Self> {
139         Deserialize::deserialize(parcel)
140             .transpose()
141             .unwrap_or(Err(StatusCode::UNEXPECTED_NULL))
142     }
143 }
144 
145 impl DeserializeArray for ParcelFileDescriptor {}
146