Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7686af39e0 | ||
|
|
16b937ebd7 | ||
|
|
ac454ec694 |
+42
-1
@@ -31,7 +31,48 @@
|
|||||||
>* -protocol: 目标服务协议 tcp、udp
|
>* -protocol: 目标服务协议 tcp、udp
|
||||||
>* -peeruser: 目标用户,如果是同一个用户下的节点,则无需设置
|
>* -peeruser: 目标用户,如果是同一个用户下的节点,则无需设置
|
||||||
>* -peerpassword: 目标密码,如果是同一个用户下的节点,则无需设置
|
>* -peerpassword: 目标密码,如果是同一个用户下的节点,则无需设置
|
||||||
>* -f: 配置文件,如果希望配置多个P2PApp参考[config.json](/config.json)
|
|
||||||
|
## 配置文件
|
||||||
|
一般保存在当前目录,安装模式下会保存到 `C:\Program Files\OpenP2P\config.json` 或 `/usr/local/openp2p/config.json`
|
||||||
|
希望修改参数,或者配置多个P2PApp可手动修改配置文件
|
||||||
|
|
||||||
|
配置实例
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"network": {
|
||||||
|
"Node": "hhd1207-222",
|
||||||
|
"User": "USERNAME1",
|
||||||
|
"Password": "PASSWORD1",
|
||||||
|
"ShareBandwidth": -1,
|
||||||
|
"ServerHost": "api.openp2p.cn",
|
||||||
|
"ServerPort": 27182,
|
||||||
|
"UDPPort1": 27182,
|
||||||
|
"UDPPort2": 27183
|
||||||
|
},
|
||||||
|
"apps": [
|
||||||
|
{
|
||||||
|
"AppName": "OfficeWindowsPC",
|
||||||
|
"Protocol": "tcp",
|
||||||
|
"SrcPort": 23389,
|
||||||
|
"PeerNode": "OFFICEPC1",
|
||||||
|
"DstPort": 3389,
|
||||||
|
"DstHost": "localhost",
|
||||||
|
"PeerUser": "",
|
||||||
|
"PeerPassword": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"AppName": "OfficeServerSSH",
|
||||||
|
"Protocol": "tcp",
|
||||||
|
"SrcPort": 22,
|
||||||
|
"PeerNode": "OFFICEPC1",
|
||||||
|
"DstPort": 22,
|
||||||
|
"DstHost": "192.168.1.5",
|
||||||
|
"PeerUser": "",
|
||||||
|
"PeerPassword": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## 升级客户端
|
## 升级客户端
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -32,8 +32,48 @@ Create multiple P2PApp by config file
|
|||||||
>* -protocol: Target service protocol tcp, udp
|
>* -protocol: Target service protocol tcp, udp
|
||||||
>* -peeruser: The target user, if it is a node under the same user, no need to set
|
>* -peeruser: The target user, if it is a node under the same user, no need to set
|
||||||
>* -peerpassword: The target password, if it is a node under the same user, no need to set
|
>* -peerpassword: The target password, if it is a node under the same user, no need to set
|
||||||
>* -f: Configuration file, if you want to configure multiple P2PApp refer to [config.json](/config.json)
|
|
||||||
|
|
||||||
|
## Config file
|
||||||
|
Generally saved in the current directory, in installation mode it will be saved to `C:\Program Files\OpenP2P\config.json` or `/usr/local/openp2p/config.json`
|
||||||
|
If you want to modify the parameters, or configure multiple P2PApps, you can manually modify the configuration file
|
||||||
|
|
||||||
|
Configuration example
|
||||||
|
```
|
||||||
|
{
|
||||||
|
"network": {
|
||||||
|
"Node": "hhd1207-222",
|
||||||
|
"User": "USERNAME1",
|
||||||
|
"Password": "PASSWORD1",
|
||||||
|
"ShareBandwidth": -1,
|
||||||
|
"ServerHost": "api.openp2p.cn",
|
||||||
|
"ServerPort": 27182,
|
||||||
|
"UDPPort1": 27182,
|
||||||
|
"UDPPort2": 27183
|
||||||
|
},
|
||||||
|
"apps": [
|
||||||
|
{
|
||||||
|
"AppName": "OfficeWindowsPC",
|
||||||
|
"Protocol": "tcp",
|
||||||
|
"SrcPort": 23389,
|
||||||
|
"PeerNode": "OFFICEPC1",
|
||||||
|
"DstPort": 3389,
|
||||||
|
"DstHost": "localhost",
|
||||||
|
"PeerUser": "",
|
||||||
|
"PeerPassword": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"AppName": "OfficeServerSSH",
|
||||||
|
"Protocol": "tcp",
|
||||||
|
"SrcPort": 22,
|
||||||
|
"PeerNode": "OFFICEPC1",
|
||||||
|
"DstPort": 22,
|
||||||
|
"DstHost": "192.168.1.5",
|
||||||
|
"PeerUser": "",
|
||||||
|
"PeerPassword": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
## Client update
|
## Client update
|
||||||
```
|
```
|
||||||
# update local client
|
# update local client
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import (
|
|||||||
|
|
||||||
var gConf Config
|
var gConf Config
|
||||||
|
|
||||||
|
const IntValueNotSet int = -99999999
|
||||||
|
|
||||||
type AppConfig struct {
|
type AppConfig struct {
|
||||||
// required
|
// required
|
||||||
AppName string
|
AppName string
|
||||||
@@ -33,8 +35,8 @@ type AppConfig struct {
|
|||||||
type Config struct {
|
type Config struct {
|
||||||
Network NetworkConfig `json:"network"`
|
Network NetworkConfig `json:"network"`
|
||||||
Apps []AppConfig `json:"apps"`
|
Apps []AppConfig `json:"apps"`
|
||||||
daemonMode bool
|
LogLevel int
|
||||||
logLevel int
|
|
||||||
mtx sync.Mutex
|
mtx sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,6 +80,8 @@ func (c *Config) save() {
|
|||||||
|
|
||||||
func (c *Config) load() error {
|
func (c *Config) load() error {
|
||||||
c.mtx.Lock()
|
c.mtx.Lock()
|
||||||
|
c.LogLevel = IntValueNotSet
|
||||||
|
c.Network.ShareBandwidth = IntValueNotSet
|
||||||
defer c.mtx.Unlock()
|
defer c.mtx.Unlock()
|
||||||
data, err := ioutil.ReadFile("config.json")
|
data, err := ioutil.ReadFile("config.json")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -62,7 +62,6 @@ func (d *daemon) run() {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
args = append(args, "-bydaemon")
|
|
||||||
for {
|
for {
|
||||||
// start worker
|
// start worker
|
||||||
gLog.Println(LevelINFO, "start worker process")
|
gLog.Println(LevelINFO, "start worker process")
|
||||||
@@ -130,7 +129,7 @@ func install() {
|
|||||||
logLevel := installFlag.Int("loglevel", 1, "0:debug 1:info 2:warn 3:error")
|
logLevel := installFlag.Int("loglevel", 1, "0:debug 1:info 2:warn 3:error")
|
||||||
installFlag.Parse(os.Args[2:])
|
installFlag.Parse(os.Args[2:])
|
||||||
checkParams(*node, *user, *password)
|
checkParams(*node, *user, *password)
|
||||||
gConf.logLevel = *logLevel
|
gConf.LogLevel = *logLevel
|
||||||
gConf.Network.ServerHost = *serverHost
|
gConf.Network.ServerHost = *serverHost
|
||||||
gConf.Network.User = *user
|
gConf.Network.User = *user
|
||||||
gConf.Network.Node = *node
|
gConf.Network.Node = *node
|
||||||
|
|||||||
+32
-14
@@ -6,6 +6,10 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -89,10 +93,23 @@ func handlePush(pn *P2PNetwork, subType uint16, msg []byte) error {
|
|||||||
|
|
||||||
}(req)
|
}(req)
|
||||||
case MsgPushUpdate:
|
case MsgPushUpdate:
|
||||||
update()
|
targetPath := filepath.Join(defaultInstallPath, defaultBinName)
|
||||||
if gConf.daemonMode {
|
args := []string{"update"}
|
||||||
|
env := os.Environ()
|
||||||
|
// Windows does not support exec syscall.
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
cmd := exec.Command(targetPath, args...)
|
||||||
|
cmd.Stdout = os.Stdout
|
||||||
|
cmd.Stderr = os.Stderr
|
||||||
|
cmd.Stdin = os.Stdin
|
||||||
|
cmd.Env = env
|
||||||
|
err := cmd.Run()
|
||||||
|
if err == nil {
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return syscall.Exec(targetPath, args, env)
|
||||||
case MsgPushReportApps:
|
case MsgPushReportApps:
|
||||||
gLog.Println(LevelINFO, "MsgPushReportApps")
|
gLog.Println(LevelINFO, "MsgPushReportApps")
|
||||||
req := ReportApps{}
|
req := ReportApps{}
|
||||||
@@ -144,22 +161,23 @@ func handlePush(pn *P2PNetwork, subType uint16, msg []byte) error {
|
|||||||
gLog.Printf(LevelERROR, "wrong MsgPushEditApp:%s %s", err, string(msg[openP2PHeaderSize:]))
|
gLog.Printf(LevelERROR, "wrong MsgPushEditApp:%s %s", err, string(msg[openP2PHeaderSize:]))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var config AppConfig
|
var oldConf AppConfig
|
||||||
// protocol0+srcPort0 exist, delApp
|
// protocol0+srcPort0 exist, delApp
|
||||||
config.AppName = newApp.AppName
|
oldConf.AppName = newApp.AppName
|
||||||
config.Protocol = newApp.Protocol0
|
oldConf.Protocol = newApp.Protocol0
|
||||||
config.SrcPort = newApp.SrcPort0
|
oldConf.SrcPort = newApp.SrcPort0
|
||||||
config.PeerNode = newApp.PeerNode
|
oldConf.PeerNode = newApp.PeerNode
|
||||||
config.DstHost = newApp.DstHost
|
oldConf.DstHost = newApp.DstHost
|
||||||
config.DstPort = newApp.DstPort
|
oldConf.DstPort = newApp.DstPort
|
||||||
|
|
||||||
gConf.delete(config)
|
gConf.delete(oldConf)
|
||||||
// AddApp
|
// AddApp
|
||||||
config.Protocol = newApp.Protocol
|
newConf := oldConf
|
||||||
config.SrcPort = newApp.SrcPort
|
newConf.Protocol = newApp.Protocol
|
||||||
gConf.add(config)
|
newConf.SrcPort = newApp.SrcPort
|
||||||
|
gConf.add(newConf)
|
||||||
gConf.save()
|
gConf.save()
|
||||||
pn.DeleteApp(config) // save quickly for the next request reportApplist
|
pn.DeleteApp(oldConf) // save quickly for the next request reportApplist
|
||||||
// autoReconnect will auto AddApp
|
// autoReconnect will auto AddApp
|
||||||
// pn.AddApp(config)
|
// pn.AddApp(config)
|
||||||
// TODO: report result
|
// TODO: report result
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ const (
|
|||||||
type V8log struct {
|
type V8log struct {
|
||||||
loggers map[LogLevel]*log.Logger
|
loggers map[LogLevel]*log.Logger
|
||||||
files map[LogLevel]*os.File
|
files map[LogLevel]*os.File
|
||||||
llevel LogLevel
|
level LogLevel
|
||||||
stopSig chan bool
|
stopSig chan bool
|
||||||
logDir string
|
logDir string
|
||||||
mtx *sync.Mutex
|
mtx *sync.Mutex
|
||||||
@@ -92,17 +92,10 @@ func InitLogger(path string, filePrefix string, level LogLevel, maxLogSize int64
|
|||||||
return pLog
|
return pLog
|
||||||
}
|
}
|
||||||
|
|
||||||
// UninitLogger ...
|
func (vl *V8log) setLevel(level LogLevel) {
|
||||||
func (vl *V8log) UninitLogger() {
|
vl.mtx.Lock()
|
||||||
if !vl.stoped {
|
defer vl.mtx.Unlock()
|
||||||
vl.stoped = true
|
vl.level = level
|
||||||
close(vl.stopSig)
|
|
||||||
for l := range logFileNames {
|
|
||||||
if l >= vl.llevel {
|
|
||||||
vl.files[l].Close()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (vl *V8log) checkFile() {
|
func (vl *V8log) checkFile() {
|
||||||
@@ -150,7 +143,7 @@ func (vl *V8log) Printf(level LogLevel, format string, params ...interface{}) {
|
|||||||
if vl.stoped {
|
if vl.stoped {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if level < vl.llevel {
|
if level < vl.level {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
pidAndLevel := []interface{}{vl.pid, loglevel[level]}
|
pidAndLevel := []interface{}{vl.pid, loglevel[level]}
|
||||||
@@ -170,7 +163,7 @@ func (vl *V8log) Println(level LogLevel, params ...interface{}) {
|
|||||||
if vl.stoped {
|
if vl.stoped {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if level < vl.llevel {
|
if level < vl.level {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
pidAndLevel := []interface{}{vl.pid, " ", loglevel[level], " "}
|
pidAndLevel := []interface{}{vl.pid, " ", loglevel[level], " "}
|
||||||
|
|||||||
+32
-7
@@ -13,6 +13,8 @@ func main() {
|
|||||||
rand.Seed(time.Now().UnixNano())
|
rand.Seed(time.Now().UnixNano())
|
||||||
binDir := filepath.Dir(os.Args[0])
|
binDir := filepath.Dir(os.Args[0])
|
||||||
os.Chdir(binDir) // for system service
|
os.Chdir(binDir) // for system service
|
||||||
|
gLog = InitLogger(binDir, "openp2p", LevelDEBUG, 1024*1024, LogFileAndConsole)
|
||||||
|
|
||||||
// TODO: install sub command, deamon process
|
// TODO: install sub command, deamon process
|
||||||
// groups := flag.String("groups", "", "you could join in several groups. like: GroupName1:Password1;GroupName2:Password2; group name 8-31 characters")
|
// groups := flag.String("groups", "", "you could join in several groups. like: GroupName1:Password1;GroupName2:Password2; group name 8-31 characters")
|
||||||
if len(os.Args) > 1 {
|
if len(os.Args) > 1 {
|
||||||
@@ -25,7 +27,7 @@ func main() {
|
|||||||
update()
|
update()
|
||||||
targetPath := filepath.Join(defaultInstallPath, defaultBinName)
|
targetPath := filepath.Join(defaultInstallPath, defaultBinName)
|
||||||
d := daemon{}
|
d := daemon{}
|
||||||
err := d.Control("restart", targetPath, []string{"-d", "-f"})
|
err := d.Control("restart", targetPath, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
gLog.Println(LevelERROR, "restart service error:", err)
|
gLog.Println(LevelERROR, "restart service error:", err)
|
||||||
} else {
|
} else {
|
||||||
@@ -53,11 +55,11 @@ func main() {
|
|||||||
srcPort := flag.Int("srcport", 0, "source port ")
|
srcPort := flag.Int("srcport", 0, "source port ")
|
||||||
protocol := flag.String("protocol", "tcp", "tcp or udp")
|
protocol := flag.String("protocol", "tcp", "tcp or udp")
|
||||||
appName := flag.String("appname", "", "app name")
|
appName := flag.String("appname", "", "app name")
|
||||||
flag.Bool("noshare", false, "deprecated. uses -sharebandwidth -1")
|
flag.Bool("noshare", false, "deprecated. uses -sharebandwidth -1") // Deprecated, rm later
|
||||||
shareBandwidth := flag.Int("sharebandwidth", 10, "N mbps share bandwidth limit, private node no limit")
|
shareBandwidth := flag.Int("sharebandwidth", 10, "N mbps share bandwidth limit, private node no limit")
|
||||||
flag.Bool("f", false, "deprecated. config file")
|
flag.Bool("f", false, "deprecated. config file") // Deprecated, rm later
|
||||||
daemonMode := flag.Bool("d", false, "daemonMode")
|
daemonMode := flag.Bool("d", false, "daemonMode")
|
||||||
byDaemon := flag.Bool("bydaemon", false, "start by daemon")
|
flag.Bool("bydaemon", false, "start by daemon") // Deprecated, rm later
|
||||||
logLevel := flag.Int("loglevel", 1, "0:debug 1:info 2:warn 3:error")
|
logLevel := flag.Int("loglevel", 1, "0:debug 1:info 2:warn 3:error")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
@@ -75,6 +77,7 @@ func main() {
|
|||||||
gConf.load()
|
gConf.load()
|
||||||
gConf.mtx.Lock()
|
gConf.mtx.Lock()
|
||||||
|
|
||||||
|
// spec paramters in commandline will always be used
|
||||||
flag.Visit(func(f *flag.Flag) {
|
flag.Visit(func(f *flag.Flag) {
|
||||||
if f.Name == "sharebandwidth" {
|
if f.Name == "sharebandwidth" {
|
||||||
gConf.Network.ShareBandwidth = *shareBandwidth
|
gConf.Network.ShareBandwidth = *shareBandwidth
|
||||||
@@ -92,14 +95,36 @@ func main() {
|
|||||||
gConf.Network.ServerHost = *serverHost
|
gConf.Network.ServerHost = *serverHost
|
||||||
}
|
}
|
||||||
if f.Name == "loglevel" {
|
if f.Name == "loglevel" {
|
||||||
gConf.logLevel = *logLevel
|
gConf.LogLevel = *logLevel
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
gLog = InitLogger(binDir, "openp2p", LogLevel(gConf.logLevel), 1024*1024, LogFileAndConsole)
|
|
||||||
|
if gConf.Network.ServerHost == "" {
|
||||||
|
gConf.Network.ServerHost = *serverHost
|
||||||
|
}
|
||||||
|
if gConf.Network.Node == "" {
|
||||||
|
gConf.Network.Node = *node
|
||||||
|
}
|
||||||
|
if gConf.Network.User == "" {
|
||||||
|
gConf.Network.User = *user
|
||||||
|
}
|
||||||
|
if gConf.Network.Password == "" {
|
||||||
|
gConf.Network.Password = *password
|
||||||
|
}
|
||||||
|
if gConf.LogLevel == IntValueNotSet {
|
||||||
|
gConf.LogLevel = *logLevel
|
||||||
|
}
|
||||||
|
if gConf.Network.ShareBandwidth == IntValueNotSet {
|
||||||
|
gConf.Network.ShareBandwidth = *shareBandwidth
|
||||||
|
}
|
||||||
|
|
||||||
|
gConf.Network.ServerPort = 27182
|
||||||
|
gConf.Network.UDPPort1 = 27182
|
||||||
|
gConf.Network.UDPPort2 = 27183
|
||||||
gLog.Println(LevelINFO, "openp2p start. version: ", OpenP2PVersion)
|
gLog.Println(LevelINFO, "openp2p start. version: ", OpenP2PVersion)
|
||||||
|
gLog.setLevel(LogLevel(gConf.LogLevel))
|
||||||
gConf.mtx.Unlock()
|
gConf.mtx.Unlock()
|
||||||
gConf.save()
|
gConf.save()
|
||||||
gConf.daemonMode = *byDaemon
|
|
||||||
if *daemonMode {
|
if *daemonMode {
|
||||||
d := daemon{}
|
d := daemon{}
|
||||||
d.run()
|
d.run()
|
||||||
|
|||||||
+1
-1
@@ -10,7 +10,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const OpenP2PVersion = "0.98.0"
|
const OpenP2PVersion = "0.99.0"
|
||||||
const ProducnName string = "openp2p"
|
const ProducnName string = "openp2p"
|
||||||
|
|
||||||
type openP2PHeader struct {
|
type openP2PHeader struct {
|
||||||
|
|||||||
@@ -16,18 +16,9 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// type updateFileInfo struct {
|
|
||||||
// Name string `json:"name,omitempty"`
|
|
||||||
// RelativePath string `json:"relativePath,omitempty"`
|
|
||||||
// Length int64 `json:"length,omitempty"`
|
|
||||||
// URL string `json:"url,omitempty"`
|
|
||||||
// Hash string `json:"hash,omitempty"`
|
|
||||||
// }
|
|
||||||
|
|
||||||
func update() {
|
func update() {
|
||||||
gLog.Println(LevelINFO, "update start")
|
gLog.Println(LevelINFO, "update start")
|
||||||
defer gLog.Println(LevelINFO, "update end")
|
defer gLog.Println(LevelINFO, "update end")
|
||||||
// TODO: download from gitee. save flow
|
|
||||||
c := http.Client{
|
c := http.Client{
|
||||||
Transport: &http.Transport{
|
Transport: &http.Transport{
|
||||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||||
@@ -61,7 +52,6 @@ func update() {
|
|||||||
gLog.Println(LevelERROR, "update error:", updateInfo.Error, updateInfo.ErrorDetail)
|
gLog.Println(LevelERROR, "update error:", updateInfo.Error, updateInfo.ErrorDetail)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
os.MkdirAll("download", 0666)
|
|
||||||
err = updateFile(updateInfo.Url, "", "openp2p")
|
err = updateFile(updateInfo.Url, "", "openp2p")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
gLog.Println(LevelERROR, "update: download failed:", err)
|
gLog.Println(LevelERROR, "update: download failed:", err)
|
||||||
@@ -112,6 +102,7 @@ func updateFile(url string, checksum string, dst string) error {
|
|||||||
os.Rename(os.Args[0]+"0", os.Args[0])
|
os.Rename(os.Args[0]+"0", os.Args[0])
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
os.Remove(tmpFile)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,11 +124,6 @@ func unzip(dst, src string) (err error) {
|
|||||||
for _, f := range archive.File {
|
for _, f := range archive.File {
|
||||||
filePath := filepath.Join(dst, f.Name)
|
filePath := filepath.Join(dst, f.Name)
|
||||||
fmt.Println("unzipping file ", filePath)
|
fmt.Println("unzipping file ", filePath)
|
||||||
|
|
||||||
// if !strings.HasPrefix(filePath, filepath.Clean(dst)+string(os.PathSeparator)) {
|
|
||||||
// fmt.Println("invalid file path")
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
if f.FileInfo().IsDir() {
|
if f.FileInfo().IsDir() {
|
||||||
fmt.Println("creating directory...")
|
fmt.Println("creating directory...")
|
||||||
os.MkdirAll(filePath, os.ModePerm)
|
os.MkdirAll(filePath, os.ModePerm)
|
||||||
|
|||||||
Reference in New Issue
Block a user