Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
liblongpath-rsync
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
liblongpath
liblongpath-rsync
Commits
2df20057
Commit
2df20057
authored
Nov 16, 2008
by
Wayne Davison
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Adding the --usermap/--groupmap/--chown options.
parent
9556f156
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
312 additions
and
52 deletions
+312
-52
NEWS
NEWS
+3
-0
flist.c
flist.c
+7
-2
options.c
options.c
+92
-0
rsync.yo
rsync.yo
+54
-0
mapfrom
support/mapfrom
+5
-0
mapto
support/mapto
+5
-0
uidlist.c
uidlist.c
+146
-50
No files found.
NEWS
View file @
2df20057
...
...
@@ -26,6 +26,9 @@ Changes since 3.0.4:
protocol 31), and 3) to follow the file-count, created-count, and
deleted-count with a break-out list of each count by type.
- Added the --usermap/--groupmap/--chown options for manipulating file
ownership during the copy.
- Added the "%C" escape to the log-output handling, which will output the
MD5 checksum of any transferred file, or all files if --checksum was
specified (when protocol 30 or above is in effect).
...
...
flist.c
View file @
2df20057
...
...
@@ -72,6 +72,7 @@ extern int sender_keeps_checksum;
extern
int
unsort_ndx
;
extern
struct
stats
stats
;
extern
char
*
filesfrom_host
;
extern
char
*
usermap
,
*
groupmap
;
extern
char
curr_dir
[
MAXPATHLEN
];
...
...
@@ -802,7 +803,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
uid
=
(
uid_t
)
read_varint
(
f
);
if
(
xflags
&
XMIT_USER_NAME_FOLLOWS
)
uid
=
recv_user_name
(
f
,
uid
);
else
if
(
inc_recurse
&&
am_root
&&
!
numeric_ids
)
else
if
(
inc_recurse
&&
am_root
&&
(
!
numeric_ids
||
usermap
)
)
uid
=
match_uid
(
uid
);
}
}
...
...
@@ -814,7 +815,7 @@ static struct file_struct *recv_file_entry(struct file_list *flist,
gid_flags
=
0
;
if
(
xflags
&
XMIT_GROUP_NAME_FOLLOWS
)
gid
=
recv_group_name
(
f
,
gid
,
&
gid_flags
);
else
if
(
inc_recurse
&&
(
!
am_root
||
!
numeric_ids
))
else
if
(
inc_recurse
&&
(
!
am_root
||
!
numeric_ids
||
groupmap
))
gid
=
match_gid
(
gid
,
&
gid_flags
);
}
}
...
...
@@ -2303,6 +2304,10 @@ struct file_list *recv_file_list(int f)
else
if
(
inc_recurse
&&
INFO_GTE
(
FLIST
,
1
)
&&
!
am_server
)
rprintf
(
FCLIENT
,
"receiving incremental file list
\n
"
);
rprintf
(
FLOG
,
"receiving file list
\n
"
);
if
(
usermap
)
parse_name_map
(
usermap
,
True
);
if
(
groupmap
)
parse_name_map
(
groupmap
,
False
);
}
start_read
=
stats
.
total_read
;
...
...
options.c
View file @
2df20057
...
...
@@ -167,6 +167,8 @@ char *rsync_path = RSYNC_PATH;
char
*
backup_dir
=
NULL
;
char
backup_dir_buf
[
MAXPATHLEN
];
char
*
sockopts
=
NULL
;
char
*
usermap
=
NULL
;
char
*
groupmap
=
NULL
;
int
rsync_port
=
0
;
int
compare_dest
=
0
;
int
copy_dest
=
0
;
...
...
@@ -296,6 +298,7 @@ static int refused_delete, refused_archive_part, refused_compress;
static
int
refused_partial
,
refused_progress
,
refused_delete_before
;
static
int
refused_delete_during
;
static
int
refused_inplace
,
refused_no_iconv
;
static
BOOL
usermap_via_chown
,
groupmap_via_chown
;
static
char
*
max_size_arg
,
*
min_size_arg
;
static
char
tmp_partialdir
[]
=
".~tmp~"
;
...
...
@@ -725,6 +728,9 @@ void usage(enum logcode F)
rprintf
(
F
,
" --delay-updates put all updated files into place at transfer's end
\n
"
);
rprintf
(
F
,
" -m, --prune-empty-dirs prune empty directory chains from the file-list
\n
"
);
rprintf
(
F
,
" --numeric-ids don't map uid/gid values by user/group name
\n
"
);
rprintf
(
F
,
" --usermap=STRING custom username mapping
\n
"
);
rprintf
(
F
,
" --groupmap=STRING custom groupname mapping
\n
"
);
rprintf
(
F
,
" --chown=USER:GROUP simple username/groupname mapping
\n
"
);
rprintf
(
F
,
" --timeout=SECONDS set I/O timeout in seconds
\n
"
);
rprintf
(
F
,
" --contimeout=SECONDS set daemon connection timeout in seconds
\n
"
);
rprintf
(
F
,
" -I, --ignore-times don't skip files that match in size and mod-time
\n
"
);
...
...
@@ -789,6 +795,7 @@ enum {OPT_VERSION = 1000, OPT_DAEMON, OPT_SENDER, OPT_EXCLUDE, OPT_EXCLUDE_FROM,
OPT_INCLUDE
,
OPT_INCLUDE_FROM
,
OPT_MODIFY_WINDOW
,
OPT_MIN_SIZE
,
OPT_CHMOD
,
OPT_READ_BATCH
,
OPT_WRITE_BATCH
,
OPT_ONLY_WRITE_BATCH
,
OPT_MAX_SIZE
,
OPT_NO_D
,
OPT_APPEND
,
OPT_NO_ICONV
,
OPT_INFO
,
OPT_DEBUG
,
OPT_USERMAP
,
OPT_GROUPMAP
,
OPT_CHOWN
,
OPT_SERVER
,
OPT_REFUSED_BASE
=
9000
};
static
struct
poptOption
long_options
[]
=
{
...
...
@@ -969,6 +976,9 @@ static struct poptOption long_options[] = {
{
"no-s"
,
0
,
POPT_ARG_VAL
,
&
protect_args
,
0
,
0
,
0
},
{
"numeric-ids"
,
0
,
POPT_ARG_VAL
,
&
numeric_ids
,
1
,
0
,
0
},
{
"no-numeric-ids"
,
0
,
POPT_ARG_VAL
,
&
numeric_ids
,
0
,
0
,
0
},
{
"usermap"
,
0
,
POPT_ARG_STRING
,
0
,
OPT_USERMAP
,
0
,
0
},
{
"groupmap"
,
0
,
POPT_ARG_STRING
,
0
,
OPT_GROUPMAP
,
0
,
0
},
{
"chown"
,
0
,
POPT_ARG_STRING
,
0
,
OPT_CHOWN
,
0
,
0
},
{
"timeout"
,
0
,
POPT_ARG_INT
,
&
io_timeout
,
0
,
0
,
0
},
{
"no-timeout"
,
0
,
POPT_ARG_VAL
,
&
io_timeout
,
0
,
0
,
0
},
{
"contimeout"
,
0
,
POPT_ARG_INT
,
&
connect_timeout
,
0
,
0
,
0
},
...
...
@@ -1625,6 +1635,76 @@ int parse_arguments(int *argc_p, const char ***argv_p)
parse_output_words
(
debug_words
,
debug_levels
,
arg
,
USER_PRIORITY
);
break
;
case
OPT_USERMAP
:
if
(
usermap
)
{
if
(
usermap_via_chown
)
{
snprintf
(
err_buf
,
sizeof
err_buf
,
"--usermap conflicts with prior --chown.
\n
"
);
return
0
;
}
snprintf
(
err_buf
,
sizeof
err_buf
,
"You can only specify --usermap once.
\n
"
);
return
0
;
}
usermap
=
(
char
*
)
poptGetOptArg
(
pc
);
usermap_via_chown
=
False
;
break
;
case
OPT_GROUPMAP
:
if
(
groupmap
)
{
if
(
groupmap_via_chown
)
{
snprintf
(
err_buf
,
sizeof
err_buf
,
"--groupmap conflicts with prior --chown.
\n
"
);
return
0
;
}
snprintf
(
err_buf
,
sizeof
err_buf
,
"You can only specify --groupmap once.
\n
"
);
return
0
;
}
groupmap
=
(
char
*
)
poptGetOptArg
(
pc
);
groupmap_via_chown
=
False
;
break
;
case
OPT_CHOWN
:
{
const
char
*
chown
=
poptGetOptArg
(
pc
);
int
len
;
if
((
arg
=
strchr
(
chown
,
':'
))
!=
NULL
)
len
=
arg
++
-
chown
;
else
len
=
strlen
(
chown
);
if
(
len
)
{
if
(
usermap
)
{
if
(
!
usermap_via_chown
)
{
snprintf
(
err_buf
,
sizeof
err_buf
,
"--chown conflicts with prior --usermap.
\n
"
);
return
0
;
}
snprintf
(
err_buf
,
sizeof
err_buf
,
"You can only specify a user-affecting --chown once.
\n
"
);
return
0
;
}
if
(
asprintf
(
&
usermap
,
"*:%.*s"
,
len
,
chown
)
<
0
)
out_of_memory
(
"parse_arguments"
);
usermap_via_chown
=
True
;
}
if
(
arg
&&
*
arg
)
{
if
(
groupmap
)
{
if
(
!
groupmap_via_chown
)
{
snprintf
(
err_buf
,
sizeof
err_buf
,
"--chown conflicts with prior --groupmap.
\n
"
);
return
0
;
}
snprintf
(
err_buf
,
sizeof
err_buf
,
"You can only specify a group-affecting --chown once.
\n
"
);
return
0
;
}
if
(
asprintf
(
&
groupmap
,
"*:%s"
,
arg
)
<
0
)
out_of_memory
(
"parse_arguments"
);
groupmap_via_chown
=
True
;
}
break
;
}
case
OPT_HELP
:
usage
(
FINFO
);
exit_cleanup
(
0
);
...
...
@@ -2435,6 +2515,18 @@ void server_options(char **args, int *argc_p)
args
[
ac
++
]
=
"--use-qsort"
;
if
(
am_sender
)
{
if
(
usermap
)
{
if
(
asprintf
(
&
arg
,
"--usermap=%s"
,
usermap
)
<
0
)
goto
oom
;
args
[
ac
++
]
=
arg
;
}
if
(
groupmap
)
{
if
(
asprintf
(
&
arg
,
"--groupmap=%s"
,
groupmap
)
<
0
)
goto
oom
;
args
[
ac
++
]
=
arg
;
}
if
(
ignore_existing
)
args
[
ac
++
]
=
"--ignore-existing"
;
...
...
rsync.yo
View file @
2df20057
...
...
@@ -385,6 +385,9 @@ to the detailed description below for a complete description. verb(
--delay-updates put all updated files into place at end
-m, --prune-empty-dirs prune empty directory chains from file-list
--numeric-ids don't map uid/gid values by user/group name
--usermap=STRING custom username mapping
--groupmap=STRING custom groupname mapping
--chown=USER:GROUP simple username/groupname mapping
--timeout=SECONDS set I/O timeout in seconds
--contimeout=SECONDS set daemon connection timeout in seconds
-I, --ignore-times don't skip files that match size and time
...
...
@@ -1716,6 +1719,57 @@ from the source system is used instead. See also the comments on the
the chroot setting affects rsync's ability to look up the names of the
users and groups and what you can do about it.
dit(bf(--usermap=STRING, --groupmap=STRING)) These options allow you to
specify users and groups that should be mapped to other values by the
receiving side. The bf(STRING) is one or more bf(FROM):bf(TO) pairs of
values separated by commas. Any matching bf(FROM) value from the sender is
replaced with a bf(TO) value from the receiver. You may specify usernames
or user IDs for the bf(FROM) and bf(TO) values, and the bf(FROM) value may
also be a wild-card string, which will be matched against the sender's
names (wild-cards do NOT match against ID numbers, though see below for
why a '*' matches everything). You may instead specify a range of ID
numbers via an inclusive range: LOW-HIGH. For example:
verb( --usermap=0-99:nobody,wayne:admin,*:normal --groupmap=usr:1,1:usr)
The first match in the list is the one that is used. You should specify
all your user mappings using a single bf(--usermap) option, and/or all
your group mappings using a single bf(--groupmap) option.
Note that the sender's name for the 0 user and group are not transmitted
to the receiver, so you should either match these values using a 0, or use
the names in effect on the receiving side (typically "root"). All other
bf(FROM) names match those in use on the sending side. All bf(TO) names
match those in use on the receiving side.
Any IDs that do not have a name on the sending side are treated as having an
empty name for the purpose of matching. This allows them to be matched via
a "*" or using an empty name. For instance:
verb( --usermap=:nobody --groupmap=*:nobody)
When the bf(--numeric-ids) option is used, the sender does not send any
names, so all the IDs are treated as having an empty name. This means that
you will need to specify numeric bf(FROM) values if you want to map these
nameless IDs to different values.
For the bf(--usermap) option to have any effect, the bf(-o) (bf(--owner))
option must be used (or implied), and the receiver will need to be running
as a super-user (see also the bf(--fake-super) option). For the bf(--groupmap)
option to have any effect, the bf(-g) (bf(--groups)) option must be used
(or implied), and the receiver will need to have permissions to set that
group.
dit(bf(--chown=USER:GROUP)) This option forces all files to be owned by USER
with group GROUP. This is a simpler interface than using bf(--usermap) and
bf(--groupmap) directly, but it is implemented using those options internally,
so you cannot mix them. If either the USER or GROUP is empty, no mapping for
the omitted user/group will occur. If GROUP is empty, the trailing colon may
be omitted, but if USER is empty, a leading colon must be supplied.
If you specify "--chown=foo:bar, this is exactly the same as specifying
"--usermap=*:foo --groupmap=*:bar", only easier.
dit(bf(--timeout=TIMEOUT)) This option allows you to set a maximum I/O
timeout in seconds. If no data is transferred for the specified time
then rsync will exit. The default is 0, which means no timeout.
...
...
support/mapfrom
0 → 100644
View file @
2df20057
#!/usr/bin/perl
while
(
<>
)
{
push
@_
,
"$2:$1"
if
/^(\w+):[^:]+:(\d+)/
;
}
print
join
(
','
,
@_
),
"\n"
;
support/mapto
0 → 100644
View file @
2df20057
#!/usr/bin/perl
while
(
<>
)
{
push
@_
,
"$1:$2"
if
/^(\w+):[^:]+:(\d+)/
;
}
print
join
(
','
,
@_
),
"\n"
;
uidlist.c
View file @
2df20057
...
...
@@ -24,6 +24,8 @@
* are special. */
#include "rsync.h"
#include "ifuncs.h"
#include "itypes.h"
#include "io.h"
extern
int
am_root
;
...
...
@@ -31,6 +33,8 @@ extern int preserve_uid;
extern
int
preserve_gid
;
extern
int
preserve_acls
;
extern
int
numeric_ids
;
extern
char
*
usermap
;
extern
char
*
groupmap
;
#ifdef HAVE_GETGROUPS
# ifndef GETGROUPS_T
...
...
@@ -40,6 +44,9 @@ extern int numeric_ids;
#define GID_NONE ((gid_t)-1)
#define NFLAGS_WILD_NAME_MATCH (1<<0)
#define NFLAGS_NAME_MATCH (1<<1)
struct
idlist
{
struct
idlist
*
next
;
const
char
*
name
;
...
...
@@ -47,8 +54,8 @@ struct idlist {
uint16
flags
;
};
static
struct
idlist
*
uidlist
;
static
struct
idlist
*
gidlist
;
static
struct
idlist
*
uidlist
,
*
uidmap
;
static
struct
idlist
*
gidlist
,
*
gidmap
;
static
struct
idlist
*
add_to_list
(
struct
idlist
**
root
,
id_t
id
,
const
char
*
name
,
id_t
id2
,
uint16
flags
)
...
...
@@ -83,22 +90,6 @@ static const char *gid_to_name(gid_t gid)
return
NULL
;
}
static
uid_t
map_uid
(
uid_t
id
,
const
char
*
name
)
{
uid_t
uid
;
if
(
id
!=
0
&&
name_to_uid
(
name
,
&
uid
))
return
uid
;
return
id
;
}
static
gid_t
map_gid
(
gid_t
id
,
const
char
*
name
)
{
gid_t
gid
;
if
(
id
!=
0
&&
name_to_gid
(
name
,
&
gid
))
return
gid
;
return
id
;
}
static
int
is_in_group
(
gid_t
gid
)
{
#ifdef HAVE_GETGROUPS
...
...
@@ -158,34 +149,53 @@ static int is_in_group(gid_t gid)
#endif
}
/* Add a uid to the list of uids. Only called on receiving side. */
static
struct
idlist
*
recv_add_uid
(
uid_t
id
,
const
char
*
name
)
/* Add a uid/gid to its list of ids. Only called on receiving side. */
static
struct
idlist
*
recv_add_id
(
struct
idlist
**
idlist_ptr
,
struct
idlist
*
idmap
,
id_t
id
,
const
char
*
name
)
{
uid_t
id2
=
name
?
map_uid
(
id
,
name
)
:
id
;
struct
idlist
*
node
;
int
flag
;
id_t
id2
;
node
=
add_to_list
(
&
uidlist
,
id
,
name
,
id2
,
0
);
if
(
!
name
)
name
=
""
;
if
(
DEBUG_GTE
(
OWN
,
2
))
{
rprintf
(
FINFO
,
"uid %u(%s) maps to %u
\n
"
,
(
unsigned
)
id
,
name
?
name
:
""
,
(
unsigned
)
id2
);
for
(
node
=
idmap
;
node
;
node
=
node
->
next
)
{
if
(
node
->
flags
&
NFLAGS_WILD_NAME_MATCH
)
{
if
(
!
wildmatch
(
node
->
name
,
name
))
continue
;
}
else
if
(
node
->
flags
&
NFLAGS_NAME_MATCH
)
{
if
(
strcmp
(
node
->
name
,
name
)
!=
0
)
continue
;
}
else
if
(
node
->
name
)
{
if
(
id
<
node
->
id
||
id
>
(
unsigned
long
)
node
->
name
)
continue
;
}
else
{
if
(
node
->
id
!=
id
)
continue
;
}
break
;
}
if
(
node
)
id2
=
node
->
id2
;
else
if
(
*
name
&&
id
)
{
if
(
idmap
==
uidmap
)
{
uid_t
uid
;
id2
=
name_to_uid
(
name
,
&
uid
)
?
uid
:
id
;
}
else
{
gid_t
gid
;
id2
=
name_to_gid
(
name
,
&
gid
)
?
gid
:
id
;
}
}
else
id2
=
id
;
return
node
;
}
/* Add a gid to the list of gids. Only called on receiving side. */
static
struct
idlist
*
recv_add_gid
(
gid_t
id
,
const
char
*
name
)
{
gid_t
id2
=
name
?
map_gid
(
id
,
name
)
:
id
;
struct
idlist
*
node
;
node
=
add_to_list
(
&
gidlist
,
id
,
name
,
id2
,
!
am_root
&&
!
is_in_group
(
id2
)
?
FLAG_SKIP_GROUP
:
0
);
flag
=
idmap
==
gidmap
&&
!
am_root
&&
!
is_in_group
(
id2
)
?
FLAG_SKIP_GROUP
:
0
;
node
=
add_to_list
(
idlist_ptr
,
id
,
*
name
?
name
:
NULL
,
id2
,
flag
);
if
(
DEBUG_GTE
(
OWN
,
2
))
{
rprintf
(
FINFO
,
"gid %u(%s) maps to %u
\n
"
,
(
unsigned
)
id
,
name
?
name
:
""
,
(
unsigned
)
id2
);
rprintf
(
FINFO
,
"%sid %u(%s) maps to %u
\n
"
,
idmap
==
uidmap
?
"u"
:
"g"
,
(
unsigned
)
id
,
name
,
(
unsigned
)
id2
);
}
return
node
;
...
...
@@ -194,12 +204,9 @@ static struct idlist *recv_add_gid(gid_t id, const char *name)
/* this function is a definate candidate for a faster algorithm */
uid_t
match_uid
(
uid_t
uid
)
{
static
uid_t
last_in
,
last_out
;
static
uid_t
last_in
=
-
1
,
last_out
=
-
1
;
struct
idlist
*
list
;
if
(
uid
==
0
)
return
0
;
if
(
uid
==
last_in
)
return
last_out
;
...
...
@@ -207,10 +214,13 @@ uid_t match_uid(uid_t uid)
for
(
list
=
uidlist
;
list
;
list
=
list
->
next
)
{
if
(
list
->
id
==
uid
)
return
last_out
=
list
->
id2
;
break
;
}
return
last_out
=
uid
;
if
(
!
list
)
list
=
recv_add_id
(
&
uidlist
,
uidmap
,
uid
,
NULL
);
return
last_out
=
list
->
id2
;
}
gid_t
match_gid
(
gid_t
gid
,
uint16
*
flags_ptr
)
...
...
@@ -226,7 +236,7 @@ gid_t match_gid(gid_t gid, uint16 *flags_ptr)
break
;
}
if
(
!
list
)
list
=
recv_add_
gid
(
gid
,
NULL
);
list
=
recv_add_
id
(
&
gidlist
,
gidmap
,
gid
,
NULL
);
last
=
list
;
}
...
...
@@ -319,7 +329,7 @@ uid_t recv_user_name(int f, uid_t uid)
free
(
name
);
name
=
NULL
;
}
node
=
recv_add_
uid
(
uid
,
name
);
/* node keeps name's memory */
node
=
recv_add_
id
(
&
uidlist
,
uidmap
,
uid
,
name
);
/* node keeps name's memory */
return
node
->
id2
;
}
...
...
@@ -335,7 +345,7 @@ gid_t recv_group_name(int f, gid_t gid, uint16 *flags_ptr)
free
(
name
);
name
=
NULL
;
}
node
=
recv_add_
gid
(
gid
,
name
);
/* node keeps name's memory */
node
=
recv_add_
id
(
&
gidlist
,
gidmap
,
gid
,
name
);
/* node keeps name's memory */
if
(
flags_ptr
&&
node
->
flags
&
FLAG_SKIP_GROUP
)
*
flags_ptr
|=
FLAG_SKIP_GROUP
;
return
node
->
id2
;
...
...
@@ -362,17 +372,103 @@ void recv_id_list(int f, struct file_list *flist)
/* Now convert all the uids/gids from sender values to our values. */
#ifdef SUPPORT_ACLS
if
(
preserve_acls
&&
!
numeric_ids
)
if
(
preserve_acls
&&
(
!
numeric_ids
||
usermap
||
groupmap
)
)
match_acl_ids
();
#endif
if
(
am_root
&&
preserve_uid
&&
!
numeric_ids
)
{
if
(
am_root
&&
preserve_uid
&&
(
!
numeric_ids
||
usermap
)
)
{
for
(
i
=
0
;
i
<
flist
->
used
;
i
++
)
F_OWNER
(
flist
->
files
[
i
])
=
match_uid
(
F_OWNER
(
flist
->
files
[
i
]));
}
if
(
preserve_gid
&&
(
!
am_root
||
!
numeric_ids
))
{
if
(
preserve_gid
&&
(
!
am_root
||
!
numeric_ids
||
groupmap
))
{
for
(
i
=
0
;
i
<
flist
->
used
;
i
++
)
{
F_GROUP
(
flist
->
files
[
i
])
=
match_gid
(
F_GROUP
(
flist
->
files
[
i
]),
&
flist
->
files
[
i
]
->
flags
);
}
}
}
void
parse_name_map
(
char
*
map
,
BOOL
usernames
)
{
struct
idlist
**
idmap_ptr
=
usernames
?
&
uidmap
:
&
gidmap
;
struct
idlist
**
idlist_ptr
=
usernames
?
&
uidlist
:
&
gidlist
;
char
*
colon
,
*
end
,
*
name
,
*
cp
=
map
+
strlen
(
map
);
id_t
id1
;
uint16
flags
;
/* Parse the list in reverse, so the order in the struct is right. */
while
(
1
)
{
end
=
cp
;
while
(
cp
>
map
&&
cp
[
-
1
]
!=
','
)
cp
--
;
if
(
!
(
colon
=
strchr
(
cp
,
':'
)))
{
rprintf
(
FERROR
,
"No colon found in --%smap: %s
\n
"
,
usernames
?
"user"
:
"group"
,
cp
);
exit_cleanup
(
RERR_SYNTAX
);
}
if
(
!
colon
[
1
])
{
rprintf
(
FERROR
,
"No name found after colon --%smap: %s
\n
"
,
usernames
?
"user"
:
"group"
,
cp
);
exit_cleanup
(
RERR_SYNTAX
);
}
*
colon
=
'\0'
;
if
(
isDigit
(
cp
))
{
char
*
dash
=
strchr
(
cp
,
'-'
);
if
(
strspn
(
cp
,
"0123456789-"
)
!=
(
size_t
)(
colon
-
cp
)
||
(
dash
&&
(
!
dash
[
1
]
||
strchr
(
dash
+
1
,
'-'
))))
{
bad_number:
rprintf
(
FERROR
,
"Invalid number in --%smap: %s
\n
"
,
usernames
?
"user"
:
"group"
,
cp
);
exit_cleanup
(
RERR_SYNTAX
);
}
if
(
dash
)
name
=
(
char
*
)
atol
(
dash
+
1
);
else
name
=
(
char
*
)
0
;
flags
=
0
;
id1
=
atol
(
cp
);
}
else
if
(
strpbrk
(
cp
,
"*[?"
))
{
flags
=
NFLAGS_WILD_NAME_MATCH
;
name
=
cp
;
id1
=
0
;
}
else
{
flags
=
NFLAGS_NAME_MATCH
;
name
=
cp
;
id1
=
0
;
}
if
(
isDigit
(
colon
+
1
))
{
if
(
strspn
(
colon
+
1
,
"0123456789"
)
!=
(
size_t
)(
end
-
colon
-
1
))
{
cp
=
colon
+
1
;
goto
bad_number
;
}
add_to_list
(
idmap_ptr
,
id1
,
name
,
atol
(
colon
+
1
),
flags
);
}
else
if
(
usernames
)
{
uid_t
uid
;
if
(
name_to_uid
(
colon
+
1
,
&
uid
))
add_to_list
(
idmap_ptr
,
id1
,
name
,
uid
,
flags
);
else
{
rprintf
(
FERROR
,
"Unknown --usermap name on receiver: %s
\n
"
,
colon
+
1
);
}
}
else
{
gid_t
gid
;
if
(
name_to_gid
(
colon
+
1
,
&
gid
))
add_to_list
(
idmap_ptr
,
id1
,
name
,
gid
,
flags
);
else
{
rprintf
(
FERROR
,
"Unknown --groupmap name on receiver: %s
\n
"
,
colon
+
1
);
}
}
if
(
cp
==
map
)
break
;
*--
cp
=
'\0'
;
/* replace comma */
}
/* The 0 user/group doesn't get its name sent, so add it explicitly. */
recv_add_id
(
idlist_ptr
,
*
idmap_ptr
,
0
,
numeric_ids
?
NULL
:
usernames
?
uid_to_name
(
0
)
:
gid_to_name
(
0
));
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment