Compare commits
1 Commits
libsyncthi
...
libsyncthi
Author | SHA1 | Date |
---|---|---|
Martchus | 2a96cc405d |
|
@ -0,0 +1,11 @@
|
|||
#include "c_bindings.h"
|
||||
|
||||
libst_logging_callback_function_t libst_logging_callback_function = NULL;
|
||||
|
||||
void libst_invoke_logging_callback(int log_level, const char *message, size_t message_size)
|
||||
{
|
||||
if (!libst_logging_callback_function) {
|
||||
return;
|
||||
}
|
||||
libst_logging_callback_function(log_level, message, message_size);
|
||||
}
|
|
@ -0,0 +1,241 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"unsafe"
|
||||
"path/filepath"
|
||||
_ "net/http/pprof" // Need to import this to support STPROFILER.
|
||||
|
||||
"github.com/syncthing/syncthing/lib/build"
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
"github.com/syncthing/syncthing/lib/logger"
|
||||
"github.com/syncthing/syncthing/lib/locations"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
"github.com/syncthing/syncthing/lib/svcutil"
|
||||
"github.com/syncthing/syncthing/lib/syncthing"
|
||||
"github.com/syncthing/syncthing/cmd/syncthing/cli"
|
||||
"github.com/syncthing/syncthing/cmd/syncthing"
|
||||
"github.com/thejerf/suture/v4"
|
||||
)
|
||||
|
||||
// include header for required C helper functions (so the following comment is NO comment)
|
||||
|
||||
// #include "c_bindings.h"
|
||||
import "C"
|
||||
|
||||
var theApp *syncthing.App
|
||||
var myID protocol.DeviceID
|
||||
var cliArgs []string
|
||||
|
||||
const (
|
||||
tlsDefaultCommonName = "syncthing"
|
||||
)
|
||||
|
||||
//export libst_own_device_id
|
||||
func libst_own_device_id() string {
|
||||
return myID.String()
|
||||
}
|
||||
|
||||
//export libst_init_logging
|
||||
func libst_init_logging() {
|
||||
l.AddHandler(logger.LevelVerbose, func(level logger.LogLevel, msg string) {
|
||||
runes := []byte(msg)
|
||||
length := len(runes)
|
||||
if length <= 0 {
|
||||
return
|
||||
}
|
||||
C.libst_invoke_logging_callback(C.int(level), (*C.char)(unsafe.Pointer(&runes[0])), C.size_t(len(runes)))
|
||||
})
|
||||
}
|
||||
|
||||
//export libst_clear_cli_args
|
||||
func libst_clear_cli_args(command string) {
|
||||
if command == "cli" {
|
||||
cliArgs = []string{}
|
||||
} else {
|
||||
cliArgs = []string{command}
|
||||
}
|
||||
}
|
||||
|
||||
//export libst_append_cli_arg
|
||||
func libst_append_cli_arg(arg string) {
|
||||
cliArgs = append(cliArgs, arg)
|
||||
}
|
||||
|
||||
//export libst_run_cli
|
||||
func libst_run_cli() int {
|
||||
if err := cli.RunWithArgs(cliArgs); err != nil {
|
||||
fmt.Println(err)
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
//export libst_run_main
|
||||
func libst_run_main() int {
|
||||
if err := syncthing_main.RunWithArgs(cliArgs); err != nil {
|
||||
fmt.Println(err)
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
//export libst_run_syncthing
|
||||
func libst_run_syncthing(configDir string, dataDir string, guiAddress string, guiApiKey string, verbose bool, allowNewerConfig bool, noDefaultConfig bool, skipPortProbing bool, ensureConfigDirExists bool, ensureDataDirExists bool) int {
|
||||
// return if already running (for simplicity we only allow one Syncthing instance at at time for now)
|
||||
if theApp != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
// set specified GUI address and API key
|
||||
if guiAddress != "" {
|
||||
os.Setenv("STGUIADDRESS", guiAddress)
|
||||
}
|
||||
if guiApiKey != "" {
|
||||
os.Setenv("STGUIAPIKEY", guiApiKey)
|
||||
}
|
||||
|
||||
// set specified config dir
|
||||
if configDir != "" {
|
||||
if !filepath.IsAbs(configDir) {
|
||||
var err error
|
||||
configDir, err = filepath.Abs(configDir)
|
||||
if err != nil {
|
||||
l.Warnln("Failed to make config path absolute:", err)
|
||||
return 3
|
||||
}
|
||||
}
|
||||
if err := locations.SetBaseDir(locations.ConfigBaseDir, configDir); err != nil {
|
||||
l.Warnln(err)
|
||||
return 3
|
||||
}
|
||||
}
|
||||
|
||||
// set specified database dir
|
||||
if dataDir != "" {
|
||||
if !filepath.IsAbs(dataDir) {
|
||||
var err error
|
||||
dataDir, err = filepath.Abs(dataDir)
|
||||
if err != nil {
|
||||
l.Warnln("Failed to make database path absolute:", err)
|
||||
return 3
|
||||
}
|
||||
}
|
||||
if err := locations.SetBaseDir(locations.DataBaseDir, dataDir); err != nil {
|
||||
l.Warnln(err)
|
||||
return 3
|
||||
}
|
||||
}
|
||||
|
||||
// ensure that the config directory exists
|
||||
if ensureConfigDirExists {
|
||||
if err := syncthing.EnsureDir(locations.GetBaseDir(locations.ConfigBaseDir), 0700); err != nil {
|
||||
l.Warnln("Failed to create config directory:", err)
|
||||
return 4
|
||||
}
|
||||
}
|
||||
|
||||
// ensure that the database directory exists
|
||||
if dataDir != "" && ensureDataDirExists {
|
||||
if err := syncthing.EnsureDir(locations.GetBaseDir(locations.DataBaseDir), 0700); err != nil {
|
||||
l.Warnln("Failed to create database directory:", err)
|
||||
return 4
|
||||
}
|
||||
}
|
||||
|
||||
// ensure that we have a certificate and key
|
||||
cert, certErr := syncthing.LoadOrGenerateCertificate(
|
||||
locations.Get(locations.CertFile),
|
||||
locations.Get(locations.KeyFile),
|
||||
)
|
||||
if certErr != nil {
|
||||
l.Warnln("Failed to load/generate certificate:", certErr)
|
||||
return 1
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
// earlyService is a supervisor that runs the services needed for or
|
||||
// before app startup; the event logger, and the config service.
|
||||
spec := svcutil.SpecWithDebugLogger(l)
|
||||
earlyService := suture.New("early", spec)
|
||||
earlyService.ServeBackground(ctx)
|
||||
|
||||
evLogger := events.NewLogger()
|
||||
earlyService.Add(evLogger)
|
||||
|
||||
// load config
|
||||
configLocation := locations.Get(locations.ConfigFile)
|
||||
l.Infoln("Loading config from:", configLocation)
|
||||
cfgWrapper, cfgErr := syncthing.LoadConfigAtStartup(configLocation, cert, evLogger, allowNewerConfig, noDefaultConfig, skipPortProbing)
|
||||
if cfgErr != nil {
|
||||
l.Warnln("Failed to initialize config:", cfgErr)
|
||||
return 2
|
||||
}
|
||||
if cfgService, ok := cfgWrapper.(suture.Service); ok {
|
||||
earlyService.Add(cfgService)
|
||||
}
|
||||
|
||||
// open database
|
||||
dbFile := locations.Get(locations.Database)
|
||||
l.Infoln("Opening database from:", dbFile)
|
||||
ldb, dbErr := syncthing.OpenDBBackend(dbFile, config.TuningAuto)
|
||||
if dbErr != nil {
|
||||
l.Warnln("Error opening database:", dbErr)
|
||||
return 4
|
||||
}
|
||||
|
||||
appOpts := syncthing.Options{
|
||||
ProfilerAddr: os.Getenv("STPROFILER"),
|
||||
NoUpgrade: true,
|
||||
Verbose: verbose,
|
||||
}
|
||||
var err error
|
||||
theApp, err = syncthing.New(cfgWrapper, ldb, evLogger, cert, appOpts)
|
||||
if err != nil {
|
||||
l.Warnln("Failed to start Syncthing:", err)
|
||||
return svcutil.ExitError.AsInt()
|
||||
}
|
||||
|
||||
// start Syncthing and block until it has finished
|
||||
returnCode := 0
|
||||
if err := theApp.Start(); err != nil {
|
||||
returnCode = svcutil.ExitError.AsInt()
|
||||
}
|
||||
returnCode = theApp.Wait().AsInt();
|
||||
theApp = nil
|
||||
return returnCode
|
||||
}
|
||||
|
||||
//export libst_stop_syncthing
|
||||
func libst_stop_syncthing() int {
|
||||
if theApp != nil {
|
||||
return int(theApp.Stop(svcutil.ExitSuccess))
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
//export libst_reset_database
|
||||
func libst_reset_database() {
|
||||
os.RemoveAll(locations.Get(locations.Database))
|
||||
}
|
||||
|
||||
//export libst_syncthing_version
|
||||
func libst_syncthing_version() *C.char {
|
||||
return C.CString(build.Version)
|
||||
}
|
||||
|
||||
//export libst_long_syncthing_version
|
||||
func libst_long_syncthing_version() *C.char {
|
||||
return C.CString(build.LongVersion)
|
||||
}
|
||||
|
||||
func main() {
|
||||
// prevent "runtime.main_main·f: function main is undeclared in the main package"
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
#ifndef LIBSYNCTHING_INTERNAL_H
|
||||
#define LIBSYNCTHING_INTERNAL_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
// allow registration of callback function
|
||||
typedef void (*libst_logging_callback_function_t) (int logLevel, const char *msg, size_t msgSize);
|
||||
extern libst_logging_callback_function_t libst_logging_callback_function;
|
||||
extern void libst_invoke_logging_callback(int log_level, const char *message, size_t message_size);
|
||||
|
||||
#endif // LIBSYNCTHING_INTERNAL_H
|
|
@ -0,0 +1,15 @@
|
|||
// Copyright (C) 2014 The Syncthing Authors.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/syncthing/syncthing/lib/logger"
|
||||
)
|
||||
|
||||
var (
|
||||
l = logger.DefaultLogger.NewFacility("main", "Main package")
|
||||
)
|
|
@ -4,7 +4,7 @@
|
|||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
package main
|
||||
package syncthing_main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
|
|
@ -7,12 +7,10 @@
|
|||
package cli
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/alecthomas/kong"
|
||||
"github.com/flynn-archive/go-shlex"
|
||||
"github.com/willabides/kongplete"
|
||||
|
||||
"github.com/syncthing/syncthing/cmd/syncthing/cmdutil"
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
|
@ -59,37 +57,22 @@ func (cli CLI) AfterApply(kongCtx *kong.Context) error {
|
|||
|
||||
type stdinCommand struct{}
|
||||
|
||||
func (*stdinCommand) Run() error {
|
||||
// Drop the `-` not to recurse into self.
|
||||
args := make([]string, len(os.Args)-1)
|
||||
copy(args, os.Args)
|
||||
|
||||
fmt.Println("Reading commands from stdin...", args)
|
||||
scanner := bufio.NewScanner(os.Stdin)
|
||||
for scanner.Scan() {
|
||||
input, err := shlex.Split(scanner.Text())
|
||||
if err != nil {
|
||||
return fmt.Errorf("parsing input: %w", err)
|
||||
}
|
||||
if len(input) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
func RunWithArgs(args []string) error {
|
||||
var cli CLI
|
||||
p, err := kong.New(&cli)
|
||||
if err != nil {
|
||||
// can't happen, really
|
||||
return fmt.Errorf("creating parser: %w", err)
|
||||
}
|
||||
ctx, err := p.Parse(input)
|
||||
kongplete.Complete(p)
|
||||
ctx, err := p.Parse(args)
|
||||
if err != nil {
|
||||
fmt.Println("Error:", err)
|
||||
continue
|
||||
return err
|
||||
}
|
||||
if err := ctx.Run(); err != nil {
|
||||
fmt.Println("Error:", err)
|
||||
continue
|
||||
return err
|
||||
}
|
||||
}
|
||||
return scanner.Err()
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
package main
|
||||
package syncthing_main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
package main
|
||||
package syncthing_main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
|
|
@ -4,12 +4,12 @@
|
|||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
package main
|
||||
package syncthing_main
|
||||
|
||||
import (
|
||||
"github.com/syncthing/syncthing/lib/logger"
|
||||
)
|
||||
|
||||
var (
|
||||
l = logger.DefaultLogger.NewFacility("main", "Main package")
|
||||
l = logger.DefaultLogger.NewFacility("syncthing_main", "Syncthing package")
|
||||
)
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
package main
|
||||
package syncthing_main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
package main
|
||||
package syncthing_main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
@ -34,7 +34,6 @@ import (
|
|||
"github.com/thejerf/suture/v4"
|
||||
"github.com/willabides/kongplete"
|
||||
|
||||
"github.com/syncthing/syncthing/cmd/syncthing/cli"
|
||||
"github.com/syncthing/syncthing/cmd/syncthing/cmdutil"
|
||||
"github.com/syncthing/syncthing/cmd/syncthing/decrypt"
|
||||
"github.com/syncthing/syncthing/cmd/syncthing/generate"
|
||||
|
@ -137,8 +136,6 @@ var entrypoint struct {
|
|||
Serve serveOptions `cmd:"" help:"Run Syncthing"`
|
||||
Generate generate.CLI `cmd:"" help:"Generate key and config, then exit"`
|
||||
Decrypt decrypt.CLI `cmd:"" help:"Decrypt or verify an encrypted folder"`
|
||||
Cli cli.CLI `cmd:"" help:"Command line interface for Syncthing"`
|
||||
InstallCompletions kongplete.InstallCompletions `cmd:"" help:"Print commands to install shell completions"`
|
||||
}
|
||||
|
||||
// serveOptions are the options for the `syncthing serve` command.
|
||||
|
@ -210,12 +207,10 @@ func defaultVars() kong.Vars {
|
|||
return vars
|
||||
}
|
||||
|
||||
func main() {
|
||||
func RunWithArgs(args []string) error {
|
||||
// First some massaging of the raw command line to fit the new model.
|
||||
// Basically this means adding the default command at the front, and
|
||||
// converting -options to --options.
|
||||
|
||||
args := os.Args[1:]
|
||||
switch {
|
||||
case len(args) == 0:
|
||||
// Empty command line is equivalent to just calling serve
|
||||
|
@ -255,6 +250,7 @@ func main() {
|
|||
ctx.BindTo(l, (*logger.Logger)(nil)) // main logger available to subcommands
|
||||
err = ctx.Run()
|
||||
parser.FatalIfErrorf(err)
|
||||
return err
|
||||
}
|
||||
|
||||
func helpHandler(options kong.HelpOptions, ctx *kong.Context) error {
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
package main
|
||||
package syncthing_main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
package main
|
||||
package syncthing_main
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package main
|
||||
package syncthing_main
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package main
|
||||
package syncthing_main
|
||||
|
||||
import "os/exec"
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
//go:build !solaris && !windows
|
||||
// +build !solaris,!windows
|
||||
|
||||
package main
|
||||
package syncthing_main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
//go:build solaris || windows
|
||||
// +build solaris windows
|
||||
|
||||
package main
|
||||
package syncthing_main
|
||||
|
||||
func startPerfStats() {
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
//go:build go1.7
|
||||
// +build go1.7
|
||||
|
||||
package main
|
||||
package syncthing_main
|
||||
|
||||
import "runtime/debug"
|
||||
|
||||
|
|
Loading…
Reference in New Issue