fileinfo.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. /*
  2. * Rufs - Remote Union File System
  3. *
  4. * Copyright 2017 Matthias Ladkau. All rights reserved.
  5. *
  6. * This Source Code Form is subject to the terms of the MIT
  7. * License, If a copy of the MIT License was not distributed with this
  8. * file, You can obtain one at https://opensource.org/licenses/MIT.
  9. */
  10. package rufs
  11. import (
  12. "fmt"
  13. "os"
  14. "path/filepath"
  15. "time"
  16. )
  17. /*
  18. Special unit test flag - use a common mode to gloss over OS specific
  19. defaults
  20. */
  21. var unitTestModes = false
  22. /*
  23. FileInfo implements os.FileInfo in an platform-agnostic way
  24. */
  25. type FileInfo struct {
  26. FiName string // Base name
  27. FiSize int64 // Size in bytes
  28. FiMode os.FileMode // File mode bits
  29. FiModTime time.Time // Modification time
  30. FiChecksum string // Checksum of files
  31. // Private fields which will not be transferred via RPC
  32. isSymLink bool // Flag if this is a symlink (unix)
  33. symLinkTarget string // Target file/directory of the symlink
  34. }
  35. /*
  36. WrapFileInfo wraps a single os.FileInfo object in a serializable FileInfo.
  37. */
  38. func WrapFileInfo(path string, i os.FileInfo) os.FileInfo {
  39. var realPath string
  40. // Check if we have a symlink
  41. mode := i.Mode()
  42. size := i.Size()
  43. isSymlink := i.Mode()&os.ModeSymlink != 0
  44. if isSymlink {
  45. var err error
  46. if realPath, err = filepath.EvalSymlinks(filepath.Join(path, i.Name())); err == nil {
  47. var ri os.FileInfo
  48. if ri, err = os.Stat(realPath); err == nil {
  49. // Write in the size of the target and file mode
  50. mode = ri.Mode()
  51. size = ri.Size()
  52. }
  53. }
  54. }
  55. // Unit test fixed file modes
  56. if unitTestModes {
  57. mode = mode & os.ModeDir
  58. if mode.IsDir() {
  59. mode = mode | 0777
  60. size = 4096
  61. } else {
  62. mode = mode | 0666
  63. }
  64. }
  65. return &FileInfo{i.Name(), size, mode, i.ModTime(), "",
  66. isSymlink, realPath}
  67. }
  68. /*
  69. WrapFileInfos wraps a list of os.FileInfo objects into a list of
  70. serializable FileInfo objects. This function will modify the given
  71. list.
  72. */
  73. func WrapFileInfos(path string, is []os.FileInfo) []os.FileInfo {
  74. for i, info := range is {
  75. is[i] = WrapFileInfo(path, info)
  76. }
  77. return is
  78. }
  79. /*
  80. Name returns the base name.
  81. */
  82. func (rfi *FileInfo) Name() string {
  83. return rfi.FiName
  84. }
  85. /*
  86. Size returns the length in bytes.
  87. */
  88. func (rfi *FileInfo) Size() int64 {
  89. return rfi.FiSize
  90. }
  91. /*
  92. Mode returns the file mode bits.
  93. */
  94. func (rfi *FileInfo) Mode() os.FileMode {
  95. return rfi.FiMode
  96. }
  97. /*
  98. ModTime returns the modification time.
  99. */
  100. func (rfi *FileInfo) ModTime() time.Time {
  101. return rfi.FiModTime
  102. }
  103. /*
  104. Checksum returns the checksum of this file. May be an empty string if it was
  105. not calculated.
  106. */
  107. func (rfi *FileInfo) Checksum() string {
  108. return rfi.FiChecksum
  109. }
  110. /*
  111. IsDir returns if this is a directory.
  112. */
  113. func (rfi *FileInfo) IsDir() bool {
  114. return rfi.FiMode.IsDir()
  115. }
  116. /*
  117. Sys should return the underlying data source but will always return nil
  118. for FileInfo nodes.
  119. */
  120. func (rfi *FileInfo) Sys() interface{} {
  121. return nil
  122. }
  123. func (rfi *FileInfo) String() string {
  124. sum := rfi.Checksum()
  125. if sum != "" {
  126. return fmt.Sprintf("%v %s [%v] %v (%v) - %v", rfi.Name(), sum, rfi.Size(),
  127. rfi.Mode(), rfi.ModTime(), rfi.Sys())
  128. }
  129. return fmt.Sprintf("%v [%v] %v (%v) - %v", rfi.Name(), rfi.Size(),
  130. rfi.Mode(), rfi.ModTime(), rfi.Sys())
  131. }