main pico / pkg / rsync-receiver / rsyncreceiver / uidlist.go
Eric Bower  ·  2026-05-31
 1package rsyncreceiver
 2
 3import (
 4	"io"
 5)
 6
 7type mapping struct {
 8	Name    string
 9	LocalId int32
10}
11
12func (rt *Transfer) recvIdMapping1(localId func(id int32, name string) int32) (map[int32]mapping, error) {
13	idMapping := make(map[int32]mapping)
14	for {
15		id, err := rt.Conn.ReadInt32()
16		if err != nil {
17			return nil, err
18		}
19		if id == 0 {
20			break
21		}
22		length, err := rt.Conn.ReadByte()
23		if err != nil {
24			return nil, err
25		}
26		name := make([]byte, length)
27		if _, err := io.ReadFull(rt.Conn.Reader, name); err != nil {
28			return nil, err
29		}
30		idMapping[id] = mapping{
31			Name:    string(name),
32			LocalId: localId(id, string(name)),
33		}
34	}
35	return idMapping, nil
36}
37
38// rsync/uidlist.c:recv_id_list.
39func (rt *Transfer) RecvIdList() (users map[int32]mapping, groups map[int32]mapping, _ error) {
40	if rt.Opts.PreserveUid {
41		var err error
42		users, err = rt.recvIdMapping1(func(remoteUid int32, remoteUsername string) int32 {
43			// TODO: look up local uid by username
44			return remoteUid
45		})
46		if err != nil {
47			return nil, nil, err
48		}
49		for remoteUid, mapping := range users {
50			rt.Logger.Debug("remote uid maps to local uid", "remoteUid", remoteUid, "name", mapping.Name, "localUid", mapping.LocalId)
51		}
52	}
53
54	if rt.Opts.PreserveGid {
55		var err error
56		groups, err = rt.recvIdMapping1(func(remoteGid int32, remoteGroupname string) int32 {
57			// TODO: look up local gid by groupname
58			return remoteGid
59		})
60		if err != nil {
61			return nil, nil, err
62		}
63		for remoteGid, mapping := range groups {
64			rt.Logger.Debug("remote gid maps to local gid", "remoteGid", remoteGid, "name", mapping.Name, "localGid", mapping.LocalId)
65		}
66	}
67
68	return users, groups, nil
69}