@@ -7,7 +7,7 @@ use std::ops::Range;
77use std:: path:: { Path , PathBuf } ;
88use std:: time:: { Duration , SystemTime } ;
99
10- use regex :: Regex ;
10+ use lazy_regex :: { Lazy , Regex } ;
1111use remotefs:: fs:: {
1212 FileType , Metadata , ReadStream , RemoteError , RemoteErrorType , RemoteFs , RemoteResult , UnixPex ,
1313 UnixPexClass , Welcome , WriteStream ,
@@ -19,6 +19,11 @@ pub use ssh2::Session as SshSession;
1919use super :: { commons, SshOpts } ;
2020use crate :: utils:: { fmt as fmt_utils, parser as parser_utils, path as path_utils} ;
2121
22+ /// NOTE: about this damn regex <https://stackoverflow.com/questions/32480890/is-there-a-regex-to-parse-the-values-from-an-ftp-directory-listing>
23+ static LS_RE : Lazy < Regex > = lazy_regex ! (
24+ r#"^([\-ld])([\-rwxsStT]{9})\s+(\d+)\s+(.+)\s+(.+)\s+(\d+)\s+(\w{3}\s+\d{1,2}\s+(?:\d{1,2}:\d{1,2}|\d{4}))\s+(.+)$"#
25+ ) ;
26+
2227/// SCP "filesystem" client
2328pub struct ScpFs {
2429 session : Option < SshSession > ,
@@ -52,15 +57,9 @@ impl ScpFs {
5257 }
5358 }
5459
55- /// ### parse_ls_output
56- ///
5760 /// Parse a line of `ls -l` output and tokenize the output into a `FsFile`
5861 fn parse_ls_output ( & self , path : & Path , line : & str ) -> Result < File , ( ) > {
5962 // Prepare list regex
60- // NOTE: about this damn regex <https://stackoverflow.com/questions/32480890/is-there-a-regex-to-parse-the-values-from-an-ftp-directory-listing>
61- lazy_static ! {
62- static ref LS_RE : Regex = Regex :: new( r#"^([\-ld])([\-rwxs]{9})\s+(\d+)\s+(.+)\s+(.+)\s+(\d+)\s+(\w{3}\s+\d{1,2}\s+(?:\d{1,2}:\d{1,2}|\d{4}))\s+(.+)$"# ) . unwrap( ) ;
63- }
6463 trace ! ( "Parsing LS line: '{}'" , line) ;
6564 // Apply regex to result
6665 match LS_RE . captures ( line) {
@@ -1385,6 +1384,37 @@ mod test {
13851384 ) ;
13861385 }
13871386
1387+ #[ test]
1388+ fn test_should_parse_special_permissions_ls_output ( ) {
1389+ let client = ScpFs :: new ( SshOpts :: new ( "localhost" ) ) ;
1390+ assert ! ( client
1391+ . parse_ls_output(
1392+ Path :: new( "/tmp" ) ,
1393+ "-rw-rwSrw- 1 manufact manufact 241813 Apr 22 09:31 L9800.SPF" ,
1394+ )
1395+ . is_ok( ) ) ;
1396+ assert ! ( client
1397+ . parse_ls_output(
1398+ Path :: new( "/tmp" ) ,
1399+ "-rw-rwsrw- 1 manufact manufact 241813 Apr 22 09:31 L9800.SPF" ,
1400+ )
1401+ . is_ok( ) ) ;
1402+
1403+ assert ! ( client
1404+ . parse_ls_output(
1405+ Path :: new( "/tmp" ) ,
1406+ "-rw-rwtrw- 1 manufact manufact 241813 Apr 22 09:31 L9800.SPF" ,
1407+ )
1408+ . is_ok( ) ) ;
1409+
1410+ assert ! ( client
1411+ . parse_ls_output(
1412+ Path :: new( "/tmp" ) ,
1413+ "-rw-rwTrw- 1 manufact manufact 241813 Apr 22 09:31 L9800.SPF" ,
1414+ )
1415+ . is_ok( ) ) ;
1416+ }
1417+
13881418 #[ test]
13891419 fn should_return_errors_on_uninitialized_client ( ) {
13901420 let mut client = ScpFs :: new ( SshOpts :: new ( "localhost" ) ) ;
0 commit comments