Browse Source

создание файла при записи

kpmy 8 years ago
parent
commit
a1e3b7e643
2 changed files with 62 additions and 10 deletions
  1. 46 3
      fs.go
  2. 16 7
      trav.go

+ 46 - 3
fs.go

@@ -12,6 +12,7 @@ import (
 	"strings"
 	"sync"
 
+	"github.com/ipfs/go-ipfs/commands/http"
 	"github.com/kpmy/mipfs/ipfs_api"
 	. "github.com/kpmy/ypk/tc"
 	"github.com/mattetti/filebuffer"
@@ -23,6 +24,7 @@ type file struct {
 	pos   int64
 	buf   *filebuffer.Buffer
 	links []*go_ipfs_api.LsLink
+	newFn func(io.ReadCloser)
 }
 
 func (f *file) Name() string {
@@ -112,7 +114,14 @@ func (f *file) Stat() (os.FileInfo, error) {
 }
 
 func (f *file) Write(p []byte) (n int, err error) {
-	panic(100)
+	if f.newFn != nil {
+		buf := filebuffer.New(p)
+		f.newFn(buf)
+		f.pos = buf.Index
+		return int(f.pos), nil
+	} else {
+		panic(100)
+	}
 }
 
 type link struct {
@@ -211,6 +220,7 @@ func (l *loc) Write(p []byte) (n int, err error) {
 }
 
 type filesystem struct {
+	webdav.FileSystem
 	node string
 	root string
 }
@@ -249,8 +259,40 @@ func (f *filesystem) OpenFile(name string, flag int, perm os.FileMode) (webdav.F
 	} else if li != nil {
 		return li, nil
 	} else {
-		panic(0)
+		switch {
+		case flag&os.O_CREATE != 0:
+			path := filepath.Dir(name)
+			_, last := filepath.Split(name)
+			nf := &file{}
+			nf.newFn = func(data io.ReadCloser) {
+				ls := split(f.root, path)
+				ns := strings.Split(strings.Trim(f.root+path, "/"+rootName), rootName)
+				fileHash, _ := ipfs_api.Shell().Add(data)
+				downHash := fileHash
+				downPath := last
+				for i := len(ns) - 1; i >= 0; i-- {
+					newHash := ls[i].Hash
+					newHash, _ = ipfs_api.Shell().PatchLink(newHash, downPath, downHash, false)
+					downHash = newHash
+					downPath = ns[i]
+					if i == 0 {
+						ipfs_api.Shell().Unpin(f.root)
+						f.root = newHash
+						ipfs_api.Shell().Pin(f.root)
+						memo.Write("root", []byte(f.root))
+					}
+				}
+				_, fi := trav(f.root, name)
+				Assert(fi != nil, 60)
+				nf.newFn = nil
+				nf.UnixLsLink = fi.UnixLsLink
+			}
+			return nf, nil
+		default:
+			Halt(100, name, " ", flag, perm)
+		}
 	}
+	return nil, http.ErrNotFound
 }
 
 func (f *filesystem) RemoveAll(name string) (err error) {
@@ -295,8 +337,9 @@ func (f *filesystem) Stat(name string) (os.FileInfo, error) {
 	} else if li != nil {
 		return li, nil
 	} else {
-		panic(0)
+		Halt(100, name)
 	}
+	return nil, http.ErrNotFound
 }
 
 var nodeID *go_ipfs_api.IdOutput

+ 16 - 7
trav.go

@@ -2,6 +2,7 @@ package mipfs
 
 import (
 	"github.com/kpmy/mipfs/ipfs_api"
+	"log"
 	"os"
 	"path/filepath"
 )
@@ -12,7 +13,7 @@ func find(li *loc, name string) (ret *loc) {
 	for _, i := range li.Links {
 		if i.Type == "Directory" && i.Name == name {
 			ls, _ := ipfs_api.Shell().FileList(i.Hash)
-			return &loc{*ls}
+			ret = &loc{*ls}
 		}
 	}
 	return
@@ -21,23 +22,31 @@ func find(li *loc, name string) (ret *loc) {
 func find2(li *loc, name string) (ret *link) {
 	for _, i := range li.Links {
 		if i.Type == "File" && i.Name == name {
-			return &link{*i}
+			ret = &link{*i}
 		}
 	}
 	return
 }
 
 func trav(root string, name string) (*loc, *link) {
-	if name == rootName {
-		ls, _ := ipfs_api.Shell().FileList(root)
-		return &loc{*ls}, nil
+	if name == rootName || name == "/" {
+		if ls, err := ipfs_api.Shell().FileList(root); err != nil {
+			log.Fatal(err)
+			panic(100)
+		} else {
+			return &loc{*ls}, nil
+		}
 	} else {
 		_, last := filepath.Split(name)
 		l, _ := trav(root, filepath.Dir(name))
 		if li := find(l, last); li != nil {
 			return li, nil
 		} else {
-			return l, find2(l, last)
+			if f := find2(l, last); f != nil {
+				return l, f
+			} else {
+				return nil, nil
+			}
 		}
 	}
 }
@@ -45,7 +54,7 @@ func trav(root string, name string) (*loc, *link) {
 func split(rootHash string, path string) (ret []*loc) {
 	var tr func(root string) *loc
 	tr = func(root string) *loc {
-		if root == rootName {
+		if root == rootName || root == "/" {
 			ls, _ := ipfs_api.Shell().FileList(rootHash)
 			l := &loc{*ls}
 			ret = append(ret, l)