-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
License: MIT Signed-off-by: Dominic Della Valle <ddvpublic@gmail.com>
- Loading branch information
Showing
23 changed files
with
2,646 additions
and
149 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
// +build !nofuse | ||
|
||
package commands | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"path/filepath" | ||
|
||
"github.com/billziss-gh/cgofuse/fuse" | ||
cmdenv "github.com/ipfs/go-ipfs/core/commands/cmdenv" | ||
mi "github.com/ipfs/go-ipfs/core/commands/mount" | ||
|
||
cmds "gx/ipfs/Qma6uuSyjkecGhMFFLfzyJDPyoDtNJSHJNweDccZhaWkgU/go-ipfs-cmds" | ||
cmdkit "gx/ipfs/Qmde5VP1qUkyQXKCfmEUA7bP64V2HAptbJ7phuPp7jXWwg/go-ipfs-cmdkit" | ||
) | ||
|
||
var MountCmd = &cmds.Command{ | ||
Helptext: cmdkit.HelpText{ | ||
Tagline: "Mounts IPFS to the filesystem.", | ||
ShortDescription: ` | ||
Mount IPFS at a read-only mountpoint on the OS (default: /ipfs and /ipns). | ||
All IPFS objects will be accessible under that directory. Note that the | ||
root will not be listable, as it is virtual. Access known paths directly. | ||
You may have to create /ipfs and /ipns before using 'ipfs mount': | ||
> sudo mkdir /ipfs /ipns | ||
> sudo chown $(whoami) /ipfs /ipns | ||
> ipfs daemon & | ||
> ipfs mount | ||
`, | ||
LongDescription: ` | ||
Mount IPFS at a read-only mountpoint on the OS. The default, /ipfs and /ipns, | ||
are set in the configuration file, but can be overriden by the options. | ||
All IPFS objects will be accessible under this directory. Note that the | ||
root will not be listable, as it is virtual. Access known paths directly. | ||
You may have to create /ipfs and /ipns before using 'ipfs mount': | ||
> sudo mkdir /ipfs /ipns | ||
> sudo chown $(whoami) /ipfs /ipns | ||
> ipfs daemon & | ||
> ipfs mount | ||
Example: | ||
# setup | ||
> mkdir foo | ||
> echo "baz" > foo/bar | ||
> ipfs add -r foo | ||
added QmWLdkp93sNxGRjnFHPaYg8tCQ35NBY3XPn6KiETd3Z4WR foo/bar | ||
added QmSh5e7S6fdcu75LAbXNZAFY2nGyZUJXyLCJDvn2zRkWyC foo | ||
> ipfs ls QmSh5e7S6fdcu75LAbXNZAFY2nGyZUJXyLCJDvn2zRkWyC | ||
QmWLdkp93sNxGRjnFHPaYg8tCQ35NBY3XPn6KiETd3Z4WR 12 bar | ||
> ipfs cat QmWLdkp93sNxGRjnFHPaYg8tCQ35NBY3XPn6KiETd3Z4WR | ||
baz | ||
# mount | ||
> ipfs daemon & | ||
> ipfs mount | ||
IPFS mounted at: /ipfs | ||
IPNS mounted at: /ipns | ||
> cd /ipfs/QmSh5e7S6fdcu75LAbXNZAFY2nGyZUJXyLCJDvn2zRkWyC | ||
> ls | ||
bar | ||
> cat bar | ||
baz | ||
> cat /ipfs/QmSh5e7S6fdcu75LAbXNZAFY2nGyZUJXyLCJDvn2zRkWyC/bar | ||
baz | ||
> cat /ipfs/QmWLdkp93sNxGRjnFHPaYg8tCQ35NBY3XPn6KiETd3Z4WR | ||
baz | ||
`, | ||
}, | ||
Options: []cmdkit.Option{ | ||
cmdkit.StringOption("ipfs-path", "f", "The path where IPFS should be mounted."), | ||
cmdkit.StringOption("ipns-path", "n", "The path where IPNS should be mounted."), | ||
}, | ||
|
||
//TODO: GetNode -> GetApi | ||
//TODO: properly migrate to cmds 2.0; review | ||
Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) (err error) { | ||
defer res.Close() | ||
|
||
node, err := cmdenv.GetNode(env) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
conf, err := cmdenv.GetConfig(env) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
mountPoint := conf.Mounts.IPFS | ||
//TODO: if mountPoint == default; platform switch; win32 = \\.\ipfs\$mountpoint | ||
//TODO: investigate, this doesn't seem to work | ||
//WinFSP sets up via the filesystem name, when undefined, this is the service/proc name | ||
// i.e. \\ipfs\mountpoint => \\$procname|$fsName\\mountpoint | ||
/* | ||
mountPoint = `\\ipfs\ipfs\` //DBG | ||
go fsh.Mount(mountPoint, []string{"-o uid=-1,gid=-1,pid=-1", "-o fstypename=ipfs", "--VolumePrefix=\\ipfs"}) | ||
*/ | ||
|
||
/* TODO: coalesce non-unique mountpoints, multi mount instances | ||
f(mountRoot, functionConfig, ...roots) | ||
config{/ipfs, /ipns, /usr/home/cooleuser/mfs} => | ||
go f("/", opts, ipfsRoot, ipnsRoot) | ||
go f("/usr/home/cooluser", opts, mfsRoot) | ||
*/ | ||
|
||
//TODO: we need to decide where to store this; we'll need some other scope for graceful destruction from `unmount` | ||
|
||
//TODO [current]: pass something to the mount instance so that we can block on it here, right now our errors will be ignored | ||
fsi := &mi.FUSEIPFS{APINode: node} | ||
fsh := fuse.NewFileSystemHost(fsi) | ||
|
||
//fsh.SetCapReaddirPlus(true) //TODO: win32 only; needs testing | ||
fsh.SetCapCaseInsensitive(false) | ||
|
||
//TODO: check state of daemon, if offline, wait for signal to exit; otherwise run in background | ||
//FIXME: cgofuse has its own signal/interrupt handler; need to ctrl+c twice | ||
go func() { | ||
defer func() { | ||
//TODO: breakout into platform specific panic handlers? | ||
if r := recover(); r != nil { | ||
if typedR, ok := r.(string); ok { | ||
if typedR == "cgofuse: cannot find winfsp" { | ||
err = errors.New("WinFSP(http://www.secfs.net/winfsp/) is required for mount on this platform, but it was not found") | ||
} | ||
err = errors.New(typedR) | ||
return | ||
} | ||
err = fmt.Errorf("Mount panicked! %v", r) | ||
} | ||
}() | ||
|
||
fsh.Mount(mountPoint, []string{"-o uid=-1,gid=-1,pid=-1,fstypename=IPFS"}) | ||
//fsh.Mount(mountPoint, []string{"-d", "-o uid=-1,gid=-1,pid=-1,fstypename=IPFS"}) | ||
}() | ||
//go fsh.Mount(mountPoint, []string{"-o uid=-1,gid=-1,pid=-1", "-d"}) | ||
|
||
//TODO: switch on signal from mount call; succeed or fail | ||
absMount, err := filepath.Abs(mountPoint) | ||
if err != nil { | ||
absMount = mountPoint | ||
} | ||
cmds.EmitOnce(res, fmt.Sprintf("%#q mounted", absMount)) | ||
return nil | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
package fusemount | ||
|
||
import ( | ||
cid "gx/ipfs/QmR8BauakNcBa3RbE4nbQu76PDiJgoQgz8AJdhJuiU4TAw/go-cid" | ||
|
||
"github.com/alexanderGugel/arc" | ||
) | ||
|
||
/* | ||
type cidCache interface { | ||
Add(*cid.Cid, fusePath) | ||
Request(*cid.Cid) fusePath | ||
Release(*cid.Cid) | ||
} | ||
*/ | ||
|
||
//TODO: ability to disable cache | ||
type cidCache struct { | ||
actual *arc.ARC | ||
} | ||
|
||
func (cc *cidCache) Add(cid cid.Cid, fp fusePath) { | ||
/* | ||
cc.Lock() | ||
k := cid.String() | ||
if _, ok := cc.activeDags[k]; !ok { | ||
cc.activeDags[k] = &cidCachePair{fp: fp, refCount: 1} | ||
} | ||
cc.Unlock() | ||
*/ | ||
|
||
/* NOTE: ok is false if already exists in cache | ||
if ok := cc.actual.Put(cid, fp); !ok { | ||
log.Errorf("Cache - Add failed for [%s]%s", cid, fp) | ||
} | ||
*/ | ||
cc.actual.Put(cid, fp) | ||
} | ||
|
||
/* | ||
func (cc *cidCache) Release(cid *cid.Cid) { | ||
cc.Lock() | ||
defer cc.Unlock() | ||
k := cid.String() | ||
if _, ok := cc.activeDags[k]; !ok { | ||
return | ||
} | ||
cc.activeDags[k].refCount-- | ||
if cc.activeDags[k].refCount == 0 { | ||
delete(cc.activeDags, k) | ||
} | ||
} | ||
*/ | ||
func (cc *cidCache) Request(cid cid.Cid) fusePath { | ||
if v, ok := cc.actual.Get(cid); ok { | ||
if _, ok = v.(fusePath); !ok { | ||
log.Errorf("Cache - Request returned invalid data") | ||
return nil | ||
} | ||
return v.(fusePath) | ||
} | ||
return nil | ||
} | ||
|
||
//TODO: size from conf? | ||
func (cc *cidCache) Init() { | ||
cc.actual = arc.New(100) //NOTE: arbitrary debug size | ||
} | ||
|
||
//TODO: for each cache (size, keys, etc) place in remove.go with notes | ||
//size: gtihub issue to unixfs size | ||
//keys: node doesn't send events yet | ||
// etc. |
Oops, something went wrong.