You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
177 lines
5.1 KiB
177 lines
5.1 KiB
// Copyright (c) 2013-2014 The btcsuite developers |
|
// Use of this source code is governed by an ISC |
|
// license that can be found in the LICENSE file. |
|
|
|
package main |
|
|
|
import ( |
|
"io" |
|
"os" |
|
"path/filepath" |
|
) |
|
|
|
// dirEmpty returns whether or not the specified directory path is empty. |
|
func dirEmpty(dirPath string) (bool, error) { |
|
f, err := os.Open(dirPath) |
|
defer f.Close() |
|
|
|
// Read the names of a max of one entry from the directory. When the |
|
// directory is empty, an io.EOF error will be returned, so allow it. |
|
names, err := f.Readdirnames(1) |
|
if err != nil && err != io.EOF { |
|
return false, err |
|
} |
|
|
|
return len(names) == 0, nil |
|
} |
|
|
|
// oldBtcdHomeDir returns the OS specific home directory btcd used prior to |
|
// version 0.3.3. This has since been replaced with btcutil.AppDataDir, but |
|
// this function is still provided for the automatic upgrade path. |
|
func oldBtcdHomeDir() string { |
|
// Search for Windows APPDATA first. This won't exist on POSIX OSes. |
|
appData := os.Getenv("APPDATA") |
|
if appData != "" { |
|
return filepath.Join(appData, "btcd") |
|
} |
|
|
|
// Fall back to standard HOME directory that works for most POSIX OSes. |
|
home := os.Getenv("HOME") |
|
if home != "" { |
|
return filepath.Join(home, ".btcd") |
|
} |
|
|
|
// In the worst case, use the current directory. |
|
return "." |
|
} |
|
|
|
// upgradeDBPathNet moves the database for a specific network from its |
|
// location prior to btcd version 0.2.0 and uses heuristics to ascertain the old |
|
// database type to rename to the new format. |
|
func upgradeDBPathNet(oldDbPath, netName string) error { |
|
// Prior to version 0.2.0, the database was named the same thing for |
|
// both sqlite and leveldb. Use heuristics to figure out the type |
|
// of the database and move it to the new path and name introduced with |
|
// version 0.2.0 accordingly. |
|
fi, err := os.Stat(oldDbPath) |
|
if err == nil { |
|
oldDbType := "sqlite" |
|
if fi.IsDir() { |
|
oldDbType = "leveldb" |
|
} |
|
|
|
// The new database name is based on the database type and |
|
// resides in a directory named after the network type. |
|
newDbRoot := filepath.Join(filepath.Dir(cfg.DataDir), netName) |
|
newDbName := blockDbNamePrefix + "_" + oldDbType |
|
if oldDbType == "sqlite" { |
|
newDbName = newDbName + ".db" |
|
} |
|
newDbPath := filepath.Join(newDbRoot, newDbName) |
|
|
|
// Create the new path if needed. |
|
err = os.MkdirAll(newDbRoot, 0700) |
|
if err != nil { |
|
return err |
|
} |
|
|
|
// Move and rename the old database. |
|
err := os.Rename(oldDbPath, newDbPath) |
|
if err != nil { |
|
return err |
|
} |
|
} |
|
|
|
return nil |
|
} |
|
|
|
// upgradeDBPaths moves the databases from their locations prior to btcd |
|
// version 0.2.0 to their new locations. |
|
func upgradeDBPaths() error { |
|
// Prior to version 0.2.0, the databases were in the "db" directory and |
|
// their names were suffixed by "testnet" and "regtest" for their |
|
// respective networks. Check for the old database and update it to the |
|
// new path introduced with version 0.2.0 accordingly. |
|
oldDbRoot := filepath.Join(oldBtcdHomeDir(), "db") |
|
upgradeDBPathNet(filepath.Join(oldDbRoot, "btcd.db"), "mainnet") |
|
upgradeDBPathNet(filepath.Join(oldDbRoot, "btcd_testnet.db"), "testnet") |
|
upgradeDBPathNet(filepath.Join(oldDbRoot, "btcd_regtest.db"), "regtest") |
|
|
|
// Remove the old db directory. |
|
err := os.RemoveAll(oldDbRoot) |
|
if err != nil { |
|
return err |
|
} |
|
|
|
return nil |
|
} |
|
|
|
// upgradeDataPaths moves the application data from its location prior to btcd |
|
// version 0.3.3 to its new location. |
|
func upgradeDataPaths() error { |
|
// No need to migrate if the old and new home paths are the same. |
|
oldHomePath := oldBtcdHomeDir() |
|
newHomePath := btcdHomeDir |
|
if oldHomePath == newHomePath { |
|
return nil |
|
} |
|
|
|
// Only migrate if the old path exists and the new one doesn't. |
|
if fileExists(oldHomePath) && !fileExists(newHomePath) { |
|
// Create the new path. |
|
btcdLog.Infof("Migrating application home path from '%s' to '%s'", |
|
oldHomePath, newHomePath) |
|
err := os.MkdirAll(newHomePath, 0700) |
|
if err != nil { |
|
return err |
|
} |
|
|
|
// Move old btcd.conf into new location if needed. |
|
oldConfPath := filepath.Join(oldHomePath, defaultConfigFilename) |
|
newConfPath := filepath.Join(newHomePath, defaultConfigFilename) |
|
if fileExists(oldConfPath) && !fileExists(newConfPath) { |
|
err := os.Rename(oldConfPath, newConfPath) |
|
if err != nil { |
|
return err |
|
} |
|
} |
|
|
|
// Move old data directory into new location if needed. |
|
oldDataPath := filepath.Join(oldHomePath, defaultDataDirname) |
|
newDataPath := filepath.Join(newHomePath, defaultDataDirname) |
|
if fileExists(oldDataPath) && !fileExists(newDataPath) { |
|
err := os.Rename(oldDataPath, newDataPath) |
|
if err != nil { |
|
return err |
|
} |
|
} |
|
|
|
// Remove the old home if it is empty or show a warning if not. |
|
ohpEmpty, err := dirEmpty(oldHomePath) |
|
if err != nil { |
|
return err |
|
} |
|
if ohpEmpty { |
|
err := os.Remove(oldHomePath) |
|
if err != nil { |
|
return err |
|
} |
|
} else { |
|
btcdLog.Warnf("Not removing '%s' since it contains files "+ |
|
"not created by this application. You may "+ |
|
"want to manually move them or delete them.", |
|
oldHomePath) |
|
} |
|
} |
|
|
|
return nil |
|
} |
|
|
|
// doUpgrades performs upgrades to btcd as new versions require it. |
|
func doUpgrades() error { |
|
err := upgradeDBPaths() |
|
if err != nil { |
|
return err |
|
} |
|
return upgradeDataPaths() |
|
}
|
|
|