mirror of
https://github.com/octoleo/syncthing.git
synced 2024-11-19 03:25:16 +00:00
83 lines
2.2 KiB
Go
83 lines
2.2 KiB
Go
|
// Copyright (C) 2022 The Syncthing Authors.
|
||
|
//
|
||
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
||
|
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||
|
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
||
|
|
||
|
package model
|
||
|
|
||
|
import (
|
||
|
"errors"
|
||
|
"os/user"
|
||
|
"strings"
|
||
|
|
||
|
"github.com/syncthing/syncthing/lib/protocol"
|
||
|
)
|
||
|
|
||
|
func (f *sendReceiveFolder) syncOwnership(file *protocol.FileInfo, path string) error {
|
||
|
if file.Platform.Windows == nil || file.Platform.Windows.OwnerName == "" {
|
||
|
// No owner data, nothing to do
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
l.Debugln("Owner name for %s is %s (group=%v)", path, file.Platform.Windows.OwnerName, file.Platform.Windows.OwnerIsGroup)
|
||
|
usid, gsid, err := lookupUserAndGroup(file.Platform.Windows.OwnerName, file.Platform.Windows.OwnerIsGroup)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
l.Debugln("Owner for %s resolved to uid=%q gid=%q", path, usid, gsid)
|
||
|
return f.mtimefs.Lchown(path, usid, gsid)
|
||
|
}
|
||
|
|
||
|
func lookupUserAndGroup(name string, group bool) (string, string, error) {
|
||
|
// Look up either the the user or the group, returning the other kind as
|
||
|
// blank. This might seem an odd maneuver, but it matches what Chown
|
||
|
// wants as input and hides the ugly nested if:s down here.
|
||
|
|
||
|
if group {
|
||
|
gr, err := lookupWithoutDomain(name, func(name string) (string, error) {
|
||
|
gr, err := user.LookupGroup(name)
|
||
|
if err == nil {
|
||
|
return gr.Gid, nil
|
||
|
}
|
||
|
return "", err
|
||
|
})
|
||
|
if err != nil {
|
||
|
return "", "", err
|
||
|
}
|
||
|
return "", gr, nil
|
||
|
}
|
||
|
|
||
|
us, err := lookupWithoutDomain(name, func(name string) (string, error) {
|
||
|
us, err := user.Lookup(name)
|
||
|
if err == nil {
|
||
|
return us.Uid, nil
|
||
|
}
|
||
|
return "", err
|
||
|
})
|
||
|
if err != nil {
|
||
|
return "", "", err
|
||
|
}
|
||
|
return us, "", nil
|
||
|
}
|
||
|
|
||
|
func lookupWithoutDomain(name string, lookup func(s string) (string, error)) (string, error) {
|
||
|
// Try to look up the user by name. The username will be either a plain
|
||
|
// username or a qualified DOMAIN\user. We'll first try to look up
|
||
|
// whatever we got, if that fails, we'll try again with just the user
|
||
|
// part without domain.
|
||
|
|
||
|
v, err := lookup(name)
|
||
|
if err == nil {
|
||
|
return v, nil
|
||
|
}
|
||
|
parts := strings.Split(name, `\`)
|
||
|
if len(parts) == 2 {
|
||
|
if v, err := lookup(parts[1]); err == nil {
|
||
|
return v, nil
|
||
|
}
|
||
|
}
|
||
|
return "", errors.New("lookup failed")
|
||
|
}
|