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.

101 lines
2.4 KiB

  1. package meta_cache
  2. import (
  3. "fmt"
  4. "strconv"
  5. "strings"
  6. )
  7. type UidGidMapper struct {
  8. uidMapper *IdMapper
  9. gidMapper *IdMapper
  10. }
  11. type IdMapper struct {
  12. localToFiler map[uint32]uint32
  13. filerToLocal map[uint32]uint32
  14. }
  15. // UidGidMapper translates local uid/gid to filer uid/gid
  16. // The local storage always persists the same as the filer.
  17. // The local->filer translation happens when updating the filer first and later saving to meta_cache.
  18. // And filer->local happens when reading from the meta_cache.
  19. func NewUidGidMapper(uidPairsStr, gidPairStr string) (*UidGidMapper, error) {
  20. uidMapper, err := newIdMapper(uidPairsStr)
  21. if err != nil {
  22. return nil, err
  23. }
  24. gidMapper, err := newIdMapper(gidPairStr)
  25. if err != nil {
  26. return nil, err
  27. }
  28. return &UidGidMapper{
  29. uidMapper: uidMapper,
  30. gidMapper: gidMapper,
  31. }, nil
  32. }
  33. func (m *UidGidMapper) LocalToFiler(uid, gid uint32) (uint32, uint32) {
  34. return m.uidMapper.LocalToFiler(uid), m.gidMapper.LocalToFiler(gid)
  35. }
  36. func (m *UidGidMapper) FilerToLocal(uid, gid uint32) (uint32, uint32) {
  37. return m.uidMapper.FilerToLocal(uid), m.gidMapper.FilerToLocal(gid)
  38. }
  39. func (m *IdMapper) LocalToFiler(id uint32) uint32 {
  40. value, found := m.localToFiler[id]
  41. if found {
  42. return value
  43. }
  44. return id
  45. }
  46. func (m *IdMapper) FilerToLocal(id uint32) uint32 {
  47. value, found := m.filerToLocal[id]
  48. if found {
  49. return value
  50. }
  51. return id
  52. }
  53. func newIdMapper(pairsStr string) (*IdMapper, error) {
  54. localToFiler, filerToLocal, err := parseUint32Pairs(pairsStr)
  55. if err != nil {
  56. return nil, err
  57. }
  58. return &IdMapper{
  59. localToFiler: localToFiler,
  60. filerToLocal: filerToLocal,
  61. }, nil
  62. }
  63. func parseUint32Pairs(pairsStr string) (localToFiler, filerToLocal map[uint32]uint32, err error) {
  64. if pairsStr == "" {
  65. return
  66. }
  67. localToFiler = make(map[uint32]uint32)
  68. filerToLocal = make(map[uint32]uint32)
  69. for _, pairStr := range strings.Split(pairsStr, ",") {
  70. pair := strings.Split(pairStr, ":")
  71. localUidStr, filerUidStr := pair[0], pair[1]
  72. localUid, localUidErr := strconv.Atoi(localUidStr)
  73. if localUidErr != nil {
  74. err = fmt.Errorf("failed to parse local %s: %v", localUidStr, localUidErr)
  75. return
  76. }
  77. filerUid, filerUidErr := strconv.Atoi(filerUidStr)
  78. if filerUidErr != nil {
  79. err = fmt.Errorf("failed to parse remote %s: %v", filerUidStr, filerUidErr)
  80. return
  81. }
  82. localToFiler[uint32(localUid)] = uint32(filerUid)
  83. filerToLocal[uint32(filerUid)] = uint32(localUid)
  84. }
  85. return
  86. }