// Given a path, read the metadata for the file, handle symlinks, hardlinks, etc and return an ArchiveBuilderFile or None if a problem was encountered.
Given a path, read the metadata for the file, handle symlinks, hardlinks, etc and return an ArchiveBuilderFile or None if a problem was encountered.
Given a path read the metadata for the file handle symlinks hardlinks etc and return an ArchiveBuilderFile or None if a problem was encountered .
fn read_file_metadata<P: AsRef<Path>>(&mut self, path: P, current_filesystem: Option<u64>) -> Option<ArchiveBuilderFile> {
		// First, let's see if it's a symlink
		let symlink_metadata = match path.as_ref().symlink_metadata() {
			Ok(metadata) => metadata,
			Err(err) => {
				warn!("Unable to read metadata for '{}'.  It will not be included in the archive.  The following error was received: {}", path.as_ref().display(), err);
				return None
			},
		};
		// Skip files, symlinks, etc that don't reside on the current filesystem we're walking, if --one-file-system is enabled
		if let Some(current_filesystem) = current_filesystem {
			if symlink_metadata.dev() != current_filesystem {
				warn!("'{}' is being skipped because of --one-file-system.", path.as_ref().display());
				return None
			}
		}
		if self.should_ignore(&symlink_metadata, path.as_ref()) {
			warn!("'{}' is being skipped because it is ignored.", path.as_ref().display());
			return None;
		}
		// If we encounter a symlink, and we aren't dereferencing, then we will
		// store information about the symlink, and all metadata will be about
		// the symlink (not the file/folder it points to).
		// If we derference the symlink then all metadata will be about the
		// file/folder the symlink points to.
		let (metadata, symlink_path) = if symlink_metadata.file_type().is_symlink() && !self.config.dereference_symlinks {
			let symlink_path: String = match fs::read_link(path.as_ref()) {
				Ok(symlink_path) => match symlink_path.to_str() {
					Some(symlink_path_str) => symlink_path_str.to_string(),
					None => {
						warn!("Unable to read symlink for '{}' as UTF-8 string.  It will not be included in the archive.", path.as_ref().display());
						return None
					},
				},
				Err(err) => {
					warn!("Unable to read symlink for '{}'.  It will not be included in the archive.  The following error was received: {}", path.as_ref().display(), err);
					return None
				},
			};
			(path.as_ref().symlink_metadata(), Some(symlink_path))
		} else {
			(path.as_ref().metadata(), None)
		};
		let metadata = match metadata {
			Ok(metadata) => metadata,
			Err(err) => {
				warn!("Unable to read metadata for '{}'.  It will not be included in the archive.  The following error was received: {}", path.as_ref().display(), err);
				return None;
			},
		};
		// Skip files, symlinks, etc that don't reside on the current filesystem we're walking, if --one-file-system is enabled
		if let Some(current_filesystem) = current_filesystem {
			if metadata.dev() != current_filesystem {
				warn!("'{}' is being skipped because of --one-file-system.", path.as_ref().display());
				return None
			}
		}
		if self.should_ignore(&metadata, path.as_ref()) {
			warn!("'{}' is being skipped because it is ignored.", path.as_ref().display());
			return None;
		}
		// Skip anything that isn't a symlink, regular file, or directory.
		if symlink_path.is_none() && !metadata.is_file() && !metadata.is_dir() {
			warn!("Skipping '{}' because it is not a symlink, directory, or regular file.", path.as_ref().display());
			return None;
		}
		let filesize = if symlink_path.is_none() && metadata.is_file() {
			metadata.len()
		} else {
			0
		};
		let canonical_path = match path.as_ref().canonicalize() {
			Ok(canonical_path) => Some(canonical_path),
			Err(_) => None,
		};
		// The path stored in the archive is relative to the archive's base_path
		let filepath = match path.as_ref().strip_prefix(&self.base_path) {
			Ok(filepath) => match filepath.to_str () {
				Some(filepath) => filepath.to_string(),
				None => {
					warn!("Unable to read path of '{}' as UTF-8 string.  It will not be included in the archive.", path.as_ref().display());
					return None
				}
			},
			Err(_) => {
				warn!("An internal error occured involving strip_prefix.  The file '{}' will not be included in the archive.", path.as_ref().display());
				return None
			}
		};
		// Handle hardlinks
		let hardlink_id = if metadata.nlink() > 1 && !metadata.is_dir() {
			let key = FileIdentifier {
				devid: metadata.dev(),
				inode: metadata.ino(),
			};
			let next_hardlink_id = self.last_hardlink_id;
			let entry = self.hardlink_map.entry(key).or_insert_with(|| {
				HardLink {
					expected_links: metadata.nlink(),
					id: next_hardlink_id,
					example_path: PathBuf::from(path.as_ref()),
				}
			});
			if entry.id == self.last_hardlink_id {
				self.last_hardlink_id += 1;
			}
			Some(entry.id)
		} else {
			None
		};
		Some(ArchiveBuilderFile {
			file: archive::File {
				path: filepath,
				is_dir: metadata.is_dir(),
				symlink: symlink_path,
				hardlink_id: hardlink_id,
				mode: metadata.mode(),
				mtime: metadata.mtime(),
				mtime_nsec: metadata.mtime_nsec(),
				uid: metadata.uid(),
				gid: metadata.gid(),
				size: filesize,
				blocks: Vec::new(),
			},
			missing: false,
			canonical_path: canonical_path,
		})
	}
