Changing smb_filename->base_name in VFS module.
Jeremy Allison
jra at samba.org
Tue Sep 4 17:12:56 UTC 2018
On Mon, Sep 03, 2018 at 02:37:49PM +0300, Vadim Lazovskiy via samba-technical wrote:
> >
> >
> > You are going to have to implement more VFS functions. At least
> > realpath and stat, I would imagine.
> >
> >
> Thank you for your reply.
>
> Still no luck.
>
> I've implemented ssdcache_stat function as follows:
>
> struct smb_filename *ssdcache_find_cached_file(vfs_handle_struct *handle,
> const struct smb_filename *smb_fname)
> {
> vfs_ssdcache_module_ctx_t *ctx;
>
> size_t i, len, max_len = 0;
> struct smb_filename *ret;
> char *new_base_name;
> const char **cache_paths;
>
> SMB_VFS_HANDLE_GET_DATA(handle, ctx, vfs_ssdcache_module_ctx_t,
> return NULL);
>
> if (!ctx->initialized) {
> errno = ENOENT;
> return NULL;
> }
>
> for (i = 0; ctx->cache_paths[i]; i++) {
> if (strstr(smb_fname->base_name, ctx->cache_paths[i]) !=
> NULL) {
> errno = ENOENT;
> return NULL;
> }
> }
>
> max_len = ctx->cache_path_max_len + strlen(smb_fname->base_name) +
> 2; // for slash and \0
> new_base_name = talloc_zero_size(talloc_tos(), max_len);
>
> if (new_base_name == NULL) {
> errno = ENOMEM;
> return NULL;
> }
>
> /* Allocate new smb_filename structure */
> ret = synthetic_smb_fname(talloc_tos(), new_base_name, NULL, NULL,
> smb_fname->flags);
>
> if (ret == NULL) {
> errno = ENOMEM;
> return NULL;
> }
>
> for (i = 0; ctx->cache_paths[i]; i++) {
> strlcat(ret->base_name, ctx->cache_paths[i], max_len);
> strlcat(ret->base_name, "/", max_len);
> strlcat(ret->base_name, smb_fname->base_name, max_len);
>
> if (access(ret->base_name, F_OK) == 0) {
> break;
> }
>
> *ret->base_name = '\0';
> }
>
> if (*ret->base_name == '\0') {
> TALLOC_FREE(new_base_name);
> TALLOC_FREE(ret);
>
> errno = ENOENT;
> return NULL;
> }
>
> return ret;
> }
>
> static int ssdcache_stat(vfs_handle_struct *handle, struct smb_filename
> *smb_fname)
> {
> vfs_ssdcache_module_ctx_t *ctx;
>
> int ret;
> struct smb_filename *smb_fname_new;
>
> SMB_VFS_HANDLE_GET_DATA(handle, ctx, vfs_ssdcache_module_ctx_t,
> return -1);
>
> if (!ctx->initialized) {
> return SMB_VFS_NEXT_STAT(handle, smb_fname);
> }
>
> /* stat file */
> if ((ret = sys_stat(smb_fname->base_name, &smb_fname->st, true)) !=
> 0) {
> return ret;
> }
>
> /* skip directories */
> if (S_ISDIR(smb_fname->st.st_ex_mode)) {
> return ret;
> }
>
> /* find cached copy */
> smb_fname_new = ssdcache_find_cached_file(handle, smb_fname);
>
> if (smb_fname_new != NULL) {
> smb_fname = smb_fname_new;
> ret = sys_stat(smb_fname->base_name, &smb_fname->st, true);
> }
>
> return ret;
> }
>
> It gave no results.
> Also realpath seems to be called only once at connect-to-share time.
>
> I have no ideas left. I overwrite all possible stat structures in
> smb_filename, but somehow somewhere structure for original file persist.
> Judging to strace:
>
> open(".cache/ssd03/1066/1066.1.avi", O_RDONLY) = 34
> fstat(34, {st_mode=S_IFREG|0666, st_size=727977984, ...}) = 0
> close(34)
>
> I can conclude that original file stat structure is compared to the result
> of fstat call on the cached file descriptor. They are defenitely different,
> so I get an error.
> I want try to implement fstat function with dev/ino spoofing in my module,
> but stuck with NULL value of fsp->fsp_name->base_name and
> fsp->fsp_name->stream_name.
> Can't determine wheither fstat-ed descriptor's file exists in cache.
>
> I appreciate any help. Thank you.
Can you post the entire source code of your vfs module please ?
That way I can take a look at it in entirity.
More information about the samba-technical
mailing list