/* * fscrypt.go - File which starts up and runs the application. Initializes * information about the application like the name, version, author, etc... * * Copyright 2017 Google Inc. * Author: Joe Richey (joerichey@google.com) * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ /* fscrypt is a command line tool for managing linux filesystem encryption. */ package main import ( "fmt" "io/ioutil" "log" "os" "github.com/urfave/cli" "github.com/google/fscrypt/actions" "github.com/google/fscrypt/filesystem" ) // Current version of the program (set by Makefile) var version string func main() { cli.AppHelpTemplate = appHelpTemplate cli.CommandHelpTemplate = commandHelpTemplate cli.SubcommandHelpTemplate = subcommandHelpTemplate if conffile := os.Getenv("FSCRYPT_CONF"); conffile != "" { actions.ConfigFileLocation = conffile } if rootmnt := os.Getenv("FSCRYPT_ROOT_MNT"); rootmnt != "" { actions.LoginProtectorMountpoint = rootmnt } if consistent := os.Getenv("FSCRYPT_CONSISTENT_OUTPUT"); consistent == "1" { filesystem.SortDescriptorsByLastMtime = true } // Create our command line application app := cli.NewApp() app.Usage = shortUsage // Grab the version passed in from the Makefile. app.Version = version app.OnUsageError = onUsageError // Setup global flags cli.HelpFlag = helpFlag cli.VersionFlag = versionFlag app.Flags = universalFlags // We hide the help subcommand so that "fscrypt --help" works // and "fscrypt help" does not. app.HideHelp = true // Initialize command list and setup all of the commands. app.Action = defaultAction app.Commands = []cli.Command{Setup, Encrypt, Unlock, Lock, Purge, Status, Metadata} for i := range app.Commands { setupCommand(&app.Commands[i]) } app.Run(os.Args) } // setupCommand performs some common setup for each command. This includes // hiding the help, formatting the description, adding in the necessary // flags, setting up error handlers, etc... Note that the command is modified // in place and its subcommands are also setup. func setupCommand(command *cli.Command) { command.Description = wrapText(command.Description, indentLength) command.HideHelp = true command.Flags = append(command.Flags, universalFlags...) if command.Action == nil { command.Action = defaultAction } // Setup function handlers command.OnUsageError = onUsageError if len(command.Subcommands) == 0 { command.Before = setupBefore } else { // Setup subcommands (if applicable) for i := range command.Subcommands { setupCommand(&command.Subcommands[i]) } } } // setupBefore makes sure our logs, errors, and output are going to the correct // io.Writers and that we haven't over-specified our flags. We only print the // logs when using verbose, and only print normal stuff when not using quiet. func setupBefore(c *cli.Context) error { log.SetOutput(ioutil.Discard) c.App.Writer = ioutil.Discard if verboseFlag.Value { log.SetOutput(os.Stdout) } if !quietFlag.Value { c.App.Writer = os.Stdout } return nil } // defaultAction will be run when no command is specified. func defaultAction(c *cli.Context) error { // Always default to showing the help if helpFlag.Value { cli.ShowAppHelp(c) return nil } // Only exit when not calling with the help command var message string if args := c.Args(); args.Present() { message = fmt.Sprintf("command \"%s\" not found", args.First()) } else { message = "no command was specified" } return &usageError{c, message} }