github.com/Cloud-Foundations/Dominator@v0.3.4/lib/filesystem/compare.go (about)

     1  package filesystem
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"io"
     7  	"syscall"
     8  )
     9  
    10  type timespec struct {
    11  	Sec  int64
    12  	Nsec int32
    13  }
    14  
    15  func compareFileSystems(left, right *FileSystem, logWriter io.Writer) bool {
    16  	if len(left.InodeTable) != len(right.InodeTable) {
    17  		if logWriter != nil {
    18  			fmt.Fprintf(logWriter, "left vs. right: %d vs. %d inodes\n",
    19  				len(left.InodeTable), len(right.InodeTable))
    20  		}
    21  		return false
    22  	}
    23  	return compareDirectoryInodes(&left.DirectoryInode, &right.DirectoryInode,
    24  		logWriter)
    25  }
    26  
    27  func compareDirectoryInodes(left, right *DirectoryInode,
    28  	logWriter io.Writer) bool {
    29  	if left == right {
    30  		return true
    31  	}
    32  	if !compareDirectoriesMetadata(left, right, logWriter) {
    33  		return false
    34  	}
    35  	if len(left.EntryList) != len(right.EntryList) {
    36  		if logWriter != nil {
    37  			fmt.Fprintf(logWriter, "left vs. right: %d vs. %d entries\n",
    38  				len(left.EntryList), len(right.EntryList))
    39  		}
    40  		return false
    41  	}
    42  	for index, leftEntry := range left.EntryList {
    43  		if !compareDirectoryEntries(leftEntry, right.EntryList[index],
    44  			logWriter) {
    45  			return false
    46  		}
    47  	}
    48  	return true
    49  }
    50  
    51  func compareDirectoriesMetadata(left, right *DirectoryInode,
    52  	logWriter io.Writer) bool {
    53  	if left.Mode != right.Mode {
    54  		if logWriter != nil {
    55  			fmt.Fprintf(logWriter, "Mode: left vs. right: %o vs. %o\n",
    56  				left.Mode, right.Mode)
    57  		}
    58  		return false
    59  	}
    60  	if left.Uid != right.Uid {
    61  		if logWriter != nil {
    62  			fmt.Fprintf(logWriter, "Uid: left vs. right: %d vs. %d\n",
    63  				left.Uid, right.Uid)
    64  		}
    65  		return false
    66  	}
    67  	if left.Gid != right.Gid {
    68  		if logWriter != nil {
    69  			fmt.Fprintf(logWriter, "Gid: left vs. right: %d vs. %d\n",
    70  				left.Gid, right.Gid)
    71  		}
    72  		return false
    73  	}
    74  	return true
    75  }
    76  
    77  func compareDirectoryEntries(left, right *DirectoryEntry,
    78  	logWriter io.Writer) bool {
    79  	if left == right {
    80  		return true
    81  	}
    82  	if left.Name != right.Name {
    83  		if logWriter != nil {
    84  			fmt.Fprintf(logWriter, "filename: left vs. right: %s vs. %s\n",
    85  				left.Name, right.Name)
    86  		}
    87  		return false
    88  	}
    89  	switch left := left.inode.(type) {
    90  	case *RegularInode:
    91  		if right, ok := right.inode.(*RegularInode); ok {
    92  			return compareRegularInodes(left, right, logWriter)
    93  		}
    94  	case *ComputedRegularInode:
    95  		if right, ok := right.inode.(*ComputedRegularInode); ok {
    96  			return compareComputedRegularInodes(left, right, logWriter)
    97  		}
    98  	case *SymlinkInode:
    99  		if right, ok := right.inode.(*SymlinkInode); ok {
   100  			return compareSymlinkInodes(left, right, logWriter)
   101  		}
   102  	case *SpecialInode:
   103  		if right, ok := right.inode.(*SpecialInode); ok {
   104  			return compareSpecialInodes(left, right, logWriter)
   105  		}
   106  	case *DirectoryInode:
   107  		if right, ok := right.inode.(*DirectoryInode); ok {
   108  			return compareDirectoryInodes(left, right, logWriter)
   109  		}
   110  	}
   111  	if logWriter != nil {
   112  		fmt.Fprintf(logWriter, "types: left vs. right: %s vs. %s\n",
   113  			left.Name, right.Name)
   114  	}
   115  	return false
   116  }
   117  
   118  func compareInodes(left, right GenericInode, logWriter io.Writer) (
   119  	sameType, sameMetadata, sameData bool) {
   120  	if left == right {
   121  		return true, true, true
   122  	}
   123  	switch left := left.(type) {
   124  	case *RegularInode:
   125  		if right, ok := right.(*RegularInode); ok {
   126  			sameType = true
   127  			sameMetadata = compareRegularInodesMetadata(left, right, logWriter)
   128  			sameData = compareRegularInodesData(left, right, logWriter)
   129  		}
   130  	case *ComputedRegularInode:
   131  		if right, ok := right.(*ComputedRegularInode); ok {
   132  			sameType = true
   133  			sameMetadata = compareComputedRegularInodesMetadata(left, right,
   134  				logWriter)
   135  			sameData = compareComputedRegularInodesData(left, right, logWriter)
   136  		}
   137  	case *SymlinkInode:
   138  		if right, ok := right.(*SymlinkInode); ok {
   139  			sameType = true
   140  			sameMetadata = compareSymlinkInodesMetadata(left, right, logWriter)
   141  			sameData = compareSymlinkInodesData(left, right, logWriter)
   142  		}
   143  	case *SpecialInode:
   144  		if right, ok := right.(*SpecialInode); ok {
   145  			sameType = true
   146  			sameMetadata = compareSpecialInodesMetadata(left, right, logWriter)
   147  			sameData = compareSpecialInodesData(left, right, logWriter)
   148  		}
   149  	case *DirectoryInode:
   150  		if right, ok := right.(*DirectoryInode); ok {
   151  			sameType = true
   152  			sameMetadata = compareDirectoriesMetadata(left, right, logWriter)
   153  		}
   154  	default:
   155  		panic(fmt.Sprintf("Unsupported entry type: %T", left))
   156  	}
   157  	if !sameType && logWriter != nil {
   158  		fmt.Fprintln(logWriter, "types: left vs. right differ")
   159  	}
   160  	return
   161  }
   162  
   163  func compareRegularInodes(left, right *RegularInode, logWriter io.Writer) bool {
   164  	if left == right {
   165  		return true
   166  	}
   167  	if !compareRegularInodesMetadata(left, right, logWriter) {
   168  		return false
   169  	}
   170  	return compareRegularInodesData(left, right, logWriter)
   171  }
   172  
   173  func compareRegularInodesMetadata(left, right *RegularInode,
   174  	logWriter io.Writer) bool {
   175  	if left.Mode != right.Mode {
   176  		if logWriter != nil {
   177  			fmt.Fprintf(logWriter, "Mode: left vs. right: %o vs. %o\n",
   178  				left.Mode, right.Mode)
   179  		}
   180  		return false
   181  	}
   182  	if left.Uid != right.Uid {
   183  		if logWriter != nil {
   184  			fmt.Fprintf(logWriter, "Uid: left vs. right: %d vs. %d\n",
   185  				left.Uid, right.Uid)
   186  		}
   187  		return false
   188  	}
   189  	if left.Gid != right.Gid {
   190  		if logWriter != nil {
   191  			fmt.Fprintf(logWriter, "Gid: left vs. right: %d vs. %d\n",
   192  				left.Gid, right.Gid)
   193  		}
   194  		return false
   195  	}
   196  	var leftMtime, rightMtime timespec
   197  	leftMtime.Sec = left.MtimeSeconds
   198  	leftMtime.Nsec = left.MtimeNanoSeconds
   199  	rightMtime.Sec = right.MtimeSeconds
   200  	rightMtime.Nsec = right.MtimeNanoSeconds
   201  	if leftMtime != rightMtime {
   202  		if logWriter != nil {
   203  			fmt.Fprintf(logWriter, "Mtime: left vs. right: %v vs. %v\n",
   204  				leftMtime, rightMtime)
   205  		}
   206  		return false
   207  	}
   208  	return true
   209  }
   210  
   211  func compareRegularInodesData(left, right *RegularInode,
   212  	logWriter io.Writer) bool {
   213  	if left.Size != right.Size {
   214  		if logWriter != nil {
   215  			fmt.Fprintf(logWriter, "Size: left vs. right: %d vs. %d\n",
   216  				left.Size, right.Size)
   217  		}
   218  		return false
   219  	}
   220  	if left.Size > 0 {
   221  		if bytes.Compare(left.Hash[:], right.Hash[:]) != 0 {
   222  			if logWriter != nil {
   223  				fmt.Fprintf(logWriter, "hash: left vs. right: %x vs. %x\n",
   224  					left.Hash, right.Hash)
   225  			}
   226  			return false
   227  		}
   228  	}
   229  	return true
   230  }
   231  
   232  func compareComputedRegularInodes(left, right *ComputedRegularInode,
   233  	logWriter io.Writer) bool {
   234  	if left == right {
   235  		return true
   236  	}
   237  	if !compareComputedRegularInodesMetadata(left, right, logWriter) {
   238  		return false
   239  	}
   240  	return compareComputedRegularInodesData(left, right, logWriter)
   241  }
   242  
   243  func compareComputedRegularInodesMetadata(left, right *ComputedRegularInode,
   244  	logWriter io.Writer) bool {
   245  	if left.Mode != right.Mode {
   246  		if logWriter != nil {
   247  			fmt.Fprintf(logWriter, "Mode: left vs. right: %o vs. %o\n",
   248  				left.Mode, right.Mode)
   249  		}
   250  		return false
   251  	}
   252  	if left.Uid != right.Uid {
   253  		if logWriter != nil {
   254  			fmt.Fprintf(logWriter, "Uid: left vs. right: %d vs. %d\n",
   255  				left.Uid, right.Uid)
   256  		}
   257  		return false
   258  	}
   259  	if left.Gid != right.Gid {
   260  		if logWriter != nil {
   261  			fmt.Fprintf(logWriter, "Gid: left vs. right: %d vs. %d\n",
   262  				left.Gid, right.Gid)
   263  		}
   264  		return false
   265  	}
   266  	if left.Source != right.Source {
   267  		if logWriter != nil {
   268  			fmt.Fprintf(logWriter, "Gid: left vs. right: %s vs. %s\n",
   269  				left.Source, right.Source)
   270  		}
   271  		return false
   272  	}
   273  	return true
   274  }
   275  
   276  func compareComputedRegularInodesData(left, right *ComputedRegularInode,
   277  	logWriter io.Writer) bool {
   278  	if left.Source != right.Source {
   279  		if logWriter != nil {
   280  			fmt.Fprintf(logWriter, "data source: left vs. right: %s vs. %s\n",
   281  				left.Source, right.Source)
   282  		}
   283  		return false
   284  	}
   285  	return true
   286  }
   287  
   288  func compareSymlinkInodes(left, right *SymlinkInode, logWriter io.Writer) bool {
   289  	if left == right {
   290  		return true
   291  	}
   292  	if !compareSymlinkInodesMetadata(left, right, logWriter) {
   293  		return false
   294  	}
   295  	return compareSymlinkInodesData(left, right, logWriter)
   296  }
   297  
   298  func compareSymlinkInodesMetadata(left, right *SymlinkInode,
   299  	logWriter io.Writer) bool {
   300  	if left.Uid != right.Uid {
   301  		if logWriter != nil {
   302  			fmt.Fprintf(logWriter, "Uid: left vs. right: %d vs. %d\n",
   303  				left.Uid, right.Uid)
   304  		}
   305  		return false
   306  	}
   307  	if left.Gid != right.Gid {
   308  		if logWriter != nil {
   309  			fmt.Fprintf(logWriter, "Gid: left vs. right: %d vs. %d\n",
   310  				left.Gid, right.Gid)
   311  		}
   312  		return false
   313  	}
   314  	return true
   315  }
   316  
   317  func compareSymlinkInodesData(left, right *SymlinkInode,
   318  	logWriter io.Writer) bool {
   319  	if left.Symlink != right.Symlink {
   320  		if logWriter != nil {
   321  			fmt.Fprintf(logWriter, "symlink: left vs. right: %s vs. %s\n",
   322  				left.Symlink, right.Symlink)
   323  		}
   324  		return false
   325  	}
   326  	return true
   327  }
   328  
   329  func compareSpecialInodes(left, right *SpecialInode, logWriter io.Writer) bool {
   330  	if left == right {
   331  		return true
   332  	}
   333  	if !compareSpecialInodesMetadata(left, right, logWriter) {
   334  		return false
   335  	}
   336  	return compareSpecialInodesData(left, right, logWriter)
   337  }
   338  
   339  func compareSpecialInodesMetadata(left, right *SpecialInode,
   340  	logWriter io.Writer) bool {
   341  	if left == right {
   342  		return true
   343  	}
   344  	if left.Mode != right.Mode {
   345  		if logWriter != nil {
   346  			fmt.Fprintf(logWriter, "Mode: left vs. right: %o vs. %o\n",
   347  				left.Mode, right.Mode)
   348  		}
   349  		return false
   350  	}
   351  	if left.Uid != right.Uid {
   352  		if logWriter != nil {
   353  			fmt.Fprintf(logWriter, "Uid: left vs. right: %d vs. %d\n",
   354  				left.Uid, right.Uid)
   355  		}
   356  		return false
   357  	}
   358  	if left.Gid != right.Gid {
   359  		if logWriter != nil {
   360  			fmt.Fprintf(logWriter, "Gid: left vs. right: %d vs. %d\n",
   361  				left.Gid, right.Gid)
   362  		}
   363  		return false
   364  	}
   365  	var leftMtime, rightMtime timespec
   366  	leftMtime.Sec = left.MtimeSeconds
   367  	leftMtime.Nsec = left.MtimeNanoSeconds
   368  	rightMtime.Sec = right.MtimeSeconds
   369  	rightMtime.Nsec = right.MtimeNanoSeconds
   370  	if leftMtime != rightMtime {
   371  		if logWriter != nil {
   372  			fmt.Fprintf(logWriter, "Mtime: left vs. right: %v vs. %v\n",
   373  				leftMtime, rightMtime)
   374  		}
   375  		return false
   376  	}
   377  	return true
   378  }
   379  
   380  func compareSpecialInodesData(left, right *SpecialInode,
   381  	logWriter io.Writer) bool {
   382  	if left.Mode&syscall.S_IFMT == syscall.S_IFBLK ||
   383  		left.Mode&syscall.S_IFMT == syscall.S_IFCHR {
   384  		if left.Rdev != right.Rdev {
   385  			if logWriter != nil {
   386  				fmt.Fprintf(logWriter, "Rdev: left vs. right: %#x vs. %#x\n",
   387  					left.Rdev, right.Rdev)
   388  			}
   389  			return false
   390  		}
   391  	}
   392  	return true
   393  }