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