mirror of
https://github.com/obarthel/amiga-smbfs.git
synced 2025-12-08 14:58:35 +00:00
Merge branch 'master' of https://github.com/obarthel/amiga-smbfs
This commit is contained in:
@@ -2725,3 +2725,50 @@ smbfs 2.5 (16.12.2018)
|
||||
|
||||
- This version fixes the instant crash in the fully optimized 68k/020+
|
||||
builds, which was cased by a missing __saveds keyword.
|
||||
|
||||
|
||||
smbfs 2.6 (16.12.2018)
|
||||
|
||||
- Added the WRITETHRESHOLD parameter which can be used to disable the
|
||||
separate transmission of the SMB message header and its payload if
|
||||
the combined sizes of both are smaller than or equal to the
|
||||
threshold value. This is intended to improve write performance for
|
||||
small amounts of data which would otherwise linger in the
|
||||
transmission queue.
|
||||
|
||||
|
||||
smbfs 2.7 (17.12.2018)
|
||||
|
||||
- Added the READTHRESHOLD counterpart to WRITETHRESHOLD which affects
|
||||
the read operations.
|
||||
|
||||
- The smb_receive_raw() function in "sock.c" no longer copies the NetBIOS
|
||||
header into the receive buffer separately, but makes sure that the
|
||||
initial receive operation takes care of it.
|
||||
|
||||
- The allocate_path_name() function in "smb_abstraction.c" failed to put
|
||||
the path separator character where it should be, resulting in the path
|
||||
name and the file/directory name to get lumped together. This affected
|
||||
creation of files and directories both.
|
||||
|
||||
|
||||
smbfs 2.8 (19.12.2018)
|
||||
|
||||
- The default values for READTHRESHOLD and WRITETHRESHOLD now have the
|
||||
effect of transmitting the SMB header and the payload separately,
|
||||
just like it was introduces in version 2.1.
|
||||
|
||||
Use something like READTHRESHOLD=1500 and WRITETHRESHOLD=1500 to
|
||||
send packets smaller than or equal to 1500 bytes as a combined
|
||||
lump of data, and data larger than 1500 bytes as separate SMB
|
||||
header and payload.
|
||||
|
||||
- When processing the share name the limitations on the individual
|
||||
components (server name, share, port number/IP service name) are
|
||||
no longer verified using hard-coded lengths, but use the respective
|
||||
buffer limits instead. The port number/IP service name length
|
||||
check is new.
|
||||
|
||||
- Added more debug log output to the code which now performs the
|
||||
file and lock name/address lookups instead of walking through
|
||||
the entire file/lock lists.
|
||||
|
||||
@@ -28,6 +28,11 @@ struct smb_server
|
||||
data blocks */
|
||||
dword max_raw_size; /* Maximum SMB_COM_WRITE_RAW and
|
||||
SMB_COM_READ_RAW data. */
|
||||
dword smb_write_threshold; /* If SMB header + payload size is smaller
|
||||
than or equal to this threshold, send
|
||||
both in a single combined send() operation
|
||||
rather than separately. */
|
||||
dword smb_read_threshold; /* Same as above, but for recv() operations. */
|
||||
int max_recv; /* added by CS */
|
||||
word server_uid;
|
||||
word tid;
|
||||
|
||||
+282
-144
@@ -261,7 +261,7 @@ static ULONG stack_usage_exit(const struct StackSwapStruct * stk);
|
||||
static LONG CVSPrintf(const TEXT * format_string, APTR args);
|
||||
static int LocalVSNPrintf(STRPTR buffer, int limit, const TEXT * formatString, APTR args);
|
||||
static void cleanup(void);
|
||||
static BOOL setup(const TEXT * program_name, const TEXT * service, const TEXT * workgroup, STRPTR username, STRPTR opt_password, BOOL opt_change_username_case, BOOL opt_change_password_case, const TEXT * opt_clientname, const TEXT * opt_servername, int opt_cachesize, int opt_max_transmit, int opt_timeout, LONG *opt_time_zone_offset, LONG *opt_dst_offset, BOOL opt_raw_smb, BOOL opt_unicode, BOOL opt_prefer_core_protocol, BOOL opt_session_setup_delay_unicode, BOOL opt_write_behind, const TEXT * device_name, const TEXT * volume_name, BOOL add_volume, const TEXT * translation_file);
|
||||
static BOOL setup(const TEXT * program_name, const TEXT * service, const TEXT * workgroup, STRPTR username, STRPTR opt_password, BOOL opt_change_username_case, BOOL opt_change_password_case, const TEXT * opt_clientname, const TEXT * opt_servername, int opt_cachesize, int opt_max_transmit, int opt_timeout, LONG *opt_time_zone_offset, LONG *opt_dst_offset, BOOL opt_raw_smb, BOOL opt_unicode, BOOL opt_prefer_core_protocol, BOOL opt_session_setup_delay_unicode, BOOL opt_write_behind, int opt_smb_request_write_threshold, int opt_smb_request_read_threshold, const TEXT * device_name, const TEXT * volume_name, BOOL add_volume, const TEXT * translation_file);
|
||||
static void file_system_handler(BOOL raise_priority, const TEXT * device_name, const TEXT * volume_name, const TEXT * service_name);
|
||||
|
||||
/****************************************************************************/
|
||||
@@ -758,6 +758,8 @@ main(void)
|
||||
KEY Protocol;
|
||||
SWITCH NetBIOSTransport;
|
||||
SWITCH WriteBehind;
|
||||
NUMBER WriteThreshold;
|
||||
NUMBER ReadThreshold;
|
||||
KEY SessionSetup;
|
||||
KEY Unicode;
|
||||
SWITCH CP437;
|
||||
@@ -798,6 +800,8 @@ main(void)
|
||||
"PROTOCOL/K,"
|
||||
"NETBIOS/S,"
|
||||
"WRITEBEHIND/S,"
|
||||
"WRITETHRESHOLD/N/K,"
|
||||
"READTHRESHOLD/N/K,"
|
||||
"SESSIONSETUP/K,"
|
||||
"UNICODE/K,"
|
||||
"CP437/S,"
|
||||
@@ -817,6 +821,8 @@ main(void)
|
||||
LONG tz_number, dst_number, debug_number;
|
||||
LONG cache_size = 0;
|
||||
LONG max_transmit = -1;
|
||||
LONG smb_write_threshold = 0;
|
||||
LONG smb_read_threshold = 0;
|
||||
LONG timeout = 0;
|
||||
TEXT env_protocol[8];
|
||||
TEXT env_workgroup_name[17];
|
||||
@@ -1015,6 +1021,30 @@ main(void)
|
||||
args.MaxNameLen = &MaxNameLen;
|
||||
}
|
||||
|
||||
str = get_icon_tool_type_value("WRITETHRESHOLD", NULL);
|
||||
if(str != NULL)
|
||||
{
|
||||
if(StrToLong(str,&smb_write_threshold) == -1)
|
||||
{
|
||||
report_error("Invalid number '%s' for 'WRITETHRESHOLD' parameter.",str);
|
||||
goto out;
|
||||
}
|
||||
|
||||
args.WriteThreshold = &smb_write_threshold;
|
||||
}
|
||||
|
||||
str = get_icon_tool_type_value("READTHRESHOLD", NULL);
|
||||
if(str != NULL)
|
||||
{
|
||||
if(StrToLong(str,&smb_read_threshold) == -1)
|
||||
{
|
||||
report_error("Invalid number '%s' for 'READTHRESHOLD' parameter.",str);
|
||||
goto out;
|
||||
}
|
||||
|
||||
args.ReadThreshold = &smb_read_threshold;
|
||||
}
|
||||
|
||||
str = get_icon_tool_type_value("TZ","TIMEZONEOFFSET");
|
||||
if(str != NULL)
|
||||
{
|
||||
@@ -1326,8 +1356,8 @@ main(void)
|
||||
{
|
||||
SHOWMSG("using code page 437 translation");
|
||||
|
||||
memmove(map_amiga_to_smb_name,unicode_to_cp437,sizeof(unicode_to_cp437));
|
||||
memmove(map_smb_to_amiga_name,cp437_to_unicode,sizeof(cp437_to_unicode));
|
||||
memcpy(map_amiga_to_smb_name,unicode_to_cp437,sizeof(unicode_to_cp437));
|
||||
memcpy(map_smb_to_amiga_name,cp437_to_unicode,sizeof(cp437_to_unicode));
|
||||
|
||||
TranslateNames = TRUE;
|
||||
}
|
||||
@@ -1335,8 +1365,8 @@ main(void)
|
||||
{
|
||||
SHOWMSG("using code page 850 translation");
|
||||
|
||||
memmove(map_amiga_to_smb_name,unicode_to_cp850,sizeof(unicode_to_cp850));
|
||||
memmove(map_smb_to_amiga_name,cp850_to_unicode,sizeof(cp850_to_unicode));
|
||||
memcpy(map_amiga_to_smb_name,unicode_to_cp850,sizeof(unicode_to_cp850));
|
||||
memcpy(map_smb_to_amiga_name,cp850_to_unicode,sizeof(cp850_to_unicode));
|
||||
|
||||
TranslateNames = TRUE;
|
||||
}
|
||||
@@ -1381,6 +1411,16 @@ main(void)
|
||||
}
|
||||
}
|
||||
|
||||
if(args.WriteThreshold == NULL)
|
||||
args.WriteThreshold = &smb_write_threshold;
|
||||
|
||||
D(("write threshold = %ld", (*args.WriteThreshold)));
|
||||
|
||||
if(args.ReadThreshold == NULL)
|
||||
args.ReadThreshold = &smb_read_threshold;
|
||||
|
||||
D(("read threshold = %ld", (*args.ReadThreshold)));
|
||||
|
||||
DisableExAll = (BOOL)(args.DisableExAll != 0);
|
||||
CaseSensitive = (BOOL)(args.CaseSensitive != 0);
|
||||
OmitHidden = (BOOL)(args.OmitHidden != 0);
|
||||
@@ -1492,6 +1532,8 @@ main(void)
|
||||
Stricmp(args.Protocol,"CORE") == SAME,
|
||||
Stricmp(args.SessionSetup,"DELAY") == SAME,
|
||||
args.WriteBehind,
|
||||
(*args.WriteThreshold),
|
||||
(*args.ReadThreshold),
|
||||
args.DeviceName,
|
||||
args.VolumeName,
|
||||
get_switch_status(args.AddVolume, TRUE),
|
||||
@@ -2910,41 +2952,71 @@ find_file_node_by_name(const TEXT * name,const struct FileNode * skip)
|
||||
struct FileNode * result = NULL;
|
||||
struct FileNode * fn;
|
||||
|
||||
#ifndef USE_SPLAY_TREE
|
||||
ASSERT( name != NULL );
|
||||
|
||||
for(fn = (struct FileNode *)FileList.mlh_Head ;
|
||||
fn->fn_MinNode.mln_Succ != NULL ;
|
||||
fn = (struct FileNode *)fn->fn_MinNode.mln_Succ)
|
||||
#ifndef USE_SPLAY_TREE
|
||||
{
|
||||
if(fn != skip && compare_names(name,fn->fn_FullName) == SAME)
|
||||
D(("searching for file with name '%s'", name));
|
||||
|
||||
for(fn = (struct FileNode *)FileList.mlh_Head ;
|
||||
fn->fn_MinNode.mln_Succ != NULL ;
|
||||
fn = (struct FileNode *)fn->fn_MinNode.mln_Succ)
|
||||
{
|
||||
result = fn;
|
||||
break;
|
||||
if(fn != skip && compare_names(name,fn->fn_FullName) == SAME)
|
||||
{
|
||||
result = fn;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(result != NULL)
|
||||
D(("found it (= 0x%08lx)", result));
|
||||
else
|
||||
D(("didn't find it"));
|
||||
}
|
||||
#else
|
||||
{
|
||||
struct splay_node * sn;
|
||||
|
||||
D(("looking up file with name '%s'", name));
|
||||
|
||||
/* Find the list of all files which match the given name. */
|
||||
sn = splay_tree_find(&FileNameTree, (splay_key_t)name);
|
||||
if(sn != NULL)
|
||||
{
|
||||
fn = (struct FileNode *)sn->sn_userdata;
|
||||
|
||||
ASSERT( fn != NULL );
|
||||
|
||||
/* Use this entry, unless it's the one which we
|
||||
* wanted to skip.
|
||||
*/
|
||||
if (fn != skip)
|
||||
{
|
||||
result = fn;
|
||||
|
||||
D(("found it (= 0x%08lx)", result));
|
||||
}
|
||||
/* Use the next entry in the list, if possible. */
|
||||
else if (sn->sn_next != NULL)
|
||||
{
|
||||
result = (struct FileNode *)sn->sn_next->sn_userdata;
|
||||
|
||||
D(("found it, but can't use it, so using the next best entry (= 0x%08lx)", result));
|
||||
|
||||
if(result == NULL)
|
||||
D(("...but didn't actually find it"));
|
||||
}
|
||||
else
|
||||
{
|
||||
D(("didn't find it"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
D(("didn't find it"));
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
struct splay_node * sn;
|
||||
|
||||
/* Find the list of all files which match the given name. */
|
||||
sn = splay_tree_find(&FileNameTree, (splay_key_t)name);
|
||||
if(sn != NULL)
|
||||
{
|
||||
fn = (struct FileNode *)sn->sn_userdata;
|
||||
|
||||
ASSERT( fn != NULL );
|
||||
|
||||
/* Use this entry, unless it's the one which we
|
||||
* wanted to skip.
|
||||
*/
|
||||
if (fn != skip)
|
||||
result = fn;
|
||||
/* Use the next entry in the list, if possible. */
|
||||
else if (sn->sn_next != NULL)
|
||||
result = (struct FileNode *)sn->sn_next->sn_userdata;
|
||||
}
|
||||
|
||||
#endif /* USE_SPLAY_TREE */
|
||||
|
||||
return(result);
|
||||
@@ -2960,35 +3032,63 @@ find_lock_node_by_name(const TEXT * name,const struct LockNode * skip)
|
||||
struct LockNode * ln;
|
||||
|
||||
#ifndef USE_SPLAY_TREE
|
||||
|
||||
for(ln = (struct LockNode *)LockList.mlh_Head ;
|
||||
ln->ln_MinNode.mln_Succ != NULL ;
|
||||
ln = (struct LockNode *)ln->ln_MinNode.mln_Succ)
|
||||
{
|
||||
if(ln != skip && compare_names(name,ln->ln_FullName) == SAME)
|
||||
D(("searching for lock with name '%s'", name));
|
||||
|
||||
for(ln = (struct LockNode *)LockList.mlh_Head ;
|
||||
ln->ln_MinNode.mln_Succ != NULL ;
|
||||
ln = (struct LockNode *)ln->ln_MinNode.mln_Succ)
|
||||
{
|
||||
result = ln;
|
||||
break;
|
||||
if(ln != skip && compare_names(name,ln->ln_FullName) == SAME)
|
||||
{
|
||||
result = ln;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(result != NULL)
|
||||
D(("found it (= 0x%08lx)", result));
|
||||
else
|
||||
D(("didn't find it"));
|
||||
}
|
||||
#else
|
||||
{
|
||||
struct splay_node * sn;
|
||||
|
||||
D(("looking up lock with name '%s'", name));
|
||||
|
||||
sn = splay_tree_find(&LockNameTree, (splay_key_t)name);
|
||||
if(sn != NULL)
|
||||
{
|
||||
ln = (struct LockNode *)sn->sn_userdata;
|
||||
|
||||
ASSERT( ln != NULL );
|
||||
|
||||
if (ln != skip)
|
||||
{
|
||||
result = ln;
|
||||
|
||||
D(("found it (= 0x%08lx)", result));
|
||||
}
|
||||
else if (sn->sn_next != NULL)
|
||||
{
|
||||
result = (struct LockNode *)sn->sn_next->sn_userdata;
|
||||
|
||||
D(("found it, but can't use it, so using the next best entry (= 0x%08lx)", result));
|
||||
|
||||
if(result == NULL)
|
||||
D(("...but didn't actually find it"));
|
||||
}
|
||||
else
|
||||
{
|
||||
D(("didn't find it"));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
D(("didn't find it"));
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
struct splay_node * sn;
|
||||
|
||||
sn = splay_tree_find(&LockNameTree, (splay_key_t)name);
|
||||
if(sn != NULL)
|
||||
{
|
||||
ln = (struct LockNode *)sn->sn_userdata;
|
||||
|
||||
ASSERT( ln != NULL );
|
||||
|
||||
if (ln != skip)
|
||||
result = ln;
|
||||
else if (sn->sn_next != NULL)
|
||||
result = (struct LockNode *)sn->sn_next->sn_userdata;
|
||||
}
|
||||
|
||||
#endif /* USE_SPLAY_TREE */
|
||||
|
||||
return(result);
|
||||
@@ -3659,6 +3759,8 @@ setup(
|
||||
BOOL opt_prefer_core_protocol,
|
||||
BOOL opt_session_setup_delay_unicode,
|
||||
BOOL opt_write_behind,
|
||||
int opt_smb_request_write_threshold,
|
||||
int opt_smb_request_read_threshold,
|
||||
const TEXT * device_name,
|
||||
const TEXT * volume_name,
|
||||
BOOL opt_add_volume,
|
||||
@@ -3681,19 +3783,19 @@ setup(
|
||||
NewList((struct List *)&LockList);
|
||||
|
||||
#ifdef USE_SPLAY_TREE
|
||||
{
|
||||
/* File names may not be unique. */
|
||||
splay_tree_init(&FileNameTree, (splay_key_compare_t)compare_names);
|
||||
FileNameTree.st_allow_duplicates = TRUE;
|
||||
|
||||
/* File names may not be unique. */
|
||||
splay_tree_init(&FileNameTree, (splay_key_compare_t)compare_names);
|
||||
FileNameTree.st_allow_duplicates = TRUE;
|
||||
splay_tree_init(&FileAddressTree, compare_file_or_lock_by_address);
|
||||
|
||||
splay_tree_init(&FileAddressTree, compare_file_or_lock_by_address);
|
||||
|
||||
/* Lock names may not be unique. */
|
||||
splay_tree_init(&LockNameTree, (splay_key_compare_t)compare_names);
|
||||
LockNameTree.st_allow_duplicates = TRUE;
|
||||
|
||||
splay_tree_init(&LockAddressTree, compare_file_or_lock_by_address);
|
||||
/* Lock names may not be unique. */
|
||||
splay_tree_init(&LockNameTree, (splay_key_compare_t)compare_names);
|
||||
LockNameTree.st_allow_duplicates = TRUE;
|
||||
|
||||
splay_tree_init(&LockAddressTree, compare_file_or_lock_by_address);
|
||||
}
|
||||
#endif /* USE_SPLAY_TREE */
|
||||
|
||||
MemoryPool = CreatePool(MEMF_ANY|MEMF_PUBLIC, 4096, 4096);
|
||||
@@ -3898,6 +4000,8 @@ setup(
|
||||
CaseSensitive,
|
||||
opt_session_setup_delay_unicode,
|
||||
opt_write_behind,
|
||||
opt_smb_request_write_threshold,
|
||||
opt_smb_request_read_threshold,
|
||||
&error,
|
||||
&smb_error_class,
|
||||
&smb_error,
|
||||
@@ -4082,15 +4186,15 @@ add_file_node(struct FileNode * fn)
|
||||
AddTail((struct List *)&FileList,(struct Node *)fn);
|
||||
|
||||
#ifdef USE_SPLAY_TREE
|
||||
{
|
||||
fn->fn_SplayNameNode.sn_key = (splay_key_t)fn->fn_FullName;
|
||||
fn->fn_SplayNameNode.sn_userdata = fn;
|
||||
splay_tree_add(&FileNameTree, &fn->fn_SplayNameNode);
|
||||
|
||||
fn->fn_SplayNameNode.sn_key = (splay_key_t)fn->fn_FullName;
|
||||
fn->fn_SplayNameNode.sn_userdata = fn;
|
||||
splay_tree_add(&FileNameTree, &fn->fn_SplayNameNode);
|
||||
|
||||
fn->fn_SplayAddressNode.sn_key = (splay_key_t)fn;
|
||||
fn->fn_SplayAddressNode.sn_userdata = fn;
|
||||
splay_tree_add(&FileAddressTree, &fn->fn_SplayAddressNode);
|
||||
|
||||
fn->fn_SplayAddressNode.sn_key = (splay_key_t)fn;
|
||||
fn->fn_SplayAddressNode.sn_userdata = fn;
|
||||
splay_tree_add(&FileAddressTree, &fn->fn_SplayAddressNode);
|
||||
}
|
||||
#endif /* USE_SPLAY_TREE */
|
||||
}
|
||||
|
||||
@@ -4104,10 +4208,17 @@ remove_file_node(struct FileNode * fn)
|
||||
Remove((struct Node *)fn);
|
||||
|
||||
#ifdef USE_SPLAY_TREE
|
||||
{
|
||||
APTR found;
|
||||
|
||||
splay_tree_remove(&FileNameTree, &fn->fn_SplayNameNode, (splay_key_t)fn->fn_FullName);
|
||||
splay_tree_remove(&FileAddressTree, NULL, (splay_key_t)fn);
|
||||
found = splay_tree_remove(&FileNameTree, &fn->fn_SplayNameNode, (splay_key_t)fn->fn_FullName);
|
||||
|
||||
D(("file name node removal %s", found != NULL ? "succeeded" : "failed"));
|
||||
|
||||
found = splay_tree_remove(&FileAddressTree, NULL, (splay_key_t)fn);
|
||||
|
||||
D(("file address node removal %s", found != NULL ? "succeeded" : "failed"));
|
||||
}
|
||||
#endif /* USE_SPLAY_TREE */
|
||||
}
|
||||
|
||||
@@ -4121,15 +4232,15 @@ add_lock_node(struct LockNode * ln)
|
||||
AddTail((struct List *)&LockList,(struct Node *)ln);
|
||||
|
||||
#ifdef USE_SPLAY_TREE
|
||||
{
|
||||
ln->ln_SplayNameNode.sn_key = (splay_key_t)ln->ln_FullName;
|
||||
ln->ln_SplayNameNode.sn_userdata = ln;
|
||||
splay_tree_add(&LockNameTree, &ln->ln_SplayNameNode);
|
||||
|
||||
ln->ln_SplayNameNode.sn_key = (splay_key_t)ln->ln_FullName;
|
||||
ln->ln_SplayNameNode.sn_userdata = ln;
|
||||
splay_tree_add(&LockNameTree, &ln->ln_SplayNameNode);
|
||||
|
||||
ln->ln_SplayAddressNode.sn_key = (splay_key_t)ln;
|
||||
ln->ln_SplayAddressNode.sn_userdata = ln;
|
||||
splay_tree_add(&LockAddressTree, &ln->ln_SplayAddressNode);
|
||||
|
||||
ln->ln_SplayAddressNode.sn_key = (splay_key_t)ln;
|
||||
ln->ln_SplayAddressNode.sn_userdata = ln;
|
||||
splay_tree_add(&LockAddressTree, &ln->ln_SplayAddressNode);
|
||||
}
|
||||
#endif /* USE_SPLAY_TREE */
|
||||
}
|
||||
|
||||
@@ -4143,10 +4254,17 @@ remove_lock_node(struct LockNode * ln)
|
||||
Remove((struct Node *)ln);
|
||||
|
||||
#ifdef USE_SPLAY_TREE
|
||||
{
|
||||
APTR found;
|
||||
|
||||
splay_tree_remove(&LockNameTree, &ln->ln_SplayNameNode, ln->ln_SplayNameNode.sn_key);
|
||||
splay_tree_remove(&LockAddressTree, NULL, (splay_key_t)ln);
|
||||
found = splay_tree_remove(&LockNameTree, &ln->ln_SplayNameNode, ln->ln_SplayNameNode.sn_key);
|
||||
|
||||
D(("lock name node removal %s", found != NULL ? "succeeded" : "failed"));
|
||||
|
||||
found = splay_tree_remove(&LockAddressTree, NULL, (splay_key_t)ln);
|
||||
|
||||
D(("lock address node removal %s", found != NULL ? "succeeded" : "failed"));
|
||||
}
|
||||
#endif /* USE_SPLAY_TREE */
|
||||
|
||||
/* This will make the lock_is_invalid() tests return
|
||||
@@ -5151,41 +5269,18 @@ restart_directory_scanning(const struct MsgPort * user,const TEXT * parent_dir_n
|
||||
SHOWSTRING(parent_dir_name);
|
||||
|
||||
#ifndef USE_SPLAY_TREE
|
||||
|
||||
for(ln = (struct LockNode *)LockList.mlh_Head ;
|
||||
ln->ln_MinNode.mln_Succ != NULL ;
|
||||
ln = (struct LockNode *)ln->ln_MinNode.mln_Succ)
|
||||
{
|
||||
/* Try not to self-disrupt directory scanning while
|
||||
* deleting the contents of the directory.
|
||||
*/
|
||||
if(ln->ln_LastUser == user)
|
||||
continue;
|
||||
|
||||
if(compare_names(parent_dir_name,ln->ln_FullName) == SAME)
|
||||
for(ln = (struct LockNode *)LockList.mlh_Head ;
|
||||
ln->ln_MinNode.mln_Succ != NULL ;
|
||||
ln = (struct LockNode *)ln->ln_MinNode.mln_Succ)
|
||||
{
|
||||
D(("restart scanning for '%s'", escape_name(ln->ln_FullName)));
|
||||
/* Try not to self-disrupt directory scanning while
|
||||
* deleting the contents of the directory.
|
||||
*/
|
||||
if(ln->ln_LastUser == user)
|
||||
continue;
|
||||
|
||||
ln->ln_RestartExamine = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* Find all the locks which share the same directory name. */
|
||||
sn = splay_tree_find(&LockNameTree, (splay_key_t)parent_dir_name);
|
||||
if(sn != NULL)
|
||||
{
|
||||
/* Check each lock in turn, restarting the directory
|
||||
* scanning process unless the same program which
|
||||
* requires the restart is the one currently
|
||||
* doing the scanning.
|
||||
*/
|
||||
for((void)NULL ; sn != NULL ; sn = sn->sn_next)
|
||||
{
|
||||
ln = sn->sn_userdata;
|
||||
|
||||
if(ln->ln_LastUser != user)
|
||||
if(compare_names(parent_dir_name,ln->ln_FullName) == SAME)
|
||||
{
|
||||
D(("restart scanning for '%s'", escape_name(ln->ln_FullName)));
|
||||
|
||||
@@ -5193,7 +5288,30 @@ restart_directory_scanning(const struct MsgPort * user,const TEXT * parent_dir_n
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
{
|
||||
/* Find all the locks which share the same directory name. */
|
||||
sn = splay_tree_find(&LockNameTree, (splay_key_t)parent_dir_name);
|
||||
if(sn != NULL)
|
||||
{
|
||||
/* Check each lock in turn, restarting the directory
|
||||
* scanning process unless the same program which
|
||||
* requires the restart is the one currently
|
||||
* doing the scanning.
|
||||
*/
|
||||
for((void)NULL ; sn != NULL ; sn = sn->sn_next)
|
||||
{
|
||||
ln = sn->sn_userdata;
|
||||
|
||||
if(ln->ln_LastUser != user)
|
||||
{
|
||||
D(("restart scanning for '%s'", escape_name(ln->ln_FullName)));
|
||||
|
||||
ln->ln_RestartExamine = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* USE_SPLAY_TREE */
|
||||
|
||||
LEAVE();
|
||||
@@ -6087,24 +6205,34 @@ Action_FreeLock(
|
||||
D(("lock on '%s'", escape_name(key->ln_FullName)));
|
||||
|
||||
#ifndef USE_SPLAY_TREE
|
||||
|
||||
for(ln = (struct LockNode *)LockList.mlh_Head ;
|
||||
ln->ln_MinNode.mln_Succ != NULL ;
|
||||
ln = (struct LockNode *)ln->ln_MinNode.mln_Succ)
|
||||
{
|
||||
if(ln == key)
|
||||
for(ln = (struct LockNode *)LockList.mlh_Head ;
|
||||
ln->ln_MinNode.mln_Succ != NULL ;
|
||||
ln = (struct LockNode *)ln->ln_MinNode.mln_Succ)
|
||||
{
|
||||
found = ln;
|
||||
break;
|
||||
if(ln == key)
|
||||
{
|
||||
found = ln;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
{
|
||||
D(("looking up the lock address (what happened to trust?)"));
|
||||
|
||||
sn = splay_tree_find(&LockAddressTree, (splay_key_t)key);
|
||||
if(sn != NULL)
|
||||
found = (struct LockNode *)sn->sn_userdata;
|
||||
sn = splay_tree_find(&LockAddressTree, (splay_key_t)key);
|
||||
if(sn != NULL)
|
||||
{
|
||||
D(("found it"));
|
||||
|
||||
found = (struct LockNode *)sn->sn_userdata;
|
||||
}
|
||||
else
|
||||
{
|
||||
D(("didn't find it (this should never happen)"));
|
||||
}
|
||||
}
|
||||
#endif /* USE_SPLAY_TREE */
|
||||
|
||||
/* This should never happen. */
|
||||
@@ -8340,24 +8468,34 @@ Action_End(
|
||||
found = NULL;
|
||||
|
||||
#ifndef USE_SPLAY_TREE
|
||||
|
||||
for(fn = (struct FileNode *)FileList.mlh_Head ;
|
||||
fn->fn_MinNode.mln_Succ != NULL ;
|
||||
fn = (struct FileNode *)fn->fn_MinNode.mln_Succ)
|
||||
{
|
||||
if(fn == which_fn)
|
||||
for(fn = (struct FileNode *)FileList.mlh_Head ;
|
||||
fn->fn_MinNode.mln_Succ != NULL ;
|
||||
fn = (struct FileNode *)fn->fn_MinNode.mln_Succ)
|
||||
{
|
||||
found = fn;
|
||||
break;
|
||||
if(fn == which_fn)
|
||||
{
|
||||
found = fn;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
{
|
||||
D(("looking up the file address (what happened to trust?)"));
|
||||
|
||||
sn = splay_tree_find(&FileAddressTree, (splay_key_t)which_fn);
|
||||
if(sn != NULL)
|
||||
found = (struct FileNode *)sn->sn_userdata;
|
||||
sn = splay_tree_find(&FileAddressTree, (splay_key_t)which_fn);
|
||||
if(sn != NULL)
|
||||
{
|
||||
D(("found it"));
|
||||
|
||||
found = (struct FileNode *)sn->sn_userdata;
|
||||
}
|
||||
else
|
||||
{
|
||||
D(("didn't find it (this should never happen)"));
|
||||
}
|
||||
}
|
||||
#endif /* USE_SPLAY_TREE */
|
||||
|
||||
if(found == NULL)
|
||||
|
||||
+104
-26
@@ -483,16 +483,18 @@ smb_encode_smb_length (byte * p, int len)
|
||||
/* 0x00 = NetBIOS session message */
|
||||
p[0] = 0;
|
||||
|
||||
/* 0 = reserved */
|
||||
p[1] = 0;
|
||||
/* Length is a 17 bit integer, the most significant
|
||||
* bit of which goes into bit #0. The other 7 bits
|
||||
* are reserved.
|
||||
*/
|
||||
p[1] = (len >> 16) & 1;
|
||||
|
||||
/* Payload length in network byte order. */
|
||||
/* Payload length in network byte order
|
||||
* (least significant 16 bits).
|
||||
*/
|
||||
p[2] = (len & 0xFF00) >> 8;
|
||||
p[3] = (len & 0xFF);
|
||||
|
||||
/* Length is actually a 17 bit integer. */
|
||||
p[1] |= (len >> 16) & 1;
|
||||
|
||||
return &p[4];
|
||||
}
|
||||
|
||||
@@ -1593,7 +1595,13 @@ smb_proc_close (struct smb_server *server, word fileid, dword wtime, int * error
|
||||
* the file-id to be valid again after a reconnection.
|
||||
*/
|
||||
int
|
||||
smb_proc_read (struct smb_server *server, struct smb_dirent *finfo, off_t offset, long count, char *data, int * error_ptr)
|
||||
smb_proc_read (
|
||||
struct smb_server *server,
|
||||
struct smb_dirent *finfo,
|
||||
off_t offset,
|
||||
long count,
|
||||
char *data,
|
||||
int * error_ptr)
|
||||
{
|
||||
char *buf = server->transmit_buffer;
|
||||
int result;
|
||||
@@ -1643,7 +1651,13 @@ smb_proc_read (struct smb_server *server, struct smb_dirent *finfo, off_t offset
|
||||
* call.
|
||||
*/
|
||||
int
|
||||
smb_proc_read_raw (struct smb_server *server, struct smb_dirent *finfo, const QUAD * const offset_quad, long count, char *data, int * error_ptr)
|
||||
smb_proc_read_raw (
|
||||
struct smb_server *server,
|
||||
struct smb_dirent *finfo,
|
||||
const QUAD * const offset_quad,
|
||||
long count,
|
||||
char *data,
|
||||
int * error_ptr)
|
||||
{
|
||||
char *buf = server->transmit_buffer;
|
||||
int result;
|
||||
@@ -1678,7 +1692,13 @@ smb_proc_read_raw (struct smb_server *server, struct smb_dirent *finfo, const QU
|
||||
}
|
||||
|
||||
int
|
||||
smb_proc_write (struct smb_server *server, struct smb_dirent *finfo, off_t offset, long count, const char *data, int * error_ptr)
|
||||
smb_proc_write (
|
||||
struct smb_server *server,
|
||||
struct smb_dirent *finfo,
|
||||
off_t offset,
|
||||
long count,
|
||||
const char *data,
|
||||
int * error_ptr)
|
||||
{
|
||||
int result;
|
||||
char *buf = server->transmit_buffer;
|
||||
@@ -1717,7 +1737,13 @@ smb_proc_write (struct smb_server *server, struct smb_dirent *finfo, off_t offse
|
||||
}
|
||||
|
||||
int
|
||||
smb_proc_write_raw (struct smb_server *server, struct smb_dirent *finfo, const QUAD * const offset_quad, long count, const char *data, int * error_ptr)
|
||||
smb_proc_write_raw (
|
||||
struct smb_server *server,
|
||||
struct smb_dirent *finfo,
|
||||
const QUAD * const offset_quad,
|
||||
long count,
|
||||
const char *data,
|
||||
int * error_ptr)
|
||||
{
|
||||
char *buf = server->transmit_buffer;
|
||||
int num_bytes_written = 0;
|
||||
@@ -1893,7 +1919,13 @@ smb_proc_write_raw (struct smb_server *server, struct smb_dirent *finfo, const Q
|
||||
}
|
||||
|
||||
int
|
||||
smb_proc_writex (struct smb_server *server, struct smb_dirent *finfo, const QUAD * const offset_quad, long count, const char *data, int * error_ptr)
|
||||
smb_proc_writex (
|
||||
struct smb_server *server,
|
||||
struct smb_dirent *finfo,
|
||||
const QUAD * const offset_quad,
|
||||
long count,
|
||||
const char *data,
|
||||
int * error_ptr)
|
||||
{
|
||||
char *buf = server->transmit_buffer;
|
||||
int result;
|
||||
@@ -1961,7 +1993,13 @@ smb_proc_writex (struct smb_server *server, struct smb_dirent *finfo, const QUAD
|
||||
}
|
||||
|
||||
int
|
||||
smb_proc_readx (struct smb_server *server, struct smb_dirent *finfo, const QUAD * const offset_quad, long count, char *data, int * error_ptr)
|
||||
smb_proc_readx (
|
||||
struct smb_server *server,
|
||||
struct smb_dirent *finfo,
|
||||
const QUAD * const offset_quad,
|
||||
long count,
|
||||
char *data,
|
||||
int * error_ptr)
|
||||
{
|
||||
char *buf = server->transmit_buffer;
|
||||
int result;
|
||||
@@ -2021,7 +2059,14 @@ smb_proc_readx (struct smb_server *server, struct smb_dirent *finfo, const QUAD
|
||||
|
||||
/* smb_proc_lockingX: We don't chain any further packets to the initial one */
|
||||
int
|
||||
smb_proc_lockingX (struct smb_server *server, struct smb_dirent *finfo, const struct smb_lkrng *locks, int num_entries, int mode, long timeout, int * error_ptr)
|
||||
smb_proc_lockingX (
|
||||
struct smb_server *server,
|
||||
struct smb_dirent *finfo,
|
||||
const struct smb_lkrng *locks,
|
||||
int num_entries,
|
||||
int mode,
|
||||
long timeout,
|
||||
int * error_ptr)
|
||||
{
|
||||
int result;
|
||||
int num_locks, num_unlocks;
|
||||
@@ -2073,7 +2118,7 @@ smb_proc_lockingX (struct smb_server *server, struct smb_dirent *finfo, const st
|
||||
return result;
|
||||
}
|
||||
|
||||
/* smb_proc_do_create: We expect entry->attry & entry->ctime to be set. */
|
||||
/* smb_proc_do_create: We expect entry->attry and entry->ctime to be set. */
|
||||
int
|
||||
smb_proc_create (struct smb_server *server, const char *path, int len, struct smb_dirent *entry, int * error_ptr)
|
||||
{
|
||||
@@ -2153,7 +2198,13 @@ smb_proc_create (struct smb_server *server, const char *path, int len, struct sm
|
||||
}
|
||||
|
||||
int
|
||||
smb_proc_mv (struct smb_server *server, const char *old_path, const int old_path_len, const char *new_path, const int new_path_len, int * error_ptr)
|
||||
smb_proc_mv (
|
||||
struct smb_server *server,
|
||||
const char *old_path,
|
||||
const int old_path_len,
|
||||
const char *new_path,
|
||||
const int new_path_len,
|
||||
int * error_ptr)
|
||||
{
|
||||
char *p;
|
||||
char *buf = server->transmit_buffer;
|
||||
@@ -2373,12 +2424,10 @@ smb_decode_dirent (const char *p, struct smb_dirent *entry)
|
||||
entry->size_low = DVAL (p, 5);
|
||||
entry->size_high = 0;
|
||||
|
||||
/* The name is given in 8.3 MS-DOS style format,
|
||||
* including the "." delimiter. This is a NUL-
|
||||
* terminated OEM string, with one byte per
|
||||
* character. If the name is shorter than 12
|
||||
* characters, it is padded with " " (space)
|
||||
* characters.
|
||||
/* The name is given in 8.3 MS-DOS style format, including the "."
|
||||
* delimiter. This is a NUL-terminated OEM string, with one byte per
|
||||
* character. If the name is shorter than 12 characters, it is
|
||||
* padded with " " (space) characters.
|
||||
*/
|
||||
name_len = 12;
|
||||
|
||||
@@ -2423,7 +2472,13 @@ smb_decode_dirent (const char *p, struct smb_dirent *entry)
|
||||
* Note that it is for short directory name seeks, i.e.: protocol < PROTOCOL_LANMAN2
|
||||
*/
|
||||
static int
|
||||
smb_proc_readdir_short (struct smb_server *server, const char *path, int fpos, int cache_size, struct smb_dirent *entry, int * error_ptr)
|
||||
smb_proc_readdir_short (
|
||||
struct smb_server *server,
|
||||
const char *path,
|
||||
int fpos,
|
||||
int cache_size,
|
||||
struct smb_dirent *entry,
|
||||
int * error_ptr)
|
||||
{
|
||||
char *p;
|
||||
char *buf;
|
||||
@@ -2712,7 +2767,12 @@ smb_get_dirent_name(char *p,int level,char ** name_ptr,int * len_ptr)
|
||||
|
||||
/* interpret a long filename structure */
|
||||
static int
|
||||
smb_decode_long_dirent (const struct smb_server *server, const char *p, struct smb_dirent *finfo, int level, int * entry_length_ptr)
|
||||
smb_decode_long_dirent (
|
||||
const struct smb_server *server,
|
||||
const char *p,
|
||||
struct smb_dirent *finfo,
|
||||
int level,
|
||||
int * entry_length_ptr)
|
||||
{
|
||||
int success = TRUE;
|
||||
|
||||
@@ -2948,7 +3008,13 @@ smb_decode_long_dirent (const struct smb_server *server, const char *p, struct s
|
||||
}
|
||||
|
||||
static int
|
||||
smb_proc_readdir_long (struct smb_server *server, const char *path, int fpos, int cache_size, struct smb_dirent *entry, int * error_ptr)
|
||||
smb_proc_readdir_long (
|
||||
struct smb_server *server,
|
||||
const char *path,
|
||||
int fpos,
|
||||
int cache_size,
|
||||
struct smb_dirent *entry,
|
||||
int * error_ptr)
|
||||
{
|
||||
int max_matches = 512; /* this should actually be based on the max_recv value */
|
||||
|
||||
@@ -3317,7 +3383,13 @@ smb_proc_readdir_long (struct smb_server *server, const char *path, int fpos, in
|
||||
}
|
||||
|
||||
int
|
||||
smb_proc_readdir (struct smb_server *server, const char *path, int fpos, int cache_size, struct smb_dirent *entry, int * error_ptr)
|
||||
smb_proc_readdir (
|
||||
struct smb_server *server,
|
||||
const char *path,
|
||||
int fpos,
|
||||
int cache_size,
|
||||
struct smb_dirent *entry,
|
||||
int * error_ptr)
|
||||
{
|
||||
int result;
|
||||
|
||||
@@ -3410,7 +3482,13 @@ smb_proc_getattr_core (struct smb_server *server, const char *path, int len, str
|
||||
}
|
||||
|
||||
int
|
||||
smb_query_path_information(struct smb_server *server, const char *path, int len, int fid, struct smb_dirent *entry, int * error_ptr)
|
||||
smb_query_path_information(
|
||||
struct smb_server *server,
|
||||
const char *path,
|
||||
int len,
|
||||
int fid,
|
||||
struct smb_dirent *entry,
|
||||
int * error_ptr)
|
||||
{
|
||||
unsigned char *outbuf = server->transmit_buffer;
|
||||
dword ext_file_attributes;
|
||||
|
||||
@@ -95,6 +95,8 @@ smba_connect (
|
||||
int opt_case_sensitive,
|
||||
int opt_session_setup_delay_unicode,
|
||||
int opt_write_behind,
|
||||
int opt_smb_request_write_threshold,
|
||||
int opt_smb_request_read_threshold,
|
||||
int * error_ptr,
|
||||
int * smb_error_class_ptr,
|
||||
int * smb_error_ptr,
|
||||
@@ -152,6 +154,22 @@ smba_connect (
|
||||
|
||||
LOG(("delay use of unicode during session setup = %s\n",opt_session_setup_delay_unicode ? "yes" : "no"));
|
||||
|
||||
/* Do not send SMB header and payload for write operations separately,
|
||||
* but in a single chunk if their combined size is smaller than
|
||||
* or equal to this threshold value.
|
||||
*/
|
||||
res->server.smb_write_threshold = opt_smb_request_write_threshold;
|
||||
|
||||
LOG(("SMB write request threshold size = %ld bytes\n", res->server.smb_write_threshold));
|
||||
|
||||
/* Do not receive SMB header and payload for read operations separately,
|
||||
* but in a single chunk if their combined size is smaller than
|
||||
* or equal to this threshold value.
|
||||
*/
|
||||
res->server.smb_read_threshold = opt_smb_request_read_threshold;
|
||||
|
||||
LOG(("SMB read request threshold size = %ld bytes\n", res->server.smb_read_threshold));
|
||||
|
||||
/* Enable asynchronous SMB_COM_WRITE_RAW operations? */
|
||||
res->server.write_behind = opt_write_behind;
|
||||
|
||||
@@ -198,6 +216,8 @@ smba_connect (
|
||||
if(servent != NULL)
|
||||
{
|
||||
data.addr.sin_port = servent->s_port;
|
||||
|
||||
LOG(("using port number %ld\n",ntohs(data.addr.sin_port)));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -214,6 +234,8 @@ smba_connect (
|
||||
if(0 < n && n < 65536)
|
||||
{
|
||||
data.addr.sin_port = htons (n);
|
||||
|
||||
LOG(("using port number %ld\n",n));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -234,19 +256,31 @@ smba_connect (
|
||||
}
|
||||
else if (res->server.raw_smb)
|
||||
{
|
||||
int port;
|
||||
|
||||
servent = getservbyname("microsoft-ds","tcp");
|
||||
if(servent != NULL)
|
||||
data.addr.sin_port = servent->s_port;
|
||||
port = servent->s_port;
|
||||
else
|
||||
data.addr.sin_port = htons (445);
|
||||
port = htons (445);
|
||||
|
||||
LOG(("using port number %ld\n",ntohs(port)));
|
||||
|
||||
data.addr.sin_port = port;
|
||||
}
|
||||
else
|
||||
{
|
||||
int port;
|
||||
|
||||
servent = getservbyname("netbios-ssn","tcp");
|
||||
if(servent != NULL)
|
||||
data.addr.sin_port = servent->s_port;
|
||||
port = servent->s_port;
|
||||
else
|
||||
data.addr.sin_port = htons (139);
|
||||
port = htons (139);
|
||||
|
||||
LOG(("using port number %ld\n",ntohs(port)));
|
||||
|
||||
data.addr.sin_port = port;
|
||||
}
|
||||
|
||||
data.fd = socket (AF_INET, SOCK_STREAM, 0);
|
||||
@@ -592,7 +626,7 @@ write_attr (smba_file_t * f, int * error_ptr)
|
||||
f->dirent.mtime = mtime;
|
||||
f->dirent.attr = attr;
|
||||
|
||||
/* If the attributes need to be updated, we cannot used smb_proc_setattrE(),
|
||||
/* If the attributes need to be updated, we cannot use smb_proc_setattrE(),
|
||||
* because that only updates the "time of last write access", but not the
|
||||
* attributes.
|
||||
*/
|
||||
@@ -1376,7 +1410,8 @@ smba_readdir (smba_file_t * f, int offs, void *callback_data, smba_callback_t ca
|
||||
f->dircache->len = 0;
|
||||
f->dircache->base = cache_index;
|
||||
|
||||
num_entries = smb_proc_readdir (&f->server->server, f->dirent.complete_path, cache_index, f->dircache->cache_size, f->dircache->cache, error_ptr);
|
||||
num_entries = smb_proc_readdir (&f->server->server, f->dirent.complete_path, cache_index, f->dircache->cache_size,
|
||||
f->dircache->cache, error_ptr);
|
||||
|
||||
/* We stop on error, or if the directory is empty. */
|
||||
if (num_entries <= 0)
|
||||
@@ -1475,12 +1510,12 @@ allocate_path_name(const smba_file_t * dir, const char *name, size_t * path_name
|
||||
if(path != NULL)
|
||||
{
|
||||
memcpy (path, dir->dirent.complete_path, dir_len);
|
||||
path[dir_len] = DOS_PATHSEP;
|
||||
path[dir_len++] = DOS_PATHSEP;
|
||||
memcpy(&path[dir_len], name, len+1); /* length includes terminating NUL character */
|
||||
|
||||
ASSERT( path_name_len_ptr != NULL );
|
||||
|
||||
(*path_name_len_ptr) = dir_len + 1 + len;
|
||||
(*path_name_len_ptr) = dir_len + len;
|
||||
}
|
||||
|
||||
return(path);
|
||||
@@ -1846,10 +1881,28 @@ extract_service (
|
||||
char * share_start;
|
||||
char * root_start;
|
||||
char * complete_service;
|
||||
char * service_copy;
|
||||
char * service_copy = NULL;
|
||||
char * service_name;
|
||||
int result = -1;
|
||||
|
||||
if (strlen (service) < 4)
|
||||
{
|
||||
report_error("Service name '%s' is too short.",service);
|
||||
|
||||
(*error_ptr) = EINVAL;
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (service[0] != '/')
|
||||
{
|
||||
report_error("Service name '%s' must begin with '/'.",service);
|
||||
|
||||
(*error_ptr) = EINVAL;
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
service_copy = malloc(strlen(service)+1);
|
||||
if(service_copy == NULL)
|
||||
{
|
||||
@@ -1861,28 +1914,11 @@ extract_service (
|
||||
}
|
||||
|
||||
strcpy (service_copy, service);
|
||||
|
||||
complete_service = service_copy;
|
||||
|
||||
if (strlen (complete_service) < 4)
|
||||
{
|
||||
report_error("Service name '%s' is too short.",complete_service);
|
||||
|
||||
(*error_ptr) = EINVAL;
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (complete_service[0] != '/')
|
||||
{
|
||||
report_error("Service name '%s' must begin with '/'.",complete_service);
|
||||
|
||||
(*error_ptr) = EINVAL;
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
while (complete_service[0] == '/')
|
||||
complete_service += 1;
|
||||
complete_service++;
|
||||
|
||||
share_start = strchr (complete_service, '/');
|
||||
if (share_start == NULL)
|
||||
@@ -1920,20 +1956,29 @@ extract_service (
|
||||
len--;
|
||||
|
||||
service_name[len] = '\0';
|
||||
|
||||
if(len > tcp_service_name_size)
|
||||
{
|
||||
report_error("TCP service name/port number is too long in '%s' (%ld characters are possible).",service_name,tcp_service_name_size);
|
||||
|
||||
(*error_ptr) = EINVAL;
|
||||
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (strlen (complete_service) > 63)
|
||||
if (strlen (complete_service) > server_size)
|
||||
{
|
||||
report_error("Server name is too long in '%s' (%ld characters are possible).",service,63);
|
||||
report_error("Server name is too long in '%s' (%ld characters are possible).",service,server_size);
|
||||
|
||||
(*error_ptr) = ENAMETOOLONG;
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (strlen (share_start) > 255)
|
||||
if (strlen (share_start) > share_size)
|
||||
{
|
||||
report_error("Share name is too long in '%s' (%ld characters are possible).",service,255);
|
||||
report_error("Share name is too long in '%s' (%ld characters are possible).",service,share_size);
|
||||
|
||||
(*error_ptr) = ENAMETOOLONG;
|
||||
|
||||
@@ -1971,6 +2016,8 @@ smba_start(
|
||||
int opt_case_sensitive,
|
||||
int opt_session_setup_delay_unicode,
|
||||
int opt_write_behind,
|
||||
int opt_smb_request_write_threshold,
|
||||
int opt_smb_request_read_threshold,
|
||||
int * error_ptr,
|
||||
int * smb_error_class_ptr,
|
||||
int * smb_error_ptr,
|
||||
@@ -2133,7 +2180,7 @@ smba_start(
|
||||
/* Make sure the hostname is 16 characters or less (for NetBIOS) */
|
||||
if (!opt_raw_smb && strlen (host_name) > 16)
|
||||
{
|
||||
report_error("Server name '%s' is too long (max %ld characters).", host_name, 16);
|
||||
report_error("Server name '%s' is too long (%ld characters are possible).", host_name, 16);
|
||||
|
||||
(*error_ptr) = ENAMETOOLONG;
|
||||
goto out;
|
||||
@@ -2222,6 +2269,8 @@ smba_start(
|
||||
opt_case_sensitive,
|
||||
opt_session_setup_delay_unicode,
|
||||
opt_write_behind,
|
||||
opt_smb_request_write_threshold,
|
||||
opt_smb_request_read_threshold,
|
||||
error_ptr,
|
||||
smb_error_class_ptr,
|
||||
smb_error_ptr,
|
||||
|
||||
@@ -162,7 +162,7 @@ int smba_rmdir(smba_server_t *s, const char *path, int *error_ptr);
|
||||
int smba_rename(smba_server_t *s, const char *from, const char *to, int *error_ptr);
|
||||
int smba_statfs(smba_server_t *s, long *bsize, long *blocks, long *bfree, int *error_ptr);
|
||||
void smb_invalidate_all_inodes(struct smb_server *server);
|
||||
int smba_start(const char *service, const char *opt_workgroup, const char *opt_username, const char *opt_password, const char *opt_clientname, const char *opt_servername, int opt_cachesize, int opt_max_transmit, int opt_timeout, int opt_raw_smb, int opt_unicode, int opt_prefer_core_protocol, int opt_case_sensitive, int opt_session_setup_delay_unicode, int opt_write_behind, int *error_ptr, int *smb_error_class_ptr, int *smb_error_ptr, smba_connect_parameters_t *smba_connect_par, smba_server_t **smba_server_ptr);
|
||||
int smba_start(const char *service, const char *opt_workgroup, const char *opt_username, const char *opt_password, const char *opt_clientname, const char *opt_servername, int opt_cachesize, int opt_max_transmit, int opt_timeout, int opt_raw_smb, int opt_unicode, int opt_prefer_core_protocol, int opt_case_sensitive, int opt_session_setup_delay_unicode, int opt_write_behind, int opt_smb_request_write_threshold, int opt_smb_request_read_threshold, int *error_ptr, int *smb_error_class_ptr, int *smb_error_ptr, smba_connect_parameters_t *smba_connect_par, smba_server_t **smba_server_ptr);
|
||||
int smba_get_dircache_size(struct smba_server *server);
|
||||
int smba_change_dircache_size(struct smba_server *server, int cache_size);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#define VERSION 2
|
||||
#define REVISION 5
|
||||
#define DATE "16.12.2018"
|
||||
#define VERS "smbfs 2.5"
|
||||
#define VSTRING "smbfs 2.5 (16.12.2018)\r\n"
|
||||
#define VERSTAG "\0$VER: smbfs 2.5 (16.12.2018)"
|
||||
#define REVISION 8
|
||||
#define DATE "19.12.2018"
|
||||
#define VERS "smbfs 2.8"
|
||||
#define VSTRING "smbfs 2.8 (19.12.2018)\r\n"
|
||||
#define VERSTAG "\0$VER: smbfs 2.8 (19.12.2018)"
|
||||
|
||||
@@ -1 +1 @@
|
||||
5
|
||||
8
|
||||
|
||||
+411
-229
@@ -203,6 +203,7 @@ smb_receive_raw (
|
||||
int * error_ptr)
|
||||
{
|
||||
unsigned char netbios_session_buf[256];
|
||||
unsigned char * netbios_session_data;
|
||||
int netbios_session_payload_size;
|
||||
int len, result;
|
||||
|
||||
@@ -211,10 +212,27 @@ smb_receive_raw (
|
||||
server->rcls = 0;
|
||||
server->err = 0;
|
||||
|
||||
/* If the NetBIOS header needs to be returned, receive it along
|
||||
* with the SMB message and whatever follows.
|
||||
*/
|
||||
if (want_header)
|
||||
{
|
||||
LOG(("NetBIOS header will be returned as part of the buffer\n"));
|
||||
|
||||
netbios_session_data = target;
|
||||
}
|
||||
/* Otherwise store the NetBIOS header in a separate buffer. */
|
||||
else
|
||||
{
|
||||
LOG(("NetBIOS header will be processed separately\n"));
|
||||
|
||||
netbios_session_data = netbios_session_buf;
|
||||
}
|
||||
|
||||
re_recv:
|
||||
|
||||
/* Read the NetBIOS session header (rfc-1002, section 4.3.1) */
|
||||
result = receive_all (sock_fd, netbios_session_buf, NETBIOS_HEADER_SIZE, error_ptr);
|
||||
result = receive_all (sock_fd, netbios_session_data, NETBIOS_HEADER_SIZE, error_ptr);
|
||||
if (result < 0)
|
||||
{
|
||||
LOG (("recv error = %ld\n", (*error_ptr)));
|
||||
@@ -231,12 +249,12 @@ smb_receive_raw (
|
||||
goto out;
|
||||
}
|
||||
|
||||
netbios_session_payload_size = (int)smb_len(netbios_session_buf);
|
||||
netbios_session_payload_size = (int)smb_len(netbios_session_data);
|
||||
SHOWVALUE(netbios_session_payload_size);
|
||||
|
||||
#if defined(DUMP_SMB)
|
||||
{
|
||||
if(command != 0 && netbios_session_buf[0] != 0x00 && netbios_session_payload_size > 0)
|
||||
if(command != 0 && netbios_session_data[0] != 0x00 && netbios_session_payload_size > 0)
|
||||
{
|
||||
/* We only want to show what's in the first few
|
||||
* bytes of a session packet. Since we only support
|
||||
@@ -248,7 +266,7 @@ smb_receive_raw (
|
||||
if(netbios_session_payload_size > 256 - NETBIOS_HEADER_SIZE)
|
||||
netbios_session_payload_size = 256 - NETBIOS_HEADER_SIZE;
|
||||
|
||||
result = receive_all (sock_fd, &netbios_session_buf[NETBIOS_HEADER_SIZE], netbios_session_payload_size - NETBIOS_HEADER_SIZE, error_ptr);
|
||||
result = receive_all (sock_fd, &netbios_session_data[NETBIOS_HEADER_SIZE], netbios_session_payload_size - NETBIOS_HEADER_SIZE, error_ptr);
|
||||
if (result < 0)
|
||||
{
|
||||
LOG (("recv error = %ld\n", (*error_ptr)));
|
||||
@@ -265,17 +283,17 @@ smb_receive_raw (
|
||||
goto out;
|
||||
}
|
||||
|
||||
dump_netbios_header(__FILE__,__LINE__,netbios_session_buf,&netbios_session_buf[NETBIOS_HEADER_SIZE],netbios_session_payload_size);
|
||||
dump_netbios_header(__FILE__,__LINE__,netbios_session_data,&netbios_session_data[NETBIOS_HEADER_SIZE],netbios_session_payload_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
dump_netbios_header(__FILE__,__LINE__,netbios_session_buf,NULL,0);
|
||||
dump_netbios_header(__FILE__,__LINE__,netbios_session_data,NULL,0);
|
||||
}
|
||||
}
|
||||
#endif /* defined(DUMP_SMB) */
|
||||
|
||||
/* Check the session type. */
|
||||
switch (netbios_session_buf[0])
|
||||
switch (netbios_session_data[0])
|
||||
{
|
||||
/* 0x00 == session message */
|
||||
case 0x00:
|
||||
@@ -300,7 +318,7 @@ smb_receive_raw (
|
||||
*/
|
||||
if(command != 0)
|
||||
{
|
||||
LOG (("Invalid session header type 0x%02lx\n", netbios_session_buf[0]));
|
||||
LOG (("Invalid session header type 0x%02lx\n", netbios_session_data[0]));
|
||||
|
||||
(*error_ptr) = error_invalid_netbios_session;
|
||||
|
||||
@@ -323,12 +341,11 @@ smb_receive_raw (
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Prepend the NetBIOS header to what is read? */
|
||||
/* Did we read the NetBIOS header already? Make sure that
|
||||
* the data to follow goes into the right receive buffer.
|
||||
*/
|
||||
if (want_header)
|
||||
{
|
||||
memcpy (target, netbios_session_buf, NETBIOS_HEADER_SIZE);
|
||||
target += NETBIOS_HEADER_SIZE;
|
||||
}
|
||||
|
||||
/* This is an optimization for the SMB_COM_READ and SMB_COM_READ_ANDX
|
||||
* commands, which tries to avoid copying the received data twice. To
|
||||
@@ -337,129 +354,248 @@ smb_receive_raw (
|
||||
* begins. Then we read the data, storing it directly in the
|
||||
* receive buffer rather than in the packet buffer, from which
|
||||
* it would otherwise have to be retrieved later.
|
||||
*
|
||||
* Note that this optimization may still not take effect because the
|
||||
* amount of data expected to be received can be so small that it
|
||||
* may make little sense to break up reception into two separate
|
||||
* recv() calls.
|
||||
*/
|
||||
if(input_payload != NULL)
|
||||
{
|
||||
int num_bytes_received = 0;
|
||||
|
||||
LOG(("input_payload=0x%08lx, payload_size=%ld\n", input_payload, input_payload_size));
|
||||
|
||||
if(command == SMBreadX)
|
||||
/* Receive SMB message header and payload separately? */
|
||||
if(len > server->smb_read_threshold)
|
||||
{
|
||||
int data_length;
|
||||
int data_offset;
|
||||
int num_bytes_received = 0;
|
||||
|
||||
/* We need to read the following data:
|
||||
*
|
||||
* 0: 32 bytes of SMB message header
|
||||
* 32: 1 byte of word count
|
||||
* 33: 1 byte of andxcommand
|
||||
* 34: 1 byte of andxreserved
|
||||
* 35: 2 bytes of andxoffset
|
||||
* 37: 2 bytes of available
|
||||
* 39: 2 bytes of datacompactionmode
|
||||
* 41: 2 bytes of reserved
|
||||
* 43: 2 bytes of datalength
|
||||
* 45: 2 bytes of dataoffset
|
||||
* 47: 10 bytes of reserved
|
||||
* 57: 2 bytes of bytecount
|
||||
*
|
||||
* This adds up to 59 bytes.
|
||||
*/
|
||||
LOG(("receiving SMB message and payload separately\n"));
|
||||
|
||||
LOG(("SMBreadX: reading the first %ld bytes\n", 59));
|
||||
LOG(("input_payload=0x%08lx, payload_size=%ld\n", input_payload, input_payload_size));
|
||||
|
||||
result = receive_all (sock_fd, target, 59, error_ptr);
|
||||
if (result < 0)
|
||||
if(command == SMBreadX)
|
||||
{
|
||||
LOG (("recv error = %ld\n", (*error_ptr)));
|
||||
goto out;
|
||||
}
|
||||
int data_length;
|
||||
int data_offset;
|
||||
|
||||
num_bytes_received += result;
|
||||
/* We need to read the following data:
|
||||
*
|
||||
* 0: 32 bytes of SMB message header
|
||||
* 32: 1 byte of word count
|
||||
* 33: 1 byte of andxcommand
|
||||
* 34: 1 byte of andxreserved
|
||||
* 35: 2 bytes of andxoffset
|
||||
* 37: 2 bytes of available
|
||||
* 39: 2 bytes of datacompactionmode
|
||||
* 41: 2 bytes of reserved
|
||||
* 43: 2 bytes of datalength
|
||||
* 45: 2 bytes of dataoffset
|
||||
* 47: 10 bytes of reserved
|
||||
* 57: 2 bytes of bytecount
|
||||
*
|
||||
* This adds up to 59 bytes.
|
||||
*/
|
||||
|
||||
ASSERT( num_bytes_received == 59 );
|
||||
LOG(("SMBreadX: reading the first %ld bytes\n", 59));
|
||||
|
||||
/* End of file reached? */
|
||||
if(num_bytes_received < 59)
|
||||
{
|
||||
/* End of file */
|
||||
LOG (("EOF\n"));
|
||||
|
||||
(*error_ptr) = error_end_of_file;
|
||||
|
||||
result = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
data_offset = WVAL(target, 45);
|
||||
|
||||
SHOWVALUE(data_offset);
|
||||
|
||||
/* Skip the padding bytes, if any. */
|
||||
if(data_offset > 59)
|
||||
{
|
||||
result = receive_all (sock_fd, target + 59, data_offset - 59, error_ptr);
|
||||
result = receive_all (sock_fd, target, 59, error_ptr);
|
||||
if (result < 0)
|
||||
{
|
||||
LOG (("recv error = %ld\n", (*error_ptr)));
|
||||
goto out;
|
||||
}
|
||||
|
||||
num_bytes_received += result;
|
||||
|
||||
ASSERT( num_bytes_received == 59 );
|
||||
|
||||
/* End of file reached? */
|
||||
if(result < data_offset - 59)
|
||||
if(num_bytes_received < 59)
|
||||
{
|
||||
/* End of file */
|
||||
LOG (("EOF\n"));
|
||||
|
||||
(*error_ptr) = error_end_of_file;
|
||||
|
||||
|
||||
result = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
data_offset = WVAL(target, 45);
|
||||
|
||||
SHOWVALUE(data_offset);
|
||||
|
||||
/* Skip the padding bytes, if any. */
|
||||
if(data_offset > 59)
|
||||
{
|
||||
LOG (("skipping %ld padding bytes\n", data_offset - 59));
|
||||
|
||||
result = receive_all (sock_fd, target + 59, data_offset - 59, error_ptr);
|
||||
if (result < 0)
|
||||
{
|
||||
LOG (("recv error = %ld\n", (*error_ptr)));
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* End of file reached? */
|
||||
if(result < data_offset - 59)
|
||||
{
|
||||
/* End of file */
|
||||
LOG (("EOF\n"));
|
||||
|
||||
(*error_ptr) = error_end_of_file;
|
||||
|
||||
result = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
num_bytes_received += result;
|
||||
}
|
||||
|
||||
data_length = WVAL(target, 43);
|
||||
|
||||
SHOWVALUE(data_length);
|
||||
|
||||
ASSERT( data_length <= input_payload_size );
|
||||
|
||||
result = receive_all (sock_fd, input_payload, data_length, error_ptr);
|
||||
if (result < 0)
|
||||
{
|
||||
LOG (("recv error = %ld\n", (*error_ptr)));
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(result < data_length)
|
||||
{
|
||||
/* End of file */
|
||||
LOG (("EOF\n"));
|
||||
|
||||
(*error_ptr) = error_end_of_file;
|
||||
|
||||
result = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
num_bytes_received += result;
|
||||
|
||||
/* This should never happen, but then we better make sure to
|
||||
* read the entire message.
|
||||
*/
|
||||
if(num_bytes_received < len)
|
||||
{
|
||||
LOG(("reading the remaining %ld bytes; this should never happen\n", len - num_bytes_received ));
|
||||
|
||||
result = receive_all (sock_fd, &target[num_bytes_received], len - num_bytes_received, error_ptr);
|
||||
if (result < 0)
|
||||
{
|
||||
LOG (("recv error = %ld\n", (*error_ptr)));
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(result < len - num_bytes_received)
|
||||
{
|
||||
/* End of file */
|
||||
LOG (("EOF\n"));
|
||||
|
||||
(*error_ptr) = error_end_of_file;
|
||||
|
||||
result = -1;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data_length = WVAL(target, 43);
|
||||
|
||||
SHOWVALUE(data_length);
|
||||
|
||||
result = receive_all (sock_fd, input_payload, data_length, error_ptr);
|
||||
if (result < 0)
|
||||
else
|
||||
{
|
||||
LOG (("recv error = %ld\n", (*error_ptr)));
|
||||
goto out;
|
||||
}
|
||||
int count_of_bytes_returned;
|
||||
int count_of_bytes_to_read;
|
||||
int buffer_format;
|
||||
|
||||
if(result < data_length)
|
||||
{
|
||||
/* End of file */
|
||||
LOG (("EOF\n"));
|
||||
ASSERT( command == SMBread );
|
||||
|
||||
(*error_ptr) = error_end_of_file;
|
||||
/* We need to read the following data:
|
||||
*
|
||||
* 0: 32 bytes of SMB message header
|
||||
* 32: 1 byte of word count
|
||||
* 33: 2 bytes of 'count of bytes returned' (1 word)
|
||||
* 35: 8 bytes of reserved data (4 words)
|
||||
* 43: 2 bytes of 'byte count' (1 word)
|
||||
* 45: 1 byte of 'buffer format'
|
||||
* 46: 2 bytes of 'count of bytes to read' (1 word).
|
||||
*
|
||||
* This adds up to 48 bytes.
|
||||
*/
|
||||
|
||||
result = -1;
|
||||
goto out;
|
||||
}
|
||||
LOG(("SMBread: reading the first %ld bytes\n", 48));
|
||||
|
||||
num_bytes_received += result;
|
||||
|
||||
/* This should never happen, but then we better make sure to
|
||||
* read the entire message.
|
||||
*/
|
||||
if(num_bytes_received < len)
|
||||
{
|
||||
LOG(("reading the remaining %ld bytes; this should never happen\n", len - num_bytes_received ));
|
||||
|
||||
result = receive_all (sock_fd, &target[num_bytes_received], len - num_bytes_received, error_ptr);
|
||||
result = receive_all (sock_fd, target, 48, error_ptr);
|
||||
if (result < 0)
|
||||
{
|
||||
LOG (("recv error = %ld\n", (*error_ptr)));
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(result < len - num_bytes_received)
|
||||
num_bytes_received += result;
|
||||
|
||||
ASSERT( num_bytes_received == 48 );
|
||||
|
||||
/* End of file reached? */
|
||||
if(num_bytes_received < 48)
|
||||
{
|
||||
/* End of file */
|
||||
LOG (("EOF\n"));
|
||||
|
||||
(*error_ptr) = error_end_of_file;
|
||||
|
||||
result = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* So we read the header. Now we need to figure out if the
|
||||
* data is in the expected format, and how many bytes are
|
||||
* waiting to be read.
|
||||
*/
|
||||
|
||||
/* The buffer format must be 1. */
|
||||
buffer_format = BVAL(target, 45);
|
||||
|
||||
LOG(("buffer format = %ld, should be %ld\n", buffer_format, 1));
|
||||
|
||||
if(buffer_format != 1)
|
||||
{
|
||||
LOG(("buffer format %ld not supported\n", buffer_format));
|
||||
|
||||
(*error_ptr) = error_invalid_buffer_format;
|
||||
|
||||
result = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
count_of_bytes_returned = WVAL(target, 33);
|
||||
count_of_bytes_to_read = WVAL(target, 46);
|
||||
|
||||
/* That should never be more data than the read buffer may hold. */
|
||||
ASSERT( count_of_bytes_to_read <= input_payload_size );
|
||||
ASSERT( count_of_bytes_to_read <= count_of_bytes_returned );
|
||||
ASSERT( count_of_bytes_returned <= input_payload_size );
|
||||
|
||||
LOG(("count of bytes to read = %ld, should be <= %ld\n", count_of_bytes_to_read, input_payload_size));
|
||||
|
||||
if(count_of_bytes_returned > input_payload_size)
|
||||
{
|
||||
LOG(("this is too much data\n"));
|
||||
|
||||
(*error_ptr) = error_message_exceeds_buffer_size;
|
||||
|
||||
result = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
result = receive_all (sock_fd, input_payload, count_of_bytes_to_read, error_ptr);
|
||||
if (result < 0)
|
||||
{
|
||||
LOG (("recv error = %ld\n", (*error_ptr)));
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(result < count_of_bytes_to_read)
|
||||
{
|
||||
/* End of file */
|
||||
LOG (("EOF\n"));
|
||||
@@ -469,100 +605,78 @@ smb_receive_raw (
|
||||
result = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
num_bytes_received += result;
|
||||
|
||||
ASSERT( count_of_bytes_to_read == count_of_bytes_returned );
|
||||
|
||||
if(count_of_bytes_to_read < count_of_bytes_returned)
|
||||
{
|
||||
LOG(("fewer data available than should be delivered; setting the remainder (%ld bytes) to 0.\n", count_of_bytes_returned - count_of_bytes_to_read));
|
||||
|
||||
memset(&input_payload[count_of_bytes_to_read],0,count_of_bytes_returned - count_of_bytes_to_read);
|
||||
}
|
||||
|
||||
/* This should never happen, but then we better make sure to
|
||||
* read the entire message.
|
||||
*/
|
||||
if(num_bytes_received < len)
|
||||
{
|
||||
LOG(("reading the remaining %ld bytes; this should never happen\n", len - num_bytes_received ));
|
||||
|
||||
result = receive_all (sock_fd, &target[num_bytes_received], len - num_bytes_received, error_ptr);
|
||||
if (result < 0)
|
||||
{
|
||||
LOG (("recv error = %ld\n", (*error_ptr)));
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(result < len - num_bytes_received)
|
||||
{
|
||||
/* End of file */
|
||||
LOG (("EOF\n"));
|
||||
|
||||
(*error_ptr) = error_end_of_file;
|
||||
|
||||
result = -1;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(DUMP_SMB)
|
||||
{
|
||||
/* If want_header==0 then this is the data returned by SMB_COM_READ_RAW. */
|
||||
dump_smb(__FILE__,__LINE__,!want_header,target,48,smb_packet_to_consumer,server->max_recv);
|
||||
|
||||
if(buffer_format == 1)
|
||||
dump_smb(__FILE__,__LINE__,!want_header,input_payload,num_bytes_received - 48,smb_packet_to_consumer,server->max_recv);
|
||||
|
||||
if(num_bytes_received < len && result > 0)
|
||||
dump_smb(__FILE__,__LINE__,!want_header,&target[num_bytes_received],result,smb_packet_to_consumer,server->max_recv);
|
||||
}
|
||||
#endif /* defined(DUMP_SMB) */
|
||||
}
|
||||
|
||||
result = num_bytes_received;
|
||||
}
|
||||
/* No, read both as a single chunk through recv() and pick
|
||||
* the SMB message header and its payload apart later. This
|
||||
* is intended to improve small read operation performance
|
||||
* for which two separate recv() operations may introduce
|
||||
* additional delays in processing.
|
||||
*/
|
||||
else
|
||||
{
|
||||
int count_of_bytes_returned;
|
||||
int count_of_bytes_to_read;
|
||||
int buffer_format;
|
||||
LOG(("receiving SMB message and payload in one chunk\n"));
|
||||
|
||||
ASSERT( command == SMBread );
|
||||
|
||||
/* We need to read the following data:
|
||||
*
|
||||
* 0: 32 bytes of SMB message header
|
||||
* 32: 1 byte of word count
|
||||
* 33: 2 bytes of 'count of bytes returned' (1 word)
|
||||
* 35: 8 bytes of reserved data (4 words)
|
||||
* 43: 2 bytes of 'byte count' (1 word)
|
||||
* 45: 1 byte of 'buffer format'
|
||||
* 46: 2 bytes of 'count of bytes to read' (1 word).
|
||||
*
|
||||
* This adds up to 48 bytes.
|
||||
*/
|
||||
|
||||
LOG(("SMBread: reading the first %ld bytes\n", 48));
|
||||
|
||||
result = receive_all (sock_fd, target, 48, error_ptr);
|
||||
result = receive_all (sock_fd, target, len, error_ptr);
|
||||
if (result < 0)
|
||||
{
|
||||
LOG (("recv error = %ld\n", (*error_ptr)));
|
||||
goto out;
|
||||
}
|
||||
|
||||
num_bytes_received += result;
|
||||
|
||||
ASSERT( num_bytes_received == 48 );
|
||||
|
||||
/* End of file reached? */
|
||||
if(num_bytes_received < 48)
|
||||
{
|
||||
/* End of file */
|
||||
LOG (("EOF\n"));
|
||||
|
||||
(*error_ptr) = error_end_of_file;
|
||||
|
||||
result = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* So we read the header. Now we need to figure out if the
|
||||
* data is in the expected format, and how many bytes are
|
||||
* waiting to be read.
|
||||
*/
|
||||
|
||||
/* The buffer format must be 1. */
|
||||
buffer_format = BVAL(target, 45);
|
||||
|
||||
LOG(("buffer format = %ld, should be %ld\n", buffer_format, 1));
|
||||
|
||||
if(buffer_format != 1)
|
||||
{
|
||||
LOG(("buffer format %ld not supported\n", buffer_format));
|
||||
|
||||
(*error_ptr) = error_invalid_buffer_format;
|
||||
|
||||
result = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
count_of_bytes_returned = WVAL(target, 33);
|
||||
count_of_bytes_to_read = WVAL(target, 46);
|
||||
|
||||
/* That should never be more data than the read buffer may hold. */
|
||||
ASSERT( count_of_bytes_to_read <= input_payload_size );
|
||||
ASSERT( count_of_bytes_to_read <= count_of_bytes_returned );
|
||||
ASSERT( count_of_bytes_returned <= input_payload_size );
|
||||
|
||||
LOG(("count of bytes to read = %ld, should be <= %ld\n", count_of_bytes_to_read, input_payload_size));
|
||||
|
||||
if(count_of_bytes_returned > input_payload_size)
|
||||
{
|
||||
(*error_ptr) = error_message_exceeds_buffer_size;
|
||||
|
||||
result = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
result = receive_all (sock_fd, input_payload, count_of_bytes_to_read, error_ptr);
|
||||
if (result < 0)
|
||||
{
|
||||
LOG (("recv error = %ld\n", (*error_ptr)));
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(result < count_of_bytes_to_read)
|
||||
if(result < len)
|
||||
{
|
||||
/* End of file */
|
||||
LOG (("EOF\n"));
|
||||
@@ -573,58 +687,85 @@ smb_receive_raw (
|
||||
goto out;
|
||||
}
|
||||
|
||||
num_bytes_received += result;
|
||||
|
||||
ASSERT( count_of_bytes_to_read == count_of_bytes_returned );
|
||||
|
||||
if(count_of_bytes_to_read < count_of_bytes_returned)
|
||||
{
|
||||
LOG(("fewer data available than should be delivered; setting the remainder (%ld bytes) to 0.\n", count_of_bytes_returned - count_of_bytes_to_read));
|
||||
|
||||
memset(&input_payload[count_of_bytes_to_read],0,count_of_bytes_returned - count_of_bytes_to_read);
|
||||
}
|
||||
|
||||
/* This should never happen, but then we better make sure to
|
||||
* read the entire message.
|
||||
*/
|
||||
if(num_bytes_received < len)
|
||||
{
|
||||
LOG(("reading the remaining %ld bytes; this should never happen\n", len - num_bytes_received ));
|
||||
|
||||
result = receive_all (sock_fd, &target[num_bytes_received], len - num_bytes_received, error_ptr);
|
||||
if (result < 0)
|
||||
{
|
||||
LOG (("recv error = %ld\n", (*error_ptr)));
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(result < len - num_bytes_received)
|
||||
{
|
||||
/* End of file */
|
||||
LOG (("EOF\n"));
|
||||
|
||||
(*error_ptr) = error_end_of_file;
|
||||
|
||||
result = -1;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(DUMP_SMB)
|
||||
{
|
||||
/* If want_header==0 then this is the data returned by SMB_COM_READ_RAW. */
|
||||
dump_smb(__FILE__,__LINE__,!want_header,target,48,smb_packet_to_consumer,server->max_recv);
|
||||
|
||||
if(buffer_format == 1)
|
||||
dump_smb(__FILE__,__LINE__,!want_header,input_payload,num_bytes_received - 48,smb_packet_to_consumer,server->max_recv);
|
||||
|
||||
if(num_bytes_received < len && result > 0)
|
||||
dump_smb(__FILE__,__LINE__,!want_header,&target[num_bytes_received],result,smb_packet_to_consumer,server->max_recv);
|
||||
dump_smb(__FILE__,__LINE__,!want_header,target,result,smb_packet_to_consumer,server->max_recv);
|
||||
}
|
||||
#endif /* defined(DUMP_SMB) */
|
||||
}
|
||||
|
||||
result = num_bytes_received;
|
||||
if(command == SMBreadX)
|
||||
{
|
||||
int data_length;
|
||||
int data_offset;
|
||||
|
||||
data_offset = WVAL(target, 45);
|
||||
SHOWVALUE(data_offset);
|
||||
|
||||
data_length = WVAL(target, 43);
|
||||
SHOWVALUE(data_length);
|
||||
|
||||
ASSERT( data_offset < len );
|
||||
ASSERT( data_offset + data_length <= len );
|
||||
ASSERT( data_length <= input_payload_size );
|
||||
|
||||
memcpy(input_payload, &target[data_offset], data_length);
|
||||
}
|
||||
else
|
||||
{
|
||||
int count_of_bytes_returned;
|
||||
int count_of_bytes_to_read;
|
||||
int buffer_format;
|
||||
|
||||
ASSERT( command == SMBread );
|
||||
|
||||
/* The buffer format must be 1. */
|
||||
buffer_format = BVAL(target, 45);
|
||||
|
||||
LOG(("buffer format = %ld, should be %ld\n", buffer_format, 1));
|
||||
|
||||
if(buffer_format != 1)
|
||||
{
|
||||
LOG(("buffer format %ld not supported\n", buffer_format));
|
||||
|
||||
(*error_ptr) = error_invalid_buffer_format;
|
||||
|
||||
result = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
count_of_bytes_returned = WVAL(target, 33);
|
||||
count_of_bytes_to_read = WVAL(target, 46);
|
||||
|
||||
/* That should never be more data than the read buffer may hold. */
|
||||
ASSERT( count_of_bytes_to_read <= input_payload_size );
|
||||
ASSERT( count_of_bytes_to_read <= count_of_bytes_returned );
|
||||
ASSERT( count_of_bytes_returned <= input_payload_size );
|
||||
|
||||
LOG(("count of bytes to read = %ld, should be <= %ld\n", count_of_bytes_to_read, input_payload_size));
|
||||
|
||||
if(count_of_bytes_returned > input_payload_size)
|
||||
{
|
||||
LOG(("this is too much data\n"));
|
||||
|
||||
(*error_ptr) = error_message_exceeds_buffer_size;
|
||||
|
||||
result = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
memcpy(input_payload, &target[48], count_of_bytes_to_read);
|
||||
|
||||
ASSERT( count_of_bytes_to_read == count_of_bytes_returned );
|
||||
|
||||
if(count_of_bytes_to_read < count_of_bytes_returned)
|
||||
{
|
||||
LOG(("fewer data available than should be delivered; setting the remainder (%ld bytes) to 0.\n", count_of_bytes_returned - count_of_bytes_to_read));
|
||||
|
||||
memset(&input_payload[count_of_bytes_to_read],0,count_of_bytes_returned - count_of_bytes_to_read);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -660,7 +801,13 @@ smb_receive_raw (
|
||||
}
|
||||
|
||||
static int
|
||||
smb_receive (struct smb_server *server, int command, int sock_fd, void * input_payload, int payload_size, int * error_ptr)
|
||||
smb_receive (
|
||||
struct smb_server *server,
|
||||
int command,
|
||||
int sock_fd,
|
||||
void * input_payload,
|
||||
int payload_size,
|
||||
int * error_ptr)
|
||||
{
|
||||
byte * packet = server->transmit_buffer;
|
||||
int result;
|
||||
@@ -953,7 +1100,7 @@ smb_connect (struct smb_server *server, int * error_ptr)
|
||||
server->mount_data.fd = result;
|
||||
}
|
||||
|
||||
LOG(("connecting to server %s with socket %ld\n", Inet_NtoA(server->mount_data.addr.sin_addr.s_addr), server->mount_data.fd));
|
||||
LOG(("connecting to server %s:%ld with socket %ld\n", Inet_NtoA(server->mount_data.addr.sin_addr.s_addr), ntohs(server->mount_data.addr.sin_port), server->mount_data.fd));
|
||||
|
||||
/* Wait a certain time period for the connection attempt to succeed? */
|
||||
if(server->timeout > 0)
|
||||
@@ -1162,7 +1309,13 @@ smb_check_server_connection(struct smb_server *server, int error)
|
||||
* case of error.
|
||||
*/
|
||||
int
|
||||
smb_request (struct smb_server *server, int command, void * input_payload, const void * output_payload, int payload_size, int * error_ptr)
|
||||
smb_request (
|
||||
struct smb_server *server,
|
||||
int command,
|
||||
void * input_payload,
|
||||
const void * output_payload,
|
||||
int payload_size,
|
||||
int * error_ptr)
|
||||
{
|
||||
unsigned char *buffer = server->transmit_buffer;
|
||||
int sock_fd = server->mount_data.fd;
|
||||
@@ -1203,7 +1356,29 @@ smb_request (struct smb_server *server, int command, void * input_payload, const
|
||||
ASSERT( payload_size < smb_len(buffer) );
|
||||
ASSERT( len > payload_size );
|
||||
|
||||
len -= payload_size;
|
||||
/* Send SMB message header and payload separately? */
|
||||
if(len > server->smb_write_threshold)
|
||||
{
|
||||
LOG(("sending SMB message and payload separately\n"));
|
||||
|
||||
len -= payload_size;
|
||||
}
|
||||
/* No, combine both into a single chunk which will be
|
||||
* transmitted with a single send(). This is intended
|
||||
* to improve small write operation performance for
|
||||
* which two separate send() operations may not succeed
|
||||
* in nudging the TCP/IP stack to transmit the data just
|
||||
* yet (Nagle algorithm, etc.).
|
||||
*/
|
||||
else
|
||||
{
|
||||
LOG(("sending SMB message and payload in one chunk\n"));
|
||||
|
||||
memcpy(&buffer[len - payload_size], output_payload, payload_size);
|
||||
|
||||
output_payload = NULL;
|
||||
payload_size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
LOG (("len = %ld, cmd = 0x%lx, input_payload=0x%08lx, output_payload=0x%08lx, payload_size=%ld\n", len, buffer[8], input_payload, output_payload, payload_size));
|
||||
@@ -1252,7 +1427,14 @@ smb_request (struct smb_server *server, int command, void * input_payload, const
|
||||
* one packet to send.
|
||||
*/
|
||||
int
|
||||
smb_trans2_request (struct smb_server *server, int command, int *data_len, int *param_len, char **data, char **param, int * error_ptr)
|
||||
smb_trans2_request (
|
||||
struct smb_server *server,
|
||||
int command,
|
||||
int *data_len,
|
||||
int *param_len,
|
||||
char **data,
|
||||
char **param,
|
||||
int * error_ptr)
|
||||
{
|
||||
unsigned char *buffer = server->transmit_buffer;
|
||||
int sock_fd = server->mount_data.fd;
|
||||
|
||||
@@ -42,9 +42,9 @@
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* The network header files (e.g. AmiTCP, Miami) define this type,
|
||||
* which clashes with how AmigaOS uses it. This moves it out of the
|
||||
* way.
|
||||
/* The <smb/smb.h> header file declares this, and it may be redefined
|
||||
* in the TCP/IP stack header files. We try to avoid trouble by moving
|
||||
* the type declaration out of the way...
|
||||
*/
|
||||
#define byte IGNORE_THIS
|
||||
|
||||
|
||||
Reference in New Issue
Block a user