1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-24 13:57:43 +03:00

libsmb: Implement SMB_FIND_FILE_UNIX_INFO2 dir listing

This keeps the original SMB_STRUCT_STAT coming from posix as part of
struct file_info. It is a slight waste of space, as the timestamps are
kept twice, but having a full SMB_STRUCT_STAT with the nlink!=0
validity check makes thinking about which mode/size/etc is the correct
one a no-brainer. We can save space later by referencing only one set
of time stamps for example.

This for the time fixes readdirplus2, but for the wrong reason: We don't yet
create files the "proper" way using posix create.

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
This commit is contained in:
Volker Lendecke 2020-02-28 11:10:47 +01:00 committed by Jeremy Allison
parent 128545ba4f
commit 890c94d585
3 changed files with 73 additions and 4 deletions

View File

@ -1,2 +0,0 @@
samba4.unix_ext.libsmbclient.readdirplus2.NT1.readdirplus2.*
samba4.unix_ext.libsmbclient.readdirplus_seek.NT1.readdirplus_seek.*

View File

@ -114,6 +114,12 @@ struct file_info {
struct timespec mtime_ts;
struct timespec atime_ts;
struct timespec ctime_ts;
/*
* Native sbuf from posix extensions. Valid if st_ex_nlink!=0.
*/
SMB_STRUCT_STAT posix_sbuf;
char *name;
char *short_name;
};

View File

@ -305,6 +305,63 @@ static size_t interpret_long_filename(TALLOC_CTX *ctx,
}
return calc_next_entry_offset(base, pdata_end);
}
case SMB_FIND_FILE_UNIX_INFO2:
{
SMB_STRUCT_STAT *sbuf = &finfo->posix_sbuf;
size_t namelen;
if (pdata_end - base < 128) {
return pdata_end - base;
}
p += 4; /* next entry offset */
if (p_resume_key) {
*p_resume_key = IVAL(p,0);
}
p += 4; /* fileindex */
fetch_file_unix_basic_info2((const uint8_t *)p, sbuf);
p += 116;
finfo->mode = S_ISDIR(sbuf->st_ex_mode) ?
FILE_ATTRIBUTE_DIRECTORY :
FILE_ATTRIBUTE_NORMAL;
if (sbuf->st_ex_mode & S_IXUSR) {
finfo->mode |= FILE_ATTRIBUTE_ARCHIVE;
}
finfo->size = sbuf->st_ex_size;
finfo->allocated_size =
sbuf->st_ex_blksize * sbuf->st_ex_blocks;
finfo->uid = sbuf->st_ex_uid;
finfo->gid = sbuf->st_ex_gid;
finfo->ino = sbuf->st_ex_ino;
finfo->btime_ts = sbuf->st_ex_btime;
finfo->mtime_ts = sbuf->st_ex_mtime;
finfo->atime_ts = sbuf->st_ex_atime;
finfo->ctime_ts = sbuf->st_ex_ctime;
namelen = IVAL(p, 0);
p += 4;
if (namelen > (pdata_end - p)) {
return pdata_end - base;
}
ret = clistr_pull_talloc(
ctx,
base_ptr,
recv_flags2,
&finfo->name,
p,
namelen,
0);
if (ret == (size_t)-1) {
return pdata_end - base;
}
return calc_next_entry_offset(base, pdata_end);
}
}
DEBUG(1,("Unknown long filename format %d\n",level));
@ -1043,6 +1100,7 @@ NTSTATUS cli_list(struct cli_state *cli, const char *mask, uint16_t attribute,
NTSTATUS status = NT_STATUS_NO_MEMORY;
struct file_info *finfo;
size_t i, num_finfo = 0;
uint32_t caps;
uint16_t info_level;
if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) {
@ -1063,8 +1121,15 @@ NTSTATUS cli_list(struct cli_state *cli, const char *mask, uint16_t attribute,
goto fail;
}
info_level = (smb1cli_conn_capabilities(cli->conn) & CAP_NT_SMBS)
? SMB_FIND_FILE_BOTH_DIRECTORY_INFO : SMB_FIND_INFO_STANDARD;
caps = smb1cli_conn_capabilities(cli->conn);
if (caps & CAP_UNIX) {
info_level = SMB_FIND_FILE_UNIX_INFO2;
} else if (caps & CAP_NT_SMBS) {
info_level = SMB_FIND_FILE_BOTH_DIRECTORY_INFO;
} else {
info_level = SMB_FIND_INFO_STANDARD;
}
req = cli_list_send(frame, ev, cli, mask, attribute, info_level);
if (req == NULL) {