version 1.12, 2019/02/12 19:39:57 |
version 1.13, 2019/02/14 18:26:52 |
|
|
* information that affects subsequent transmissions. |
* information that affects subsequent transmissions. |
*/ |
*/ |
#define FLIST_MODE_SAME 0x0002 /* mode is repeat */ |
#define FLIST_MODE_SAME 0x0002 /* mode is repeat */ |
|
#define FLIST_UID_SAME 0x0008 /* uid is repeat */ |
#define FLIST_GID_SAME 0x0010 /* gid is repeat */ |
#define FLIST_GID_SAME 0x0010 /* gid is repeat */ |
#define FLIST_NAME_SAME 0x0020 /* name is repeat */ |
#define FLIST_NAME_SAME 0x0020 /* name is repeat */ |
#define FLIST_NAME_LONG 0x0040 /* name >255 bytes */ |
#define FLIST_NAME_LONG 0x0040 /* name >255 bytes */ |
|
|
flist_send(struct sess *sess, int fdin, int fdout, const struct flist *fl, |
flist_send(struct sess *sess, int fdin, int fdout, const struct flist *fl, |
size_t flsz) |
size_t flsz) |
{ |
{ |
size_t i, sz, gidsz = 0; |
size_t i, sz, gidsz = 0, uidsz = 0; |
uint8_t flag; |
uint8_t flag; |
const struct flist *f; |
const struct flist *f; |
const char *fn; |
const char *fn; |
struct ident *gids = NULL; |
struct ident *gids = NULL, *uids = NULL; |
int rc = 0; |
int rc = 0; |
|
|
/* Double-check that we've no pending multiplexed data. */ |
/* Double-check that we've no pending multiplexed data. */ |
|
|
goto out; |
goto out; |
} |
} |
|
|
|
/* Conditional part: uid. */ |
|
|
|
if (sess->opts->preserve_uids) { |
|
if (!io_write_int(sess, fdout, f->st.uid)) { |
|
ERRX1(sess, "io_write_int"); |
|
goto out; |
|
} |
|
if (!idents_add(sess, 0, &uids, &uidsz, f->st.uid)) { |
|
ERRX1(sess, "idents_add"); |
|
goto out; |
|
} |
|
} |
|
|
/* Conditional part: gid. */ |
/* Conditional part: gid. */ |
|
|
if (sess->opts->preserve_gids) { |
if (sess->opts->preserve_gids) { |
|
|
ERRX1(sess, "io_write_int"); |
ERRX1(sess, "io_write_int"); |
goto out; |
goto out; |
} |
} |
if (!idents_gid_add(sess, &gids, &gidsz, f->st.gid)) { |
if (!idents_add(sess, 1, &gids, &gidsz, f->st.gid)) { |
ERRX1(sess, "idents_gid_add"); |
ERRX1(sess, "idents_add"); |
goto out; |
goto out; |
} |
} |
} |
} |
|
|
goto out; |
goto out; |
} |
} |
|
|
/* Conditionally write gid list and terminator. */ |
/* Conditionally write identifier lists. */ |
|
|
|
if (sess->opts->preserve_uids) { |
|
LOG2(sess, "sending uid list: %zu", uidsz); |
|
if (!idents_send(sess, fdout, uids, uidsz)) { |
|
ERRX1(sess, "idents_send"); |
|
goto out; |
|
} |
|
} |
|
|
if (sess->opts->preserve_gids) { |
if (sess->opts->preserve_gids) { |
LOG2(sess, "sending gid list: %zu", gidsz); |
LOG2(sess, "sending gid list: %zu", gidsz); |
if (!idents_send(sess, fdout, gids, gidsz)) { |
if (!idents_send(sess, fdout, gids, gidsz)) { |
|
|
rc = 1; |
rc = 1; |
out: |
out: |
idents_free(gids, gidsz); |
idents_free(gids, gidsz); |
|
idents_free(uids, uidsz); |
return rc; |
return rc; |
} |
} |
|
|
|
|
struct flist *fl = NULL; |
struct flist *fl = NULL; |
struct flist *ff; |
struct flist *ff; |
const struct flist *fflast = NULL; |
const struct flist *fflast = NULL; |
size_t flsz = 0, flmax = 0, lsz, gidsz = 0; |
size_t flsz = 0, flmax = 0, lsz, gidsz = 0, uidsz = 0; |
uint8_t flag; |
uint8_t flag; |
char last[MAXPATHLEN]; |
char last[MAXPATHLEN]; |
uint64_t lval; /* temporary values... */ |
uint64_t lval; /* temporary values... */ |
int32_t ival; |
int32_t ival; |
struct ident *gids = NULL; |
struct ident *gids = NULL, *uids = NULL; |
|
|
last[0] = '\0'; |
last[0] = '\0'; |
|
|
|
|
} else |
} else |
ff->st.mode = fflast->st.mode; |
ff->st.mode = fflast->st.mode; |
|
|
|
/* Conditional part: uid. */ |
|
|
|
if (sess->opts->preserve_uids) { |
|
if (!(FLIST_UID_SAME & flag)) { |
|
if (!io_read_int(sess, fd, &ival)) { |
|
ERRX1(sess, "io_read_int"); |
|
goto out; |
|
} |
|
ff->st.uid = ival; |
|
} else if (fflast == NULL) { |
|
ERRX(sess, "same uid " |
|
"without last entry"); |
|
goto out; |
|
} else |
|
ff->st.uid = fflast->st.uid; |
|
} |
|
|
/* Conditional part: gid. */ |
/* Conditional part: gid. */ |
|
|
if (sess->opts->preserve_gids) { |
if (sess->opts->preserve_gids) { |
|
|
sess->total_size += ff->st.size; |
sess->total_size += ff->st.size; |
} |
} |
|
|
/* |
/* Conditionally read the user/group list. */ |
* Now conditionally read the group list. |
|
* We then remap all group identifiers to the local ids. |
|
*/ |
|
|
|
|
if (sess->opts->preserve_uids) { |
|
if (!idents_recv(sess, fd, &uids, &uidsz)) { |
|
ERRX1(sess, "idents_recv"); |
|
goto out; |
|
} |
|
LOG2(sess, "received uid list: %zu", uidsz); |
|
} |
|
|
if (sess->opts->preserve_gids) { |
if (sess->opts->preserve_gids) { |
if (!idents_recv(sess, fd, &gids, &gidsz)) { |
if (!idents_recv(sess, fd, &gids, &gidsz)) { |
ERRX1(sess, "idents_recv"); |
ERRX1(sess, "idents_recv"); |
|
|
*sz = flsz; |
*sz = flsz; |
*flp = fl; |
*flp = fl; |
|
|
/* Lastly, remap and reassign group identifiers. */ |
/* Conditionally remap and reassign identifiers. */ |
|
|
|
if (sess->opts->preserve_uids) { |
|
idents_remap(sess, 0, uids, uidsz); |
|
idents_assign_uid(sess, fl, flsz, uids, uidsz); |
|
} |
|
|
if (sess->opts->preserve_gids) { |
if (sess->opts->preserve_gids) { |
idents_gid_remap(sess, gids, gidsz); |
idents_remap(sess, 1, gids, gidsz); |
idents_gid_assign(sess, fl, flsz, gids, gidsz); |
idents_assign_gid(sess, fl, flsz, gids, gidsz); |
} |
} |
|
|
idents_free(gids, gidsz); |
idents_free(gids, gidsz); |
|
idents_free(uids, uidsz); |
return 1; |
return 1; |
out: |
out: |
flist_free(fl, flsz); |
flist_free(fl, flsz); |
idents_free(gids, gidsz); |
idents_free(gids, gidsz); |
|
idents_free(uids, uidsz); |
*sz = 0; |
*sz = 0; |
*flp = NULL; |
*flp = NULL; |
return 0; |
return 0; |