github.com/palcoin-project/palcd@v1.0.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 palcutil.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, "palcd")
    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, ".palcd")
    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, "palcd.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 palcd.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  }