OSDN Git Service

Hulk did something
[bytom/vapor.git] / vendor / golang.org / x / crypto / acme / autocert / cache.go
diff --git a/vendor/golang.org/x/crypto/acme/autocert/cache.go b/vendor/golang.org/x/crypto/acme/autocert/cache.go
new file mode 100644 (file)
index 0000000..61a5fd2
--- /dev/null
@@ -0,0 +1,130 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package autocert
+
+import (
+       "context"
+       "errors"
+       "io/ioutil"
+       "os"
+       "path/filepath"
+)
+
+// ErrCacheMiss is returned when a certificate is not found in cache.
+var ErrCacheMiss = errors.New("acme/autocert: certificate cache miss")
+
+// Cache is used by Manager to store and retrieve previously obtained certificates
+// as opaque data.
+//
+// The key argument of the methods refers to a domain name but need not be an FQDN.
+// Cache implementations should not rely on the key naming pattern.
+type Cache interface {
+       // Get returns a certificate data for the specified key.
+       // If there's no such key, Get returns ErrCacheMiss.
+       Get(ctx context.Context, key string) ([]byte, error)
+
+       // Put stores the data in the cache under the specified key.
+       // Underlying implementations may use any data storage format,
+       // as long as the reverse operation, Get, results in the original data.
+       Put(ctx context.Context, key string, data []byte) error
+
+       // Delete removes a certificate data from the cache under the specified key.
+       // If there's no such key in the cache, Delete returns nil.
+       Delete(ctx context.Context, key string) error
+}
+
+// DirCache implements Cache using a directory on the local filesystem.
+// If the directory does not exist, it will be created with 0700 permissions.
+type DirCache string
+
+// Get reads a certificate data from the specified file name.
+func (d DirCache) Get(ctx context.Context, name string) ([]byte, error) {
+       name = filepath.Join(string(d), name)
+       var (
+               data []byte
+               err  error
+               done = make(chan struct{})
+       )
+       go func() {
+               data, err = ioutil.ReadFile(name)
+               close(done)
+       }()
+       select {
+       case <-ctx.Done():
+               return nil, ctx.Err()
+       case <-done:
+       }
+       if os.IsNotExist(err) {
+               return nil, ErrCacheMiss
+       }
+       return data, err
+}
+
+// Put writes the certificate data to the specified file name.
+// The file will be created with 0600 permissions.
+func (d DirCache) Put(ctx context.Context, name string, data []byte) error {
+       if err := os.MkdirAll(string(d), 0700); err != nil {
+               return err
+       }
+
+       done := make(chan struct{})
+       var err error
+       go func() {
+               defer close(done)
+               var tmp string
+               if tmp, err = d.writeTempFile(name, data); err != nil {
+                       return
+               }
+               select {
+               case <-ctx.Done():
+                       // Don't overwrite the file if the context was canceled.
+               default:
+                       newName := filepath.Join(string(d), name)
+                       err = os.Rename(tmp, newName)
+               }
+       }()
+       select {
+       case <-ctx.Done():
+               return ctx.Err()
+       case <-done:
+       }
+       return err
+}
+
+// Delete removes the specified file name.
+func (d DirCache) Delete(ctx context.Context, name string) error {
+       name = filepath.Join(string(d), name)
+       var (
+               err  error
+               done = make(chan struct{})
+       )
+       go func() {
+               err = os.Remove(name)
+               close(done)
+       }()
+       select {
+       case <-ctx.Done():
+               return ctx.Err()
+       case <-done:
+       }
+       if err != nil && !os.IsNotExist(err) {
+               return err
+       }
+       return nil
+}
+
+// writeTempFile writes b to a temporary file, closes the file and returns its path.
+func (d DirCache) writeTempFile(prefix string, b []byte) (string, error) {
+       // TempFile uses 0600 permissions
+       f, err := ioutil.TempFile(string(d), prefix)
+       if err != nil {
+               return "", err
+       }
+       if _, err := f.Write(b); err != nil {
+               f.Close()
+               return "", err
+       }
+       return f.Name(), f.Close()
+}