2016-03-15 16:58:51 +00:00
package main
import (
"fmt"
"log"
2017-07-02 11:45:34 +00:00
"net"
2016-03-15 16:58:51 +00:00
"os"
"runtime"
2017-07-02 11:45:34 +00:00
"time"
2017-03-04 10:27:20 +00:00
"github.com/SommerEngineering/Sync/Sync"
"github.com/howeyc/gopass"
"golang.org/x/crypto/ssh"
2016-03-15 16:58:51 +00:00
)
func main ( ) {
// Show the current version:
2017-07-02 11:45:34 +00:00
log . Println ( ` Sync v1.3.1 ` )
2016-03-15 16:58:51 +00:00
// Allow Go to use all CPUs:
runtime . GOMAXPROCS ( runtime . NumCPU ( ) )
// Read the configuration from the command-line args:
readFlags ( )
// Check if the directories are provided:
if localDir == ` ` || remoteDir == ` ` {
log . Println ( ` Please provide the local and remote directory. ` )
2016-03-16 07:03:29 +00:00
os . Exit ( 1 )
2016-03-15 16:58:51 +00:00
return
}
// Should I use the current working dir?
if localDir == ` . ` {
if currentWD , currentWDError := os . Getwd ( ) ; currentWDError != nil {
log . Println ( "Cannot use the current working directory as local directory: " + currentWDError . Error ( ) )
2016-03-16 07:03:29 +00:00
os . Exit ( 2 )
2016-03-15 16:58:51 +00:00
return
} else {
log . Println ( "I use the current working directory as local directory: " + currentWD )
localDir = currentWD
}
}
// Remove trailing separators from both directories
localDir = correctPath ( localDir )
remoteDir = correctPath ( remoteDir )
// Check if local dir exist
if dirInfo , dirError := os . Stat ( localDir ) ; dirError != nil {
log . Println ( "There is an error with the local directory: " + dirError . Error ( ) )
2016-03-16 07:03:29 +00:00
os . Exit ( 3 )
2016-03-15 16:58:51 +00:00
return
} else {
if ! dirInfo . IsDir ( ) {
log . Println ( "There is an error with the local directory: You provided a file instead!" )
2016-03-16 07:03:29 +00:00
os . Exit ( 4 )
2016-03-15 16:58:51 +00:00
return
}
}
// Check if the password was provided:
for true {
if password == ` ` {
// Promt for the password:
fmt . Print ( ` Please provide the password for the connection: ` )
2016-03-16 07:03:29 +00:00
if pass , errPass := gopass . GetPasswd ( ) ; errPass != nil {
log . Println ( ` There was an error reading the password securely: ` + errPass . Error ( ) )
os . Exit ( 5 )
return
} else {
password = string ( pass )
}
2016-03-15 16:58:51 +00:00
} else {
break
}
}
// Give some information about the state
if supervised {
log . Println ( "I use the supervised mode." )
} else {
log . Println ( "I do not use the supervised mode." )
}
if pushOnly {
log . Println ( "I use the push only mode i.e. backup mode. Any remote change will be ignored." )
} else {
log . Println ( "I use the full mode and consider also remote changes." )
}
// Create the SSH configuration:
Sync . SetPassword4Callback ( password )
config := & ssh . ClientConfig {
User : username ,
Auth : [ ] ssh . AuthMethod {
ssh . Password ( password ) ,
ssh . PasswordCallback ( Sync . PasswordCallback ) ,
ssh . KeyboardInteractive ( Sync . KeyboardInteractiveChallenge ) ,
} ,
2017-07-02 11:45:34 +00:00
HostKeyCallback : showHostKey ( ) ,
2016-03-15 16:58:51 +00:00
}
// Connect to the SSH server:
ssh := Sync . ConnectSSH ( config , serverAddrString )
if ssh == nil {
log . Println ( ` It was not possible to connect to the SSH server. ` )
2016-03-16 07:03:29 +00:00
os . Exit ( 6 )
2016-03-15 16:58:51 +00:00
return
}
defer ssh . Close ( )
Sync . Synchronise ( ssh , supervised , pushOnly , localDir , remoteDir )
log . Println ( "Synchronising done." )
}
2017-07-02 11:45:34 +00:00
func showHostKey ( ) ssh . HostKeyCallback {
return func ( hostname string , remote net . Addr , key ssh . PublicKey ) error {
log . Printf ( "Your server's hostname is %s (%s) and its public key is %s. If this is wrong, please abort the program now! Wait 16 seconds for your check." , hostname , remote . String ( ) , ssh . FingerprintSHA256 ( key ) )
time . Sleep ( 16 * time . Second )
return nil
}
}