Skip to content
Snippets Groups Projects
Commit 2a6a684d authored by Thomas Guillem's avatar Thomas Guillem Committed by Jean-Baptiste Kempf
Browse files

samba: use the new API

And fix potential data races, that could have become criticial with the
new medialibary (more than one samba access in //). Indeed, the SMBCCTX
and SMBCFILE were stored statically and fetch from an unique fd without
any lock mechanism.
parent 3c486ed9
No related branches found
No related tags found
Loading
Pipeline #169812 passed with stage
in 15 minutes and 15 seconds
......@@ -40,7 +40,23 @@
typedef struct
{
int i_smb;
SMBCCTX *ctx;
SMBCFILE *file;
union
{
struct {
smbc_close_fn close;
smbc_read_fn read;
smbc_lseek_fn lseek;
} filevt;
struct {
smbc_closedir_fn closedir;
smbc_stat_fn stat;
smbc_readdir_fn readdir;
} dirvt;
};
uint64_t size;
vlc_url_t url;
} access_sys_t;
......@@ -83,7 +99,7 @@ static int Seek( stream_t *p_access, uint64_t i_pos )
msg_Dbg( p_access, "seeking to %"PRId64, i_pos );
i_ret = smbc_lseek( p_sys->i_smb, i_pos, SEEK_SET );
i_ret = p_sys->filevt.lseek( p_sys->ctx, p_sys->file, i_pos, SEEK_SET );
if( i_ret == -1 )
{
msg_Err( p_access, "seek failed (%s)", vlc_strerror_c(errno) );
......@@ -105,13 +121,11 @@ static ssize_t Read( stream_t *p_access, void *p_buffer, size_t i_len )
* than this limit will likely result on a ECONNABORTED
* (STATUS_CONNECTION_ABORTED) error. Since this value can be lowered by
* the server, let decrease this limit (/8) to have more chance to get a
* working limit on our side.
* XXX: There is no way to retrieve this value when using the old smbc_*
* interface. */
* working limit on our side. */
if( i_len > (1024 << 10) ) /* 8MB / 8 = 1MB */
i_len = 1024 << 10;
i_read = smbc_read( p_sys->i_smb, p_buffer, i_len );
i_read = p_sys->filevt.read( p_sys->ctx, p_sys->file, p_buffer, i_len );
if( i_read < 0 )
{
msg_Err( p_access, "read failed (%s)", vlc_strerror_c(errno) );
......@@ -134,7 +148,7 @@ static int DirRead (stream_t *p_access, input_item_node_t *p_node )
struct smbc_dirent *p_entry;
while( i_ret == VLC_SUCCESS && ( p_entry = smbc_readdir( p_sys->i_smb ) ) )
while( i_ret == VLC_SUCCESS && ( p_entry = p_sys->dirvt.readdir( p_sys->ctx, p_sys->file ) ) )
{
const char *psz_server = p_sys->url.psz_host;
const char *psz_path = p_sys->url.psz_path;
......@@ -180,7 +194,7 @@ static int DirRead (stream_t *p_access, input_item_node_t *p_node )
break;
}
struct stat st;
smbc_stat(uri, &st);
p_sys->dirvt.stat(p_sys->ctx, uri, &st);
input_item_t *p_item;
free(psz_encoded_name);
......@@ -260,17 +274,26 @@ static int Open(vlc_object_t *obj)
vlc_url_t url;
vlc_credential credential;
char *psz_decoded_path = NULL, *uri, *psz_var_domain = NULL;
int fd;
uint64_t size;
bool is_dir;
int ret = VLC_EGENERIC;
SMBCFILE *file = NULL;
SMBCCTX *ctx;
if (smbc_init(smb_auth, 0))
return VLC_EGENERIC;
ctx = smbc_new_context();
if (ctx == NULL)
return VLC_ENOMEM;
smbc_setDebug(ctx, 0);
smbc_setFunctionAuthData(ctx, smb_auth);
if (!smbc_init_context(ctx))
goto error;
if (vlc_UrlParseFixup(&url, access->psz_url) != 0)
{
vlc_UrlClean(&url);
return VLC_EGENERIC;
goto error;
}
if (url.psz_path != NULL)
......@@ -279,7 +302,7 @@ static int Open(vlc_object_t *obj)
if (psz_decoded_path == NULL)
{
vlc_UrlClean(&url);
return VLC_EGENERIC;
goto error;
}
}
......@@ -288,6 +311,9 @@ static int Open(vlc_object_t *obj)
credential.psz_realm = psz_var_domain;
vlc_credential_get(&credential, access, "smb-user", "smb-pwd", NULL, NULL);
smbc_stat_fn stat_fn = smbc_getFunctionStat(ctx);
assert(stat_fn);
for (;;)
{
struct stat st;
......@@ -301,10 +327,12 @@ static int Open(vlc_object_t *obj)
free(psz_var_domain);
free(psz_decoded_path);
vlc_UrlClean(&url);
return VLC_ENOMEM;
ret = VLC_ENOMEM;
goto error;
}
if (smbc_stat(uri, &st) == 0)
if (stat_fn(ctx, uri, &st) == 0)
{
is_dir = S_ISDIR(st.st_mode) != 0;
size = st.st_size;
......@@ -343,34 +371,58 @@ static int Open(vlc_object_t *obj)
if (is_dir)
{
smbc_opendir_fn opendir_fn = smbc_getFunctionOpendir(ctx);
assert(opendir_fn);
sys->dirvt.closedir = smbc_getFunctionClosedir(ctx);
assert(sys->dirvt.closedir);
sys->dirvt.readdir = smbc_getFunctionReaddir(ctx);
assert(sys->dirvt.readdir);
sys->dirvt.stat = stat_fn;
sys->url = url;
access->pf_readdir = DirRead;
access->pf_control = access_vaDirectoryControlHelper;
fd = smbc_opendir(uri);
if (fd < 0)
file = opendir_fn(ctx, uri);
if (file == NULL)
vlc_UrlClean(&sys->url);
}
else
{
smbc_open_fn open_fn = smbc_getFunctionOpen(ctx);
assert(open_fn);
sys->filevt.close = smbc_getFunctionClose(ctx);
assert(sys->filevt.close);
sys->filevt.read = smbc_getFunctionRead(ctx);
assert(sys->filevt.read);
sys->filevt.lseek = smbc_getFunctionLseek(ctx);
assert(sys->filevt.lseek);
access->pf_read = Read;
access->pf_control = Control;
access->pf_seek = Seek;
fd = smbc_open(uri, O_RDONLY, 0);
file = open_fn(ctx, uri, O_RDONLY, 0);
vlc_UrlClean(&url);
}
free(uri);
if (fd < 0)
if (file == NULL)
{
msg_Err(obj, "cannot open %s: %s",
access->psz_location, vlc_strerror_c(errno));
return VLC_EGENERIC;
goto error;
}
sys->size = size;
sys->i_smb = fd;
sys->ctx = ctx;
sys->file = file;
return VLC_SUCCESS;
error:
smbc_free_context(ctx, 1);
return ret;
}
static void Close(vlc_object_t *obj)
......@@ -381,9 +433,11 @@ static void Close(vlc_object_t *obj)
vlc_UrlClean(&sys->url);
if (access->pf_readdir != NULL)
smbc_closedir(sys->i_smb);
sys->dirvt.closedir(sys->ctx, sys->file);
else
smbc_close(sys->i_smb);
sys->filevt.close(sys->ctx, sys->file);
smbc_free_context(sys->ctx, 1);
}
vlc_module_begin()
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment