From: Ralph Boehme Date: Wed, 20 May 2020 19:51:00 +0000 (+0200) Subject: vfs_preopen: implement SMB_VFS_OPENAT() X-Git-Tag: ldb-2.2.0~382 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3e5cb65fa85f698e8c3d8b7168081a397622f85f;p=thirdparty%2Fsamba.git vfs_preopen: implement SMB_VFS_OPENAT() Signed-off-by: Ralph Boehme Reviewed-by: Jeremy Allison --- diff --git a/source3/modules/vfs_preopen.c b/source3/modules/vfs_preopen.c index e7cdf9e4776..ade31ff4457 100644 --- a/source3/modules/vfs_preopen.c +++ b/source3/modules/vfs_preopen.c @@ -452,8 +452,87 @@ static int preopen_open(vfs_handle_struct *handle, return res; } +static int preopen_openat(struct vfs_handle_struct *handle, + const struct files_struct *dirfsp, + const struct smb_filename *smb_fname, + struct files_struct *fsp, + int flags, + mode_t mode) +{ + struct preopen_state *state; + int res; + unsigned long num; + + DEBUG(10, ("preopen_open called on %s\n", smb_fname_str_dbg(smb_fname))); + + state = preopen_state_get(handle); + if (state == NULL) { + return SMB_VFS_NEXT_OPENAT(handle, + dirfsp, + smb_fname, + fsp, + flags, + mode); + } + + res = SMB_VFS_NEXT_OPENAT(handle, dirfsp, smb_fname, fsp, flags, mode); + if (res == -1) { + return -1; + } + + if ((flags & O_ACCMODE) != O_RDONLY) { + return res; + } + + if (!is_in_path(smb_fname->base_name, state->preopen_names, true)) { + DEBUG(10, ("%s does not match the preopen:names list\n", + smb_fname_str_dbg(smb_fname))); + return res; + } + + TALLOC_FREE(state->template_fname); + state->template_fname = talloc_asprintf( + state, "%s/%s", + dirfsp->fsp_name->base_name, smb_fname->base_name); + + if (state->template_fname == NULL) { + return res; + } + + if (!preopen_parse_fname(state->template_fname, &num, + &state->number_start, &state->num_digits)) { + TALLOC_FREE(state->template_fname); + return res; + } + + if (num > state->fnum_sent) { + /* + * Helpers were too slow, there's no point in reading + * files in helpers that we already read in the + * parent. + */ + state->fnum_sent = num; + } + + if ((state->fnum_queue_end != 0) /* Something was started earlier */ + && (num < (state->fnum_queue_end - state->queue_max))) { + /* + * "num" is before the queue we announced. This means + * a new run is started. + */ + state->fnum_sent = num; + } + + state->fnum_queue_end = num + state->queue_max; + + preopen_queue_run(state); + + return res; +} + static struct vfs_fn_pointers vfs_preopen_fns = { - .open_fn = preopen_open + .open_fn = preopen_open, + .openat_fn = preopen_openat, }; static_decl_vfs;