github.com/dashpay/godash@v0.0.0-20160726055534-e038a21e0e3d/upgrade.go (about) 1 // Copyright (c) 2013-2014 The btcsuite developers 2 // Copyright (c) 2016 The Dash developers 3 // Use of this source code is governed by an ISC 4 // license that can be found in the LICENSE file. 5 6 package main 7 8 import ( 9 "io" 10 "os" 11 "path/filepath" 12 ) 13 14 // dirEmpty returns whether or not the specified directory path is empty. 15 func dirEmpty(dirPath string) (bool, error) { 16 f, err := os.Open(dirPath) 17 defer f.Close() 18 19 // Read the names of a max of one entry from the directory. When the 20 // directory is empty, an io.EOF error will be returned, so allow it. 21 names, err := f.Readdirnames(1) 22 if err != nil && err != io.EOF { 23 return false, err 24 } 25 26 return len(names) == 0, nil 27 } 28 29 // oldBtcdHomeDir returns the OS specific home directory btcd used prior to 30 // version 0.3.3. This has since been replaced with godashutil.AppDataDir, but 31 // this function is still provided for the automatic upgrade path. 32 func oldBtcdHomeDir() string { 33 // Search for Windows APPDATA first. This won't exist on POSIX OSes. 34 appData := os.Getenv("APPDATA") 35 if appData != "" { 36 return filepath.Join(appData, "btcd") 37 } 38 39 // Fall back to standard HOME directory that works for most POSIX OSes. 40 home := os.Getenv("HOME") 41 if home != "" { 42 return filepath.Join(home, ".btcd") 43 } 44 45 // In the worst case, use the current directory. 46 return "." 47 } 48 49 // upgradeDBPathNet moves the database for a specific network from its 50 // location prior to btcd version 0.2.0 and uses heuristics to ascertain the old 51 // database type to rename to the new format. 52 func upgradeDBPathNet(oldDbPath, netName string) error { 53 // Prior to version 0.2.0, the database was named the same thing for 54 // both sqlite and leveldb. Use heuristics to figure out the type 55 // of the database and move it to the new path and name introduced with 56 // version 0.2.0 accordingly. 57 fi, err := os.Stat(oldDbPath) 58 if err == nil { 59 oldDbType := "sqlite" 60 if fi.IsDir() { 61 oldDbType = "leveldb" 62 } 63 64 // The new database name is based on the database type and 65 // resides in a directory named after the network type. 66 newDbRoot := filepath.Join(filepath.Dir(cfg.DataDir), netName) 67 newDbName := blockDbNamePrefix + "_" + oldDbType 68 if oldDbType == "sqlite" { 69 newDbName = newDbName + ".db" 70 } 71 newDbPath := filepath.Join(newDbRoot, newDbName) 72 73 // Create the new path if needed. 74 err = os.MkdirAll(newDbRoot, 0700) 75 if err != nil { 76 return err 77 } 78 79 // Move and rename the old database. 80 err := os.Rename(oldDbPath, newDbPath) 81 if err != nil { 82 return err 83 } 84 } 85 86 return nil 87 } 88 89 // upgradeDBPaths moves the databases from their locations prior to btcd 90 // version 0.2.0 to their new locations. 91 func upgradeDBPaths() error { 92 // Prior to version 0.2.0, the databases were in the "db" directory and 93 // their names were suffixed by "testnet" and "regtest" for their 94 // respective networks. Check for the old database and update it to the 95 // new path introduced with version 0.2.0 accordingly. 96 oldDbRoot := filepath.Join(oldBtcdHomeDir(), "db") 97 upgradeDBPathNet(filepath.Join(oldDbRoot, "btcd.db"), "mainnet") 98 upgradeDBPathNet(filepath.Join(oldDbRoot, "btcd_testnet.db"), "testnet") 99 upgradeDBPathNet(filepath.Join(oldDbRoot, "btcd_regtest.db"), "regtest") 100 101 // Remove the old db directory. 102 err := os.RemoveAll(oldDbRoot) 103 if err != nil { 104 return err 105 } 106 107 return nil 108 } 109 110 // upgradeDataPaths moves the application data from its location prior to btcd 111 // version 0.3.3 to its new location. 112 func upgradeDataPaths() error { 113 // No need to migrate if the old and new home paths are the same. 114 oldHomePath := oldBtcdHomeDir() 115 newHomePath := btcdHomeDir 116 if oldHomePath == newHomePath { 117 return nil 118 } 119 120 // Only migrate if the old path exists and the new one doesn't. 121 if fileExists(oldHomePath) && !fileExists(newHomePath) { 122 // Create the new path. 123 btcdLog.Infof("Migrating application home path from '%s' to '%s'", 124 oldHomePath, newHomePath) 125 err := os.MkdirAll(newHomePath, 0700) 126 if err != nil { 127 return err 128 } 129 130 // Move old btcd.conf into new location if needed. 131 oldConfPath := filepath.Join(oldHomePath, defaultConfigFilename) 132 newConfPath := filepath.Join(newHomePath, defaultConfigFilename) 133 if fileExists(oldConfPath) && !fileExists(newConfPath) { 134 err := os.Rename(oldConfPath, newConfPath) 135 if err != nil { 136 return err 137 } 138 } 139 140 // Move old data directory into new location if needed. 141 oldDataPath := filepath.Join(oldHomePath, defaultDataDirname) 142 newDataPath := filepath.Join(newHomePath, defaultDataDirname) 143 if fileExists(oldDataPath) && !fileExists(newDataPath) { 144 err := os.Rename(oldDataPath, newDataPath) 145 if err != nil { 146 return err 147 } 148 } 149 150 // Remove the old home if it is empty or show a warning if not. 151 ohpEmpty, err := dirEmpty(oldHomePath) 152 if err != nil { 153 return err 154 } 155 if ohpEmpty { 156 err := os.Remove(oldHomePath) 157 if err != nil { 158 return err 159 } 160 } else { 161 btcdLog.Warnf("Not removing '%s' since it contains files "+ 162 "not created by this application. You may "+ 163 "want to manually move them or delete them.", 164 oldHomePath) 165 } 166 } 167 168 return nil 169 } 170 171 // doUpgrades performs upgrades to btcd as new versions require it. 172 func doUpgrades() error { 173 err := upgradeDBPaths() 174 if err != nil { 175 return err 176 } 177 return upgradeDataPaths() 178 }