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, Parcel, 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}; 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 Serialize for ParcelFileDescriptor { serialize(&self, parcel: &mut Parcel) -> Result<()>52 fn serialize(&self, parcel: &mut Parcel) -> Result<()> { 53 let fd = self.0.as_raw_fd(); 54 let status = unsafe { 55 // Safety: `Parcel` always contains a valid pointer to an 56 // `AParcel`. Likewise, `ParcelFileDescriptor` always contains a 57 // valid file, so we can borrow a valid file 58 // descriptor. `AParcel_writeParcelFileDescriptor` does NOT take 59 // ownership of the fd, so we need not duplicate it first. 60 sys::AParcel_writeParcelFileDescriptor(parcel.as_native_mut(), fd) 61 }; 62 status_result(status) 63 } 64 } 65 66 impl SerializeArray for ParcelFileDescriptor {} 67 68 impl SerializeOption for ParcelFileDescriptor { serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()>69 fn serialize_option(this: Option<&Self>, parcel: &mut Parcel) -> Result<()> { 70 if let Some(f) = this { 71 f.serialize(parcel) 72 } else { 73 let status = unsafe { 74 // Safety: `Parcel` always contains a valid pointer to an 75 // `AParcel`. `AParcel_writeParcelFileDescriptor` accepts the 76 // value `-1` as the file descriptor to signify serializing a 77 // null file descriptor. 78 sys::AParcel_writeParcelFileDescriptor(parcel.as_native_mut(), -1i32) 79 }; 80 status_result(status) 81 } 82 } 83 } 84 85 impl SerializeArray for Option<ParcelFileDescriptor> {} 86 87 impl DeserializeOption for ParcelFileDescriptor { deserialize_option(parcel: &Parcel) -> Result<Option<Self>>88 fn deserialize_option(parcel: &Parcel) -> Result<Option<Self>> { 89 let mut fd = -1i32; 90 unsafe { 91 // Safety: `Parcel` always contains a valid pointer to an 92 // `AParcel`. We pass a valid mutable pointer to an i32, which 93 // `AParcel_readParcelFileDescriptor` assigns the valid file 94 // descriptor into, or `-1` if deserializing a null file 95 // descriptor. The read function passes ownership of the file 96 // descriptor to its caller if it was non-null, so we must take 97 // ownership of the file and ensure that it is eventually closed. 98 status_result(sys::AParcel_readParcelFileDescriptor( 99 parcel.as_native(), 100 &mut fd, 101 ))?; 102 } 103 if fd < 0 { 104 Ok(None) 105 } else { 106 let file = unsafe { 107 // Safety: At this point, we know that the file descriptor was 108 // not -1, so must be a valid, owned file descriptor which we 109 // can safely turn into a `File`. 110 File::from_raw_fd(fd) 111 }; 112 Ok(Some(ParcelFileDescriptor::new(file))) 113 } 114 } 115 } 116 117 impl DeserializeArray for Option<ParcelFileDescriptor> {} 118 119 impl Deserialize for ParcelFileDescriptor { deserialize(parcel: &Parcel) -> Result<Self>120 fn deserialize(parcel: &Parcel) -> Result<Self> { 121 Deserialize::deserialize(parcel) 122 .transpose() 123 .unwrap_or(Err(StatusCode::UNEXPECTED_NULL)) 124 } 125 } 126 127 impl DeserializeArray for ParcelFileDescriptor {} 128