2 * Copyright (C) 2017 "IoT.bzh"
3 * Author Sebastien Douheret <sebastien@iot.bzh>
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
27 common "github.com/iotbzh/xds-common/golib"
28 "github.com/iotbzh/xds-server/lib/xsapiv1"
29 uuid "github.com/satori/go.uuid"
32 // IFOLDER interface implementation for native/path mapping folders
37 config xsapiv1.FolderConfig
40 // NewFolderPathMap Create a new instance of PathMap
41 func NewFolderPathMap(ctx *Context) *PathMap {
44 config: xsapiv1.FolderConfig{
45 Status: xsapiv1.StatusDisable,
52 func (f *PathMap) NewUID(suffix string) string {
53 uuid := uuid.NewV1().String()
61 func (f *PathMap) Add(cfg xsapiv1.FolderConfig) (*xsapiv1.FolderConfig, error) {
62 if cfg.DataPathMap.ServerPath == "" {
63 return nil, fmt.Errorf("ServerPath must be set")
66 // Use shareRootDir if ServerPath is a relative path
67 dir := cfg.DataPathMap.ServerPath
68 if !filepath.IsAbs(dir) {
69 dir = filepath.Join(f.Config.FileConf.ShareRootDir, dir)
73 if !common.Exists(dir) {
74 // try to create if not existing
75 if err := os.MkdirAll(dir, 0755); err != nil {
76 return nil, fmt.Errorf("Cannot create ServerPath directory: %s", dir)
79 if !common.Exists(dir) {
80 return nil, fmt.Errorf("ServerPath directory is not accessible: %s", dir)
84 f.config.RootPath = dir
85 f.config.DataPathMap.ServerPath = dir
86 f.config.IsInSync = true
88 // Verify file created by XDS agent when needed
89 if cfg.DataPathMap.CheckFile != "" {
90 errMsg := "ServerPath sanity check error (%d): %v"
91 ckFile := f.ConvPathCli2Svr(cfg.DataPathMap.CheckFile)
92 if !common.Exists(ckFile) {
93 return nil, fmt.Errorf(errMsg, 1, "file not present")
95 if cfg.DataPathMap.CheckContent != "" {
96 fd, err := os.OpenFile(ckFile, os.O_APPEND|os.O_RDWR, 0600)
98 return nil, fmt.Errorf(errMsg, 2, err)
102 // Check specific message written by agent
103 content, err := ioutil.ReadAll(fd)
105 return nil, fmt.Errorf(errMsg, 3, err)
107 if string(content) != cfg.DataPathMap.CheckContent {
108 return nil, fmt.Errorf(errMsg, 4, "file content differ")
111 // Write a specific message that will be check back on agent side
112 msg := "Pathmap checked message written by xds-server ID: " + f.Config.ServerUID + "\n"
113 if n, err := fd.WriteString(msg); n != len(msg) || err != nil {
114 return nil, fmt.Errorf(errMsg, 5, err)
119 f.config.Status = xsapiv1.StatusEnable
121 return &f.config, nil
124 // GetConfig Get public part of folder config
125 func (f *PathMap) GetConfig() xsapiv1.FolderConfig {
129 // GetFullPath returns the full path of a directory (from server POV)
130 func (f *PathMap) GetFullPath(dir string) string {
132 return f.config.DataPathMap.ServerPath
134 return filepath.Join(f.config.DataPathMap.ServerPath, dir)
137 // ConvPathCli2Svr Convert path from Client to Server
138 func (f *PathMap) ConvPathCli2Svr(s string) string {
139 if f.config.ClientPath != "" && f.config.DataPathMap.ServerPath != "" {
140 return strings.Replace(s,
142 f.config.DataPathMap.ServerPath,
148 // ConvPathSvr2Cli Convert path from Server to Client
149 func (f *PathMap) ConvPathSvr2Cli(s string) string {
150 if f.config.ClientPath != "" && f.config.DataPathMap.ServerPath != "" {
151 return strings.Replace(s,
152 f.config.DataPathMap.ServerPath,
160 func (f *PathMap) Remove() error {
165 // Update update some fields of a folder
166 func (f *PathMap) Update(cfg xsapiv1.FolderConfig) (*xsapiv1.FolderConfig, error) {
167 if f.config.ID != cfg.ID {
168 return nil, fmt.Errorf("Invalid id")
171 return &f.config, nil
174 // RegisterEventChange requests registration for folder change event
175 func (f *PathMap) RegisterEventChange(cb *FolderEventCB, data *FolderEventCBData) error {
179 // UnRegisterEventChange remove registered callback
180 func (f *PathMap) UnRegisterEventChange() error {
184 // Sync Force folder files synchronization
185 func (f *PathMap) Sync() error {
189 // IsInSync Check if folder files are in-sync
190 func (f *PathMap) IsInSync() (bool, error) {