func (b *DirectoryBackend) Close() error {
	err := b.lock.Close()
	if err != nil {
		b.log.WithError(err).Warn("failed to close lock file")
	}
	return nil
}
Close this backend instance, freeing any associated resources.
package backend
import (
	"errors"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
	"github.com/cossacklabs/acra/keystore/v2/keystore/filesystem/backend/api"
	log "github.com/sirupsen/logrus"
)
const serviceName = "keystore"
const directorySubsystemName = "directory-backend"
const (
	keyDirPerm  = os.FileMode(0700)
	keyFilePerm = os.FileMode(0600)
	versionPerm = os.FileMode(0644)
)
var (
	ErrNotDirectory       = errors.New("root key directory is not a directory")
	ErrInvalidPermissions = errors.New("invalid key directory access permissions")
	ErrInvalidVersion     = errors.New("invalid keystore version file content")
)
type DirectoryBackend struct {
	root string
	log  *log.Entry
	lock *fileLock
}
const (
	lockFile      = ".lock"
	versionFile   = "version"
	versionString = "Acra Keystore v2"
)
func CreateDirectoryBackend(root string) (*DirectoryBackend, error) {
	newLog := log.WithFields(log.Fields{
		"service":   serviceName,
		"subsystem": directorySubsystemName,
	})
	errLog := newLog.WithField("path", root)
	fi, err := os.Stat(root)
	if err == nil {
		if !fi.IsDir() {
			errLog.Debug("root key directory is not a directory")
			return nil, ErrNotDirectory
		}
		if fi.Mode().Perm() != keyDirPerm {
			errLog.WithFields(log.Fields{
				"actual-perm":   fi.Mode().Perm(),
				"expected-perm": keyDirPerm,
			}).
				Debugf("invalid access permissions on root key directory")
			return nil, ErrInvalidPermissions
		}
	} else {
		if os.IsNotExist(err) {
			err = os.MkdirAll(root, keyDirPerm)
			if err != nil {
				errLog.WithError(err).Debug("failed to create root key directory")
				return nil, err
			}
		} else {
			errLog.WithError(err).Debug("failed to stat root key directory")
			return nil, err
		}
	}
	err = checkVersionFile(root)
	if err != nil {
		errLog.WithError(err).Debug("failed to create version file")
		return nil, err
	}
	lock, err := newFileLock(filepath.Join(root, lockFile))
	if err != nil {
		errLog.WithError(err).Debug("failed to create lock file")
		return nil, err
	}
	return &DirectoryBackend{
		root: root,
		log:  newLog,
		lock: lock,
	}, nil
}
func OpenDirectoryBackend(root string) (*DirectoryBackend, error) {
	newLog := log.WithFields(log.Fields{
		"service":   serviceName,
		"subsystem": directorySubsystemName,
	})
	errLog := newLog.WithField("path", root)
	fi, err := os.Stat(root)
	if err != nil {
		errLog.WithError(err).Debug("failed to stat root key directory")
		if os.IsNotExist(err) {
			err = api.ErrNotExist
		}
		return nil, err
	}
	if !fi.IsDir() {
		errLog.Debug("root key directory is not a directory")
		return nil, ErrNotDirectory
	}
	if fi.Mode().Perm() != keyDirPerm {
		errLog.WithFields(log.Fields{
			"actual-perm":   fi.Mode().Perm(),
			"expected-perm": keyDirPerm,
		}).
			Debugf("invalid access permissions on root key directory")
		return nil, ErrInvalidPermissions
	}
	err = CheckDirectoryVersion(root)
	if err != nil {
		errLog.WithError(err).Debug("not a keystore")
		return nil, err
	}
	lock, err := newFileLock(filepath.Join(root, lockFile))
	if err != nil {
		errLog.WithError(err).Debug("failed to create lock file")
		return nil, err
	}
	return &DirectoryBackend{
		root: root,
		log:  newLog,
		lock: lock,
	}, nil
}
func versionFilePath(rootDir string) string {
	return filepath.Join(rootDir, versionFile)
}
func CheckDirectoryVersion(rootDir string) error {
	content, err := ioutil.ReadFile(versionFilePath(rootDir))
	if err != nil {
		return err
	}
	if string(content) != versionString {
		return ErrInvalidVersion
	}
	return nil
}
func checkVersionFile(rootDir string) error {
	err := CheckDirectoryVersion(rootDir)
	if err == nil {
		return nil
	}
	if !os.IsNotExist(err) {
		return err
	}
	return createVersionFile(rootDir)
}
func createVersionFile(rootDir string) (err error) {
	path := versionFilePath(rootDir)
	file, err := os.OpenFile(path, os.O_CREATE|os.O_EXCL|os.O_WRONLY, versionPerm)
	if err != nil {
		return err
	}
	defer func() {
		err2 := file.Close()
		if err == nil {
			err = err2
		}
	}()
	_, err = file.WriteString(versionString)
	if err != nil {
		return err
	}
	err = file.Sync()
	if err != nil {
		return err
	}
	return nil
}