github.com/u-root/u-root@v7.0.1-0.20200915234505-ad7babab0a8e+incompatible/cmds/exp/hdparm/hdparm.go (about) 1 // Copyright 2019 the u-root Authors. All rights reserved 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // hdparm performs control operations on disks. 6 // 7 // hdparm is modeled after linux command of the same name, 8 // using a command [switches] verb model, but many of the verbs 9 // are also switches which can conflict. 10 // 11 // Upstream hdparm also decided a conf file in /etc/ would be 12 // a good idea; we have no plans to support that. 13 // 14 // We also have no plans to support ata12. It's 2019. 15 // 16 // Unlike the standard hdparm command, we do not allow empty 17 // arguments for commands requiring a password. 18 // 19 // Synopsis: 20 // hdparm [--i] [--security-unlock[=password]] [--user-master|--timeout] [device ...] 21 // 22 package main 23 24 import ( 25 "flag" 26 "fmt" 27 "log" 28 "time" 29 30 "github.com/u-root/u-root/pkg/mount/scuzz" 31 ) 32 33 // Because all the verbs and options are switches, hence global, 34 // we can have all the functions take one Disk as a parameter and 35 // return a string and error. This simplifies other aspects of this program. 36 type op func(scuzz.Disk) (string, error) 37 38 var ( 39 verbose = flag.Bool("v", false, "verbose log") 40 debug = func(string, ...interface{}) {} 41 unlock = flag.String("security-unlock", "", "Unlock the drive with a password") 42 identify = flag.Bool("i", false, "Get drive identifying information") 43 admin = flag.Bool("user-master", false, "Unlock admin (true) or user (false)") 44 timeoutDuration = flag.String("timeout", "15s", "Timeout for operations expressed as a Go duration (e.g. 15s)") 45 verbs = []string{"security-unlock", "i"} 46 ) 47 48 // The hdparm switches can conflict. This function returns nil if there is no conflict, and a (hopefully) 49 // helpful error message otherwise. As a side effect it assigns verb. 50 // TODO: use the visitor pattern to make this better. The next flag that's added will include that fix. 51 func checkVerbs() (op, error) { 52 var v []string 53 var verb op 54 55 if len(*unlock) > 0 { 56 verb = unlockop 57 v = append(v, "security-unlock") 58 } 59 if *identify { 60 verb = identifyop 61 v = append(v, "i") 62 } 63 64 if len(v) > 1 { 65 return nil, fmt.Errorf("%v verbs were invoked and only one is allowed", v) 66 } 67 if len(v) < 1 { 68 return nil, fmt.Errorf("no verbs were invoked and one of %v is required", verbs) 69 } 70 return verb, nil 71 } 72 73 func unlockop(d scuzz.Disk) (string, error) { 74 return "", d.Unlock(*unlock, *admin) 75 } 76 77 func identifyop(d scuzz.Disk) (string, error) { 78 i, err := d.Identify() 79 if err != nil { 80 return "", err 81 } 82 return i.String(), nil 83 } 84 85 func main() { 86 flag.Parse() 87 88 verb, err := checkVerbs() 89 if err != nil { 90 log.Fatal(err) 91 } 92 93 if *verbose { 94 debug = log.Printf 95 } 96 scuzz.Debug = debug 97 98 timeout, err := time.ParseDuration(*timeoutDuration) 99 if err != nil { 100 log.Fatal(err) 101 } 102 103 for _, n := range flag.Args() { 104 d, err := scuzz.NewSGDisk(n, scuzz.WithTimeout(timeout)) 105 if err != nil { 106 log.Printf("%v: %v", n, err) 107 continue 108 } 109 s, err := verb(d) 110 if err != nil { 111 log.Printf("%v: %v", n, err.Error()) 112 } 113 if len(s) > 0 { 114 fmt.Println(s) 115 } 116 } 117 118 }