// commandShouldRunOnDaemon determines, from commmand details, whether a // command ought to be executed on an IPFS daemon. // // It returns a client if the command should be executed on a daemon and nil if // it should be executed on a client. It returns an error if the command must // NOT be executed on either. func commandShouldRunOnDaemon(details cmdDetails, req cmds.Request, root *cmds.Command) (cmdsHttp.Client, error) { path := req.Path() // root command. if len(path) < 1 { return nil, nil } if details.cannotRunOnClient && details.cannotRunOnDaemon { return nil, fmt.Errorf("command disabled: %s", path[0]) } if details.doesNotUseRepo && details.canRunOnClient() { return nil, nil } // at this point need to know whether api is running. we defer // to this point so that we dont check unnecessarily // did user specify an api to use for this command? apiAddrStr, _, err := req.Option(coreCmds.ApiOption).String() if err != nil { return nil, err } client, err := getApiClient(req.InvocContext().ConfigRoot, apiAddrStr) if err == repo.ErrApiNotRunning { if apiAddrStr != "" && req.Command() != daemonCmd { // if user SPECIFIED an api, and this cmd is not daemon // we MUST use it. so error out. return nil, err } // ok for api not to be running } else if err != nil { // some other api error return nil, err } if client != nil { // daemon is running if details.cannotRunOnDaemon { e := "cannot use API with this command." // check if daemon locked. legacy error text, for now. daemonLocked, _ := fsrepo.LockedByOtherProcess(req.InvocContext().ConfigRoot) if daemonLocked { e = "ipfs daemon is running. please stop it to run this command" } return nil, cmds.ClientError(e) } return client, nil } if details.cannotRunOnClient { return nil, cmds.ClientError("must run on the ipfs daemon") } return nil, nil }
func doMount(node *core.IpfsNode, fsdir, nsdir string) error { fmtFuseErr := func(err error, mountpoint string) error { s := err.Error() if strings.Contains(s, fuseNoDirectory) { s = strings.Replace(s, `fusermount: "fusermount:`, "", -1) s = strings.Replace(s, `\n", exit status 1`, "", -1) return cmds.ClientError(s) } if s == fuseExitStatus1 { s = fmt.Sprintf("fuse failed to access mountpoint %s", mountpoint) return cmds.ClientError(s) } return err } // this sync stuff is so that both can be mounted simultaneously. var fsmount mount.Mount var nsmount mount.Mount var err1 error var err2 error done := make(chan struct{}) go func() { fsmount, err1 = rofs.Mount(node, fsdir) done <- struct{}{} }() go func() { nsmount, err2 = ipns.Mount(node, nsdir, fsdir) done <- struct{}{} }() <-done <-done if err1 != nil || err2 != nil { log.Infof("error mounting: %s %s", err1, err2) if fsmount != nil { fsmount.Unmount() } if nsmount != nil { nsmount.Unmount() } if err1 != nil { return fmtFuseErr(err1, fsdir) } return fmtFuseErr(err2, nsdir) } // setup node state, so that it can be cancelled node.Mounts.Ipfs = fsmount node.Mounts.Ipns = nsmount return nil }
// parseAddresses is a function that takes in a slice of string peer addresses // (multiaddr + peerid) and returns slices of multiaddrs and peerids. func parseAddresses(addrs []string) (iaddrs []iaddr.IPFSAddr, err error) { iaddrs = make([]iaddr.IPFSAddr, len(addrs)) for i, saddr := range addrs { iaddrs[i], err = iaddr.ParseString(saddr) if err != nil { return nil, cmds.ClientError("invalid peer address: " + err.Error()) } } return }
// commandShouldRunOnDaemon determines, from commmand details, whether a // command ought to be executed on an IPFS daemon. // // It returns true if the command should be executed on a daemon and false if // it should be executed on a client. It returns an error if the command must // NOT be executed on either. func commandShouldRunOnDaemon(details cmdDetails, req cmds.Request, root *cmds.Command) (bool, error) { path := req.Path() // root command. if len(path) < 1 { return false, nil } if details.cannotRunOnClient && details.cannotRunOnDaemon { return false, fmt.Errorf("command disabled: %s", path[0]) } if details.doesNotUseRepo && details.canRunOnClient() { return false, nil } // at this point need to know whether daemon is running. we defer // to this point so that some commands dont open files unnecessarily. daemonLocked, err := fsrepo.LockedByOtherProcess(req.InvocContext().ConfigRoot) if err != nil { return false, err } if daemonLocked { log.Info("a daemon is running...") if details.cannotRunOnDaemon { e := "ipfs daemon is running. please stop it to run this command" return false, cmds.ClientError(e) } return true, nil } if details.cannotRunOnClient { return false, cmds.ClientError("must run on the ipfs daemon") } return false, nil }
// TODO need to decide whether to expose the override as a file or a // directory. That is: should we allow the user to also specify the // name of the file? // TODO cmds.StringOption("event-logs", "l", "Location for machine-readable event logs."), }, PreRun: func(req cmds.Request) error { daemonLocked, err := fsrepo.LockedByOtherProcess(req.InvocContext().ConfigRoot) if err != nil { return err } log.Info("checking if daemon is running...") if daemonLocked { log.Debug("Ipfs daemon is running.") e := "ipfs daemon is running. please stop it to run this command" return cmds.ClientError(e) } return nil }, Run: func(req cmds.Request, res cmds.Response) { if req.InvocContext().Online { res.SetError(errors.New("init must be run offline only!"), cmds.ErrNormal) return } empty, _, err := req.Option("e").Bool() // if !empty, it's okay empty == false if err != nil { res.SetError(err, cmds.ErrNormal) return }
}, Options: []cmds.Option{ cmds.StringOption("format", "f", "optional output format"), }, Run: func(req cmds.Request, res cmds.Response) { node, err := req.InvocContext().GetNode() if err != nil { res.SetError(err, cmds.ErrNormal) return } var id peer.ID if len(req.Arguments()) > 0 { id = peer.ID(b58.Decode(req.Arguments()[0])) if len(id) == 0 { res.SetError(cmds.ClientError("Invalid peer id"), cmds.ErrClient) return } } else { id = node.Identity } if id == node.Identity { output, err := printSelf(node) if err != nil { res.SetError(err, cmds.ErrNormal) return } res.SetOutput(output) return }