github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/client/cmd_simplefs_read.go (about) 1 // Copyright 2015 Keybase, Inc. All rights reserved. Use of 2 // this source code is governed by the included BSD license. 3 4 package client 5 6 import ( 7 "fmt" 8 9 "golang.org/x/net/context" 10 11 "github.com/keybase/cli" 12 "github.com/keybase/client/go/libcmdline" 13 "github.com/keybase/client/go/libkb" 14 keybase1 "github.com/keybase/client/go/protocol/keybase1" 15 ) 16 17 const readBufSizeDefault = 1600 18 19 // CmdSimpleFSRead is the 'fs read' command. 20 type CmdSimpleFSRead struct { 21 libkb.Contextified 22 path keybase1.Path 23 bufSize int 24 } 25 26 // NewCmdSimpleFSRead creates a new cli.Command. 27 func NewCmdSimpleFSRead(cl *libcmdline.CommandLine, g *libkb.GlobalContext) cli.Command { 28 return cli.Command{ 29 Name: "read", 30 ArgumentHelp: "<path>", 31 Usage: "output file contents to standard output", 32 Action: func(c *cli.Context) { 33 cl.ChooseCommand(&CmdSimpleFSRead{Contextified: libkb.NewContextified(g)}, "read", c) 34 cl.SetNoStandalone() 35 }, 36 Flags: []cli.Flag{ 37 cli.IntFlag{ 38 Name: "b, buffersize", 39 Value: readBufSizeDefault, 40 Usage: "read buffer size", 41 }, 42 cli.IntFlag{ 43 Name: "rev", 44 Usage: "a revision number for the KBFS folder", 45 }, 46 cli.StringFlag{ 47 Name: "time", 48 Usage: "a time for the KBFS folder (eg \"2018-07-27 22:05\")", 49 }, 50 cli.StringFlag{ 51 Name: "reltime, relative-time", 52 Usage: "a relative time for the KBFS folder (eg \"5m\")", 53 }, 54 }, 55 } 56 } 57 58 // Run runs the command in client/server mode. 59 func (c *CmdSimpleFSRead) Run() error { 60 cli, err := GetSimpleFSClient(c.G()) 61 if err != nil { 62 return err 63 } 64 65 ctx := context.TODO() 66 67 opid, err2 := cli.SimpleFSMakeOpid(ctx) 68 if err2 != nil { 69 return err2 70 } 71 err = cli.SimpleFSOpen(ctx, keybase1.SimpleFSOpenArg{ 72 OpID: opid, 73 Dest: c.path, 74 Flags: keybase1.OpenFlags_READ | keybase1.OpenFlags_EXISTING, 75 }) 76 if err != nil { 77 return err 78 } 79 defer cli.SimpleFSClose(ctx, opid) 80 var offset int64 81 for { 82 c.G().Log.Debug("SimpleFS: Reading at %d", offset) 83 84 content, err := cli.SimpleFSRead(ctx, keybase1.SimpleFSReadArg{ 85 OpID: opid, 86 Offset: offset, 87 Size: c.bufSize, 88 }) 89 if err != nil { 90 return err 91 } 92 c.G().Log.Debug("SimpleFS: Read %d", len(content.Data)) 93 94 if len(content.Data) > 0 { 95 offset += int64(len(content.Data)) 96 c.output(content.Data) 97 } else { 98 break 99 } 100 } 101 102 return err 103 } 104 105 func (c *CmdSimpleFSRead) output(data []byte) { 106 ui := c.G().UI.GetTerminalUI() 107 _, _ = ui.UnescapedOutputWriter().Write(data) 108 } 109 110 // ParseArgv does nothing for this command. 111 func (c *CmdSimpleFSRead) ParseArgv(ctx *cli.Context) error { 112 nargs := len(ctx.Args()) 113 var err error 114 115 c.bufSize = ctx.Int("buffersize") 116 117 if nargs != 1 { 118 return fmt.Errorf("read requires a path argument") 119 } 120 121 // TODO: "rev" should be a real int64, need to update the 122 // `cli` library for that. 123 p, err := makeSimpleFSPathWithArchiveParams( 124 ctx.Args()[0], int64(ctx.Int("rev")), ctx.String("time"), 125 getRelTime(ctx)) 126 if err != nil { 127 return err 128 } 129 130 c.path = p 131 return nil 132 } 133 134 // GetUsage says what this command needs to operate. 135 func (c *CmdSimpleFSRead) GetUsage() libkb.Usage { 136 return libkb.Usage{ 137 Config: true, 138 KbKeyring: true, 139 API: true, 140 } 141 }