mirror of
https://github.com/obarthel/amiga-smbfs.git
synced 2025-12-08 14:58:35 +00:00
Updated to version 2.10
The smb_receive_raw() function in "sock.c" again copies the NetBIOS header into the receive buffer separately, rolling back an earlier change which did not seem to be sound, and also served to make complicated code even more complicated :-/ Added the SCATTERGATHER tuning option which defaults to "no". Instead of breaking down write operations into two separate send() calls (one short, one very large), setting SCATTERGATHER=yes can call sendmsg() instead which allows the entire operation to be completed in one single step. This approach was suggested by Patrik Axelsson. Currently, I am uncertain if all AmiTCP V3/V4 TCP/IP stacks implement sendmsg() for TCP sockets in the same consistent manner, which is why this feature is not enabled by default.
This commit is contained in:
@@ -33,6 +33,7 @@ struct smb_server
|
||||
both in a single combined send() operation
|
||||
rather than separately. */
|
||||
dword smb_read_threshold; /* Same as above, but for recv() operations. */
|
||||
int scatter_gather; /* Use sendmsg() rather than send() where useful? */
|
||||
int tcp_no_delay; /* Disable the Nagle algorithm for send()? */
|
||||
int socket_receive_buffer_size; /* Desired socket receive buffer size, if > 0. */
|
||||
int socket_send_buffer_size; /* Desired socket transmit buffer size, if > 0. */
|
||||
|
||||
+137
-134
@@ -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, int opt_smb_request_write_threshold, int opt_smb_request_read_threshold, BOOL tcp_no_delay, int socket_receive_buffer_size, int socket_send_buffer_size, 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, BOOL scatter_gather, BOOL tcp_no_delay, int socket_receive_buffer_size, int socket_send_buffer_size, 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);
|
||||
|
||||
/****************************************************************************/
|
||||
@@ -760,7 +760,9 @@ main(void)
|
||||
SWITCH WriteBehind;
|
||||
NUMBER WriteThreshold;
|
||||
NUMBER ReadThreshold;
|
||||
KEY ScatterGather;
|
||||
SWITCH TCPNoDelay;
|
||||
KEY TCPDelay;
|
||||
NUMBER SocketReceiveBuf;
|
||||
NUMBER SocketSendBuf;
|
||||
KEY SessionSetup;
|
||||
@@ -805,9 +807,11 @@ main(void)
|
||||
"WRITEBEHIND/S,"
|
||||
"WRITETHRESHOLD/N/K,"
|
||||
"READTHRESHOLD/N/K,"
|
||||
"SCATTERGATHER/K,"
|
||||
"TCP_NODELAY=TCPNODELAY/S,"
|
||||
"TCPDELAY/K,"
|
||||
"SO_RCVBUF=SOCKETRECEIVEBUFFER/N/K,"
|
||||
"SO_SNDBUF=SOCKETSENDBUFER/N/K,"
|
||||
"SO_SNDBUF=SOCKETSENDBUFFER/N/K,"
|
||||
"SESSIONSETUP/K,"
|
||||
"UNICODE/K,"
|
||||
"CP437/S,"
|
||||
@@ -1001,6 +1005,10 @@ main(void)
|
||||
if(args.ChangePasswordCase == NULL && get_icon_tool_type_value("CHANGECASE", NULL) != NULL)
|
||||
args.ChangePasswordCase = "yes";
|
||||
|
||||
args.TCPDelay = get_icon_tool_type_value("TCPDELAY", NULL);
|
||||
if(args.TCPDelay == NULL && get_icon_tool_type_value("TCPNODELAY", "TCP_NODELAY") != NULL)
|
||||
args.TCPDelay = "no";
|
||||
|
||||
args.DisableExAll = get_icon_tool_type_value("DISABLEEXALL", NULL) != NULL;
|
||||
args.OmitHidden = get_icon_tool_type_value("OMITHIDDEN", NULL) != NULL;
|
||||
args.Quiet = get_icon_tool_type_value("QUIET", NULL) != NULL;
|
||||
@@ -1008,7 +1016,6 @@ main(void)
|
||||
args.CaseSensitive = get_icon_tool_type_value("CASE", "CASESENSITIVE") != NULL;
|
||||
args.NetBIOSTransport = get_icon_tool_type_value("NETBIOS", NULL) != NULL;
|
||||
args.WriteBehind = get_icon_tool_type_value("WRITEBEHIND", NULL) != NULL;
|
||||
args.TCPNoDelay = get_icon_tool_type_value("TCPNODELAY", "TCP_NODELAY") != NULL;
|
||||
|
||||
args.ClientName = get_icon_tool_type_value("CLIENT", "CLIENTNAME");
|
||||
args.ServerName = get_icon_tool_type_value("SERVER", "SERVERNAME");
|
||||
@@ -1054,6 +1061,8 @@ main(void)
|
||||
args.ReadThreshold = &smb_read_threshold;
|
||||
}
|
||||
|
||||
args.ScatterGather = get_icon_tool_type_value("SCATTERGATHER", NULL);
|
||||
|
||||
str = get_icon_tool_type_value("TZ","TIMEZONEOFFSET");
|
||||
if(str != NULL)
|
||||
{
|
||||
@@ -1306,6 +1315,10 @@ main(void)
|
||||
if(args.ChangePasswordCase == NULL && args.ChangeCase)
|
||||
args.ChangePasswordCase = "yes";
|
||||
|
||||
/* Disable the TCP delay? */
|
||||
if(args.TCPDelay == NULL && args.TCPNoDelay)
|
||||
args.TCPDelay = "no";
|
||||
|
||||
/* Use the default if no device or volume name is given. */
|
||||
if(args.DeviceName == NULL && args.VolumeName == NULL)
|
||||
{
|
||||
@@ -1454,7 +1467,9 @@ main(void)
|
||||
|
||||
D(("read threshold = %ld", (*args.ReadThreshold)));
|
||||
|
||||
D(("tcp no delay = %s", args.TCPNoDelay ? "requested" : "not requested"));
|
||||
D(("scatter gather = %s", get_switch_status(args.ScatterGather, FALSE) ? "enabled" : "disabled"));
|
||||
|
||||
D(("tcp delay = %s", get_switch_status(args.TCPDelay, FALSE) ? "enabled" : "disabled"));
|
||||
|
||||
if(args.SocketReceiveBuf == NULL)
|
||||
args.SocketReceiveBuf = &socket_receive_buffer;
|
||||
@@ -1579,7 +1594,8 @@ main(void)
|
||||
args.WriteBehind,
|
||||
(*args.WriteThreshold),
|
||||
(*args.ReadThreshold),
|
||||
args.TCPNoDelay,
|
||||
get_switch_status(args.ScatterGather, FALSE),
|
||||
get_switch_status(args.TCPDelay, FALSE),
|
||||
(*args.SocketReceiveBuf),
|
||||
(*args.SocketSendBuf),
|
||||
args.DeviceName,
|
||||
@@ -3221,21 +3237,40 @@ name_already_in_use(const TEXT * name)
|
||||
return(error);
|
||||
}
|
||||
|
||||
/* Check whether an Amiga file name uses special characters which
|
||||
* should be avoided when used with the SMB file sharing protocol.
|
||||
/* Check whether an AmigaDOS path name uses special characters which should be
|
||||
* avoided when used with the SMB file sharing protocol. This test accepts '/'
|
||||
* and ':' as valid characters that may appear in an AmigaDOS path name.
|
||||
*
|
||||
* Reserved characters are control codes in the range 0..31, as well as
|
||||
* '<' (less than), '>' (greater than), ':' (colon), '"' (double quote),
|
||||
* '/' (forward slash), '\' (backslash), '|' (vertical bar or pipe),
|
||||
* '?' (question mark) and '*' (asterisk). The '?' and '*' are the MS-DOS
|
||||
* wildcard pattern characters which the SMB delete and rename commands
|
||||
* would process if they were part of the "file name".
|
||||
*
|
||||
* This list can be found (2018-12-28) here:
|
||||
* https://docs.microsoft.com/en-us/windows/desktop/fileio/naming-a-file
|
||||
*
|
||||
* We also reject the use of "." and ".." as path names.
|
||||
*/
|
||||
static BOOL
|
||||
name_contains_reserved_smb_characters(const TEXT * name)
|
||||
path_name_is_invalid(const TEXT * name, int name_len)
|
||||
{
|
||||
BOOL result = TRUE;
|
||||
TEXT c;
|
||||
int i;
|
||||
|
||||
/* Disallow "." and "..". */
|
||||
if(name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0')))
|
||||
if((name_len == 1 && name[0] == '.') || (name_len == 1 && name[0] == '.' && name[1] == '.'))
|
||||
goto out;
|
||||
|
||||
/* Disallow the use of the backslash in file names. */
|
||||
if(strchr(name,SMB_PATH_SEPARATOR) != NULL)
|
||||
goto out;
|
||||
for(i = 0 ; i < name_len ; i++)
|
||||
{
|
||||
c = name[i];
|
||||
|
||||
if(c < ' ' || strchr("<>\"\\|?*", c) != NULL)
|
||||
goto out;
|
||||
}
|
||||
|
||||
result = FALSE;
|
||||
|
||||
@@ -3427,7 +3462,7 @@ is_valid_device_name(const TEXT * name, int len)
|
||||
/****************************************************************************/
|
||||
|
||||
/* Check if a file name is right and proper for AmigaDOS use,
|
||||
* which excludes the use unprintable characters, the path
|
||||
* which excludes the use of unprintable characters, the path
|
||||
* delimiters ':' and '/', but also the SMB path delimeter
|
||||
* character '\'.
|
||||
*
|
||||
@@ -3809,6 +3844,7 @@ setup(
|
||||
BOOL opt_write_behind,
|
||||
int opt_smb_request_write_threshold,
|
||||
int opt_smb_request_read_threshold,
|
||||
BOOL opt_scatter_gather,
|
||||
BOOL opt_tcp_no_delay,
|
||||
int opt_socket_receive_buffer_size,
|
||||
int opt_socket_send_buffer_size,
|
||||
@@ -4053,6 +4089,7 @@ setup(
|
||||
opt_write_behind,
|
||||
opt_smb_request_write_threshold,
|
||||
opt_smb_request_read_threshold,
|
||||
opt_scatter_gather,
|
||||
opt_tcp_no_delay,
|
||||
opt_socket_receive_buffer_size,
|
||||
opt_socket_send_buffer_size,
|
||||
@@ -4360,8 +4397,8 @@ truncate_64_bit_position(const QUAD * position_quad)
|
||||
* characters through the use of 'C' style escape sequences. Returns a
|
||||
* pointer to a local static buffer which contains the escaped string.
|
||||
* If the escape form of the name is too long to fit into the buffer,
|
||||
* the text " [...]" will be appended to contents of the buffer, to indicate
|
||||
* that the name was truncated.
|
||||
* the text " [...]" will be appended to the contents of the buffer, to
|
||||
* indicate that the name was truncated.
|
||||
*/
|
||||
TEXT *
|
||||
escape_name(const TEXT * name)
|
||||
@@ -5485,46 +5522,6 @@ file_is_invalid(const struct FileNode * fn,int * error_ptr)
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/* Check if the name of a file or drawer contains MS-DOS
|
||||
* wildcard characters ("?" and "*") which may not be
|
||||
* suitable for some file system operations, e.g. rename
|
||||
* or delete.
|
||||
*/
|
||||
static BOOL
|
||||
name_contains_wildcard_characters(const TEXT * name)
|
||||
{
|
||||
const TEXT * file_name;
|
||||
BOOL result = FALSE;
|
||||
int len;
|
||||
TEXT c;
|
||||
int i;
|
||||
|
||||
ENTER();
|
||||
|
||||
SHOWSTRING(name);
|
||||
|
||||
file_name = FilePart(name);
|
||||
len = strlen(file_name);
|
||||
|
||||
for(i = 0 ; i < len ; i++)
|
||||
{
|
||||
c = file_name[i];
|
||||
|
||||
if(c == '?' || c == '*')
|
||||
{
|
||||
D(("found a wildcard in '%s'",name));
|
||||
|
||||
result = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
RETURN(result);
|
||||
return(result);
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/* Try to obtain the path name stored in a FileLock which
|
||||
* a file or directory name is associated with. The parent
|
||||
* FileLock can be NULL, which is interpreted as being a
|
||||
@@ -5725,19 +5722,10 @@ Action_DeleteObject(
|
||||
*/
|
||||
name_len = convert_from_bcpl_to_c_string(name,sizeof(name),bcpl_name);
|
||||
|
||||
/* The SMB_COM_DELETE command supports deleting sets
|
||||
* of matching files/drawers through wildcards. Only
|
||||
* the last part of the path (the name of the file
|
||||
* or directory) may contain the wildcard.
|
||||
*/
|
||||
if(name_contains_wildcard_characters(name))
|
||||
if(path_name_is_invalid(name, name_len))
|
||||
{
|
||||
D(("name '%s' is not safe to use with delete operation", name));
|
||||
|
||||
/* Do not try to delete sets of matching files
|
||||
* and drawers. We only came to delete a single
|
||||
* directory entry.
|
||||
*/
|
||||
D(("'%s' is not a valid path name", name));
|
||||
|
||||
error = ERROR_OBJECT_NOT_FOUND;
|
||||
goto out;
|
||||
}
|
||||
@@ -5917,14 +5905,10 @@ Action_CreateDir(
|
||||
|
||||
name_len = convert_from_bcpl_to_c_string(name,sizeof(name),bcpl_name);
|
||||
|
||||
/* Do not allow for a directory to be created whose
|
||||
* name contains MS-DOS wildcard characters. This will
|
||||
* only end in tears later...
|
||||
*/
|
||||
if(name_contains_wildcard_characters(name))
|
||||
if(path_name_is_invalid(name, name_len))
|
||||
{
|
||||
D(("will not create a directory '%s' which contains wildcard characters", name));
|
||||
|
||||
D(("'%s' is not a valid path name", name));
|
||||
|
||||
error = ERROR_INVALID_COMPONENT_NAME;
|
||||
goto out;
|
||||
}
|
||||
@@ -6049,6 +6033,14 @@ Action_LocateObject(
|
||||
|
||||
name_len = convert_from_bcpl_to_c_string(name,sizeof(name),bcpl_name);
|
||||
|
||||
if(path_name_is_invalid(name, name_len))
|
||||
{
|
||||
D(("'%s' is not a valid path name", name));
|
||||
|
||||
error = ERROR_OBJECT_NOT_FOUND;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(NOT ServerData->server.unicode_enabled)
|
||||
{
|
||||
error = translate_amiga_name_to_smb_name(name,name_len,sizeof(name));
|
||||
@@ -6056,12 +6048,6 @@ Action_LocateObject(
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(name_contains_reserved_smb_characters(FilePart(name)))
|
||||
{
|
||||
error = ERROR_OBJECT_NOT_FOUND;
|
||||
goto out;
|
||||
}
|
||||
|
||||
error = build_full_path_name(parent_name,name,name_len,&full_name);
|
||||
if(error != OK)
|
||||
goto out;
|
||||
@@ -6438,6 +6424,14 @@ Action_SetProtect(
|
||||
|
||||
name_len = convert_from_bcpl_to_c_string(name,sizeof(name),bcpl_name);
|
||||
|
||||
if(path_name_is_invalid(name, name_len))
|
||||
{
|
||||
D(("'%s' is not a valid path name", name));
|
||||
|
||||
error = ERROR_OBJECT_NOT_FOUND;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(NOT ServerData->server.unicode_enabled)
|
||||
{
|
||||
error = translate_amiga_name_to_smb_name(name,name_len,sizeof(name));
|
||||
@@ -6595,18 +6589,10 @@ Action_RenameObject(
|
||||
|
||||
name_len = convert_from_bcpl_to_c_string(name,sizeof(name),source_bcpl_name);
|
||||
|
||||
/* The SMB_COM_RENAME command supports renaming through
|
||||
* wildcards. Only the last part of the path (the name
|
||||
* of the file or directory) may contain the wildcard.
|
||||
*/
|
||||
if(name_contains_wildcard_characters(name))
|
||||
if(path_name_is_invalid(name, name_len))
|
||||
{
|
||||
D(("found a wildcard in the source path '%s'; this is unsafe to use with the rename operation",name));
|
||||
|
||||
/* Do not rename/move sets of matching files and
|
||||
* directories. We only came to rename/move a
|
||||
* single directory entry.
|
||||
*/
|
||||
D(("'%s' is not a valid path name", name));
|
||||
|
||||
error = ERROR_OBJECT_NOT_FOUND;
|
||||
goto out;
|
||||
}
|
||||
@@ -6638,14 +6624,10 @@ Action_RenameObject(
|
||||
|
||||
name_len = convert_from_bcpl_to_c_string(name,sizeof(name),destination_bcpl_name);
|
||||
|
||||
if(name_contains_wildcard_characters(name))
|
||||
if(path_name_is_invalid(name, name_len))
|
||||
{
|
||||
D(("found a wildcard in the destination path '%s'; this is unsafe to use with the rename operation",name));
|
||||
|
||||
/* Do not allow the destination name to contain
|
||||
* MS-DOS wildcard characters. This will only end
|
||||
* in tears later...
|
||||
*/
|
||||
D(("'%s' is not a valid path name", name));
|
||||
|
||||
error = ERROR_INVALID_COMPONENT_NAME;
|
||||
goto out;
|
||||
}
|
||||
@@ -8138,7 +8120,6 @@ Action_Find(
|
||||
struct FileNode * fn = NULL;
|
||||
STRPTR parent_name;
|
||||
TEXT name[MAX_FILENAME_LEN+1];
|
||||
BOOL wildcard_characters_found_in_name = FALSE;
|
||||
int name_len;
|
||||
BOOL create_new_file = FALSE;
|
||||
STRPTR temp = NULL;
|
||||
@@ -8178,28 +8159,16 @@ Action_Find(
|
||||
|
||||
name_len = convert_from_bcpl_to_c_string(name,sizeof(name),bcpl_name);
|
||||
|
||||
/* Do not allow MS-DOS wildcard characters to be used
|
||||
* when creating a new file.
|
||||
*/
|
||||
if(action != ACTION_FINDINPUT)
|
||||
if(path_name_is_invalid(name, name_len))
|
||||
{
|
||||
if(name_contains_wildcard_characters(name))
|
||||
{
|
||||
if(action == ACTION_FINDOUTPUT)
|
||||
{
|
||||
D(("will not create a file with wildcard characters in its name"));
|
||||
D(("'%s' is not a valid path name", name));
|
||||
|
||||
error = ERROR_INVALID_COMPONENT_NAME;
|
||||
goto out;
|
||||
}
|
||||
if(action == ACTION_FINDINPUT)
|
||||
error = ERROR_OBJECT_NOT_FOUND;
|
||||
else
|
||||
error = ERROR_INVALID_COMPONENT_NAME;
|
||||
|
||||
/* We don't know yet if MODE_READWRITE will
|
||||
* succeed in opening the file whose name
|
||||
* contains wildcard characters. This will
|
||||
* be checked later, if needed.
|
||||
*/
|
||||
wildcard_characters_found_in_name = TRUE;
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(NOT ServerData->server.unicode_enabled)
|
||||
@@ -8209,12 +8178,6 @@ Action_Find(
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(name_contains_reserved_smb_characters(FilePart(name)))
|
||||
{
|
||||
error = ERROR_OBJECT_NOT_FOUND;
|
||||
goto out;
|
||||
}
|
||||
|
||||
error = build_full_path_name(parent_name,name,name_len,&full_name);
|
||||
if(error != OK)
|
||||
goto out;
|
||||
@@ -8279,16 +8242,6 @@ Action_Find(
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Do not create a file whose name would contain
|
||||
* MS-DOS wildcard characters. This will only
|
||||
* end in tears later...
|
||||
*/
|
||||
if(wildcard_characters_found_in_name)
|
||||
{
|
||||
error = ERROR_INVALID_COMPONENT_NAME;
|
||||
goto out;
|
||||
}
|
||||
|
||||
error = split_path_name(full_name,strlen(full_name),&temp,&dir_name,&base_name);
|
||||
if(error != OK)
|
||||
{
|
||||
@@ -8646,10 +8599,38 @@ Action_Seek(
|
||||
|
||||
default:
|
||||
|
||||
D(("seek mode %ld not known", mode));
|
||||
|
||||
error = ERROR_ACTION_NOT_KNOWN;
|
||||
goto out;
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
{
|
||||
const TEXT * mode_name;
|
||||
|
||||
switch(mode)
|
||||
{
|
||||
case OFFSET_BEGINNING:
|
||||
|
||||
mode_name = "OFFSET_BEGINNING";
|
||||
break;
|
||||
|
||||
case OFFSET_CURRENT:
|
||||
|
||||
mode_name = "OFFSET_CURRENT";
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
mode_name = "OFFSET_END";
|
||||
break;
|
||||
}
|
||||
|
||||
D(("Seek(..., %ld, %s); current position = %s", position, mode_name, convert_quad_to_string(&reference_position_quad)));
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
|
||||
if(position < 0)
|
||||
{
|
||||
QUAD position_quad;
|
||||
@@ -8660,6 +8641,8 @@ Action_Seek(
|
||||
/* We cannot seek back beyond the beginning of the file. */
|
||||
if(compare_64_to_64(&reference_position_quad,&position_quad) < 0)
|
||||
{
|
||||
D(("cannot seek back beyond the beginning of the file."));
|
||||
|
||||
error = ERROR_SEEK_ERROR;
|
||||
goto out;
|
||||
}
|
||||
@@ -8671,6 +8654,8 @@ Action_Seek(
|
||||
/* Careful, we need to check for overflow, too. */
|
||||
if(add_64_plus_32_to_64(&reference_position_quad,position,&new_position_quad) > 0)
|
||||
{
|
||||
D(("position is too large"));
|
||||
|
||||
error = ERROR_SEEK_ERROR;
|
||||
goto out;
|
||||
}
|
||||
@@ -8682,6 +8667,8 @@ Action_Seek(
|
||||
|
||||
result = truncate_64_bit_position(&previous_position_quad);
|
||||
|
||||
D(("new position = %s; returning %ld", convert_quad_to_string(&new_position_quad), result));
|
||||
|
||||
out:
|
||||
|
||||
(*error_ptr) = error;
|
||||
@@ -8852,6 +8839,14 @@ Action_SetDate(
|
||||
|
||||
name_len = convert_from_bcpl_to_c_string(name,sizeof(name),bcpl_name);
|
||||
|
||||
if(path_name_is_invalid(name, name_len))
|
||||
{
|
||||
D(("'%s' is not a valid path name", name));
|
||||
|
||||
error = ERROR_OBJECT_NOT_FOUND;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(NOT ServerData->server.unicode_enabled)
|
||||
{
|
||||
error = translate_amiga_name_to_smb_name(name,name_len,sizeof(name));
|
||||
@@ -9712,6 +9707,14 @@ Action_SetComment(
|
||||
|
||||
name_len = convert_from_bcpl_to_c_string(name,sizeof(name),bcpl_name);
|
||||
|
||||
if(path_name_is_invalid(name, name_len))
|
||||
{
|
||||
D(("'%s' is not a valid path name", name));
|
||||
|
||||
error = ERROR_OBJECT_NOT_FOUND;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(NOT ServerData->server.unicode_enabled)
|
||||
{
|
||||
error = translate_amiga_name_to_smb_name(name,name_len,sizeof(name));
|
||||
|
||||
@@ -68,12 +68,12 @@ init_open_file_list(smba_server_t *res)
|
||||
NewList((struct List *)&res->open_files);
|
||||
|
||||
#ifdef USE_SPLAY_TREE
|
||||
{
|
||||
splay_tree_init(&res->open_file_address_tree, (splay_key_compare_t)compare_files_by_address);
|
||||
|
||||
splay_tree_init(&res->open_file_address_tree, (splay_key_compare_t)compare_files_by_address);
|
||||
|
||||
splay_tree_init(&res->open_file_name_tree, (splay_key_compare_t)compare_names);
|
||||
res->open_file_name_tree.st_allow_duplicates = TRUE;
|
||||
|
||||
splay_tree_init(&res->open_file_name_tree, (splay_key_compare_t)compare_names);
|
||||
res->open_file_name_tree.st_allow_duplicates = TRUE;
|
||||
}
|
||||
#endif /* USE_SPLAY_TREE */
|
||||
}
|
||||
|
||||
@@ -97,6 +97,7 @@ smba_connect (
|
||||
int opt_write_behind,
|
||||
int opt_smb_request_write_threshold,
|
||||
int opt_smb_request_read_threshold,
|
||||
int opt_scatter_gather,
|
||||
int opt_tcp_no_delay,
|
||||
int opt_socket_receive_buffer_size,
|
||||
int opt_socket_send_buffer_size,
|
||||
@@ -173,6 +174,11 @@ smba_connect (
|
||||
|
||||
LOG(("SMB read request threshold size = %ld bytes\n", res->server.smb_read_threshold));
|
||||
|
||||
/* Use sendmsg() instead of send() where useful? */
|
||||
res->server.scatter_gather = opt_scatter_gather;
|
||||
|
||||
LOG(("use sendmsg() instead of send() where useful = %s\n",opt_scatter_gather ? "yes" : "no"));
|
||||
|
||||
/* Disable the Nagle algorithm, causing send() to immediately
|
||||
* result in the data being transmitted?
|
||||
*/
|
||||
@@ -506,15 +512,15 @@ add_smba_file(smba_server_t * s, smba_file_t *f)
|
||||
AddTail ((struct List *)&s->open_files, (struct Node *)f);
|
||||
|
||||
#ifdef USE_SPLAY_TREE
|
||||
{
|
||||
f->splay_address_node.sn_key = f;
|
||||
f->splay_address_node.sn_userdata = f;
|
||||
splay_tree_add(&s->open_file_address_tree, &f->splay_address_node);
|
||||
|
||||
f->splay_address_node.sn_key = f;
|
||||
f->splay_address_node.sn_userdata = f;
|
||||
splay_tree_add(&s->open_file_address_tree, &f->splay_address_node);
|
||||
|
||||
f->splay_name_node.sn_key = f->dirent.complete_path;
|
||||
f->splay_name_node.sn_userdata = f;
|
||||
splay_tree_add(&s->open_file_name_tree, &f->splay_name_node);
|
||||
|
||||
f->splay_name_node.sn_key = f->dirent.complete_path;
|
||||
f->splay_name_node.sn_userdata = f;
|
||||
splay_tree_add(&s->open_file_name_tree, &f->splay_name_node);
|
||||
}
|
||||
#endif /* USE_SPLAY_TREE */
|
||||
}
|
||||
|
||||
@@ -526,10 +532,10 @@ remove_smba_file(smba_server_t * s, smba_file_t *f)
|
||||
Remove((struct Node *)f);
|
||||
|
||||
#ifdef USE_SPLAY_TREE
|
||||
|
||||
splay_tree_remove(&s->open_file_address_tree, NULL, (splay_key_t)f);
|
||||
splay_tree_remove(&s->open_file_name_tree, &f->splay_name_node, f->splay_name_node.sn_key);
|
||||
|
||||
{
|
||||
splay_tree_remove(&s->open_file_address_tree, NULL, (splay_key_t)f);
|
||||
splay_tree_remove(&s->open_file_name_tree, &f->splay_name_node, f->splay_name_node.sn_key);
|
||||
}
|
||||
#endif /* USE_SPLAY_TREE */
|
||||
}
|
||||
|
||||
@@ -687,26 +693,26 @@ file_is_valid(smba_server_t * s, const smba_file_t * f)
|
||||
int is_valid;
|
||||
|
||||
#ifndef USE_SPLAY_TREE
|
||||
|
||||
const smba_file_t * file;
|
||||
|
||||
is_valid = FALSE;
|
||||
|
||||
for (file = (smba_file_t *)s->open_files.mlh_Head ;
|
||||
file->node.mln_Succ != NULL ;
|
||||
file = (smba_file_t *)file->node.mln_Succ)
|
||||
{
|
||||
if (file == f)
|
||||
const smba_file_t * file;
|
||||
|
||||
is_valid = FALSE;
|
||||
|
||||
for (file = (smba_file_t *)s->open_files.mlh_Head ;
|
||||
file->node.mln_Succ != NULL ;
|
||||
file = (smba_file_t *)file->node.mln_Succ)
|
||||
{
|
||||
is_valid = TRUE;
|
||||
break;
|
||||
if (file == f)
|
||||
{
|
||||
is_valid = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
is_valid = (splay_tree_find(&s->open_file_address_tree, (splay_key_t)f) != NULL);
|
||||
|
||||
{
|
||||
is_valid = (splay_tree_find(&s->open_file_address_tree, (splay_key_t)f) != NULL);
|
||||
}
|
||||
#endif /* USE_SPLAY_TREE */
|
||||
|
||||
return(is_valid);
|
||||
@@ -1660,37 +1666,12 @@ close_path (smba_server_t * s, const char *path, int * error_ptr)
|
||||
smba_file_t *p;
|
||||
|
||||
#ifndef USE_SPLAY_TREE
|
||||
|
||||
for (p = (smba_file_t *)s->open_files.mlh_Head;
|
||||
p->node.mln_Succ != NULL;
|
||||
p = (smba_file_t *)p->node.mln_Succ)
|
||||
{
|
||||
if (p->is_valid && compare_names(p->dirent.complete_path, path) == SAME)
|
||||
for (p = (smba_file_t *)s->open_files.mlh_Head;
|
||||
p->node.mln_Succ != NULL;
|
||||
p = (smba_file_t *)p->node.mln_Succ)
|
||||
{
|
||||
result = invalidate_smba_file(s, p, path, error_ptr);
|
||||
if(result < 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
struct splay_node * sn;
|
||||
|
||||
/* Find all files which match the same path name. */
|
||||
sn = splay_tree_find(&s->open_file_name_tree, (splay_key_t)path);
|
||||
if(sn != NULL)
|
||||
{
|
||||
/* Walk through all the files, marking them as no longer
|
||||
* valid and closing them, if necessary. Note that we
|
||||
* do not remove them from the list of open files, we just
|
||||
* mark them for reopening later, if needed.
|
||||
*/
|
||||
for((void)NULL ; sn != NULL ; sn = sn->sn_next)
|
||||
{
|
||||
p = sn->sn_userdata;
|
||||
|
||||
if (p->is_valid)
|
||||
if (p->is_valid && compare_names(p->dirent.complete_path, path) == SAME)
|
||||
{
|
||||
result = invalidate_smba_file(s, p, path, error_ptr);
|
||||
if(result < 0)
|
||||
@@ -1698,7 +1679,32 @@ close_path (smba_server_t * s, const char *path, int * error_ptr)
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
{
|
||||
struct splay_node * sn;
|
||||
|
||||
/* Find all files which match the same path name. */
|
||||
sn = splay_tree_find(&s->open_file_name_tree, (splay_key_t)path);
|
||||
if(sn != NULL)
|
||||
{
|
||||
/* Walk through all the files, marking them as no longer
|
||||
* valid and closing them, if necessary. Note that we
|
||||
* do not remove them from the list of open files, we just
|
||||
* mark them for reopening later, if needed.
|
||||
*/
|
||||
for((void)NULL ; sn != NULL ; sn = sn->sn_next)
|
||||
{
|
||||
p = sn->sn_userdata;
|
||||
|
||||
if (p->is_valid)
|
||||
{
|
||||
result = invalidate_smba_file(s, p, path, error_ptr);
|
||||
if(result < 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* USE_SPLAY_TREE */
|
||||
|
||||
return(result);
|
||||
@@ -2032,6 +2038,7 @@ smba_start(
|
||||
int opt_write_behind,
|
||||
int opt_smb_request_write_threshold,
|
||||
int opt_smb_request_read_threshold,
|
||||
int opt_scatter_gather,
|
||||
int opt_tcp_no_delay,
|
||||
int opt_socket_receive_buffer_size,
|
||||
int opt_socket_send_buffer_size,
|
||||
@@ -2288,6 +2295,7 @@ smba_start(
|
||||
opt_write_behind,
|
||||
opt_smb_request_write_threshold,
|
||||
opt_smb_request_read_threshold,
|
||||
opt_scatter_gather,
|
||||
opt_tcp_no_delay,
|
||||
opt_socket_receive_buffer_size,
|
||||
opt_socket_send_buffer_size,
|
||||
|
||||
@@ -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 opt_smb_request_write_threshold, int opt_smb_request_read_threshold, int opt_tcp_no_delay, int opt_socket_receive_buffer_size, int opt_socket_send_buffer_size, 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 opt_scatter_gather, int opt_tcp_no_delay, int opt_socket_receive_buffer_size, int opt_socket_send_buffer_size, 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 9
|
||||
#define DATE "24.12.2018"
|
||||
#define VERS "smbfs 2.9"
|
||||
#define VSTRING "smbfs 2.9 (24.12.2018)\r\n"
|
||||
#define VERSTAG "\0$VER: smbfs 2.9 (24.12.2018)"
|
||||
#define REVISION 10
|
||||
#define DATE "29.12.2018"
|
||||
#define VERS "smbfs 2.10"
|
||||
#define VSTRING "smbfs 2.10 (29.12.2018)\r\n"
|
||||
#define VERSTAG "\0$VER: smbfs 2.10 (29.12.2018)"
|
||||
|
||||
@@ -1 +1 @@
|
||||
9
|
||||
10
|
||||
|
||||
+241
-147
@@ -202,131 +202,138 @@ smb_receive_raw (
|
||||
int want_header,
|
||||
int * error_ptr)
|
||||
{
|
||||
unsigned char netbios_session_buf[256];
|
||||
unsigned char * netbios_session_data;
|
||||
unsigned char netbios_session_buf[NETBIOS_HEADER_SIZE];
|
||||
int netbios_session_payload_size;
|
||||
int len, result;
|
||||
|
||||
ASSERT( error_ptr != NULL );
|
||||
|
||||
server->rcls = 0;
|
||||
server->err = 0;
|
||||
|
||||
/* If the NetBIOS header needs to be returned, receive it along
|
||||
* with the SMB message and whatever follows.
|
||||
/* We need to read the NetBIOS session header before we can move
|
||||
* on and read the SMB data. Because the NetBIOS session header
|
||||
* may be a keepalive message or something else we can safely
|
||||
* ignore, we will retry reading the header until we get to the
|
||||
* point where it is safe to read the SMB data.
|
||||
*/
|
||||
if (want_header)
|
||||
while(TRUE)
|
||||
{
|
||||
LOG(("NetBIOS header will be returned as part of the buffer\n"));
|
||||
server->rcls = 0;
|
||||
server->err = 0;
|
||||
|
||||
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_data, NETBIOS_HEADER_SIZE, error_ptr);
|
||||
if (result < 0)
|
||||
{
|
||||
LOG (("recv error = %ld\n", (*error_ptr)));
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (result < NETBIOS_HEADER_SIZE)
|
||||
{
|
||||
LOG (("expected %ld bytes, got %ld\n", NETBIOS_HEADER_SIZE, result));
|
||||
|
||||
(*error_ptr) = error_end_of_file;
|
||||
|
||||
result = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
netbios_session_payload_size = (int)smb_len(netbios_session_data);
|
||||
SHOWVALUE(netbios_session_payload_size);
|
||||
|
||||
#if defined(DUMP_SMB)
|
||||
{
|
||||
if(command != 0 && netbios_session_data[0] != 0x00 && netbios_session_payload_size > 0)
|
||||
/* Read the NetBIOS session header (rfc-1002, section 4.3.1) */
|
||||
result = receive_all (sock_fd, netbios_session_buf, NETBIOS_HEADER_SIZE, error_ptr);
|
||||
if (result < 0)
|
||||
{
|
||||
/* We only want to show what's in the first few
|
||||
* bytes of a session packet. Since we only support
|
||||
* two session packet types (session message and
|
||||
* session keep alive) we will abort processing
|
||||
* anyway so it doesn't matter if we ignore any
|
||||
* data beyond the first 256 bytes.
|
||||
*/
|
||||
if(netbios_session_payload_size > 256 - NETBIOS_HEADER_SIZE)
|
||||
netbios_session_payload_size = 256 - NETBIOS_HEADER_SIZE;
|
||||
|
||||
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)));
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(result < netbios_session_payload_size - NETBIOS_HEADER_SIZE)
|
||||
{
|
||||
LOG (("result (%ld) < %ld\n", result, netbios_session_payload_size - NETBIOS_HEADER_SIZE));
|
||||
|
||||
(*error_ptr) = error_end_of_file;
|
||||
|
||||
result = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
dump_netbios_header(__FILE__,__LINE__,netbios_session_data,&netbios_session_data[NETBIOS_HEADER_SIZE],netbios_session_payload_size);
|
||||
LOG (("recv error = %ld\n", (*error_ptr)));
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
|
||||
if (result < NETBIOS_HEADER_SIZE)
|
||||
{
|
||||
dump_netbios_header(__FILE__,__LINE__,netbios_session_data,NULL,0);
|
||||
LOG (("expected %ld bytes, got %ld\n", NETBIOS_HEADER_SIZE, result));
|
||||
|
||||
(*error_ptr) = error_end_of_file;
|
||||
|
||||
result = -1;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
#endif /* defined(DUMP_SMB) */
|
||||
|
||||
/* Check the session type. */
|
||||
switch (netbios_session_data[0])
|
||||
{
|
||||
/* 0x00 == session message */
|
||||
case 0x00:
|
||||
netbios_session_payload_size = (int)smb_len(netbios_session_buf);
|
||||
SHOWVALUE(netbios_session_payload_size);
|
||||
|
||||
break;
|
||||
#if defined(DUMP_SMB)
|
||||
{
|
||||
if(command != 0 && netbios_session_buf[0] != 0x00 && netbios_session_payload_size > 0)
|
||||
{
|
||||
unsigned char netbios_session_payload[256];
|
||||
|
||||
/* 0x85 == session keepalive */
|
||||
case 0x85:
|
||||
/* We only want to show what's in the first few
|
||||
* bytes of a session packet. Since we only support
|
||||
* two session packet types (session message and
|
||||
* session keep alive) we will abort processing
|
||||
* anyway so it doesn't matter if we ignore any
|
||||
* data beyond the first 256 bytes.
|
||||
*/
|
||||
if(netbios_session_payload_size > 256)
|
||||
netbios_session_payload_size = 256;
|
||||
|
||||
result = receive_all (sock_fd, netbios_session_payload, netbios_session_payload_size, error_ptr);
|
||||
if (result < 0)
|
||||
{
|
||||
LOG (("recv error = %ld\n", (*error_ptr)));
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(result < netbios_session_payload_size)
|
||||
{
|
||||
LOG (("result (%ld) < %ld\n", result, netbios_session_payload_size));
|
||||
|
||||
(*error_ptr) = error_end_of_file;
|
||||
|
||||
result = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
dump_netbios_header(__FILE__,__LINE__,netbios_session_buf,netbios_session_payload,netbios_session_payload_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
dump_netbios_header(__FILE__,__LINE__,netbios_session_buf,NULL,0);
|
||||
}
|
||||
}
|
||||
#endif /* defined(DUMP_SMB) */
|
||||
|
||||
/* Is this a session keepalive message? If so,
|
||||
* read the next frame.
|
||||
*/
|
||||
if (netbios_session_buf[0] == 0x85)
|
||||
{
|
||||
LOG (("Got SESSION KEEP ALIVE\n"));
|
||||
goto re_recv;
|
||||
|
||||
/* 0x81 == session request */
|
||||
/* 0x82 == positive session response */
|
||||
/* 0x83 == negative session response */
|
||||
/* 0x84 == retarget session response */
|
||||
default:
|
||||
|
||||
/* The session setup may need to know about the
|
||||
* NetBIOS session response, but for any command
|
||||
* these message types are invalid.
|
||||
*/
|
||||
if(command != 0)
|
||||
{
|
||||
LOG (("Invalid session header type 0x%02lx\n", netbios_session_data[0]));
|
||||
|
||||
(*error_ptr) = error_invalid_netbios_session;
|
||||
|
||||
result = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
/* Is this a regular session message? This is what
|
||||
* we came for.
|
||||
*/
|
||||
else if (netbios_session_buf[0] == 0x00)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check the session type again, looking for
|
||||
* anything peculiar.
|
||||
*/
|
||||
switch (netbios_session_buf[0])
|
||||
{
|
||||
/* 0x00 == session message */
|
||||
case 0x00:
|
||||
|
||||
/* This is what we came for. */
|
||||
break;
|
||||
|
||||
/* 0x81 == session request */
|
||||
/* 0x82 == positive session response */
|
||||
/* 0x83 == negative session response */
|
||||
/* 0x84 == retarget session response */
|
||||
default:
|
||||
|
||||
/* The session setup may need to know about the
|
||||
* NetBIOS session response, but for any command
|
||||
* these message types are invalid.
|
||||
*/
|
||||
if(command != 0)
|
||||
{
|
||||
LOG (("Invalid session header type 0x%02lx\n", netbios_session_buf[0]));
|
||||
|
||||
(*error_ptr) = error_invalid_netbios_session;
|
||||
|
||||
result = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Ignore this message type. */
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* The length in the NetBIOS header is the raw data length (17 bits) */
|
||||
@@ -341,11 +348,12 @@ smb_receive_raw (
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Did we read the NetBIOS header already? Make sure that
|
||||
* the data to follow goes into the right receive buffer.
|
||||
*/
|
||||
/* Prepend the NetBIOS header to what is read? */
|
||||
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
|
||||
@@ -414,7 +422,7 @@ smb_receive_raw (
|
||||
LOG (("EOF\n"));
|
||||
|
||||
(*error_ptr) = error_end_of_file;
|
||||
|
||||
|
||||
result = -1;
|
||||
goto out;
|
||||
}
|
||||
@@ -442,7 +450,7 @@ smb_receive_raw (
|
||||
LOG (("EOF\n"));
|
||||
|
||||
(*error_ptr) = error_end_of_file;
|
||||
|
||||
|
||||
result = -1;
|
||||
goto out;
|
||||
}
|
||||
@@ -543,7 +551,7 @@ smb_receive_raw (
|
||||
LOG (("EOF\n"));
|
||||
|
||||
(*error_ptr) = error_end_of_file;
|
||||
|
||||
|
||||
result = -1;
|
||||
goto out;
|
||||
}
|
||||
@@ -612,7 +620,7 @@ smb_receive_raw (
|
||||
|
||||
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));
|
||||
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);
|
||||
}
|
||||
@@ -760,7 +768,7 @@ smb_receive_raw (
|
||||
|
||||
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));
|
||||
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);
|
||||
}
|
||||
@@ -1405,22 +1413,71 @@ smb_request (
|
||||
dump_smb(__FILE__,__LINE__,0,buffer+NETBIOS_HEADER_SIZE,len-NETBIOS_HEADER_SIZE,smb_packet_from_consumer,server->max_recv);
|
||||
#endif /* defined(DUMP_SMB) */
|
||||
|
||||
result = send (sock_fd, (void *) buffer, len, 0);
|
||||
if (result < 0)
|
||||
{
|
||||
LOG(("send() for %ld bytes failed (errno=%ld)\n", len, errno));
|
||||
|
||||
(*error_ptr) = errno;
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(output_payload != NULL && payload_size > 0)
|
||||
{
|
||||
result = send (sock_fd, (void *)output_payload, payload_size, 0);
|
||||
/* Use two send() calls for header and payload? */
|
||||
if(!server->scatter_gather)
|
||||
{
|
||||
LOG(("using two send() calls\n"));
|
||||
|
||||
result = send (sock_fd, (void *) buffer, len, 0);
|
||||
if (result < 0)
|
||||
{
|
||||
LOG(("send() for %ld bytes failed (errno=%ld)\n", len, errno));
|
||||
|
||||
(*error_ptr) = errno;
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
result = send (sock_fd, (void *)output_payload, payload_size, 0);
|
||||
if (result < 0)
|
||||
{
|
||||
LOG(("payload send() for %ld bytes failed (errno=%ld)\n", payload_size, errno));
|
||||
|
||||
(*error_ptr) = errno;
|
||||
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
/* No, use sendmsg() to transmit both header and payload
|
||||
* in one single step.
|
||||
*/
|
||||
else
|
||||
{
|
||||
struct msghdr msg;
|
||||
struct iovec iov[2];
|
||||
|
||||
LOG(("using sendmsg() for %ld+%ld = %ld bytes\n", len, payload_size, len+payload_size));
|
||||
|
||||
memset(&msg,0,sizeof(msg));
|
||||
|
||||
msg.msg_iov = iov;
|
||||
msg.msg_iovlen = 2;
|
||||
|
||||
iov[0].iov_base = buffer;
|
||||
iov[0].iov_len = len;
|
||||
|
||||
iov[1].iov_base = (void *)output_payload;
|
||||
iov[1].iov_len = payload_size;
|
||||
|
||||
result = sendmsg (sock_fd, &msg, 0);
|
||||
if (result < 0)
|
||||
{
|
||||
LOG(("sendmsg() for %ld+%ld bytes failed (errno=%ld)\n", len, payload_size, errno));
|
||||
|
||||
(*error_ptr) = errno;
|
||||
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = send (sock_fd, (void *) buffer, len, 0);
|
||||
if (result < 0)
|
||||
{
|
||||
LOG(("payload send() for %ld bytes failed (errno=%ld)\n", payload_size, errno));
|
||||
LOG(("send() for %ld bytes failed (errno=%ld)\n", len, errno));
|
||||
|
||||
(*error_ptr) = errno;
|
||||
|
||||
@@ -1581,36 +1638,73 @@ smb_request_write_raw (struct smb_server *server, unsigned const char *source, i
|
||||
|
||||
ASSERT( length <= 65535 );
|
||||
|
||||
/* Send the NetBIOS header. */
|
||||
/* Prepare the NetBIOS header, which in this case is
|
||||
* providing the length of the data to follow it.
|
||||
*/
|
||||
smb_encode_smb_length (nb_header, length);
|
||||
|
||||
#if defined(DUMP_SMB)
|
||||
dump_netbios_header(__FILE__,__LINE__,nb_header,NULL,0);
|
||||
#endif /* defined(DUMP_SMB) */
|
||||
|
||||
result = send (sock_fd, nb_header, NETBIOS_HEADER_SIZE, 0);
|
||||
if(result < 0)
|
||||
{
|
||||
LOG(("send() for %ld bytes failed (errno=%ld)\n", NETBIOS_HEADER_SIZE, errno));
|
||||
|
||||
(*error_ptr) = errno;
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
#if defined(DUMP_SMB)
|
||||
dump_smb(__FILE__,__LINE__,0,source,length,smb_packet_from_consumer,server->max_recv);
|
||||
#endif /* defined(DUMP_SMB) */
|
||||
|
||||
/* Now send the data to be written. */
|
||||
result = send (sock_fd, (void *)source, length, 0);
|
||||
if(result < 0)
|
||||
/* Use two send() calls to transmit header and data? */
|
||||
if(!server->scatter_gather)
|
||||
{
|
||||
LOG(("send() for %ld bytes failed (errno=%ld)\n", length, errno));
|
||||
LOG(("using two send() calls\n"));
|
||||
|
||||
(*error_ptr) = errno;
|
||||
/* Send the NetBIOS header. */
|
||||
result = send (sock_fd, nb_header, NETBIOS_HEADER_SIZE, 0);
|
||||
if(result < 0)
|
||||
{
|
||||
LOG(("send() for %ld bytes failed (errno=%ld)\n", NETBIOS_HEADER_SIZE, errno));
|
||||
|
||||
goto out;
|
||||
(*error_ptr) = errno;
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Now send the data to be written. */
|
||||
result = send (sock_fd, (void *)source, length, 0);
|
||||
if(result < 0)
|
||||
{
|
||||
LOG(("send() for %ld bytes failed (errno=%ld)\n", length, errno));
|
||||
|
||||
(*error_ptr) = errno;
|
||||
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
/* No, use sendmsg() to transmit header and data in
|
||||
* one single step.
|
||||
*/
|
||||
else
|
||||
{
|
||||
struct msghdr msg;
|
||||
struct iovec iov[2];
|
||||
|
||||
LOG(("using sendmsg() for %ld+%ld = %ld bytes\n", NETBIOS_HEADER_SIZE, length, NETBIOS_HEADER_SIZE+length));
|
||||
|
||||
memset(&msg,0,sizeof(msg));
|
||||
|
||||
msg.msg_iov = iov;
|
||||
msg.msg_iovlen = 2;
|
||||
|
||||
iov[0].iov_base = nb_header;
|
||||
iov[0].iov_len = NETBIOS_HEADER_SIZE;
|
||||
|
||||
iov[1].iov_base = (void *)source;
|
||||
iov[1].iov_len = length;
|
||||
|
||||
result = sendmsg (sock_fd, &msg, 0);
|
||||
if (result < 0)
|
||||
{
|
||||
LOG(("sendmsg() for %ld+%ld bytes failed (errno=%ld)\n", NETBIOS_HEADER_SIZE, length, errno));
|
||||
|
||||
(*error_ptr) = errno;
|
||||
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait for the server to respond. */
|
||||
|
||||
Reference in New Issue
Block a user