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