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  }