2019-05-17 17:56:02 +00:00
|
|
|
package main
|
2016-09-15 17:39:46 +00:00
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2019-04-26 14:22:05 +00:00
|
|
|
"os"
|
|
|
|
|
2016-09-15 17:39:46 +00:00
|
|
|
"github.com/dennwc/btrfs"
|
|
|
|
"github.com/spf13/cobra"
|
|
|
|
)
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
RootCmd.AddCommand(
|
|
|
|
SubvolumeCmd,
|
|
|
|
SendCmd,
|
|
|
|
ReceiveCmd,
|
|
|
|
)
|
|
|
|
|
|
|
|
SubvolumeCmd.AddCommand(
|
|
|
|
SubvolumeCreateCmd,
|
|
|
|
SubvolumeDeleteCmd,
|
2016-09-16 17:09:14 +00:00
|
|
|
SubvolumeListCmd,
|
2016-09-15 17:39:46 +00:00
|
|
|
)
|
2016-09-19 17:01:22 +00:00
|
|
|
|
|
|
|
SendCmd.Flags().StringP("parent", "p", "", "Send an incremental stream from <parent> to <subvol>.")
|
2016-09-15 17:39:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
var RootCmd = &cobra.Command{
|
|
|
|
Use: "btrfs [--help] [--version] <group> [<group>...] <command> [<args>]",
|
|
|
|
Short: "Use --help as an argument for information on a specific group or command.",
|
|
|
|
}
|
|
|
|
|
|
|
|
var SubvolumeCmd = &cobra.Command{
|
2016-09-19 17:01:22 +00:00
|
|
|
Use: "subvolume <command> <args>",
|
|
|
|
Aliases: []string{"subvol", "sub", "sv"},
|
2016-09-15 17:39:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
var SubvolumeCreateCmd = &cobra.Command{
|
|
|
|
Use: "create [-i <qgroupid>] [<dest>/]<name>",
|
|
|
|
Short: "Create a subvolume",
|
|
|
|
Long: `Create a subvolume <name> in <dest>. If <dest> is not given subvolume <name> will be created in the current directory.`,
|
|
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
|
|
if len(args) == 0 {
|
|
|
|
return fmt.Errorf("subvolume not specified")
|
|
|
|
} else if len(args) > 1 {
|
|
|
|
return fmt.Errorf("only one subvolume name is allowed")
|
|
|
|
}
|
|
|
|
return btrfs.CreateSubVolume(args[0])
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
var SubvolumeDeleteCmd = &cobra.Command{
|
|
|
|
Use: "delete [options] <subvolume> [<subvolume>...]",
|
|
|
|
Short: "Delete subvolume(s)",
|
|
|
|
Long: `Delete subvolumes from the filesystem. The corresponding directory
|
|
|
|
is removed instantly but the data blocks are removed later.
|
|
|
|
The deletion does not involve full commit by default due to
|
|
|
|
performance reasons (as a consequence, the subvolume may appear again
|
|
|
|
after a crash). Use one of the --commit options to wait until the
|
|
|
|
operation is safely stored on the media.`,
|
|
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
|
|
for _, arg := range args {
|
|
|
|
if err := btrfs.DeleteSubVolume(arg); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2016-09-16 17:09:14 +00:00
|
|
|
var SubvolumeListCmd = &cobra.Command{
|
2016-09-19 17:01:22 +00:00
|
|
|
Use: "list <mount>",
|
|
|
|
Short: "List subvolumes",
|
|
|
|
Aliases: []string{"ls"},
|
2016-09-16 17:09:14 +00:00
|
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
|
|
if len(args) != 1 {
|
|
|
|
return fmt.Errorf("expected one destination argument")
|
|
|
|
}
|
2016-10-01 12:10:12 +00:00
|
|
|
fs, err := btrfs.Open(args[0], true)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer fs.Close()
|
|
|
|
list, err := fs.ListSubvolumes(nil)
|
2016-09-16 17:09:14 +00:00
|
|
|
if err == nil {
|
|
|
|
for _, v := range list {
|
|
|
|
fmt.Printf("%+v\n", v)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return err
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2016-09-15 17:39:46 +00:00
|
|
|
var SendCmd = &cobra.Command{
|
2016-09-19 17:01:22 +00:00
|
|
|
Use: "send [-v] [-p <parent>] [-c <clone-src>] [-f <outfile>] <subvol> [<subvol>...]",
|
2016-09-15 17:39:46 +00:00
|
|
|
Short: "Send the subvolume(s) to stdout.",
|
|
|
|
Long: `Sends the subvolume(s) specified by <subvol> to stdout.
|
|
|
|
<subvol> should be read-only here.`,
|
|
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
2016-09-19 17:01:22 +00:00
|
|
|
parent, _ := cmd.Flags().GetString("parent")
|
|
|
|
return btrfs.Send(os.Stdout, parent, args...)
|
2016-09-15 17:39:46 +00:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
var ReceiveCmd = &cobra.Command{
|
2016-09-21 12:31:08 +00:00
|
|
|
Use: "receive [-v] [-f <infile>] [--max-errors <N>] <mount>",
|
2016-09-15 17:39:46 +00:00
|
|
|
Short: "Receive subvolumes from stdin.",
|
|
|
|
Long: `Receives one or more subvolumes that were previously
|
|
|
|
sent with btrfs send. The received subvolumes are stored
|
|
|
|
into <mount>.`,
|
|
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
|
|
if len(args) != 1 {
|
|
|
|
return fmt.Errorf("expected one destination argument")
|
|
|
|
}
|
|
|
|
return btrfs.Receive(os.Stdin, args[0])
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
if err := RootCmd.Execute(); err != nil {
|
|
|
|
fmt.Println(err)
|
|
|
|
os.Exit(-1)
|
|
|
|
}
|
|
|
|
}
|