From 051e11b3670843cc59b9910c1dfd279b955317e4 Mon Sep 17 00:00:00 2001 From: ok-nick Date: Sun, 28 Apr 2024 14:05:08 -0400 Subject: [PATCH] fix stuff affecting sftp example --- examples/sftp/src/main.rs | 49 ++++++++++++++++++--------------------- src/command/commands.rs | 18 +++++++------- src/ext/file.rs | 8 +++---- src/filter/ticket.rs | 15 ++++-------- src/placeholder_file.rs | 4 ++-- 5 files changed, 41 insertions(+), 53 deletions(-) diff --git a/examples/sftp/src/main.rs b/examples/sftp/src/main.rs index a2d7a26..e73171e 100644 --- a/examples/sftp/src/main.rs +++ b/examples/sftp/src/main.rs @@ -5,7 +5,7 @@ use std::{ io::{self, BufWriter, Read, Seek, SeekFrom, Write}, net::TcpStream, os::windows::fs::OpenOptionsExt, - path::{Path, PathBuf}, + path::Path, sync::mpsc, }; @@ -18,8 +18,7 @@ use wincs::{ filter::{info, ticket, SyncFilter}, placeholder_file::{Metadata, PlaceholderFile}, request::Request, - CloudErrorKind, PopulationType, Registration, SecurityId, Session as WincsSession, - SyncRootIdBuilder, + CloudErrorKind, PopulationType, Registration, SecurityId, SyncRootIdBuilder, }; // max should be 65536, this is done both in term-scp and sshfs because it's the @@ -72,15 +71,15 @@ fn main() { .unwrap(); } - covert_to_placeholder(PathBuf::from(&client_path)); + convert_to_placeholder(Path::new(&client_path)); - let conn = WincsSession::new() + let connection = wincs::Session::new() .connect(&client_path, Filter { sftp }) .unwrap(); wait_for_ctrlc(); - conn.disconnect().unwrap(); + connection.disconnect().unwrap(); sync_root_id.unregister().unwrap(); } @@ -88,23 +87,29 @@ fn get_client_path() -> String { env::var("CLIENT_PATH").unwrap() } -fn covert_to_placeholder(path: PathBuf) { +fn convert_to_placeholder(path: &Path) { for entry in path.read_dir().unwrap() { let entry = entry.unwrap(); + let is_dir = entry.path().is_dir(); + let mut open_options = File::options(); open_options.read(true); - if entry.path().is_dir() { + if is_dir { + // FILE_FLAG_BACKUP_SEMANTICS, needed to obtain handle to directory open_options.custom_flags(0x02000000); } - let f = open_options.open(entry.path()).unwrap(); - let options = if entry.path().is_dir() { + + let convert_options = if is_dir { ConvertOptions::default().has_children() } else { ConvertOptions::default() }; - f.to_placeholder(options).unwrap(); - if entry.path().is_dir() { - covert_to_placeholder(entry.path()); + + let file = open_options.open(entry.path()).unwrap(); + file.to_placeholder(convert_options).unwrap(); + + if is_dir { + convert_to_placeholder(&entry.path()); } } } @@ -172,8 +177,6 @@ impl Filter { // TODO: everything is just forwarded to external functions... This should be // changed in the wrapper api impl SyncFilter for Filter { - // type Error = SftpError; - // TODO: handle unwraps fn fetch_data(&self, request: Request, ticket: ticket::FetchData, info: info::FetchData) { println!("fetch_data {:?}", request.file_blob()); @@ -184,6 +187,7 @@ impl SyncFilter for Filter { let end = range.end; let mut position = range.start; + // TODO: allow callback to return Result in SyncFilter let res = || -> Result<(), _> { let mut server_file = self .sftp @@ -273,7 +277,7 @@ impl SyncFilter for Filter { match info.source_in_scope() { // TODO: use fs::copy or fs::rename, whatever it is to move the local files, - // then use CovertToPlaceholder. I'm not sure if I have to do this recursively + // then use ConvertToPlaceholder. I'm not sure if I have to do this recursively // for each file or only the top-level folder TODO: which // rename flags do I use? how do I know if I should be overwriting? true => self @@ -314,9 +318,9 @@ impl SyncFilter for Filter { info: info::FetchPlaceholders, ) { println!( - "fetch_placeholders {:?} {}", + "fetch_placeholders {:?} {:?}", request.path(), - info.pattern().to_string().unwrap() + info.pattern() ); let absolute = request.path(); let client_path = get_client_path(); @@ -347,17 +351,10 @@ impl SyncFilter for Filter { .overwrite() // .mark_sync() // need this? .blob(path.as_os_str().as_encoded_bytes()) - - // if stat.is_file() { - // placeholder = placeholder.has_no_children(); - // } }) .collect::>(); - match placeholders.is_empty() { - true => ticket.pass().unwrap(), - false => ticket.pass_with_placeholder(&*placeholders).unwrap(), - }; + ticket.pass_with_placeholder(&placeholders).unwrap(); } fn closed(&self, request: Request, info: info::Closed) { diff --git a/src/command/commands.rs b/src/command/commands.rs index 316dbf0..6c03f8f 100644 --- a/src/command/commands.rs +++ b/src/command/commands.rs @@ -151,7 +151,7 @@ impl Command for Update<'_> { #[derive(Debug, Clone, Default)] pub struct CreatePlaceholders<'a> { /// The placeholders to create. - pub placeholders: Option<&'a [PlaceholderFile<'a>]>, // FIXME: placeholder should be mutable + pub placeholders: &'a [PlaceholderFile<'a>], // FIXME: placeholder should be mutable /// The total amount of placeholders that are a child of the current directory. pub total: u64, } @@ -186,17 +186,17 @@ impl Command for CreatePlaceholders<'_> { fn build(&self) -> CF_OPERATION_PARAMETERS_0 { CF_OPERATION_PARAMETERS_0 { TransferPlaceholders: CF_OPERATION_PARAMETERS_0_7 { + // TODO: this flag tells the system there are no more placeholders in this directory (when that can be untrue) + // in the future, implement streaming Flags: CloudFilters::CF_OPERATION_TRANSFER_PLACEHOLDERS_FLAG_DISABLE_ON_DEMAND_POPULATION, CompletionStatus: Foundation::STATUS_SUCCESS, PlaceholderTotalCount: self.total as i64, - PlaceholderArray: self - .placeholders - .map(|placeholders| placeholders.as_ptr() as *mut _) // FIXME - .unwrap_or_else(ptr::null_mut), - PlaceholderCount: self - .placeholders - .map(|placeholders| placeholders.len() as u32) - .unwrap_or(0), + PlaceholderArray: match self.placeholders.is_empty() { + // If the slice is empty there will be an invalid memory access error, not with null pointers, however. + true => ptr::null_mut(), + false => self.placeholders.as_ptr() as *mut _, + }, + PlaceholderCount: self.placeholders.len() as u32, EntriesProcessed: 0, }, } diff --git a/src/ext/file.rs b/src/ext/file.rs index 9315803..1e92286 100644 --- a/src/ext/file.rs +++ b/src/ext/file.rs @@ -603,11 +603,9 @@ impl<'a> ConvertOptions<'a> { self } - /// Marks the placeholder as having no child placeholders on creation. - /// - /// If [PopulationType::Full][crate::PopulationType] is specified on registration, this flag - /// will prevent [SyncFilter::fetch_placeholders][crate::SyncFilter::fetch_placeholders] from - /// being called for this placeholder. + // TODO: make the name of this function more specific + /// Marks the placeholder as "partially full," such that [SyncFilter::fetch_placeholders][crate::SyncFilter::fetch_placeholders] + /// will be invoked when this directory is next accessed so that the remaining placeholders are inserted. /// /// Only applicable to placeholder directories. pub fn has_children(mut self) -> Self { diff --git a/src/filter/ticket.rs b/src/filter/ticket.rs index 81c5c7d..aafcfcc 100644 --- a/src/filter/ticket.rs +++ b/src/filter/ticket.rs @@ -77,22 +77,15 @@ impl FetchPlaceholders { } } - /// Returns the empty list of placeholders. - pub fn pass(&self) -> core::Result>> { - command::CreatePlaceholders { - placeholders: None, - total: 0, - } - .execute(self.connection_key, self.transfer_key) - } - - /// Returns the list of placeholders. + /// Creates a list of placeholder files/directorys on the file system. + /// + /// The value returned is the final [Usn][crate::Usn] (and if they succeeded) after each placeholder is created. pub fn pass_with_placeholder<'a>( &self, placeholders: &'a [PlaceholderFile<'a>], ) -> core::Result>> { command::CreatePlaceholders { - placeholders: Some(placeholders), + placeholders, total: placeholders.len() as _, } .execute(self.connection_key, self.transfer_key) diff --git a/src/placeholder_file.rs b/src/placeholder_file.rs index ee2f302..1ebd5a4 100644 --- a/src/placeholder_file.rs +++ b/src/placeholder_file.rs @@ -114,8 +114,8 @@ impl<'a> PlaceholderFile<'a> { /// [FileExt::to_placeholder][crate::ext::FileExt::to_placeholder] for efficiency purposes. If you /// need to create multiple placeholders, consider using [BatchCreate][crate::BatchCreate]. /// - /// If you need to create placeholders from a callback, do not use this method. Instead, use - /// [Request::create_placeholder][crate::Request::create_placeholder]. + /// If you need to create placeholders from the [SyncFilter::fetch_placeholders][crate::SyncFilter::fetch_placeholders] callback, do not use this method. Instead, use + /// [FetchPlaceholders::pass_with_placeholders][crate::ticket::FetchPlaceholders::pass_with_placeholders]. pub fn create>(mut self, parent: impl AsRef) -> core::Result { unsafe { CfCreatePlaceholders(