195 lines
3.7 KiB
C++
195 lines
3.7 KiB
C++
#include <errno.h>
|
|
#include <unistd.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/time.h>
|
|
#include <arpa/inet.h>
|
|
#include <cstring>
|
|
#include <stdio.h>
|
|
#include <ctype.h>
|
|
#include <stdlib.h>
|
|
#include <fcntl.h>
|
|
#include <inttypes.h>
|
|
#include <errno.h>
|
|
#include "config.h"
|
|
#include "fs.h"
|
|
#include "clients/smbclient.h"
|
|
#include "util.h"
|
|
|
|
SmbClient::SmbClient()
|
|
{
|
|
}
|
|
|
|
SmbClient::~SmbClient()
|
|
{
|
|
}
|
|
|
|
int SmbClient::Connect(const std::string &url, const std::string &user, const std::string &pass)
|
|
{
|
|
struct smb2_url *smb_url;
|
|
|
|
smb2 = smb2_init_context();
|
|
if (smb2 == NULL)
|
|
{
|
|
sprintf(response, "Failed to init SMB context");
|
|
return 0;
|
|
}
|
|
|
|
smb_url = smb2_parse_url(smb2, url.c_str());
|
|
if (smb_url == NULL || smb_url->share == NULL || strlen(smb_url->share) == 0)
|
|
{
|
|
sprintf(response, "Invalid SMB Url");
|
|
return 0;
|
|
}
|
|
|
|
if (pass.length() > 0)
|
|
smb2_set_password(smb2, pass.c_str());
|
|
smb2_set_security_mode(smb2, SMB2_NEGOTIATE_SIGNING_ENABLED);
|
|
smb2_set_version(smb2, SMB2_VERSION_ANY);
|
|
smb2_set_timeout(smb2, 30);
|
|
|
|
if (smb2_connect_share(smb2, smb_url->server, smb_url->share, user.c_str()) < 0)
|
|
{
|
|
sprintf(response, "%s", smb2_get_error(smb2));
|
|
return 0;
|
|
}
|
|
|
|
smb2_destroy_url(smb_url);
|
|
connected = true;
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
* SmbLastResponse - return a pointer to the last response received
|
|
*/
|
|
const char *SmbClient::LastResponse()
|
|
{
|
|
return (const char *)response;
|
|
}
|
|
|
|
/*
|
|
* SmbQuit - disconnect from remote
|
|
*
|
|
* return 1 if successful, 0 otherwise
|
|
*/
|
|
int SmbClient::Quit()
|
|
{
|
|
smb2_destroy_context(smb2);
|
|
smb2 = NULL;
|
|
connected = false;
|
|
return 1;
|
|
}
|
|
/*
|
|
* SmbGet - issue a GET command and write received data to output
|
|
*
|
|
* return 1 if successful, 0 otherwise
|
|
*/
|
|
|
|
int SmbClient::Get(const std::string &outputfile, const std::string &ppath, uint64_t offset)
|
|
{
|
|
std::string path = std::string(ppath);
|
|
path = Util::Trim(path, "/");
|
|
|
|
struct smb2fh* in = smb2_open(smb2, path.c_str(), O_RDONLY);
|
|
if (in == NULL)
|
|
{
|
|
sprintf(response, "%s", smb2_get_error(smb2));
|
|
return 0;
|
|
}
|
|
|
|
FILE* out = NULL;
|
|
if (offset > 0)
|
|
{
|
|
out = FS::Append(outputfile);
|
|
}
|
|
else
|
|
{
|
|
out = FS::Create(outputfile);
|
|
}
|
|
|
|
if (out == NULL)
|
|
{
|
|
// sprintf(response, "%s", lang_strings[STR_FAILED]);
|
|
return 0;
|
|
}
|
|
|
|
uint8_t *buff = (uint8_t*)malloc(max_read_size);
|
|
int count = 0;
|
|
*g_bytes_transfered = offset;
|
|
|
|
if (offset > 0)
|
|
{
|
|
smb2_lseek(smb2, in, offset, SEEK_SET, NULL);
|
|
}
|
|
|
|
while ((count = smb2_read(smb2, in, buff, max_read_size)) != 0)
|
|
{
|
|
if (count < 0)
|
|
{
|
|
sprintf(response, "%s", smb2_get_error(smb2));
|
|
FS::Close(out);
|
|
smb2_close(smb2, in);
|
|
free((void*)buff);
|
|
return 0;
|
|
}
|
|
FS::Write(out, buff, count);
|
|
*g_bytes_transfered += count;
|
|
}
|
|
|
|
FS::Close(out);
|
|
smb2_close(smb2, in);
|
|
free((void*)buff);
|
|
return 1;
|
|
}
|
|
|
|
|
|
int SmbClient::GetRange(const std::string &ppath, DataSink &sink, uint64_t size, uint64_t offset)
|
|
{
|
|
std::string path = std::string(ppath);
|
|
path = Util::Trim(path, "/");
|
|
struct smb2fh *in = smb2_open(smb2, path.c_str(), O_RDONLY);
|
|
if (in == NULL)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int ret = this->GetRange((void *)in, sink, size, offset);
|
|
smb2_close(smb2, in);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int SmbClient::GetRange(void *fp, DataSink &sink, uint64_t size, uint64_t offset)
|
|
{
|
|
struct smb2fh *in = (struct smb2fh *)fp;
|
|
|
|
smb2_lseek(smb2, in, offset, SEEK_SET, NULL);
|
|
|
|
uint8_t *buff = (uint8_t *)malloc(max_read_size);
|
|
int count = 0;
|
|
size_t bytes_remaining = size;
|
|
do
|
|
{
|
|
size_t bytes_to_read = std::min<size_t>(max_read_size, bytes_remaining);
|
|
count = smb2_read(smb2, in, buff, bytes_to_read);
|
|
if (count > 0)
|
|
{
|
|
bytes_remaining -= count;
|
|
bool ok = sink.write((char *)buff, count);
|
|
if (!ok)
|
|
{
|
|
free((uint8_t *)buff);
|
|
return 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
} while (1);
|
|
|
|
free((char *)buff);
|
|
|
|
return 1;
|
|
}
|