github.com/masterhung0112/hk_server/v5@v5.0.0-20220302090640-ec71aef15e1c/shared/filestore/localstore.go (about)

     1  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
     2  // See LICENSE.txt for license information.
     3  
     4  package filestore
     5  
     6  import (
     7  	"bytes"
     8  	"io"
     9  	"io/ioutil"
    10  	"os"
    11  	"path/filepath"
    12  	"time"
    13  
    14  	"github.com/pkg/errors"
    15  
    16  	"github.com/masterhung0112/hk_server/v5/shared/mlog"
    17  )
    18  
    19  const (
    20  	TestFilePath = "/testfile"
    21  )
    22  
    23  type LocalFileBackend struct {
    24  	directory string
    25  }
    26  
    27  // copyFile will copy a file from src path to dst path.
    28  // Overwrites any existing files at dst.
    29  // Permissions are copied from file at src to the new file at dst.
    30  func copyFile(src, dst string) (err error) {
    31  	in, err := os.Open(src)
    32  	if err != nil {
    33  		return
    34  	}
    35  	defer in.Close()
    36  
    37  	if err = os.MkdirAll(filepath.Dir(dst), os.ModePerm); err != nil {
    38  		return
    39  	}
    40  	out, err := os.Create(dst)
    41  	if err != nil {
    42  		return
    43  	}
    44  	defer func() {
    45  		if e := out.Close(); e != nil {
    46  			err = e
    47  		}
    48  	}()
    49  
    50  	_, err = io.Copy(out, in)
    51  	if err != nil {
    52  		return
    53  	}
    54  
    55  	err = out.Sync()
    56  	if err != nil {
    57  		return
    58  	}
    59  
    60  	stat, err := os.Stat(src)
    61  	if err != nil {
    62  		return
    63  	}
    64  	err = os.Chmod(dst, stat.Mode())
    65  	if err != nil {
    66  		return
    67  	}
    68  
    69  	return
    70  }
    71  
    72  func (b *LocalFileBackend) TestConnection() error {
    73  	f := bytes.NewReader([]byte("testingwrite"))
    74  	if _, err := writeFileLocally(f, filepath.Join(b.directory, TestFilePath)); err != nil {
    75  		return errors.Wrap(err, "unable to write to the local filesystem storage")
    76  	}
    77  	os.Remove(filepath.Join(b.directory, TestFilePath))
    78  	mlog.Debug("Able to write files to local storage.")
    79  	return nil
    80  }
    81  
    82  func (b *LocalFileBackend) Reader(path string) (ReadCloseSeeker, error) {
    83  	f, err := os.Open(filepath.Join(b.directory, path))
    84  	if err != nil {
    85  		return nil, errors.Wrapf(err, "unable to open file %s", path)
    86  	}
    87  	return f, nil
    88  }
    89  
    90  func (b *LocalFileBackend) ReadFile(path string) ([]byte, error) {
    91  	f, err := ioutil.ReadFile(filepath.Join(b.directory, path))
    92  	if err != nil {
    93  		return nil, errors.Wrapf(err, "unable to read file %s", path)
    94  	}
    95  	return f, nil
    96  }
    97  
    98  func (b *LocalFileBackend) FileExists(path string) (bool, error) {
    99  	_, err := os.Stat(filepath.Join(b.directory, path))
   100  
   101  	if os.IsNotExist(err) {
   102  		return false, nil
   103  	}
   104  
   105  	if err != nil {
   106  		return false, errors.Wrapf(err, "unable to know if file %s exists", path)
   107  	}
   108  	return true, nil
   109  }
   110  
   111  func (b *LocalFileBackend) FileSize(path string) (int64, error) {
   112  	info, err := os.Stat(filepath.Join(b.directory, path))
   113  	if err != nil {
   114  		return 0, errors.Wrapf(err, "unable to get file size for %s", path)
   115  	}
   116  	return info.Size(), nil
   117  }
   118  
   119  func (b *LocalFileBackend) FileModTime(path string) (time.Time, error) {
   120  	info, err := os.Stat(filepath.Join(b.directory, path))
   121  	if err != nil {
   122  		return time.Time{}, errors.Wrapf(err, "unable to get modification time for file %s", path)
   123  	}
   124  	return info.ModTime(), nil
   125  }
   126  
   127  func (b *LocalFileBackend) CopyFile(oldPath, newPath string) error {
   128  	if err := copyFile(filepath.Join(b.directory, oldPath), filepath.Join(b.directory, newPath)); err != nil {
   129  		return errors.Wrapf(err, "unable to copy file from %s to %s", oldPath, newPath)
   130  	}
   131  	return nil
   132  }
   133  
   134  func (b *LocalFileBackend) MoveFile(oldPath, newPath string) error {
   135  	if err := os.MkdirAll(filepath.Dir(filepath.Join(b.directory, newPath)), 0750); err != nil {
   136  		return errors.Wrapf(err, "unable to create the new destination directory %s", filepath.Dir(newPath))
   137  	}
   138  
   139  	if err := os.Rename(filepath.Join(b.directory, oldPath), filepath.Join(b.directory, newPath)); err != nil {
   140  		return errors.Wrapf(err, "unable to move the file to %s to the destination directory", newPath)
   141  	}
   142  
   143  	return nil
   144  }
   145  
   146  func (b *LocalFileBackend) WriteFile(fr io.Reader, path string) (int64, error) {
   147  	return writeFileLocally(fr, filepath.Join(b.directory, path))
   148  }
   149  
   150  func writeFileLocally(fr io.Reader, path string) (int64, error) {
   151  	if err := os.MkdirAll(filepath.Dir(path), 0750); err != nil {
   152  		directory, _ := filepath.Abs(filepath.Dir(path))
   153  		return 0, errors.Wrapf(err, "unable to create the directory %s for the file %s", directory, path)
   154  	}
   155  	fw, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
   156  	if err != nil {
   157  		return 0, errors.Wrapf(err, "unable to open the file %s to write the data", path)
   158  	}
   159  	defer fw.Close()
   160  	written, err := io.Copy(fw, fr)
   161  	if err != nil {
   162  		return written, errors.Wrapf(err, "unable write the data in the file %s", path)
   163  	}
   164  	return written, nil
   165  }
   166  
   167  func (b *LocalFileBackend) AppendFile(fr io.Reader, path string) (int64, error) {
   168  	fp := filepath.Join(b.directory, path)
   169  	if _, err := os.Stat(fp); err != nil {
   170  		return 0, errors.Wrapf(err, "unable to find the file %s to append the data", path)
   171  	}
   172  	fw, err := os.OpenFile(fp, os.O_WRONLY|os.O_APPEND, 0600)
   173  	if err != nil {
   174  		return 0, errors.Wrapf(err, "unable to open the file %s to append the data", path)
   175  	}
   176  	defer fw.Close()
   177  	written, err := io.Copy(fw, fr)
   178  	if err != nil {
   179  		return written, errors.Wrapf(err, "unable append the data in the file %s", path)
   180  	}
   181  	return written, nil
   182  }
   183  
   184  func (b *LocalFileBackend) RemoveFile(path string) error {
   185  	if err := os.Remove(filepath.Join(b.directory, path)); err != nil {
   186  		return errors.Wrapf(err, "unable to remove the file %s", path)
   187  	}
   188  	return nil
   189  }
   190  
   191  func (b *LocalFileBackend) ListDirectory(path string) ([]string, error) {
   192  	var paths []string
   193  	fileInfos, err := ioutil.ReadDir(filepath.Join(b.directory, path))
   194  	if err != nil {
   195  		if os.IsNotExist(err) {
   196  			return paths, nil
   197  		}
   198  		return nil, errors.Wrapf(err, "unable to list the directory %s", path)
   199  	}
   200  	for _, fileInfo := range fileInfos {
   201  		paths = append(paths, filepath.ToSlash(filepath.Join(path, fileInfo.Name())))
   202  	}
   203  	return paths, nil
   204  }
   205  
   206  func (b *LocalFileBackend) RemoveDirectory(path string) error {
   207  	if err := os.RemoveAll(filepath.Join(b.directory, path)); err != nil {
   208  		return errors.Wrapf(err, "unable to remove the directory %s", path)
   209  	}
   210  	return nil
   211  }