github.com/rkt/rkt@v1.30.1-0.20200224141603-171c416fac02/tests/testutils/datadirsetup.go (about) 1 // Copyright 2015 The rkt Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package testutils 16 17 import ( 18 "crypto/sha1" 19 "fmt" 20 "io" 21 "os" 22 "path/filepath" 23 24 "github.com/hashicorp/errwrap" 25 "github.com/rkt/rkt/pkg/group" 26 ) 27 28 const casDbPerm = os.FileMode(0660) 29 30 var ( 31 // dirs relative to data directory 32 dirs = map[string]os.FileMode{ 33 ".": os.FileMode(0750 | os.ModeSetgid), 34 "tmp": os.FileMode(0750 | os.ModeSetgid), 35 36 // Cas directories. 37 // Please keep in sync with dist/init/systemd/tmpfiles.d/rkt.conf 38 // Make sure 'rkt' group can read/write some of the 'cas' 39 // directories so that users in the group can fetch images 40 "cas": os.FileMode(0770 | os.ModeSetgid), 41 "cas/db": os.FileMode(0770 | os.ModeSetgid), 42 "cas/imagelocks": os.FileMode(0770 | os.ModeSetgid), 43 "cas/imageManifest": os.FileMode(0770 | os.ModeSetgid), 44 "cas/blob": os.FileMode(0770 | os.ModeSetgid), 45 "cas/tmp": os.FileMode(0770 | os.ModeSetgid), 46 "cas/tree": os.FileMode(0700 | os.ModeSetgid), 47 "cas/treestorelocks": os.FileMode(0700 | os.ModeSetgid), 48 "locks": os.FileMode(0750 | os.ModeSetgid), 49 50 // Pods directories. 51 "pods": os.FileMode(0750 | os.ModeSetgid), 52 "pods/embryo": os.FileMode(0750 | os.ModeSetgid), 53 "pods/prepare": os.FileMode(0750 | os.ModeSetgid), 54 "pods/prepared": os.FileMode(0750 | os.ModeSetgid), 55 "pods/run": os.FileMode(0750 | os.ModeSetgid), 56 "pods/exited-garbage": os.FileMode(0750 | os.ModeSetgid), 57 "pods/garbage": os.FileMode(0750 | os.ModeSetgid), 58 } 59 ) 60 61 func createFileWithPermissions(path string, uid int, gid int, perm os.FileMode) error { 62 _, err := os.OpenFile(path, os.O_CREATE|os.O_EXCL|os.O_RDWR, 0666) 63 if err != nil { 64 if !os.IsExist(err) { 65 return err 66 } 67 // file exists 68 } 69 70 return setPermissions(path, uid, gid, perm) 71 } 72 73 func setPermissions(path string, uid int, gid int, perm os.FileMode) error { 74 if err := os.Chown(path, uid, gid); err != nil { 75 return errwrap.Wrap(fmt.Errorf("error setting %q directory group", path), err) 76 } 77 78 if err := os.Chmod(path, perm); err != nil { 79 return errwrap.Wrap(fmt.Errorf("error setting %q directory permissions", path), err) 80 } 81 82 return nil 83 } 84 85 func createDirStructure(dataDir string, gid int) error { 86 for dir, perm := range dirs { 87 path := filepath.Join(dataDir, dir) 88 89 if err := os.MkdirAll(path, perm); err != nil { 90 return errwrap.Wrap(fmt.Errorf("error creating %q directory", path), err) 91 } 92 93 if err := setPermissions(path, 0, gid, perm); err != nil { 94 return err 95 } 96 } 97 98 return nil 99 } 100 101 func setCasDbFilesPermissions(casDbPath string, gid int, perm os.FileMode) error { 102 casDbWalker := func(path string, info os.FileInfo, err error) error { 103 if err != nil { 104 return err 105 } 106 if info.Mode().IsRegular() { 107 if err := setPermissions(path, 0, gid, perm); err != nil { 108 return err 109 } 110 } 111 112 return nil 113 } 114 115 if err := filepath.Walk(casDbPath, casDbWalker); err != nil { 116 return err 117 } 118 119 return nil 120 } 121 122 func createDbFiles(casDbPath string, gid int, perm os.FileMode) error { 123 // HACK: to avoid some import cycles we don't use store.DbFilename 124 DbFilename := "ql.db" 125 dbPath := filepath.Join(casDbPath, DbFilename) 126 if err := createFileWithPermissions(dbPath, 0, gid, perm); err != nil { 127 return errwrap.Wrap(fmt.Errorf("error creating %s", dbPath), err) 128 } 129 130 // ql database uses a Write-Ahead Logging (WAL) file whose name is 131 // generated from the sha1 hash of the database name 132 h := sha1.New() 133 io.WriteString(h, DbFilename) 134 walFilename := fmt.Sprintf(".%x", h.Sum(nil)) 135 walFilePath := filepath.Join(casDbPath, walFilename) 136 if err := createFileWithPermissions(walFilePath, 0, gid, perm); err != nil { 137 return errwrap.Wrap(fmt.Errorf("error creating %s", walFilename), err) 138 } 139 140 return nil 141 } 142 143 func setupDataDir(dataDir string) error { 144 gid, err := group.LookupGid("rkt") 145 if err != nil { 146 return err 147 } 148 149 if err := createDirStructure(dataDir, gid); err != nil { 150 return err 151 } 152 153 casDbPath := filepath.Join(dataDir, "cas", "db") 154 if err := setCasDbFilesPermissions(casDbPath, gid, casDbPerm); err != nil { 155 return err 156 } 157 158 if err := createDbFiles(casDbPath, gid, casDbPerm); err != nil { 159 return err 160 } 161 162 return nil 163 }