func CachePath(path ...string) string {
	varDir := os.Getenv("LXD_DIR")
	logDir := "/var/cache/lxd"
	if varDir != "" {
		logDir = filepath.Join(varDir, "cache")
	}
	items := []string{logDir}
	items = append(items, path...)
	return filepath.Join(items...)
}
CachePath returns the directory that LXD should its cache under. If LXD_DIR is
set, this path is $LXD_DIR/cache, otherwise it is /var/cache/lxd.
package shared
import (
	"bufio"
	"bytes"
	"crypto/rand"
	"crypto/sha256"
	"crypto/sha512"
	"encoding/gob"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"hash"
	"io"
	"io/ioutil"
	"net/http"
	"net/url"
	"os"
	"os/exec"
	"path"
	"path/filepath"
	"reflect"
	"regexp"
	"runtime"
	"strconv"
	"strings"
	"time"
	"unicode"
	"github.com/lxc/lxd/shared/cancel"
	"github.com/lxc/lxd/shared/ioprogress"
	"github.com/pkg/errors"
)
const SnapshotDelimiter = "/"
const DefaultPort = "8443"
func URLEncode(path string, query map[string]string) (string, error) {
	u, err := url.Parse(path)
	if err != nil {
		return "", err
	}
	params := url.Values{}
	for key, value := range query {
		params.Add(key, value)
	}
	u.RawQuery = params.Encode()
	return u.String(), nil
}
func AddSlash(path string) string {
	if path[len(path)-1] != '/' {
		return path + "/"
	}
	return path
}
func PathExists(name string) bool {
	_, err := os.Lstat(name)
	if err != nil && os.IsNotExist(err) {
		return false
	}
	return true
}
func PathIsEmpty(path string) (bool, error) {
	f, err := os.Open(path)
	if err != nil {
		return false, err
	}
	defer f.Close()
	_, err = f.Readdir(1)
	if err == io.EOF {
		return true, nil
	}
	return false, err
}
func IsDir(name string) bool {
	stat, err := os.Stat(name)
	if err != nil {
		return false
	}
	return stat.IsDir()
}
func IsUnixSocket(path string) bool {
	stat, err := os.Stat(path)
	if err != nil {
		return false
	}
	return (stat.Mode() & os.ModeSocket) == os.ModeSocket
}
func HostPath(path string) string {
	if len(path) == 0 {
		return path
	}
	if path == "-" {
		return path
	}
	snap := os.Getenv("SNAP")
	snapName := os.Getenv("SNAP_NAME")
	if snap == "" || snapName != "lxd" {
		return path
	}
	if path[0] != os.PathSeparator {
		ppid := os.Getppid()
		if ppid < 1 {
			return path
		}
		pwd, err := os.Readlink(fmt.Sprintf("/proc/%d/cwd", ppid))
		if err != nil {
			return path
		}
		path = filepath.Clean(strings.Join([]string{pwd, path}, string(os.PathSeparator)))
	}
	for _, prefix := range []string{"/dev", "/snap", "/var/snap", "/var/lib/snapd"} {
		if path == prefix || strings.HasPrefix(path, fmt.Sprintf("%s/", prefix)) {
			return path
		}
	}
	return fmt.Sprintf("/var/lib/snapd/hostfs%s", path)
}
func VarPath(path ...string) string {
	varDir := os.Getenv("LXD_DIR")
	if varDir == "" {
		varDir = "/var/lib/lxd"
	}
	items := []string{varDir}
	items = append(items, path...)
	return filepath.Join(items...)
}