fn read_file_metadata < P : AsRef < Path > > ( & mut self , path : P , current_filesystem : Option < u64 > ) -> Option < ArchiveBuilderFile > { // First, let's see if it's a symlink let symlink_metadata = match path . as_ref ( ) . symlink_metadata ( ) { Ok ( metadata ) => metadata , Err ( err ) => { warn ! ( " " path as_ref ( ) display ( ) err ) ; return None } , } ; // Skip files, symlinks, etc that don't reside on the current filesystem we're walking, if --one-file-system is enabled if let Some ( current_filesystem ) = current_filesystem { if symlink_metadata . dev ( ) != current_filesystem { warn ! ( " " path as_ref ( ) display ( ) ) ; return None } } if self . should_ignore ( & symlink_metadata , path . as_ref ( ) ) { warn ! ( " " path as_ref ( ) display ( ) ) ; return None ; } // If we encounter a symlink, and we aren't dereferencing, then we will // store information about the symlink, and all metadata will be about // the symlink (not the file/folder it points to). // If we derference the symlink then all metadata will be about the // file/folder the symlink points to. let ( metadata , symlink_path ) = if symlink_metadata . file_type ( ) . is_symlink ( ) && ! self . config . dereference_symlinks { let symlink_path : String = match fs :: read_link ( path . as_ref ( ) ) { Ok ( symlink_path ) => match symlink_path . to_str ( ) { Some ( symlink_path_str ) => symlink_path_str . to_string ( ) , None => { warn ! ( " " path as_ref ( ) display ( ) ) ; return None } , } , Err ( err ) => { warn ! ( " " path as_ref ( ) display ( ) err ) ; return None } , } ; ( path . as_ref ( ) . symlink_metadata ( ) , Some ( symlink_path ) ) } else { ( path . as_ref ( ) . metadata ( ) , None ) } ; let metadata = match metadata { Ok ( metadata ) => metadata , Err ( err ) => { warn ! ( " " path as_ref ( ) display ( ) err ) ; return None ; } , } ; // Skip files, symlinks, etc that don't reside on the current filesystem we're walking, if --one-file-system is enabled if let Some ( current_filesystem ) = current_filesystem { if metadata . dev ( ) != current_filesystem { warn ! ( " " path as_ref ( ) display ( ) ) ; return None } } if self . should_ignore ( & metadata , path . as_ref ( ) ) { warn ! ( " " path as_ref ( ) display ( ) ) ; return None ; } // Skip anything that isn't a symlink, regular file, or directory. if symlink_path . is_none ( ) && ! metadata . is_file ( ) && ! metadata . is_dir ( ) { warn ! ( " " path as_ref ( ) display ( ) ) ; return None ; } let filesize = if symlink_path . is_none ( ) && metadata . is_file ( ) { metadata . len ( ) } else { 0 } ; let canonical_path = match path . as_ref ( ) . canonicalize ( ) { Ok ( canonical_path ) => Some ( canonical_path ) , Err ( _ ) => None , } ; // The path stored in the archive is relative to the archive's base_path let filepath = match path . as_ref ( ) . strip_prefix ( & self . base_path ) { Ok ( filepath ) => match filepath . to_str ( ) { Some ( filepath ) => filepath . to_string ( ) , None => { warn ! ( " " path as_ref ( ) display ( ) ) ; return None } } , Err ( _ ) => { warn ! ( " " path as_ref ( ) display ( ) ) ; return None } } ; // Handle hardlinks let hardlink_id = if metadata . nlink ( ) > 1 && ! metadata . is_dir ( ) { let key = FileIdentifier { devid : metadata . dev ( ) , inode : metadata . ino ( ) , } ; let next_hardlink_id = self . last_hardlink_id ; let entry = self . hardlink_map . entry ( key ) . or_insert_with ( | | { HardLink { expected_links : metadata . nlink ( ) , id : next_hardlink_id , example_path : PathBuf :: from ( path . as_ref ( ) ) , } } ) ; if entry . id == self . last_hardlink_id { self . last_hardlink_id += 1 ; } Some ( entry . id ) } else { None } ; Some ( ArchiveBuilderFile { file : archive :: File { path : filepath , is_dir : metadata . is_dir ( ) , symlink : symlink_path , hardlink_id : hardlink_id , mode : metadata . mode ( ) , mtime : metadata . mtime ( ) , mtime_nsec : metadata . mtime_nsec ( ) , uid : metadata . uid ( ) , gid : metadata . gid ( ) , size : filesize , blocks : Vec :: new ( ) , } , missing : false , canonical_path : canonical_path , } ) }
Given a path, read the metadata for the file, handle symlinks, hardlinks, etc and return an ArchiveBuilderFile or None if a problem was encountered.
Given a path read the metadata for the file handle symlinks hardlinks etc and return an ArchiveBuilderFile or None if a problem was encountered .
&mut self
path
P
current_filesystem
Option<u64>