mirror of
https://github.com/samba-team/samba.git
synced 2024-12-25 23:21:54 +03:00
s3: Fix streams enumeration bug in OneFS implementation
Previously, we didn’t call SMB_VFS_OPEN_DIR from the streams module, instead we called fdopendir(). As a result we failed to populate the dir_state list in the readdirplus module. So when we tried to view the stream data, we will always returned NULL. To solve this I separated onefs_opendir() and the initialization of the dir_state list. This is done by introducing a new utility function “onefs_rdp_add_dir_state()”, which initializes the dir_state structure and adds it to the dir_state list. This function is called from the streams module before calling readdir().
This commit is contained in:
parent
c19214424b
commit
8e8aa27e1b
@ -224,6 +224,9 @@ NTSTATUS onefs_split_ntfs_stream_name(TALLOC_CTX *mem_ctx, const char *fname,
|
||||
|
||||
bool onefs_get_config(int snum, int config_type,
|
||||
struct onefs_vfs_config *cfg);
|
||||
|
||||
int onefs_rdp_add_dir_state(connection_struct *conn, SMB_STRUCT_DIR *dirp);
|
||||
|
||||
/*
|
||||
* System Interfaces
|
||||
*/
|
||||
|
@ -182,6 +182,54 @@ rdp_fill_cache(struct rdp_dir_state *dsp)
|
||||
return nread;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a dir_state to track an open directory that we're enumerating.
|
||||
*
|
||||
* This utility function is globally accessible for use by other parts of the
|
||||
* onefs.so module to initialize a dir_state when a directory is opened through
|
||||
* a path other than the VFS layer.
|
||||
*
|
||||
* @return 0 on success and errno on failure
|
||||
*
|
||||
* @note: Callers of this function MUST cleanup the dir_state through a proper
|
||||
* call to VFS_CLOSEDIR().
|
||||
*/
|
||||
int
|
||||
onefs_rdp_add_dir_state(connection_struct *conn, SMB_STRUCT_DIR *dirp)
|
||||
{
|
||||
int ret = 0;
|
||||
struct rdp_dir_state *dsp = NULL;
|
||||
|
||||
/* No-op if readdirplus is disabled */
|
||||
if (!lp_parm_bool(SNUM(conn), PARM_ONEFS_TYPE,
|
||||
PARM_USE_READDIRPLUS, PARM_USE_READDIRPLUS_DEFAULT))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Create a struct dir_state */
|
||||
dsp = SMB_MALLOC_P(struct rdp_dir_state);
|
||||
if (!dsp) {
|
||||
DEBUG(0, ("Error allocating struct rdp_dir_state.\n"));
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
/* Initialize the dir_state structure and add it to the list */
|
||||
ret = rdp_init(dsp);
|
||||
if (ret) {
|
||||
DEBUG(0, ("Error initializing readdirplus() buffers: %s\n",
|
||||
strerror(ret)));
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Set the SMB_STRUCT_DIR in the dsp */
|
||||
dsp->dirp = dirp;
|
||||
|
||||
DLIST_ADD(dirstatelist, dsp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a directory for enumeration.
|
||||
*
|
||||
@ -201,7 +249,6 @@ onefs_opendir(vfs_handle_struct *handle, const char *fname, const char *mask,
|
||||
{
|
||||
int ret = 0;
|
||||
SMB_STRUCT_DIR *ret_dirp;
|
||||
struct rdp_dir_state *dsp = NULL;
|
||||
|
||||
/* Fallback to default system routines if readdirplus is disabled */
|
||||
if (!lp_parm_bool(SNUM(handle->conn), PARM_ONEFS_TYPE,
|
||||
@ -210,13 +257,6 @@ onefs_opendir(vfs_handle_struct *handle, const char *fname, const char *mask,
|
||||
return SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr);
|
||||
}
|
||||
|
||||
/* Create a struct dir_state */
|
||||
dsp = SMB_MALLOC_P(struct rdp_dir_state);
|
||||
if (!dsp) {
|
||||
DEBUG(0, ("Error allocating struct rdp_dir_state.\n"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Open the directory */
|
||||
ret_dirp = SMB_VFS_NEXT_OPENDIR(handle, fname, mask, attr);
|
||||
if (!ret_dirp) {
|
||||
@ -224,21 +264,15 @@ onefs_opendir(vfs_handle_struct *handle, const char *fname, const char *mask,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Initialize the dir_state structure and add it to the list */
|
||||
ret = rdp_init(dsp);
|
||||
/* Create the dir_state struct and add it to the list */
|
||||
ret = onefs_rdp_add_dir_state(handle->conn, ret_dirp);
|
||||
if (ret) {
|
||||
DEBUG(0, ("Error initializing readdirplus() buffers: %s\n",
|
||||
strerror(ret)));
|
||||
DEBUG(0, ("Error adding dir_state to the list\n"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Set the SMB_STRUCT_DIR in the dsp */
|
||||
dsp->dirp = ret_dirp;
|
||||
|
||||
DLIST_ADD(dirstatelist, dsp);
|
||||
|
||||
DEBUG(9, ("Opened handle on directory: \"%s\", DIR %p\n",
|
||||
fname, dsp->dirp));
|
||||
fname, ret_dirp));
|
||||
|
||||
return ret_dirp;
|
||||
}
|
||||
|
@ -540,6 +540,19 @@ static NTSTATUS walk_onefs_streams(connection_struct *conn, files_struct *fsp,
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Initialize the dir state struct and add it to the list.
|
||||
* This is a layer violation, and really should be handled by a
|
||||
* VFS_FDOPENDIR() call which would properly setup the dir state.
|
||||
* But since this is all within the onefs.so module, we cheat for
|
||||
* now and call directly into the readdirplus code.
|
||||
* NOTE: This state MUST be freed by a proper VFS_CLOSEDIR() call. */
|
||||
ret = onefs_rdp_add_dir_state(conn, dirp);
|
||||
if (ret) {
|
||||
DEBUG(0, ("Error adding dir_state to the list\n"));
|
||||
status = map_nt_error_from_unix(errno);
|
||||
goto out;
|
||||
}
|
||||
|
||||
fake_fs.conn = conn;
|
||||
fake_fs.fh = &fake_fh;
|
||||
fake_fs.fsp_name = SMB_STRDUP(fname);
|
||||
|
Loading…
Reference in New Issue
Block a user