aboutsummaryrefslogtreecommitdiff
path: root/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'cmd')
-rw-r--r--cmd/ext4/ext4.go2
-rw-r--r--cmd/fscrypt/commands.go746
-rw-r--r--cmd/fscrypt/errors.go21
-rw-r--r--cmd/fscrypt/flags.go27
-rw-r--r--cmd/fscrypt/fscrypt.go159
-rw-r--r--cmd/fscrypt/status.go37
6 files changed, 514 insertions, 478 deletions
diff --git a/cmd/ext4/ext4.go b/cmd/ext4/ext4.go
index 1df1f23..440fd25 100644
--- a/cmd/ext4/ext4.go
+++ b/cmd/ext4/ext4.go
@@ -37,7 +37,7 @@ var (
ext4Usage = fmt.Sprintf("(%s | %s) [options]", mountpointArg, deviceArg)
)
-func main() { ext4Command.Run() }
+func main() { ext4Command.Run(nil) }
var ext4Command = &cmd.Command{
Title: "manage ext4 encryption feature flag",
diff --git a/cmd/fscrypt/commands.go b/cmd/fscrypt/commands.go
index 4eec1e6..bbfcf2b 100644
--- a/cmd/fscrypt/commands.go
+++ b/cmd/fscrypt/commands.go
@@ -21,14 +21,13 @@
package main
import (
- "fmt"
"log"
"os"
"github.com/pkg/errors"
- "github.com/urfave/cli"
"github.com/google/fscrypt/actions"
+ "github.com/google/fscrypt/cmd"
"github.com/google/fscrypt/metadata"
)
@@ -193,7 +192,7 @@ func selectOrCreateProtector(ctx *actions.Context) (*actions.Protector, bool, er
return protector, true, err
}
- shouldCreate, err := askQuestion("Should we create a new protector?", false)
+ shouldCreate, err := cmd.AskQuestion("Should we create a new protector?", false)
if err != nil {
return nil, false, err
}
@@ -316,423 +315,348 @@ func unlockPath(path string) error {
// Action: statusAction,
// }
-// Metadata is a collection of commands for manipulating the metadata files.
-var Metadata = cli.Command{
- Name: "metadata",
- Usage: "[ADVANCED] manipulate the policy or protector metadata",
- Description: `These commands allow a user to directly create, delete, or
- change the metadata files. It is important to note that using
- these commands, especially the destructive ones, can make files
- encrypted with fscrypt unavailable. For instance, deleting a
- policy effectively deletes all the contents of the corresponding
- directory. Some example use cases include:
-
- (1) Directly creating protectors and policies using the "create"
- subcommand. These can then be applied with "fscrypt encrypt".
-
- (2) Changing the passphrase for a passphrase protector using the
- "change-passphrase" subcommand.
-
- (3) Creating a policy protected with multiple protectors using
- the "create policy" and "add-protector-to-policy" subcommands.
-
- (4) Changing the protector protecting a policy using the
- "add-protector-to-policy" and "remove-protector-from-policy"
- subcommands.`,
- Subcommands: []cli.Command{createMetadata, destoryMetadata, changePassphrase,
- addProtectorToPolicy, removeProtectorFromPolicy, dumpMetadata},
-}
-
-var createMetadata = cli.Command{
- Name: "create",
- ArgsUsage: fmt.Sprintf("[protector | policy] %s", mountpointArg),
- Usage: "manually create new metadata on a filesystem",
- Subcommands: []cli.Command{createProtector, createPolicy},
-}
-
-var createProtector = cli.Command{
- Name: "protector",
- ArgsUsage: mountpointArg,
- Usage: "create a new protector on a filesystem",
- Description: fmt.Sprintf(`This command creates a new protector on %s
- that does not (yet) protect any policy. After creation, the user
- can use %s with "fscrypt encrypt" to protect a directory with
- this new protector. The creation process is identical to the
- first step of "fscrypt encrypt" when the user has requested to
- create a new passphrase. The user will be prompted for the
- source, name, and secret data for the new protector (when
- applicable). As with "fscrypt encrypt", these prompts can be
- disabled with the appropriate flags.`, mountpointArg,
- shortDisplay(protectorFlag)),
- Flags: []cli.Flag{sourceFlag, nameFlag, keyFileFlag, userFlag},
- Action: createProtectorAction,
-}
-
-func createProtectorAction(c *cli.Context) error {
- if c.NArg() != 1 {
- return expectedArgsErr(c, 1, false)
- }
-
- target, err := parseUserFlag(false)
- if err != nil {
- return newExitError(c, err)
- }
- mountpoint := c.Args().Get(0)
- ctx, err := actions.NewContextFromMountpoint(mountpoint, target)
- if err != nil {
- return newExitError(c, err)
- }
-
- prompt := fmt.Sprintf("Create new protector on %q", ctx.Mount.Path)
- if err := askConfirmation(prompt, true, ""); err != nil {
- return newExitError(c, err)
- }
-
- protector, err := createProtectorFromContext(ctx)
- if err != nil {
- return newExitError(c, err)
- }
- protector.Lock()
-
- fmt.Fprintf(c.App.Writer, "Protector %s created on filesystem %q.\n",
- protector.Descriptor(), ctx.Mount.Path)
- return nil
-}
-
-var createPolicy = cli.Command{
- Name: "policy",
- ArgsUsage: fmt.Sprintf("%s %s", mountpointArg, shortDisplay(protectorFlag)),
- Usage: "create a new protector on a filesystem",
- Description: fmt.Sprintf(`This command creates a new protector on %s
- that has not (yet) been applied to any directory. After
- creation, the user can use %s with "fscrypt encrypt" to encrypt
- a directory with this new policy. As all policies must be
- protected with at least one protector, this command requires
- specifying one with %s. To create a policy protected by many
- protectors, use this command and "fscrypt metadata
- add-protector-to-policy".`, mountpointArg,
- shortDisplay(policyFlag), shortDisplay(protectorFlag)),
- Flags: []cli.Flag{protectorFlag, keyFileFlag},
- Action: createPolicyAction,
-}
-
-func createPolicyAction(c *cli.Context) error {
- if c.NArg() != 1 {
- return expectedArgsErr(c, 1, false)
- }
-
- ctx, err := actions.NewContextFromMountpoint(c.Args().Get(0), nil)
- if err != nil {
- return newExitError(c, err)
- }
-
- if err := checkRequiredFlags(c, []*stringFlag{protectorFlag}); err != nil {
- return err
- }
- protector, err := getProtectorFromFlag(protectorFlag.Value, ctx.TargetUser)
- if err != nil {
- return newExitError(c, err)
- }
- if err := protector.Unlock(existingKeyFn); err != nil {
- return newExitError(c, err)
- }
- defer protector.Lock()
-
- prompt := fmt.Sprintf("Create new policy on %q", ctx.Mount.Path)
- if err := askConfirmation(prompt, true, ""); err != nil {
- return newExitError(c, err)
- }
-
- policy, err := actions.CreatePolicy(ctx, protector)
- if err != nil {
- return newExitError(c, err)
- }
- policy.Lock()
-
- fmt.Fprintf(c.App.Writer, "Policy %s created on filesystem %q.\n",
- policy.Descriptor(), ctx.Mount.Path)
- return nil
-}
-
-var destoryMetadata = cli.Command{
- Name: "destroy",
- ArgsUsage: fmt.Sprintf("[%s | %s | %s]", shortDisplay(protectorFlag),
- shortDisplay(policyFlag), mountpointArg),
- Usage: "delete a filesystem's, protector's, or policy's metadata",
- Description: fmt.Sprintf(`This command can be used to perform three
- different destructive operations. Note that in all of these
- cases, data will usually be lost, so use with care.
-
- (1) If used with %[1]s, this command deletes all the data
- associated with that protector. This means all directories
- protected with that protector will become PERMANENTLY
- inaccessible (unless the policies were protected by multiple
- protectors).
-
- (2) If used with %[2]s, this command deletes all the data
- associated with that policy. This means all directories (usually
- just one) using this policy will become PERMANENTLY
- inaccessible.
-
- (3) If used with %[3]s, all the metadata on that filesystem will
- be deleted, causing all directories on that filesystem using
- fscrypt to become PERMANENTLY inaccessible. To start using this
- directory again, "fscrypt setup %[3]s" will need to be rerun.`,
- shortDisplay(protectorFlag), shortDisplay(policyFlag),
- mountpointArg),
- Flags: []cli.Flag{protectorFlag, policyFlag, forceFlag},
- Action: destoryMetadataAction,
-}
-
-func destoryMetadataAction(c *cli.Context) error {
- switch c.NArg() {
- case 0:
- switch {
- case protectorFlag.Value != "":
- // Case (1) - protector destroy
- protector, err := getProtectorFromFlag(protectorFlag.Value, nil)
- if err != nil {
- return newExitError(c, err)
- }
-
- prompt := fmt.Sprintf("Destroy protector %s on %q?",
- protector.Descriptor(), protector.Context.Mount.Path)
- warning := "All files protected only with this protector will be lost!!"
- if err := askConfirmation(prompt, false, warning); err != nil {
- return newExitError(c, err)
- }
- if err := protector.Destroy(); err != nil {
- return newExitError(c, err)
- }
-
- fmt.Fprintf(c.App.Writer, "Protector %s deleted from filesystem %q.\n",
- protector.Descriptor(), protector.Context.Mount.Path)
- case policyFlag.Value != "":
- // Case (2) - policy destroy
- policy, err := getPolicyFromFlag(policyFlag.Value, nil)
- if err != nil {
- return newExitError(c, err)
- }
-
- prompt := fmt.Sprintf("Destroy policy %s on %q?",
- policy.Descriptor(), policy.Context.Mount.Path)
- warning := "All files using this policy will be lost!!"
- if err := askConfirmation(prompt, false, warning); err != nil {
- return newExitError(c, err)
- }
- if err := policy.Destroy(); err != nil {
- return newExitError(c, err)
- }
-
- fmt.Fprintf(c.App.Writer, "Policy %s deleted from filesystem %q.\n",
- policy.Descriptor(), policy.Context.Mount.Path)
- default:
- message := fmt.Sprintf("Must specify one of: %s, %s, or %s",
- mountpointArg,
- shortDisplay(protectorFlag),
- shortDisplay(policyFlag))
- return &usageError{c, message}
- }
- case 1:
- // Case (3) - mountpoint destroy
- path := c.Args().Get(0)
- ctx, err := actions.NewContextFromMountpoint(path, nil)
- if err != nil {
- return newExitError(c, err)
- }
-
- prompt := fmt.Sprintf("Destroy all the metadata on %q?", ctx.Mount.Path)
- warning := "All the encrypted files on this filesystem will be lost!!"
- if err := askConfirmation(prompt, false, warning); err != nil {
- return newExitError(c, err)
- }
- if err := ctx.Mount.RemoveAllMetadata(); err != nil {
- return newExitError(c, err)
- }
-
- fmt.Fprintf(c.App.Writer, "All metadata on %q deleted.\n", ctx.Mount.Path)
- default:
- return expectedArgsErr(c, 1, true)
- }
- return nil
-}
-
-var changePassphrase = cli.Command{
- Name: "change-passphrase",
- ArgsUsage: shortDisplay(protectorFlag),
- Usage: "change the passphrase used for a protector",
- Description: `This command takes a specified passphrase protector and
- changes the corresponding passphrase. Note that this does not
- create or destroy any protectors.`,
- Flags: []cli.Flag{protectorFlag},
- Action: changePassphraseAction,
-}
-
-func changePassphraseAction(c *cli.Context) error {
- if c.NArg() != 0 {
- return expectedArgsErr(c, 0, false)
- }
- if err := checkRequiredFlags(c, []*stringFlag{protectorFlag}); err != nil {
- return err
- }
-
- protector, err := getProtectorFromFlag(protectorFlag.Value, nil)
- if err != nil {
- return newExitError(c, err)
- }
- if err := protector.Unlock(oldExistingKeyFn); err != nil {
- return newExitError(c, err)
- }
- defer protector.Lock()
- if err := protector.Rewrap(newCreateKeyFn); err != nil {
- return newExitError(c, err)
- }
-
- fmt.Fprintf(c.App.Writer, "Passphrase for protector %s successfully changed.\n",
- protector.Descriptor())
- return nil
-}
-
-var addProtectorToPolicy = cli.Command{
- Name: "add-protector-to-policy",
- ArgsUsage: fmt.Sprintf("%s %s", shortDisplay(protectorFlag), shortDisplay(policyFlag)),
- Usage: "start protecting a policy with some protector",
- Description: `This command changes the specified policy to be
- protected with the specified protector. This means that any
- directories using this policy will now be accessible with this
- protector. This command will fail if the policy is already
- protected with this protector.`,
- Flags: []cli.Flag{protectorFlag, policyFlag, unlockWithFlag, keyFileFlag},
- Action: addProtectorAction,
-}
-
-func addProtectorAction(c *cli.Context) error {
- if c.NArg() != 0 {
- return expectedArgsErr(c, 0, false)
- }
- if err := checkRequiredFlags(c, []*stringFlag{protectorFlag, policyFlag}); err != nil {
- return err
- }
+// var Metadata = cli.Command{
+// Name: "metadata",
+// Usage: "[ADVANCED] manipulate the policy or protector metadata",
+// Description: `These commands allow a user to directly create, delete, or
+// change the metadata files. It is important to note that using
+// these commands, especially the destructive ones, can make files
+// encrypted with fscrypt unavailable. For instance, deleting a
+// policy effectively deletes all the contents of the corresponding
+// directory. Some example use cases include:
+
+// (1) Directly creating protectors and policies using the "create"
+// subcommand. These can then be applied with "fscrypt encrypt".
+
+// (2) Changing the passphrase for a passphrase protector using the
+// "change-passphrase" subcommand.
+
+// (3) Creating a policy protected with multiple protectors using
+// the "create policy" and "add-protector-to-policy" subcommands.
+
+// (4) Changing the protector protecting a policy using the
+// "add-protector-to-policy" and "remove-protector-from-policy"
+// subcommands.`,
+// Subcommands: []cli.Command{createMetadata, destoryMetadata, changePassphrase,
+// addProtectorToPolicy, removeProtectorFromPolicy, dumpMetadata},
+// }
- protector, err := getProtectorFromFlag(protectorFlag.Value, nil)
- if err != nil {
- return newExitError(c, err)
- }
- policy, err := getPolicyFromFlag(policyFlag.Value, protector.Context.TargetUser)
- if err != nil {
- return newExitError(c, err)
- }
- // Sanity check before unlocking everything
- if err := policy.AddProtector(protector); errors.Cause(err) != actions.ErrLocked {
- return newExitError(c, err)
- }
+// var createProtector = cli.Command{
+// Name: "protector",
+// ArgsUsage: mountpointArg,
+// Usage: "create a new protector on a filesystem",
+// Description: fmt.Sprintf(`This command creates a new protector on %s
+// that does not (yet) protect any policy. After creation, the user
+// can use %s with "fscrypt encrypt" to protect a directory with
+// this new protector. The creation process is identical to the
+// first step of "fscrypt encrypt" when the user has requested to
+// create a new passphrase. The user will be prompted for the
+// source, name, and secret data for the new protector (when
+// applicable). As with "fscrypt encrypt", these prompts can be
+// disabled with the appropriate flags.`, mountpointArg,
+// shortDisplay(protectorFlag)),
+// Flags: []cli.Flag{sourceFlag, nameFlag, keyFileFlag, userFlag},
+// Action: createProtectorAction,
+// }
- prompt := fmt.Sprintf("Protect policy %s with protector %s?",
- policy.Descriptor(), protector.Descriptor())
- warning := "All files using this policy will be accessible with this protector!!"
- if err := askConfirmation(prompt, true, warning); err != nil {
- return newExitError(c, err)
- }
+// var createPolicy = cli.Command{
+// Name: "policy",
+// ArgsUsage: fmt.Sprintf("%s %s", mountpointArg, shortDisplay(protectorFlag)),
+// Usage: "create a new protector on a filesystem",
+// Description: fmt.Sprintf(`This command creates a new protector on %s
+// that has not (yet) been applied to any directory. After
+// creation, the user can use %s with "fscrypt encrypt" to encrypt
+// a directory with this new policy. As all policies must be
+// protected with at least one protector, this command requires
+// specifying one with %s. To create a policy protected by many
+// protectors, use this command and "fscrypt metadata
+// add-protector-to-policy".`, mountpointArg,
+// shortDisplay(policyFlag), shortDisplay(protectorFlag)),
+// Flags: []cli.Flag{protectorFlag, keyFileFlag},
+// Action: createPolicyAction,
+// }
- if err := protector.Unlock(existingKeyFn); err != nil {
- return newExitError(c, err)
- }
- if err := policy.Unlock(optionFn, existingKeyFn); err != nil {
- return newExitError(c, err)
- }
- if err := policy.AddProtector(protector); err != nil {
- return newExitError(c, err)
- }
+//// ***** WIP END/BEGIN HERE *****
+
+// var destoryMetadata = cli.Command{
+// Name: "destroy",
+// ArgsUsage: fmt.Sprintf("[%s | %s | %s]", shortDisplay(protectorFlag),
+// shortDisplay(policyFlag), mountpointArg),
+// Usage: "delete a filesystem's, protector's, or policy's metadata",
+// Description: fmt.Sprintf(`This command can be used to perform three
+// different destructive operations. Note that in all of these
+// cases, data will usually be lost, so use with care.
+
+// (1) If used with %[1]s, this command deletes all the data
+// associated with that protector. This means all directories
+// protected with that protector will become PERMANENTLY
+// inaccessible (unless the policies were protected by multiple
+// protectors).
+
+// (2) If used with %[2]s, this command deletes all the data
+// associated with that policy. This means all directories (usually
+// just one) using this policy will become PERMANENTLY
+// inaccessible.
+
+// (3) If used with %[3]s, all the metadata on that filesystem will
+// be deleted, causing all directories on that filesystem using
+// fscrypt to become PERMANENTLY inaccessible. To start using this
+// directory again, "fscrypt setup %[3]s" will need to be rerun.`,
+// shortDisplay(protectorFlag), shortDisplay(policyFlag),
+// mountpointArg),
+// Flags: []cli.Flag{protectorFlag, policyFlag, forceFlag},
+// Action: destoryMetadataAction,
+// }
- fmt.Fprintf(c.App.Writer, "Protector %s now protecting policy %s.\n",
- protector.Descriptor(), policy.Descriptor())
- return nil
-}
+// func destoryMetadataAction(c *cli.Context) error {
+// switch c.NArg() {
+// case 0:
+// switch {
+// case protectorFlag.Value != "":
+// // Case (1) - protector destroy
+// protector, err := getProtectorFromFlag(protectorFlag.Value, nil)
+// if err != nil {
+// return newExitError(c, err)
+// }
+
+// prompt := fmt.Sprintf("Destroy protector %s on %q?",
+// protector.Descriptor(), protector.Context.Mount.Path)
+// warning := "All files protected only with this protector will be lost!!"
+// if err := askConfirmation(prompt, false, warning); err != nil {
+// return newExitError(c, err)
+// }
+// if err := protector.Destroy(); err != nil {
+// return newExitError(c, err)
+// }
+
+// fmt.Fprintf(c.App.Writer, "Protector %s deleted from filesystem %q.\n",
+// protector.Descriptor(), protector.Context.Mount.Path)
+// case policyFlag.Value != "":
+// // Case (2) - policy destroy
+// policy, err := getPolicyFromFlag(policyFlag.Value, nil)
+// if err != nil {
+// return newExitError(c, err)
+// }
+
+// prompt := fmt.Sprintf("Destroy policy %s on %q?",
+// policy.Descriptor(), policy.Context.Mount.Path)
+// warning := "All files using this policy will be lost!!"
+// if err := askConfirmation(prompt, false, warning); err != nil {
+// return newExitError(c, err)
+// }
+// if err := policy.Destroy(); err != nil {
+// return newExitError(c, err)
+// }
+
+// fmt.Fprintf(c.App.Writer, "Policy %s deleted from filesystem %q.\n",
+// policy.Descriptor(), policy.Context.Mount.Path)
+// default:
+// message := fmt.Sprintf("Must specify one of: %s, %s, or %s",
+// mountpointArg,
+// shortDisplay(protectorFlag),
+// shortDisplay(policyFlag))
+// return &usageError{c, message}
+// }
+// case 1:
+// // Case (3) - mountpoint destroy
+// path := c.Args().Get(0)
+// ctx, err := actions.NewContextFromMountpoint(path, nil)
+// if err != nil {
+// return newExitError(c, err)
+// }
+
+// prompt := fmt.Sprintf("Destroy all the metadata on %q?", ctx.Mount.Path)
+// warning := "All the encrypted files on this filesystem will be lost!!"
+// if err := askConfirmation(prompt, false, warning); err != nil {
+// return newExitError(c, err)
+// }
+// if err := ctx.Mount.RemoveAllMetadata(); err != nil {
+// return newExitError(c, err)
+// }
+
+// fmt.Fprintf(c.App.Writer, "All metadata on %q deleted.\n", ctx.Mount.Path)
+// default:
+// return expectedArgsErr(c, 1, true)
+// }
+// return nil
+// }
-var removeProtectorFromPolicy = cli.Command{
- Name: "remove-protector-from-policy",
- ArgsUsage: fmt.Sprintf("%s %s", shortDisplay(protectorFlag), shortDisplay(policyFlag)),
- Usage: "stop protecting a policy with some protector",
- Description: `This command changes the specified policy to no longer be
- protected with the specified protector. This means that any
- directories using this policy will cannot be accessed with this
- protector. This command will fail if the policy not already
- protected with this protector or if it is the policy's only
- protector.`,
- Flags: []cli.Flag{protectorFlag, policyFlag, forceFlag},
- Action: removeProtectorAction,
-}
+// var changePassphrase = cli.Command{
+// Name: "change-passphrase",
+// ArgsUsage: shortDisplay(protectorFlag),
+// Usage: "change the passphrase used for a protector",
+// Description: `This command takes a specified passphrase protector and
+// changes the corresponding passphrase. Note that this does not
+// create or destroy any protectors.`,
+// Flags: []cli.Flag{protectorFlag},
+// Action: changePassphraseAction,
+// }
-func removeProtectorAction(c *cli.Context) error {
- if c.NArg() != 0 {
- return expectedArgsErr(c, 0, false)
- }
- if err := checkRequiredFlags(c, []*stringFlag{protectorFlag, policyFlag}); err != nil {
- return err
- }
+// func changePassphraseAction(c *cli.Context) error {
+// if c.NArg() != 0 {
+// return expectedArgsErr(c, 0, false)
+// }
+// if err := checkRequiredFlags(c, []*stringFlag{protectorFlag}); err != nil {
+// return err
+// }
+
+// protector, err := getProtectorFromFlag(protectorFlag.Value, nil)
+// if err != nil {
+// return newExitError(c, err)
+// }
+// if err := protector.Unlock(oldExistingKeyFn); err != nil {
+// return newExitError(c, err)
+// }
+// defer protector.Lock()
+// if err := protector.Rewrap(newCreateKeyFn); err != nil {
+// return newExitError(c, err)
+// }
+
+// fmt.Fprintf(c.App.Writer, "Passphrase for protector %s successfully changed.\n",
+// protector.Descriptor())
+// return nil
+// }
- // We do not need to unlock anything for this operation
- protector, err := getProtectorFromFlag(protectorFlag.Value, nil)
- if err != nil {
- return newExitError(c, err)
- }
- policy, err := getPolicyFromFlag(policyFlag.Value, protector.Context.TargetUser)
- if err != nil {
- return newExitError(c, err)
- }
+// var addProtectorToPolicy = cli.Command{
+// Name: "add-protector-to-policy",
+// ArgsUsage: fmt.Sprintf("%s %s", shortDisplay(protectorFlag), shortDisplay(policyFlag)),
+// Usage: "start protecting a policy with some protector",
+// Description: `This command changes the specified policy to be
+// protected with the specified protector. This means that any
+// directories using this policy will now be accessible with this
+// protector. This command will fail if the policy is already
+// protected with this protector.`,
+// Flags: []cli.Flag{protectorFlag, policyFlag, unlockWithFlag, keyFileFlag},
+// Action: addProtectorAction,
+// }
- prompt := fmt.Sprintf("Stop protecting policy %s with protector %s?",
- policy.Descriptor(), protector.Descriptor())
- warning := "All files using this policy will NO LONGER be accessible with this protector!!"
- if err := askConfirmation(prompt, false, warning); err != nil {
- return newExitError(c, err)
- }
+// func addProtectorAction(c *cli.Context) error {
+// if c.NArg() != 0 {
+// return expectedArgsErr(c, 0, false)
+// }
+// if err := checkRequiredFlags(c, []*stringFlag{protectorFlag, policyFlag}); err != nil {
+// return err
+// }
+
+// protector, err := getProtectorFromFlag(protectorFlag.Value, nil)
+// if err != nil {
+// return newExitError(c, err)
+// }
+// policy, err := getPolicyFromFlag(policyFlag.Value, protector.Context.TargetUser)
+// if err != nil {
+// return newExitError(c, err)
+// }
+// // Sanity check before unlocking everything
+// if err := policy.AddProtector(protector); errors.Cause(err) != actions.ErrLocked {
+// return newExitError(c, err)
+// }
+
+// prompt := fmt.Sprintf("Protect policy %s with protector %s?",
+// policy.Descriptor(), protector.Descriptor())
+// warning := "All files using this policy will be accessible with this protector!!"
+// if err := askConfirmation(prompt, true, warning); err != nil {
+// return newExitError(c, err)
+// }
+
+// if err := protector.Unlock(existingKeyFn); err != nil {
+// return newExitError(c, err)
+// }
+// if err := policy.Unlock(optionFn, existingKeyFn); err != nil {
+// return newExitError(c, err)
+// }
+// if err := policy.AddProtector(protector); err != nil {
+// return newExitError(c, err)
+// }
+
+// fmt.Fprintf(c.App.Writer, "Protector %s now protecting policy %s.\n",
+// protector.Descriptor(), policy.Descriptor())
+// return nil
+// }
- if err := policy.RemoveProtector(protector); err != nil {
- return newExitError(c, err)
- }
+// var removeProtectorFromPolicy = cli.Command{
+// Name: "remove-protector-from-policy",
+// ArgsUsage: fmt.Sprintf("%s %s", shortDisplay(protectorFlag), shortDisplay(policyFlag)),
+// Usage: "stop protecting a policy with some protector",
+// Description: `This command changes the specified policy to no longer be
+// protected with the specified protector. This means that any
+// directories using this policy will cannot be accessed with this
+// protector. This command will fail if the policy not already
+// protected with this protector or if it is the policy's only
+// protector.`,
+// Flags: []cli.Flag{protectorFlag, policyFlag, forceFlag},
+// Action: removeProtectorAction,
+// }
- fmt.Fprintf(c.App.Writer, "Protector %s no longer protecting policy %s.\n",
- protector.Descriptor(), policy.Descriptor())
- return nil
-}
+// func removeProtectorAction(c *cli.Context) error {
+// if c.NArg() != 0 {
+// return expectedArgsErr(c, 0, false)
+// }
+// if err := checkRequiredFlags(c, []*stringFlag{protectorFlag, policyFlag}); err != nil {
+// return err
+// }
+
+// // We do not need to unlock anything for this operation
+// protector, err := getProtectorFromFlag(protectorFlag.Value, nil)
+// if err != nil {
+// return newExitError(c, err)
+// }
+// policy, err := getPolicyFromFlag(policyFlag.Value, protector.Context.TargetUser)
+// if err != nil {
+// return newExitError(c, err)
+// }
+
+// prompt := fmt.Sprintf("Stop protecting policy %s with protector %s?",
+// policy.Descriptor(), protector.Descriptor())
+// warning := "All files using this policy will NO LONGER be accessible with this protector!!"
+// if err := askConfirmation(prompt, false, warning); err != nil {
+// return newExitError(c, err)
+// }
+
+// if err := policy.RemoveProtector(protector); err != nil {
+// return newExitError(c, err)
+// }
+
+// fmt.Fprintf(c.App.Writer, "Protector %s no longer protecting policy %s.\n",
+// protector.Descriptor(), policy.Descriptor())
+// return nil
+// }
-var dumpMetadata = cli.Command{
- Name: "dump",
- ArgsUsage: fmt.Sprintf("[%s | %s]", shortDisplay(protectorFlag), shortDisplay(policyFlag)),
- Usage: "print debug data for a policy or protector",
- Description: fmt.Sprintf(`This commands dumps all of the debug data for
- a protector (if %s is used) or policy (if %s is used). This data
- includes the data pulled from the %q config file, the
- appropriate mountpoint data, and any options for the policy or
- hashing costs for the protector. Any cryptographic keys are
- wiped and are not printed out.`, shortDisplay(protectorFlag),
- shortDisplay(policyFlag), actions.ConfigFileLocation),
- Flags: []cli.Flag{protectorFlag, policyFlag},
- Action: dumpMetadataAction,
-}
+// var dumpMetadata = cli.Command{
+// Name: "dump",
+// ArgsUsage: fmt.Sprintf("[%s | %s]", shortDisplay(protectorFlag), shortDisplay(policyFlag)),
+// Usage: "print debug data for a policy or protector",
+// Description: fmt.Sprintf(`This commands dumps all of the debug data for
+// a protector (if %s is used) or policy (if %s is used). This data
+// includes the data pulled from the %q config file, the
+// appropriate mountpoint data, and any options for the policy or
+// hashing costs for the protector. Any cryptographic keys are
+// wiped and are not printed out.`, shortDisplay(protectorFlag),
+// shortDisplay(policyFlag), actions.ConfigFileLocation),
+// Flags: []cli.Flag{protectorFlag, policyFlag},
+// Action: dumpMetadataAction,
+// }
-func dumpMetadataAction(c *cli.Context) error {
- switch {
- case protectorFlag.Value != "":
- // Case (1) - protector print
- protector, err := getProtectorFromFlag(protectorFlag.Value, nil)
- if err != nil {
- return newExitError(c, err)
- }
- fmt.Fprintln(c.App.Writer, protector)
- case policyFlag.Value != "":
- // Case (2) - policy print
- policy, err := getPolicyFromFlag(policyFlag.Value, nil)
- if err != nil {
- return newExitError(c, err)
- }
- fmt.Fprintln(c.App.Writer, policy)
- default:
- message := fmt.Sprintf("Must specify one of: %s or %s",
- shortDisplay(protectorFlag),
- shortDisplay(policyFlag))
- return &usageError{c, message}
- }
- return nil
-}
+// func dumpMetadataAction(c *cli.Context) error {
+// switch {
+// case protectorFlag.Value != "":
+// // Case (1) - protector print
+// protector, err := getProtectorFromFlag(protectorFlag.Value, nil)
+// if err != nil {
+// return newExitError(c, err)
+// }
+// fmt.Fprintln(c.App.Writer, protector)
+// case policyFlag.Value != "":
+// // Case (2) - policy print
+// policy, err := getPolicyFromFlag(policyFlag.Value, nil)
+// if err != nil {
+// return newExitError(c, err)
+// }
+// fmt.Fprintln(c.App.Writer, policy)
+// default:
+// message := fmt.Sprintf("Must specify one of: %s or %s",
+// shortDisplay(protectorFlag),
+// shortDisplay(policyFlag))
+// return &usageError{c, message}
+// }
+// return nil
+// }
diff --git a/cmd/fscrypt/errors.go b/cmd/fscrypt/errors.go
index 1c7ee75..4489fe5 100644
--- a/cmd/fscrypt/errors.go
+++ b/cmd/fscrypt/errors.go
@@ -27,6 +27,7 @@ import (
"github.com/pkg/errors"
"github.com/google/fscrypt/actions"
+ "github.com/google/fscrypt/cmd"
"github.com/google/fscrypt/crypto"
"github.com/google/fscrypt/filesystem"
"github.com/google/fscrypt/metadata"
@@ -56,7 +57,7 @@ var (
ErrSpecifyUser = errors.New("user must be specified when run as root")
)
-var loadHelpText = fmt.Sprintf("You may need to mount a linked filesystem. Run with %s for more information.", shortDisplay(verboseFlag))
+var loadHelpText = fmt.Sprintf("You may need to mount a linked filesystem. Run with %s for more information.", cmd.VerboseFlag)
var fscryptHelpTextMap = map[error]string{
actions.ErrBadConfigFile: `Run "sudo fscrypt setup" to recreate the file.`,
@@ -67,7 +68,7 @@ var fscryptHelpTextMap = map[error]string{
func getErrorSuggestions(err error) string {
switch errors.Cause(err) {
case filesystem.ErrNotSetup:
- return fmt.Sprintf(`Run "fscrypt setup %s" to use fscrypt on this filesystem.`, mountpointArg)
+ return fmt.Sprintf(`Run "fscrypt setup %s" to use fscrypt on this filesystem.`, unusedMountpointArg)
case crypto.ErrKeyLock:
return `Too much memory was requested to be locked in RAM. The
current limit for this user can be checked with "ulimit
@@ -89,7 +90,7 @@ func getErrorSuggestions(err error) string {
case security.ErrAccessUserKeyring:
return fmt.Sprintf(`You can only use %s to access the user
keyring of another user if you are running as root.`,
- shortDisplay(userFlag))
+ userFlag)
case actions.ErrNoConfigFile:
return `Run "sudo fscrypt setup" to create the file.`
case actions.ErrMissingPolicyMetadata:
@@ -101,13 +102,13 @@ func getErrorSuggestions(err error) string {
inconsistent state. This most likely means the filesystem
metadata is corrupted.`
case actions.ErrMissingProtectorName:
- return fmt.Sprintf("Use %s to specify a protector name.", shortDisplay(nameFlag))
- case ErrNoDesctructiveOps:
- return fmt.Sprintf("Use %s to automatically run destructive operations.", shortDisplay(forceFlag))
+ return fmt.Sprintf("Use %s to specify a protector name.", nameFlag)
+ case cmd.ErrMustForce:
+ return fmt.Sprintf("Use %s to automatically run destructive operations.", cmd.ForceFlag)
case ErrSpecifyProtector:
- return fmt.Sprintf("Use %s to specify a protector.", shortDisplay(protectorFlag))
+ return fmt.Sprintf("Use %s to specify a protector.", protectorFlag)
case ErrSpecifyKeyFile:
- return fmt.Sprintf("Use %s to specify a key file.", shortDisplay(keyFileFlag))
+ return fmt.Sprintf("Use %s to specify a key file.", keyFileFlag)
case ErrBadOwners:
return `Encryption can only be setup on directories you own,
even if you have write permission for the directory.`
@@ -120,7 +121,7 @@ func getErrorSuggestions(err error) string {
return fmt.Sprintf(`Either this command should be run as root to
properly clear the inode cache, or it should be run with
%s=false (this may leave encrypted files and directories
- in an accessible state).`, shortDisplay(dropCachesFlag))
+ in an accessible state).`, dropCachesFlag)
case ErrSpecifyUser:
return fmt.Sprintf(`When running this command as root, you
usually still want to provision/remove keys for a normal
@@ -128,7 +129,7 @@ func getErrorSuggestions(err error) string {
as a protector (so the corresponding files will be
accessible for that user). This can be done with %s. To
use the root user's keyring or passphrase, use
- --%s=root.`, shortDisplay(userFlag), userFlag.GetName())
+ --%s=root.`, userFlag, userFlag.Name)
case ErrAllLoadsFailed:
return loadHelpText
default:
diff --git a/cmd/fscrypt/flags.go b/cmd/fscrypt/flags.go
index 2bf7f73..5983053 100644
--- a/cmd/fscrypt/flags.go
+++ b/cmd/fscrypt/flags.go
@@ -100,16 +100,17 @@ var (
Usage: `Specifiy which user should be used for login passphrases
or to which user's keyring keys should be provisioned.`,
}
- protectorFlag = &cmd.StringFlag{
+ mountpointIDArg = "MOUNTPOINT:ID"
+ protectorFlag = &cmd.StringFlag{
Name: "protector",
- ArgName: "MOUNTPOINT:ID",
+ ArgName: mountpointIDArg,
Usage: `Specify an existing protector on filesystem MOUNTPOINT
with protector descriptor ID which should be used in the
command.`,
}
unlockWithFlag = &cmd.StringFlag{
Name: "unlock-with",
- ArgName: "MOUNTPOINT:ID",
+ ArgName: mountpointIDArg,
Usage: `Specify an existing protector on filesystem MOUNTPOINT
with protector descriptor ID which should be used to
unlock a policy (usually specified with --policy). This
@@ -119,7 +120,7 @@ var (
}
policyFlag = &cmd.StringFlag{
Name: "policy",
- ArgName: "MOUNTPOINT:ID",
+ ArgName: mountpointIDArg,
Usage: `Specify an existing policy on filesystem MOUNTPOINT with
key descriptor ID which should be used in the command.`,
}
@@ -175,19 +176,21 @@ func getPolicyFromFlag(flagValue string, target *user.User) (*actions.Policy, er
// there are no problems accessing the user keyring.
func parseUserFlag(checkKeyring bool) (targetUser *user.User, err error) {
if userFlag.Value != "" {
- targetUser, err = user.Lookup(userFlag.Value)
+ if targetUser, err = user.Lookup(userFlag.Value); err != nil {
+ return nil, err
+ }
} else {
- if util.IsUserRoot() {
+ targetID := util.CurrentUserID()
+ if targetID == 0 {
return nil, ErrSpecifyUser
}
- targetUser, err = util.EffectiveUser()
- }
- if err != nil {
- return nil, err
+ targetUser = util.GetUser(targetID)
}
if checkKeyring {
- _, err = security.UserKeyringID(targetUser, true)
+ if _, err = security.UserKeyringID(targetUser, true); err != nil {
+ return nil, err
+ }
}
- return targetUser, err
+ return targetUser, nil
}
diff --git a/cmd/fscrypt/fscrypt.go b/cmd/fscrypt/fscrypt.go
index 65da7cb..4348567 100644
--- a/cmd/fscrypt/fscrypt.go
+++ b/cmd/fscrypt/fscrypt.go
@@ -39,24 +39,26 @@ import (
// Arguments used in fscrypt commands.
var (
unusedMountpointArg = &cmd.Argument{
- Name: "mountpoint",
- Usage: "path to a mountpoint on which to setup fscrypt",
+ ArgName: "mountpoint",
+ Usage: "path to a mountpoint on which to setup fscrypt",
}
usedMountpointArg = &cmd.Argument{
- Name: "mountpoint",
- Usage: "path to a mountpoint being used with fscrypt",
+ ArgName: "mountpoint",
+ Usage: "path to a mountpoint being used with fscrypt",
}
directoryToEncryptArg = &cmd.Argument{
- Name: "directory",
- Usage: "path to an empty directory to encrypt with fscrypt",
+ ArgName: "directory",
+ Usage: "path to an empty directory to encrypt with fscrypt",
}
encryptedPathArg = &cmd.Argument{
- Name: "path",
- Usage: "file or directory encrypted with fscrypt",
+ ArgName: "path",
+ Usage: "file or directory encrypted with fscrypt",
}
)
-func main() { fscryptCommand.Run() }
+func main() { fscryptCommand.Run(fscryptHelpTextMap) }
+
+var baseFlags = []cmd.Flag{cmd.VerboseFlag, cmd.QuietFlag, cmd.HelpFlag}
var fscryptCommand = cmd.Command{
Title: "manage linux filesystem encryption",
@@ -65,16 +67,9 @@ var fscryptCommand = cmd.Command{
cmd.VerboseFlag, cmd.QuietFlag),
cmd.VersionUsage,
},
- SubCommands: []*Command{
- setupCommand,
- encryptCommand,
- unlockCommand,
- purgeCommand,
- // statusCommand,
- // metadataCommand,
- cmd.VersionCommand,
- },
- Flags: []cmd.Flag{cmd.VerboseFlag, cmd.QuietFlag, cmd.HelpFlag},
+ SubCommands: []*cmd.Command{setupCommand, encryptCommand, unlockCommand,
+ purgeCommand, statusCommand, metadataCommand, cmd.VersionCommand},
+ Flags: baseFlags,
ManPage: &cmd.ManPage{Name: "fscrypt", Section: 8},
}
@@ -88,7 +83,7 @@ var setupCommand = &cmd.Command{
},
Arguments: []*cmd.Argument{unusedMountpointArg},
InheritFlags: true,
- Flags: []cmd.Flag{configFileFlag, targetFlag, legacyFlag, cmd.ForceFlag},
+ Flags: []cmd.Flag{timeTargetFlag, legacyFlag, cmd.ForceFlag},
ManPage: &cmd.ManPage{Name: "fscrypt-setup", Section: 8},
Action: setupAction,
}
@@ -97,7 +92,7 @@ func setupAction(c *cmd.Context) error {
switch len(c.Args) {
case 0:
// Case (1) - global setup
- return createGlobalConfig(configFileFlag.Value)
+ return createGlobalConfig(actions.ConfigFileLocation)
case 1:
// Case (2) - filesystem setup
return setupFilesystem(c.Args[0])
@@ -110,7 +105,7 @@ func setupAction(c *cmd.Context) error {
var encryptCommand = &cmd.Command{
Name: "encrypt",
Title: "start encrypting an empty directory",
- UsageLines: nil, // TODO(joerichey)
+ UsageLines: []string{"???"}, // TODO(joerichey)
Arguments: []*cmd.Argument{directoryToEncryptArg},
InheritFlags: true,
Flags: []cmd.Flag{sourceFlag, nameFlag, protectorFlag, policyFlag,
@@ -143,7 +138,7 @@ func encryptAction(c *cmd.Context) error {
var unlockCommand = &cmd.Command{
Name: "unlock",
Title: "unlock an encrypted file or directory",
- UsageLines: nil, // TODO(joerichey)
+ UsageLines: []string{"???"}, // TODO(joerichey)
Arguments: []*cmd.Argument{encryptedPathArg},
InheritFlags: true,
Flags: []cmd.Flag{protectorFlag, policyFlag, keyFileFlag, userFlag},
@@ -192,7 +187,7 @@ func purgeAction(c *cmd.Context) error {
if err != nil {
return err
}
- ctx, err := actions.NewContextFromMountpoint(c.Args[0], target)
+ ctx, err := actions.NewContextFromMountpoint(c.Args[0], targetUser)
if err != nil {
return err
}
@@ -211,7 +206,7 @@ func purgeAction(c *cmd.Context) error {
fmt.Fprintf(cmd.Output, "Policies purged from filesystem %q.\n", ctx.Mount.Path)
if !dropCachesFlag.Value {
- fmt.Fprintf(cmd.Output, "Filesystem %q should now be unmounted.\n", cmd.Mount.Path)
+ fmt.Fprintf(cmd.Output, "Filesystem %q should now be unmounted.\n", ctx.Mount.Path)
return nil
}
if err = security.DropFilesystemCache(); err != nil {
@@ -251,6 +246,118 @@ func statusAction(c *cmd.Context) error {
return mntErr
}
default:
- return expectedArgsErr(c, 1, true)
+ return cmd.CheckExpectedArgs(c, 1, true)
+ }
+}
+
+// metadata is a collection of commands for manipulating the metadata files.
+var metadataCommand = &cmd.Command{
+ Name: "metadata",
+ Title: "manipulate fscrypt metadata directly",
+ UsageLines: []string{fmt.Sprintf("<command> [command options] [%s] [%s]",
+ protectorFlag, policyFlag)},
+ SubCommands: []*cmd.Command{createCommand}, // destroyCommand, changeCommand,
+ // addProtectorCommand, removeProtectorCommand, dumpCommand},
+ InheritFlags: true,
+ Flags: []cmd.Flag{protectorFlag, policyFlag},
+ ManPage: &cmd.ManPage{Name: "fscrypt-metadata", Section: 8},
+}
+
+var createCommand = &cmd.Command{
+ Name: "create",
+ Title: "manually create metadata on a filesystem",
+ UsageLines: []string{
+ fmt.Sprintf("protector %s", usedMountpointArg),
+ fmt.Sprintf("policy %s, %s", usedMountpointArg, protectorFlag),
+ },
+ SubCommands: []*cmd.Command{createProtectorCommand, createPolicyCommand},
+ Arguments: []*cmd.Argument{usedMountpointArg},
+ Flags: baseFlags,
+}
+
+var createProtectorCommand = &cmd.Command{
+ Name: "protector",
+ Title: "create a protector without creating a policy",
+ UsageLines: []string{"???"}, // TODO(joerichey)
+ InheritArguments: true,
+ InheritFlags: true,
+ Flags: []cmd.Flag{sourceFlag, nameFlag, keyFileFlag, userFlag},
+ Action: createProtectorAction,
+}
+
+func createProtectorAction(c *cmd.Context) error {
+ if err := cmd.CheckExpectedArgs(c, 1, false); err != nil {
+ return err
+ }
+
+ targetUser, err := parseUserFlag(true)
+ if err != nil {
+ return err
+ }
+ ctx, err := actions.NewContextFromMountpoint(c.Args[0], targetUser)
+ if err != nil {
+ return err
+ }
+
+ prompt := fmt.Sprintf("Create new protector on %q", ctx.Mount.Path)
+ if err := cmd.AskConfirmation(prompt, "", true); err != nil {
+ return err
+ }
+
+ protector, err := createProtectorFromContext(ctx)
+ if err != nil {
+ return err
+ }
+ protector.Lock()
+
+ fmt.Fprintf(cmd.Output, "Protector %s created on filesystem %q.\n",
+ protector.Descriptor(), ctx.Mount.Path)
+ return nil
+}
+
+var createPolicyCommand = &cmd.Command{
+ Name: "policy",
+ Title: "create a policy using an existing protector",
+ UsageLines: []string{fmt.Sprintf("%s %s [%s]",
+ usedMountpointArg, protectorFlag, keyFileFlag)},
+ InheritArguments: true,
+ InheritFlags: true,
+ Flags: []cmd.Flag{protectorFlag, keyFileFlag},
+ Action: createPolicyAction,
+}
+
+func createPolicyAction(c *cmd.Context) error {
+ if err := cmd.CheckExpectedArgs(c, 1, false); err != nil {
+ return err
+ }
+ if err := cmd.CheckRequiredFlags([]*cmd.StringFlag{protectorFlag}); err != nil {
+ return err
+ }
+
+ ctx, err := actions.NewContextFromMountpoint(c.Args[0], nil)
+ if err != nil {
+ return err
+ }
+ protector, err := getProtectorFromFlag(protectorFlag.Value, ctx.TargetUser)
+ if err != nil {
+ return err
+ }
+ if err := protector.Unlock(existingKeyFn); err != nil {
+ return err
}
+ defer protector.Lock()
+
+ prompt := fmt.Sprintf("Create new policy on %q", ctx.Mount.Path)
+ if err := cmd.AskConfirmation(prompt, "", true); err != nil {
+ return err
+ }
+ policy, err := actions.CreatePolicy(ctx, protector)
+ if err != nil {
+ return err
+ }
+ policy.Lock()
+
+ fmt.Fprintf(cmd.Output, "Policy %s created on filesystem %q.\n",
+ policy.Descriptor(), ctx.Mount.Path)
+ return nil
}
diff --git a/cmd/fscrypt/status.go b/cmd/fscrypt/status.go
index 1465a4e..87799a8 100644
--- a/cmd/fscrypt/status.go
+++ b/cmd/fscrypt/status.go
@@ -30,6 +30,7 @@ import (
"github.com/pkg/errors"
"github.com/google/fscrypt/actions"
+ "github.com/google/fscrypt/cmd"
"github.com/google/fscrypt/filesystem"
"github.com/google/fscrypt/metadata"
)
@@ -66,7 +67,7 @@ func yesNoString(b bool) string {
}
// writeGlobalStatus prints all the filesystem that use (or could use) fscrypt.
-func writeGlobalStatus(w io.Writer) error {
+func writeGlobalStatus() error {
mounts, err := filesystem.AllFilesystems()
if err != nil {
return err
@@ -75,7 +76,7 @@ func writeGlobalStatus(w io.Writer) error {
supportCount := 0
useCount := 0
- t := makeTableWriter(w, "MOUNTPOINT\tDEVICE\tFILESYSTEM\tENCRYPTION\tFSCRYPT")
+ t := makeTableWriter(cmd.Output, "MOUNTPOINT\tDEVICE\tFILESYSTEM\tENCRYPTION\tFSCRYPT")
for _, mount := range mounts {
// Only print mountpoints backed by devices or using fscrypt.
usingFscrypt := mount.CheckSetup() == nil
@@ -102,14 +103,14 @@ func writeGlobalStatus(w io.Writer) error {
}
}
- fmt.Fprintf(w, "filesystems supporting encryption: %d\n", supportCount)
- fmt.Fprintf(w, "filesystems with fscrypt metadata: %d\n\n", useCount)
+ fmt.Fprintf(cmd.Output, "filesystems supporting encryption: %d\n", supportCount)
+ fmt.Fprintf(cmd.Output, "filesystems with fscrypt metadata: %d\n\n", useCount)
return t.Flush()
}
// writeOptions writes a table of the status for a slice of protector options.
-func writeOptions(w io.Writer, options []*actions.ProtectorOption) {
- t := makeTableWriter(w, "PROTECTOR\tLINKED\tDESCRIPTION")
+func writeOptions(options []*actions.ProtectorOption) {
+ t := makeTableWriter(cmd.Output, "PROTECTOR\tLINKED\tDESCRIPTION")
for _, option := range options {
if option.LoadError != nil {
fmt.Fprintf(t, "%s\t\t[%s]\n", option.Descriptor(), option.LoadError)
@@ -128,7 +129,7 @@ func writeOptions(w io.Writer, options []*actions.ProtectorOption) {
t.Flush()
}
-func writeFilesystemStatus(w io.Writer, ctx *actions.Context) error {
+func writeFilesystemStatus(ctx *actions.Context) error {
options, err := ctx.ProtectorOptions()
if err != nil {
return err
@@ -143,15 +144,15 @@ func writeFilesystemStatus(w io.Writer, ctx *actions.Context) error {
pluralize(len(options), "protector"), pluralize(len(policyDescriptors), "policy"))
if len(options) > 0 {
- writeOptions(w, options)
+ writeOptions(options)
}
if len(policyDescriptors) == 0 {
return nil
}
- fmt.Fprintln(w)
- t := makeTableWriter(w, "POLICY\tUNLOCKED\tPROTECTORS")
+ fmt.Fprintln(cmd.Output)
+ t := makeTableWriter(cmd.Output, "POLICY\tUNLOCKED\tPROTECTORS")
for _, descriptor := range policyDescriptors {
policy, err := actions.GetPolicy(ctx, descriptor)
if err != nil {
@@ -165,7 +166,7 @@ func writeFilesystemStatus(w io.Writer, ctx *actions.Context) error {
return t.Flush()
}
-func writePathStatus(w io.Writer, path string) error {
+func writePathStatus(path string) error {
ctx, err := actions.NewContextFromPath(path, nil)
if err != nil {
return err
@@ -175,14 +176,14 @@ func writePathStatus(w io.Writer, path string) error {
return err
}
- fmt.Fprintf(w, "%q is encrypted with fscrypt.\n", path)
- fmt.Fprintln(w)
- fmt.Fprintf(w, "Policy: %s\n", policy.Descriptor())
- fmt.Fprintf(w, "Unlocked: %s\n", yesNoString(policy.IsProvisioned()))
- fmt.Fprintln(w)
+ fmt.Fprintf(cmd.Output, "%q is encrypted with fscrypt.\n", path)
+ fmt.Fprintln(cmd.Output)
+ fmt.Fprintf(cmd.Output, "Policy: %s\n", policy.Descriptor())
+ fmt.Fprintf(cmd.Output, "Unlocked: %s\n", yesNoString(policy.IsProvisioned()))
+ fmt.Fprintln(cmd.Output)
options := policy.ProtectorOptions()
- fmt.Fprintf(w, "Protected with %s:\n", pluralize(len(options), "protector"))
- writeOptions(w, options)
+ fmt.Fprintf(cmd.Output, "Protected with %s:\n", pluralize(len(options), "protector"))
+ writeOptions(cmd.Output, options)
return nil
}