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