Add support for writing to a file (and creating it if not existent)
This commit is contained in:
parent
8acab006b6
commit
8d8ec70683
19
http.go
19
http.go
|
@ -269,6 +269,24 @@ func (rt *Router) routeServerListDirectory(w http.ResponseWriter, r *http.Reques
|
||||||
json.NewEncoder(w).Encode(stats)
|
json.NewEncoder(w).Encode(stats)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Writes a file to the system for the server.
|
||||||
|
func (rt *Router) routeServerWriteFile(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||||
|
s := rt.Servers.Get(ps.ByName("server"))
|
||||||
|
|
||||||
|
p := r.URL.Query().Get("file")
|
||||||
|
defer r.Body.Close()
|
||||||
|
err := s.Filesystem.Writefile(p, r.Body)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
zap.S().Errorw("failed to write file to directory", zap.String("server", s.Uuid), zap.String("path", p), zap.Error(err))
|
||||||
|
|
||||||
|
http.Error(w, "failed to write file to directory", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
w.WriteHeader(http.StatusNoContent)
|
||||||
|
}
|
||||||
|
|
||||||
// Creates a new directory for the server.
|
// Creates a new directory for the server.
|
||||||
func (rt *Router) routeServerCreateDirectory(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
func (rt *Router) routeServerCreateDirectory(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||||
s := rt.Servers.Get(ps.ByName("server"))
|
s := rt.Servers.Get(ps.ByName("server"))
|
||||||
|
@ -374,6 +392,7 @@ func (rt *Router) ConfigureRouter() *httprouter.Router {
|
||||||
router.GET("/api/servers/:server/files/list-directory", rt.AuthenticateToken("s:files", rt.AuthenticateServer(rt.routeServerListDirectory)))
|
router.GET("/api/servers/:server/files/list-directory", rt.AuthenticateToken("s:files", rt.AuthenticateServer(rt.routeServerListDirectory)))
|
||||||
router.PUT("/api/servers/:server/files/rename", rt.AuthenticateToken("s:files", rt.AuthenticateServer(rt.routeServerRenameFile)))
|
router.PUT("/api/servers/:server/files/rename", rt.AuthenticateToken("s:files", rt.AuthenticateServer(rt.routeServerRenameFile)))
|
||||||
router.POST("/api/servers/:server/files/copy", rt.AuthenticateToken("s:files", rt.AuthenticateServer(rt.routeServerCopyFile)))
|
router.POST("/api/servers/:server/files/copy", rt.AuthenticateToken("s:files", rt.AuthenticateServer(rt.routeServerCopyFile)))
|
||||||
|
router.POST("/api/servers/:server/files/write", rt.AuthenticateToken("s:files", rt.AuthenticateServer(rt.routeServerWriteFile)))
|
||||||
router.POST("/api/servers/:server/files/create-directory", rt.AuthenticateToken("s:files", rt.AuthenticateServer(rt.routeServerCreateDirectory)))
|
router.POST("/api/servers/:server/files/create-directory", rt.AuthenticateToken("s:files", rt.AuthenticateServer(rt.routeServerCreateDirectory)))
|
||||||
router.POST("/api/servers/:server/files/delete", rt.AuthenticateToken("s:files", rt.AuthenticateServer(rt.routeServerDeleteFile)))
|
router.POST("/api/servers/:server/files/delete", rt.AuthenticateToken("s:files", rt.AuthenticateServer(rt.routeServerDeleteFile)))
|
||||||
router.POST("/api/servers/:server/power", rt.AuthenticateToken("s:power", rt.AuthenticateServer(rt.routeServerPower)))
|
router.POST("/api/servers/:server/power", rt.AuthenticateToken("s:power", rt.AuthenticateServer(rt.routeServerPower)))
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
@ -196,6 +197,68 @@ func (fs *Filesystem) Readfile(p string) (io.Reader, error) {
|
||||||
return bytes.NewReader(b), nil
|
return bytes.NewReader(b), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Writes a file to the system. If the file does not already exist one will be created.
|
||||||
|
//
|
||||||
|
// @todo should probably have a write lock here so we don't write twice at once.
|
||||||
|
func (fs *Filesystem) Writefile(p string, r io.Reader) error {
|
||||||
|
cleaned, err := fs.SafePath(p)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the file does not exist on the system already go ahead and create the pathway
|
||||||
|
// to it and an empty file. We'll then write to it later on after this completes.
|
||||||
|
if stat, err := os.Stat(cleaned); err != nil && os.IsNotExist(err) {
|
||||||
|
if err := os.MkdirAll(filepath.Dir(cleaned), 0755); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := fs.Chown(filepath.Dir(cleaned)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else if err != nil {
|
||||||
|
return err
|
||||||
|
} else if stat.IsDir() {
|
||||||
|
return errors.New("cannot use a directory as a file for writing")
|
||||||
|
}
|
||||||
|
|
||||||
|
// This will either create the file if it does not already exist, or open and
|
||||||
|
// truncate the existing file.
|
||||||
|
file, err := os.OpenFile(cleaned, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
// Create a new buffered writer that will write to the file we just opened
|
||||||
|
// and stream in the contents from the reader.
|
||||||
|
w := bufio.NewWriter(file)
|
||||||
|
|
||||||
|
buf := make([]byte, 1024)
|
||||||
|
for {
|
||||||
|
n, err := r.Read(buf)
|
||||||
|
if err != nil && err != io.EOF {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if n == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := w.Write(buf[:n]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := w.Flush(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, chown the file to ensure the permissions don't end up out-of-whack
|
||||||
|
// if we had just created it.
|
||||||
|
return fs.Chown(p)
|
||||||
|
}
|
||||||
|
|
||||||
// Defines the stat struct object.
|
// Defines the stat struct object.
|
||||||
type Stat struct {
|
type Stat struct {
|
||||||
Info os.FileInfo
|
Info os.FileInfo
|
||||||
|
|
Loading…
Reference in New Issue
Block a user