Changing smb_filename->base_name in VFS module.

Vadim Lazovskiy vadim.lazovskiy at gmail.com
Mon Sep 3 11:37:49 UTC 2018


>
>
> 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.


More information about the samba-technical mailing list