17417: Add arm64 packages for our Golang components.
[arvados.git] / lib / mount / command.go
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: Apache-2.0
4
5 package mount
6
7 import (
8         "flag"
9         "io"
10         "log"
11         "net/http"
12         // pprof is only imported to register its HTTP handlers
13         _ "net/http/pprof"
14         "os"
15
16         "git.arvados.org/arvados.git/sdk/go/arvados"
17         "git.arvados.org/arvados.git/sdk/go/arvadosclient"
18         "git.arvados.org/arvados.git/sdk/go/keepclient"
19         "github.com/arvados/cgofuse/fuse"
20 )
21
22 var Command = &cmd{}
23
24 type cmd struct {
25         // ready, if non-nil, will be closed when the mount is
26         // initialized.  If ready is non-nil, it RunCommand() should
27         // not be called more than once, or when ready is already
28         // closed.
29         ready chan struct{}
30         // It is safe to call Unmount only after ready has been
31         // closed.
32         Unmount func() (ok bool)
33 }
34
35 // RunCommand implements the subcommand "mount <path> [fuse options]".
36 //
37 // The "-d" fuse option (and perhaps other features) ignores the
38 // stderr argument and prints to os.Stderr instead.
39 func (c *cmd) RunCommand(prog string, args []string, stdin io.Reader, stdout, stderr io.Writer) int {
40         logger := log.New(stderr, prog+" ", 0)
41         flags := flag.NewFlagSet(prog, flag.ContinueOnError)
42         ro := flags.Bool("ro", false, "read-only")
43         experimental := flags.Bool("experimental", false, "acknowledge this is an experimental command, and should not be used in production (required)")
44         blockCache := flags.Int("block-cache", 4, "read cache size (number of 64MiB blocks)")
45         pprof := flags.String("pprof", "", "serve Go profile data at `[addr]:port`")
46         err := flags.Parse(args)
47         if err != nil {
48                 logger.Print(err)
49                 return 2
50         }
51         if !*experimental {
52                 logger.Printf("error: experimental command %q used without --experimental flag", prog)
53                 return 2
54         }
55         if *pprof != "" {
56                 go func() {
57                         log.Println(http.ListenAndServe(*pprof, nil))
58                 }()
59         }
60
61         client := arvados.NewClientFromEnv()
62         ac, err := arvadosclient.New(client)
63         if err != nil {
64                 logger.Print(err)
65                 return 1
66         }
67         kc, err := keepclient.MakeKeepClient(ac)
68         if err != nil {
69                 logger.Print(err)
70                 return 1
71         }
72         kc.BlockCache = &keepclient.BlockCache{MaxBlocks: *blockCache}
73         host := fuse.NewFileSystemHost(&keepFS{
74                 Client:     client,
75                 KeepClient: kc,
76                 ReadOnly:   *ro,
77                 Uid:        os.Getuid(),
78                 Gid:        os.Getgid(),
79                 ready:      c.ready,
80         })
81         c.Unmount = host.Unmount
82         ok := host.Mount("", flags.Args())
83         if !ok {
84                 return 1
85         }
86         return 0
87 }