Updated to version 1.146

Please keep in mind that this is still a development version and might surprise you (not necessarily in a good way).

Do not let me discourage you to build and test this version, although there will be some risks involved such as data corruption or loss of data.
This commit is contained in:
obarthel
2018-06-03 11:36:04 +02:00
parent 32c75549a4
commit 31c8fb0d77
11 changed files with 1204 additions and 264 deletions
+51
View File
@@ -1865,3 +1865,54 @@ smbfs 1.144 (1.6.2018)
proper directory information, such as the Samba 3.0.37 version which
is part of the FRITZ!Box firmware. Note that once Unicode support is
enabled, the UTF8, CP437, CP850 and TRANSLATE options will be ignored.
smbfs 1.145 (2.6.2018)
- I broke renaming by mixing up the length of the new name with the
old name length. Fixed.
- Renaming now also works on hidden files and system files, just like
deletion works on system files and hidden files, too. Keep in mind
that a file or directory which is not write-enabled cannot be
renamed (that's what the documentation says, anyway).
- Plugged the SMB_COM_READ_RAW/SMB_COM_WRITE_RAW code back into the
file system. Added support for 64 bit file position information.
smbfs 1.146 (3.6.2018)
- Added extra sanity checks for file handles and file locks, which
should prevent files from getting closed twice, or locks from
getting freed twice. We also detect files and locks which smbfs
does not know and reject these before it's too late.
- Dropped more unused code, e.g. in the cache invalidation function.
- Instead of using local string buffers, we now allocate memory for
the buffers instead. This avoids truncating path/service names
if these would have become too long for the original local string
buffer to hold.
- Added the options PREFERWRITERAW, PREFERREADRAW and WRITEBEHIND.
The first two will make smbfs use SMB_COM_WRITE_RAW over
SMB_COM_WRITE_ANDX and SMB_COM_READ_RAW over SMB_COM_READ_ANDX,
respectively. WRITEBEHIND activates somewhat asynchronous
SMB_COM_WRITE_RAW operations, but don't get your hopes up just
yet, as the effects are (so far) rather minor.
Careful about the PREFERWRITERAW/PREFERREADRAW switches: if the
server does not support these operations, smbfs will fall back
onto the original SMB_COM_WRITE and SMB_COM_READ commands which
cannot be used safely with files larger than 4 Gigabytes.
- Changed the command template: the debug options are now at the
end of the list.
- The use of the DEBUGFILE option would pretty reliably trigger
an Enforcer hit, followed by a system crash. Note to self:
don't leave dangling BPTRs behind.
- If no modification time is provided for a directory entry,
the creation time will be substituted for it.
+4
View File
@@ -79,6 +79,8 @@ int smb_proc_setattr_core(struct smb_server *server, const char *path, int len,
int smb_proc_setattrE(struct smb_server *server, word fid, struct smb_dirent *new_entry, int * error_ptr);
int smb_proc_dskattr (struct smb_server *server, struct smb_dskattr *attr, int * error_ptr);
int smb_proc_connect(struct smb_server *server, int * error_ptr);
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);
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);
/* sock.c */
int smb_discard_netbios_frames(struct smb_server *server, int sock_fd, int * error_ptr);
@@ -87,5 +89,7 @@ void smb_release(struct smb_server *server);
int smb_connect(struct smb_server *server, int * error_ptr);
int smb_request(struct smb_server *server, int command, void * input_payload,const void * output_payload,int payload_size, int * error_ptr);
int smb_trans2_request(struct smb_server *server, int command, int *data_len, int *param_len, char **data, char **param, int * error_ptr);
int smb_request_read_raw (struct smb_server *server, unsigned char *target, int max_len, int * error_ptr);
int smb_request_write_raw (struct smb_server *server, unsigned const char *source, int length, int * error_ptr);
#endif /* _SMB_FS_H_SMB_H */
+9
View File
@@ -59,6 +59,15 @@ struct smb_server
/* olsen (2012-12-10): raw SMB over TCP instead of NBT transport? */
int raw_smb;
/* olsen (2016-06-03): Prefer SMB_COM_WRITE_RAW to SMB_COM_WRITE_ANDX? */
int prefer_write_raw;
/* olsen (2016-04-20): Use write-behind with SMB_COM_WRITE_RAW? */
int write_behind;
/* olsen (2016-06-03): Prefer SMB_COM_READ_RAW to SMB_COM_READ_ANDX? */
int prefer_read_raw;
/* olsen (2018-05-09): Timeout for send/receive operations in seconds. */
int timeout;
+36 -44
View File
@@ -5,14 +5,6 @@
#ifndef _SMBNO_H_
#define _SMBNO_H_
/* these define the attribute byte as seen by DOS */
#define aRONLY (1L<<0)
#define aHIDDEN (1L<<1)
#define aSYSTEM (1L<<2)
#define aVOLID (1L<<3)
#define aDIR (1L<<4)
#define aARCH (1L<<5)
/* error classes */
#define SUCCESS 0 /* The request was successful. */
#define ERRDOS 0x01 /* Error is from the core DOS operating system set. */
@@ -62,37 +54,37 @@
/* Error codes for the ERRSRV class */
#define ERRerror 1 /* Non specific error code */
#define ERRbadpw 2 /* Bad password */
#define ERRbadtype 3 /* reserved */
#define ERRaccess 4 /* No permissions to do the requested operation */
#define ERRinvnid 5 /* tid invalid */
#define ERRinvnetname 6 /* Invalid servername */
#define ERRinvdevice 7 /* Invalid device */
#define ERRqfull 49 /* Print queue full */
#define ERRqtoobig 50 /* Queued item too big */
#define ERRqeof 51
#define ERRinvpfid 52 /* Invalid print file in smb_fid */
#define ERRsmbcmd 64 /* Unrecognised command */
#define ERRsrverror 65 /* smb server internal error */
#define ERRbadBID 66
#define ERRfilespecs 67 /* fid and pathname invalid combination */
#define ERRbadlink 68 /* reserved */
#define ERRbadpermits 69 /* Access specified for a file is not valid */
#define ERRbadpid 70 /* reserved */
#define ERRsetattrmode 71 /* attribute mode invalid */
#define ERRpaused 81 /* Message server paused */
#define ERRmsgoff 82 /* Not receiving messages */
#define ERRnoroom 83 /* No room for message */
#define ERRrmuns 87 /* too many remote usernames */
#define ERRtimeout 88 /* operation timed out */
#define ERRnoresource 89 /* No resources currently available for request. */
#define ERRtoomanyuids 90 /* too many userids */
#define ERRbaduid 91 /* bad userid */
#define ERRuseMPX 250 /* temporarily unable to use raw mode, use MPX mode */
#define ERRuseSTD 251 /* temporarily unable to use raw mode, use std.mode */
#define ERRcontMPX 252 /* resume MPX mode */
#define ERRbadPW 254
#define ERRerror 1 /* Non specific error code */
#define ERRbadpw 2 /* Bad password */
#define ERRbadtype 3 /* reserved */
#define ERRaccess 4 /* No permissions to do the requested operation */
#define ERRinvnid 5 /* tid invalid */
#define ERRinvnetname 6 /* Invalid servername */
#define ERRinvdevice 7 /* Invalid device */
#define ERRqfull 49 /* Print queue full */
#define ERRqtoobig 50 /* Queued item too big */
#define ERRqeof 51
#define ERRinvpfid 52 /* Invalid print file in smb_fid */
#define ERRsmbcmd 64 /* Unrecognised command */
#define ERRsrverror 65 /* smb server internal error */
#define ERRbadBID 66
#define ERRfilespecs 67 /* fid and pathname invalid combination */
#define ERRbadlink 68 /* reserved */
#define ERRbadpermits 69 /* Access specified for a file is not valid */
#define ERRbadpid 70 /* reserved */
#define ERRsetattrmode 71 /* attribute mode invalid */
#define ERRpaused 81 /* Message server paused */
#define ERRmsgoff 82 /* Not receiving messages */
#define ERRnoroom 83 /* No room for message */
#define ERRrmuns 87 /* too many remote usernames */
#define ERRtimeout 88 /* operation timed out */
#define ERRnoresource 89 /* No resources currently available for request. */
#define ERRtoomanyuids 90 /* too many userids */
#define ERRbaduid 91 /* bad userid */
#define ERRuseMPX 250 /* temporarily unable to use raw mode, use MPX mode */
#define ERRuseSTD 251 /* temporarily unable to use raw mode, use std.mode */
#define ERRcontMPX 252 /* resume MPX mode */
#define ERRbadPW 254
#define ERRnotifyEnumDir 1024
#define ERRaccountExpired 2239
#define ERRbadClient 2240
@@ -420,13 +412,13 @@
#define SMB_OPEN_WRITE_THROUGH_ENABLED 0x4000
/* SMB header flags (which go into the "flags" field). */
#define SMB_FLG_SERVER_TO_REDIR 0x80
#define SMB_FLG_SERVER_TO_REDIR 0x80
#define SMB_FLG_REQUEST_BATCH_OPLOCK 0x40
#define SMB_FLG_REQUEST_OPLOCK 0x20
#define SMB_FLG_CANONICAL_PATHNAMES 0x10
#define SMB_FLG_CASELESS_PATHNAMES 0x08
#define SMB_FLG_REQUEST_OPLOCK 0x20
#define SMB_FLG_CANONICAL_PATHNAMES 0x10
#define SMB_FLG_CASELESS_PATHNAMES 0x08
#define SMB_FLG_CLIENT_BUF_AVAIL 0x02
#define SMB_FLG_SUPPORT_LOCKREAD 0x0
#define SMB_FLG_SUPPORT_LOCKREAD 0x01
/* More SMB header flags (which go into the "flags2" field). */
#define SMB_FLG2_UNICODE_STRINGS 0x8000
+481 -76
View File
File diff suppressed because it is too large Load Diff
+294 -53
View File
@@ -42,6 +42,7 @@
* SMBnegprot SMB_COM_NEGOTIATE 0x72 Core Protocol - negotiate protocol
* SMBopen SMB_COM_OPEN 0x02 Core Protocol deprecated open file (-> SMB_COM_NT_CREATE_ANDX)
* SMBread SMB_COM_READ 0x0A Core Protocol deprecated read from file (-> SMB_COM_READ_ANDX)
* SMBreadbraw SMB_COM_READ_RAW 0x1a Core Protocol deprecated read a block of data with no smb header (-> SMB_COM_READ_ANDX)
* SMBreadX SMB_COM_READ_ANDX 0x2E LAN Manager 1.0 - read and X
* SMBrmdir SMB_COM_DELETE_DIRECTORY 0x01 Core Protocol - delete directory
* SMBsearch SMB_COM_SEARCH 0x81 Core Protocol deprecated search directory (-> SMB_COM_TRANSACTION2+TRANS2_FIND_FIRST2)
@@ -53,6 +54,7 @@
* SMBtrans2 SMB_COM_TRANSACTION2 0x32 LAN Manager 1.2 - TRANS2 protocol set
* SMBunlink SMB_COM_DELETE 0x06 Core Protocol - delete file
* SMBwrite SMB_COM_WRITE 0x0B Core Protocol deprecated write to file (-> SMB_COM_WRITE_ANDX)
* SMBwritebraw SMB_COM_WRITE_RAW 0x1d LAN Manager 1.0 deprecated write a block of data with no smb header (-> SMB_COM_WRITE_ANDX)
* SMBwriteX SMB_COM_WRITE_ANDX 0x2F LAN Manager 1.0 - write and X
*/
@@ -296,7 +298,7 @@ copy_latin1_to_utf16le(byte * to,int to_size, const byte * from,int len)
}
(*to++) = '\0';
(*to++) = '\0';
(*to) = '\0';
num_bytes_written += 2;
}
@@ -359,7 +361,7 @@ copy_utf16le_to_latin1(byte * to,int to_size,const byte * from,int len)
static size_t strnlen(const char * s,size_t max_size)
{
const char * start = s;
size_t result = 0;
size_t result;
if(max_size > 0)
{
@@ -471,7 +473,9 @@ static byte *
smb_encode_dialect (byte * p, const byte * name, int len)
{
(*p++) = 2;
strcpy (p, name);
memcpy(p, name, len);
p[len] = '\0';
return p + len + 1;
}
@@ -480,6 +484,7 @@ static byte *
smb_encode_ascii (byte * p, const byte * name, int len)
{
(*p++) = 4;
memcpy (p, name, len);
p[len] = '\0';
@@ -1303,11 +1308,17 @@ smb_proc_open (struct smb_server *server, const char *pathname, int len, int wri
params = smb_decode_word(params, &entry->fileid);
params += sizeof(dword); /* CreateDisposition */
entry->ctime = local2utc (convert_long_date_to_time_t(params));
params += 2 * sizeof(dword); /* CreateTime */
entry->atime = local2utc (convert_long_date_to_time_t(params));
params += 2 * sizeof(dword); /* LastAccessTime */
entry->wtime = local2utc (convert_long_date_to_time_t(params));
params += 2 * sizeof(dword); /* LastWriteTime */
entry->ctime = entry->atime = entry->mtime = entry->wtime = local2utc (convert_long_date_to_time_t(params));
entry->mtime = local2utc (convert_long_date_to_time_t(params));
params += 2 * sizeof(dword); /* LastChangeTime */
params = smb_decode_dword(params, &ext_file_attributes);
@@ -1381,6 +1392,10 @@ smb_proc_open (struct smb_server *server, const char *pathname, int len, int wri
entry->fileid = WVAL (buf, smb_vwv0);
entry->attr = WVAL (buf, smb_vwv1);
/* This is actually the mtime value, but we use it
* in all other places as well.
*/
entry->ctime = entry->atime = entry->mtime = entry->wtime = local2utc (DVAL (buf, smb_vwv2));
entry->size_low = DVAL (buf, smb_vwv4);
@@ -1474,6 +1489,39 @@ smb_proc_read (struct smb_server *server, struct smb_dirent *finfo, off_t offset
return result;
}
/* count must be <= 65535. No error number is returned. A result of 0
indicates an error, which has to be investigated by a normal read
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)
{
char *buf = server->transmit_buffer;
int result;
ASSERT( count <= 65535 );
retry:
smb_setup_header (server, SMBreadbraw, 10, 0);
WSET (buf, smb_vwv0, finfo->fileid);
DSET (buf, smb_vwv1, offset_quad->Low);
WSET (buf, smb_vwv3, count); /* maxcnt */
WSET (buf, smb_vwv4, 0); /* mincnt */
DSET (buf, smb_vwv5, 0); /* timeout */
WSET (buf, smb_vwv7, 0); /* reserved */
DSET (buf, smb_vwv8, offset_quad->High);
result = smb_request_read_raw (server, data, count, error_ptr);
if (result < 0)
{
if (smb_retry (server))
goto retry;
}
return result;
}
int
smb_proc_write (struct smb_server *server, struct smb_dirent *finfo, off_t offset, long count, const char *data, int * error_ptr)
{
@@ -1513,6 +1561,179 @@ smb_proc_write (struct smb_server *server, struct smb_dirent *finfo, off_t offse
return result;
}
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)
{
char *buf = server->transmit_buffer;
int num_bytes_written = 0;
int result;
long max_len;
long len;
byte *p;
ASSERT( count <= 65535 );
LOG (("number of bytes to send = %ld\n", count));
/* Calculate maximum number of bytes that could be transferred with
* a single SMB_COM_WRITE_RAW packet...
*
* 'max_buffer_size' is the maximum size of a complete SMB message
* including the message header, the parameter and data blocks.
*
* The message header accounts for
* 4(protocol)+1(command)+4(status)+1(flags)+2(flags2)+2(pidhigh)+
* 8(securityfeatures)+2(reserved)+2(tid)+2(pidlow)+2(uid)+2(mid)
* = 32 bytes
*
* The parameters of a SMB_COM_WRITE_RAW command account for
* 1(wordcount)+2(fid)+2(countofbytes)+2(reserved1)+4(offset)+
* 4(timeout)+2(writemode)+4(reserved2)+2(datalength)+2(dataoffset)+
* 4(offset high)
* = 29 bytes
*
* The data part of a SMB_COM_WRITE_RAW command account for
* 2(bytecount)+0(pad) = 2 bytes, not including
* the actual payload
*
* This leaves 'max_buffer_size' - 63 for the payload.
*/
max_len = server->max_buffer_size;
if(max_len > 65535)
max_len = 65535;
max_len -= 63;
LOG(("maximum length for payload = %ld bytes\n", max_len));
/* Number of bytes to write is smaller than the maximum
* number of bytes which may be sent in a single SMB
* message, including parameter and data fields?
*/
if (count <= max_len)
{
LOG(("count (%ld) <= max_len (%ld) -- send no data with the message.\n",count,max_len));
len = 0; /* Send a zero length SMB_COM_WRITE_RAW message, followed by the raw data. */
}
else
{
len = count - max_len; /* Send some of the data as part of the SMB_COM_WRITE_RAW message, followed by the remaining raw data. */
LOG(("count (%ld) > max_len (%ld) -- send %ld bytes with the message.\n",count,max_len,len));
}
retry:
p = smb_setup_header (server, SMBwritebraw, 14, len);
WSET (buf, smb_vwv0, finfo->fileid);
WSET (buf, smb_vwv1, count);
WSET (buf, smb_vwv2, 0); /* reserved */
DSET (buf, smb_vwv3, offset_quad->Low);
DSET (buf, smb_vwv5, 0); /* timeout */
if(server->write_behind)
WSET (buf, smb_vwv7, 0); /* do not send a final result response. */
else
WSET (buf, smb_vwv7, 1); /* send final result response */
DSET (buf, smb_vwv8, 0); /* reserved */
if (server->protocol > PROTOCOL_COREPLUS)
{
WSET (buf, smb_vwv10, len);
WSET (buf, smb_vwv11, p - smb_base(buf));
WSET (buf, smb_vwv12, offset_quad->High);
}
else
{
WSET (buf, smb_vwv10, 0);
}
LOG(("requesting SMBwritebraw\n"));
result = smb_request_ok_with_payload (server, SMBwritebraw, 1, 0, NULL, data, len, error_ptr);
if (result < 0)
{
if (smb_retry (server))
goto retry;
else
goto out;
}
num_bytes_written += len;
data += len;
count -= len;
LOG (("bytes sent so far = %ld\n", num_bytes_written));
if(count > 0)
{
LOG(("sending %ld bytes of data (raw)\n",count));
ASSERT( count <= 65535 );
result = smb_request_write_raw (server, data, count, error_ptr);
if (result < 0)
{
/* Roll back the counters */
num_bytes_written -= len;
data -= len;
count += len;
if (smb_retry (server))
goto retry;
else
goto out;
}
if(server->write_behind)
{
/* We just assume success; the next file operation to follow
* will set an error status if something went wrong.
*/
result = num_bytes_written + count;
}
else
{
int error;
/* We have to do the checks of smb_request_ok here as well */
if ((error = smb_valid_packet (server->transmit_buffer)) != 0)
{
LOG (("not a valid packet!\n"));
(*error_ptr) = error;
result = -1;
goto out;
}
else if (server->rcls != 0)
{
LOG (("server error %ld/%ld\n", server->rcls, server->err));
smb_printerr (server->rcls, server->err);
(*error_ptr) = error_check_smb_error;
result = -1;
goto out;
}
result = num_bytes_written + count;
}
LOG (("bytes sent so far = %ld\n", result));
}
out:
return result;
}
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)
{
@@ -1735,7 +1956,7 @@ smb_proc_create (struct smb_server *server, const char *path, int len, struct sm
}
int
smb_proc_mv (struct smb_server *server, const char *opath, const int olen, const char *npath, const int nlen, 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;
@@ -1743,9 +1964,9 @@ smb_proc_mv (struct smb_server *server, const char *opath, const int olen, const
int result;
if(server->unicode_enabled)
size = 2 + 1 + 2 * (olen+1) + 1 + 2 * (nlen+1);
size = 2 + 1 + 2 * (old_path_len+1) + 1 + 2 * (new_path_len+1);
else
size = 2 + 1 + (olen+1) + 1 + (nlen+1);
size = 2 + 1 + (old_path_len+1) + 1 + (new_path_len+1);
ASSERT( smb_payload_size(server, 1, size) >= 0 );
@@ -1753,20 +1974,20 @@ smb_proc_mv (struct smb_server *server, const char *opath, const int olen, const
p = smb_setup_header (server, SMBmv, 1, size);
WSET (buf, smb_vwv0, 0);
WSET (buf, smb_vwv0, SMB_FILE_ATTRIBUTE_SYSTEM | SMB_FILE_ATTRIBUTE_HIDDEN);
if(server->unicode_enabled)
{
(*p++) = 4; /* A null-terminated string follows. */
p += copy_latin1_to_utf16le(p,2 * (olen+1),opath,olen);
p += copy_latin1_to_utf16le(p,2 * (old_path_len+1),old_path,old_path_len);
(*p++) = 4; /* A null-terminated string follows. */
(void) copy_latin1_to_utf16le(p,2 * (nlen+1),npath,nlen);
(void) copy_latin1_to_utf16le(p,2 * (new_path_len+1),new_path,new_path_len);
}
else
{
p = smb_encode_ascii (p, opath, olen);
smb_encode_ascii (p, npath, olen);
p = smb_encode_ascii (p, old_path, old_path_len);
(void) smb_encode_ascii (p, new_path, new_path_len);
}
result = smb_request_ok (server, SMBmv, 0, 0, error_ptr);
@@ -2058,10 +2279,10 @@ smb_proc_readdir_short (struct smb_server *server, const char *path, int fpos, i
word count;
char status[SMB_STATUS_SIZE];
int entries_asked = (server->max_recv - 100) / SMB_DIRINFO_SIZE;
int dirlen = strlen (path);
int path_len = strlen (path);
char * mask;
mask = malloc(dirlen + 4 + 1);
mask = malloc(path_len + 4 + 1);
if (mask == NULL)
{
(*error_ptr) = ENOMEM;
@@ -2070,8 +2291,8 @@ smb_proc_readdir_short (struct smb_server *server, const char *path, int fpos, i
goto out;
}
strcpy (mask, path);
strcat (mask, "\\*.*");
memcpy(mask, path, path_len);
memcpy(&mask[path_len], "\\*.*", 5); /* Length includes terminating NUL. */
LOG (("SMB call readdir %ld @ %ld\n", cache_size, fpos));
LOG ((" mask = '%s'\n", escape_name(mask)));
@@ -3500,9 +3721,7 @@ smb_proc_reconnect (struct smb_server *server, int * error_ptr)
int password_len;
unsigned char nt_password[24];
int nt_password_len;
unsigned char full_share[SMB_MAXNAMELEN+1];
int full_share_len;
int full_share_size;
char * share_name = NULL;
byte *packet;
dword max_buffer_size;
int packet_size;
@@ -3511,7 +3730,7 @@ smb_proc_reconnect (struct smb_server *server, int * error_ptr)
if (result < 0)
{
LOG (("could not smb_connect\n"));
goto fail;
goto out;
}
/* Unless we know better, we don't go for Unicode just yet. */
@@ -3569,7 +3788,7 @@ smb_proc_reconnect (struct smb_server *server, int * error_ptr)
(*error_ptr) = ENOMEM;
result = -1;
goto fail;
goto out;
}
packet = server->transmit_buffer;
@@ -3591,7 +3810,7 @@ smb_proc_reconnect (struct smb_server *server, int * error_ptr)
if (result < 0)
{
LOG (("Failed to send SESSION REQUEST.\n"));
goto fail;
goto out;
}
if (packet[0] != 0x82)
@@ -3607,7 +3826,7 @@ smb_proc_reconnect (struct smb_server *server, int * error_ptr)
(*error_ptr) = error_session_request_failed;
result = -1;
goto fail;
goto out;
}
LOG (("Passed SESSION REQUEST.\n"));
@@ -3616,7 +3835,7 @@ smb_proc_reconnect (struct smb_server *server, int * error_ptr)
/* Now we are ready to send a SMB Negotiate Protocol packet. */
plength = 0;
for (i = 0; i < num_prots ; i++)
plength += strlen (prots[i].name) + 2;
plength += 1 + strlen (prots[i].name) + 1;
ASSERT( smb_payload_size(server, 0, plength) >= 0 );
@@ -3633,11 +3852,9 @@ smb_proc_reconnect (struct smb_server *server, int * error_ptr)
if (result < 0)
{
LOG (("Failure requesting SMBnegprot\n"));
goto fail;
goto out;
}
LOG (("Verified!\n"));
p = SMB_VWV (packet);
p = smb_decode_word (p, &dialect_index);
@@ -3652,7 +3869,7 @@ smb_proc_reconnect (struct smb_server *server, int * error_ptr)
(*error_ptr) = error_unsupported_dialect;
result = -1;
goto fail;
goto out;
}
server->protocol = prots[dialect_index].prot;
@@ -3695,7 +3912,7 @@ smb_proc_reconnect (struct smb_server *server, int * error_ptr)
/* Skip "system time" (1 qword) and "server time zone" (1 word). */
p += 2 * sizeof(dword) + sizeof(word);
server->crypt_key_length = (*p++);
server->crypt_key_length = (*p);
memcpy(server->crypt_key,SMB_BUF(packet),server->crypt_key_length);
}
@@ -3785,6 +4002,7 @@ smb_proc_reconnect (struct smb_server *server, int * error_ptr)
if((server->security_mode & NEGOTIATE_USER_SECURITY) == 0)
{
SHOWMSG("share level security; zapping passwords");
strcpy(password,"");
password_len = 0;
@@ -3891,7 +4109,7 @@ smb_proc_reconnect (struct smb_server *server, int * error_ptr)
if (result < 0)
{
LOG (("SMBsessetupX failed\n"));
goto fail;
goto out;
}
smb_decode_word (packet + 32, &server->server_uid);
@@ -3915,38 +4133,57 @@ smb_proc_reconnect (struct smb_server *server, int * error_ptr)
if(nt_password_len > 0)
{
int server_name_len;
int service_len;
int share_name_len;
int share_name_size;
int padding_needed;
strlcpy(full_share,"//",sizeof(full_share));
strlcat(full_share,server->mount_data.server_name,sizeof(full_share));
strlcat(full_share,"/",sizeof(full_share));
strlcat(full_share,server->mount_data.service,sizeof(full_share));
server_name_len = strlen(server->mount_data.server_name);
service_len = strlen(server->mount_data.service);
full_share_len = strlen(full_share);
share_name_len = 2 + server_name_len + 1 + service_len;
for(i = 0 ; i < full_share_len ; i++)
share_name = malloc(share_name_len+1);
if(share_name == NULL)
{
if(full_share[i] == '/')
full_share[i] = '\\';
LOG (("No memory! Bailing out.\n"));
(*error_ptr) = ENOMEM;
result = -1;
goto out;
}
StringToUpper(full_share);
memcpy(share_name,"//",2);
memcpy(&share_name[2],server->mount_data.server_name,server_name_len);
share_name[2 + server_name_len] = '/';
memcpy(&share_name[2 + server_name_len + 1],server->mount_data.service,service_len+1); /* Length includes terminating NUL byte. */
D(("full_share = '%s'", escape_name(full_share)));
/* Flip the slashes, so they become backslashes. */
for(i = 0 ; i < share_name_len ; i++)
{
if(share_name[i] == '/')
share_name[i] = '\\';
}
StringToUpper(share_name);
D(("share_name = '%s'", escape_name(share_name)));
if(server->unicode_enabled)
full_share_size = 2 * (full_share_len + 1);
share_name_size = 2 * (share_name_len + 1);
else
full_share_size = full_share_len + 1;
share_name_size = share_name_len + 1;
if(server->unicode_enabled && (password_len % 2) == 0)
padding_needed = 1;
else
padding_needed = 0;
ASSERT( smb_payload_size(server, 4, password_len + padding_needed + full_share_size + strlen(dev)+1) >= 0 );
ASSERT( smb_payload_size(server, 4, password_len + padding_needed + share_name_size + strlen(dev)+1) >= 0 );
smb_setup_header (server, SMBtconX, 4, password_len + padding_needed + full_share_size + strlen(dev)+1);
smb_setup_header (server, SMBtconX, 4, password_len + padding_needed + share_name_size + strlen(dev)+1);
WSET (packet, smb_vwv0, 0xFF);
WSET (packet, smb_vwv3, password_len);
@@ -3960,11 +4197,11 @@ smb_proc_reconnect (struct smb_server *server, int * error_ptr)
(*p++) = 0;
if(server->unicode_enabled)
copy_latin1_to_utf16le(p,full_share_size,full_share,full_share_len);
copy_latin1_to_utf16le(p,share_name_size,share_name,share_name_len);
else
memcpy(p,full_share,full_share_size);
memcpy(p,share_name,share_name_size);
p += full_share_size;
p += share_name_size;
strcpy(p,dev);
@@ -3974,7 +4211,7 @@ smb_proc_reconnect (struct smb_server *server, int * error_ptr)
SHOWVALUE(SMB_WCT(packet));
LOG (("SMBtconX not verified.\n"));
goto fail;
goto out;
}
SHOWVALUE(SMB_WCT(packet));
@@ -3999,7 +4236,7 @@ smb_proc_reconnect (struct smb_server *server, int * error_ptr)
if (result < 0)
{
LOG (("SMBtcon not verified.\n"));
goto fail;
goto out;
}
LOG (("OK! Managed to set up SMBtcon!\n"));
@@ -4050,7 +4287,7 @@ smb_proc_reconnect (struct smb_server *server, int * error_ptr)
(*error_ptr) = ENOMEM;
result = -1;
goto fail;
goto out;
}
}
@@ -4067,11 +4304,15 @@ smb_proc_reconnect (struct smb_server *server, int * error_ptr)
LOG (("Normal exit\n"));
return 0;
result = 0;
fail:
out:
server->state = CONN_INVALID;
if(share_name != NULL)
free(share_name);
if(result < 0)
server->state = CONN_INVALID;
return result;
}
+186 -83
View File
@@ -49,6 +49,9 @@ smba_connect (
int timeout,
int opt_raw_smb,
int opt_unicode,
int opt_prefer_write_raw,
int opt_write_behind,
int opt_prefer_read_raw,
int * error_ptr,
int * smb_error_class_ptr,
int * smb_error_ptr,
@@ -75,16 +78,25 @@ smba_connect (
memset (&data, 0, sizeof (data));
memset (hostname, 0, sizeof (hostname));
/* Olaf (2012-12-10): force raw SMB over TCP rather than NetBIOS. */
/* Use raw SMB over TCP rather than NetBIOS. */
if(opt_raw_smb)
res->server.raw_smb = TRUE;
/* olsen (2018-05-09): Timeout for send/receive operations in seconds. */
/* Timeout for send/receive operations in seconds. */
res->server.timeout = timeout;
/* olsen (2018-06-01): Enable Unicode support if the server supports it. */
/* Enable Unicode support if the server supports it, too. */
res->server.use_unicode = opt_unicode;
/* Prefer SMB_COM_WRITE_RAW over SMB_COM_WRITE_ANDX? */
res->server.prefer_write_raw = opt_prefer_write_raw;
/* Enable asynchronous SMB_COM_WRITE_RAW operations? */
res->server.write_behind = opt_write_behind;
/* Prefer SMB_COM_READ_RAW over SMB_COM_READ_ANDX? */
res->server.prefer_read_raw = opt_prefer_read_raw;
if(smba_setup_dircache (res,cache_size,error_ptr) < 0)
{
ReportError("Directory cache initialization failed (%ld, %s).",(*error_ptr),posix_strerror(*error_ptr));
@@ -97,6 +109,7 @@ smba_connect (
gethostname (hostname, MAXHOSTNAMELEN);
/* Only retain the host name, drop any domain names following it. */
if ((s = strchr (hostname, '.')) != NULL)
(*s) = '\0';
@@ -405,38 +418,59 @@ write_attr (smba_file_t * f, int * error_ptr)
/*****************************************************************************/
void
smba_close (smba_file_t * f, int * error_ptr)
smba_close (smba_server_t * s, smba_file_t * f)
{
if(f != NULL)
smba_file_t * found;
smba_file_t * file;
found = NULL;
for(file = (smba_file_t *)s->open_files.mlh_Head ;
file->node.mln_Succ != NULL ;
file = (smba_file_t *)file->node.mln_Succ)
{
if(f->node.mln_Succ != NULL || f->node.mln_Pred != NULL)
Remove((struct Node *)f);
if(f->attr_dirty)
write_attr(f, error_ptr);
if (f->dirent.opened)
if(file == f)
{
LOG (("closing file '%s' (fileid=0x%04lx)\n", escape_name(f->dirent.complete_path), f->dirent.fileid));
found = f;
break;
}
}
if(found != NULL)
{
int ignored_error;
Remove((struct Node *)found);
if(found->attr_dirty)
write_attr(found, &ignored_error);
if (found->dirent.opened)
{
LOG (("closing file '%s' (fileid=0x%04lx)\n", escape_name(found->dirent.complete_path), found->dirent.fileid));
/* Don't change the modification time unless the contents
* of the file were changed.
*/
smb_proc_close (&f->server->server, f->dirent.fileid, f->modified ? f->dirent.mtime : 0, error_ptr);
smb_proc_close (&found->server->server, found->dirent.fileid, found->modified ? found->dirent.mtime : 0, &ignored_error);
}
if (f->dircache != NULL)
if (found->dircache != NULL)
{
f->dircache->cache_for = NULL;
f->dircache->len = 0;
f->dircache = NULL;
found->dircache->cache_for = NULL;
found->dircache->len = 0;
found->dircache = NULL;
}
f->server->num_open_files--;
found->server->num_open_files--;
LOG(("file closed, number of open files = %ld\n",f->server->num_open_files));
LOG(("file closed, number of open files = %ld\n",found->server->num_open_files));
free (f);
free (found);
}
else
{
LOG(("file seems to be invalid\n"));
}
}
@@ -455,7 +489,8 @@ smba_read (smba_file_t * f, char *data, long len, const QUAD * const offset, int
D(("read %ld bytes from offset %ld",len,offset));
if (f->server->server.protocol >= PROTOCOL_LANMAN1)
/* SMB_COM_READ_ANDX supported? */
if (f->server->server.protocol >= PROTOCOL_LANMAN1 && !f->server->server.prefer_read_raw)
{
QUAD position_quad = (*offset);
int max_readx_size;
@@ -517,6 +552,48 @@ smba_read (smba_file_t * f, char *data, long len, const QUAD * const offset, int
}
while (len > 0);
}
/* SMB_COM_READ_RAW and SMB_COM_WRITE_RAW supported? */
else if ((f->server->server.capabilities & CAP_RAW_MODE) != 0)
{
int max_raw_size = f->server->server.max_raw_size;
QUAD position_quad = (*offset);
int n;
do
{
/* SMB_COM_READ_RAW can only read up to 65535 bytes. */
n = min(len, 65535);
/* The maximum number of bytes to be read in raw
* mode may be limited, too.
*/
if(n > max_raw_size)
n = max_raw_size;
/* Limit how much data we are prepared to receive? */
if(n > max_receive)
n = max_receive;
result = smb_proc_read_raw (&f->server->server, &f->dirent, &position_quad, n, data, error_ptr);
if(result <= 0)
{
D(("!!! wanted to read %ld bytes, got %ld",n,result));
break;
}
num_bytes_read += result;
len -= result;
add_64_plus_32_to_64(&position_quad,result,&position_quad);
data += result;
if(result < n)
{
D(("read returned fewer characters than expected (%ld < %ld)",result,n));
break;
}
}
while(len > 0);
}
else
{
int max_size_smb_com_read;
@@ -611,7 +688,7 @@ smba_write (smba_file_t * f, const char *data, long len, const QUAD * const offs
max_buffer_size = f->server->server.max_buffer_size;
/* SMB_COM_WRITE_ANDX supported? */
if (f->server->server.protocol >= PROTOCOL_LANMAN1)
if (f->server->server.protocol >= PROTOCOL_LANMAN1 && !f->server->server.prefer_write_raw)
{
QUAD position_quad = (*offset);
int max_writex_size;
@@ -672,6 +749,62 @@ smba_write (smba_file_t * f, const char *data, long len, const QUAD * const offs
}
while(len > 0);
}
else if ((f->server->server.capabilities & CAP_RAW_MODE) != 0)
{
int max_raw_size = f->server->server.max_raw_size;
int max_size_smb_com_write_raw;
QUAD position_quad = (*offset);
int n;
/* Try to send the maximum number of bytes with the two SMBwritebraw packets.
* This is how it breaks down:
*
* The message header accounts for
* 4(protocol)+1(command)+4(status)+1(flags)+2(flags2)+2(pidhigh)+
* 8(securityfeatures)+2(reserved)+2(tid)+2(pidlow)+2(uid)+2(mid)
* = 32 bytes
*
* The parameters of a SMB_COM_WRITE_RAW command account for
* 1(wordcount)+2(fid)+2(countofbytes)+2(reserved1)+4(offset)+
* 4(timeout)+2(writemode)+4(reserved2)+2(datalength)+
* 2(dataoffset) = 25 bytes
*
* The data part of a SMB_COM_WRITE_RAW command accounts for
* 2(bytecount) = 2 bytes
*
* This leaves 'max_buffer_size' - 59 for the payload.
*/
/*max_size_smb_com_write_raw = 2 * f->server->server.max_buffer_size - (SMB_HEADER_LEN + 12 * sizeof (word) + 4) - 8;*/
max_size_smb_com_write_raw = max(max_buffer_size, max_raw_size) - 59;
/* SMB_COM_WRITE_RAW cannot transmit more than 65535 bytes. */
if(max_size_smb_com_write_raw > 65535)
max_size_smb_com_write_raw = 65535;
LOG (("len = %ld, max_size_smb_com_write_raw = %ld\n", len, max_size_smb_com_write_raw));
do
{
n = min(len, max_size_smb_com_write_raw);
ASSERT( n > 0 );
if(n > max_raw_size)
n = max_raw_size;
ASSERT( n <= 65535 );
result = smb_proc_write_raw (&f->server->server, &f->dirent, &position_quad, n, data, error_ptr);
if(result < 0)
goto out;
data += result;
add_64_plus_32_to_64(&position_quad,result,&position_quad);
len -= result;
num_bytes_written += result;
}
while(len > 0);
}
else
{
int max_size_smb_com_write, count;
@@ -1053,56 +1186,23 @@ smba_readdir (smba_file_t * f, long offs, void *d, smba_callback_t callback, int
/*****************************************************************************/
static void
invalidate_dircache (struct smba_server * server, const char * path)
invalidate_dircache (struct smba_server * server)
{
dircache_t * dircache = server->dircache;
char other_path[SMB_MAXNAMELEN + 1];
ENTER();
if(path != NULL)
{
int len,i;
strlcpy(other_path,path,sizeof(other_path));
len = strlen(other_path);
for(i = len-1 ; i >= 0 ; i--)
{
if(i == 0)
{
other_path[0] = DOS_PATHSEP;
other_path[1] = '\0';
}
else if (other_path[i] == DOS_PATHSEP)
{
other_path[i] = '\0';
break;
}
}
}
else
{
other_path[0] = '\0';
}
D(("other_path = '%s'", escape_name(other_path)));
if(dircache->cache_for != NULL)
D(("dircache->cache_for->dirent.complete_path = '%s'", escape_name(dircache->cache_for->dirent.complete_path)));
else
SHOWMSG("-- directory cache is empty --");
if(path == NULL || (dircache->cache_for != NULL && CompareNames(other_path,dircache->cache_for->dirent.complete_path) == SAME))
{
SHOWMSG("clearing directory cache");
dircache->eof = dircache->len = dircache->base = 0;
dircache->eof = dircache->len = dircache->base = 0;
if(dircache->cache_for != NULL)
{
dircache->cache_for->dircache = NULL;
dircache->cache_for = NULL;
}
if(dircache->cache_for != NULL)
{
dircache->cache_for->dircache = NULL;
dircache->cache_for = NULL;
}
LEAVE();
@@ -1161,8 +1261,6 @@ smba_create (smba_file_t * dir, const char *name, int * error_ptr)
goto out;
}
/* invalidate_dircache (dir->server, path); */
out:
if(path != NULL)
@@ -1177,13 +1275,18 @@ int
smba_mkdir (smba_file_t * dir, const char *name, int * error_ptr)
{
char *path = NULL;
int path_len;
int name_len;
int result;
result = make_open (dir, open_dont_need_fid, open_writable, open_dont_truncate, error_ptr);
if (result < 0)
goto out;
path = malloc (strlen (name) + dir->dirent.len + 2);
name_len = strlen (name);
path_len = dir->dirent.len + 1 + name_len;
path = malloc (path_len + 1);
if(path == NULL)
{
(*error_ptr) = ENOMEM;
@@ -1194,14 +1297,13 @@ smba_mkdir (smba_file_t * dir, const char *name, int * error_ptr)
memcpy (path, dir->dirent.complete_path, dir->dirent.len);
path[dir->dirent.len] = DOS_PATHSEP;
strcpy (&path[dir->dirent.len + 1], name);
memcpy (&path[dir->dirent.len + 1], name, name_len);
path[path_len] = '\0';
result = smb_proc_mkdir (&dir->server->server, path, strlen (path), error_ptr);
result = smb_proc_mkdir (&dir->server->server, path, path_len, error_ptr);
if(result < 0)
goto out;
/* invalidate_dircache (dir->server, path); */
out:
if(path != NULL)
@@ -1259,8 +1361,6 @@ smba_remove (smba_server_t * s, const char *path, int * error_ptr)
if(result < 0)
goto out;
/* invalidate_dircache (s, path); */
out:
return result;
@@ -1281,8 +1381,6 @@ smba_rmdir (smba_server_t * s, const char *path, int * error_ptr)
if(result < 0)
goto out;
/* invalidate_dircache (s, path); */
out:
return result;
@@ -1303,8 +1401,6 @@ smba_rename (smba_server_t * s, const char *from, const char *to, int * error_pt
if(result < 0)
goto out;
/* invalidate_dircache (s, from); */
out:
return(result);
@@ -1340,7 +1436,7 @@ smb_invalidate_all_inodes (struct smb_server *server)
ENTER();
invalidate_dircache (server->abstraction, NULL);
invalidate_dircache (server->abstraction);
for (f = (smba_file_t *)server->abstraction->open_files.mlh_Head;
f->node.mln_Succ != NULL;
@@ -1512,6 +1608,9 @@ smba_start(
int opt_timeout,
int opt_raw_smb,
int opt_unicode,
int opt_prefer_write_raw,
int opt_write_behind,
int opt_prefer_read_raw,
int * error_ptr,
int * smb_error_class_ptr,
int * smb_error_ptr,
@@ -1574,12 +1673,13 @@ smba_start(
}
/* Brian Willette: Now we will set the server name to the DNS
hostname, hopefully this will be the same as the NetBIOS name for
the server.
We do this because the user supplied no hostname, and we
need one for NetBIOS, this is the best guess choice we have
NOTE: If the names are different between DNS and NetBIOS on
the windows side, the user MUST use the -s option. */
* hostname, hopefully this will be the same as the NetBIOS name for
* the server.
* We do this because the user supplied no hostname, and we
* need one for NetBIOS, this is the best guess choice we have
* NOTE: If the names are different between DNS and NetBIOS on
* the windows side, the user MUST use the -s option.
*/
for (i = 0; h->h_name[i] != '.' && h->h_name[i] != '\0' && i < 255; i++)
hostName[i] = h->h_name[i];
@@ -1683,6 +1783,9 @@ smba_start(
opt_timeout,
opt_raw_smb,
opt_unicode,
opt_prefer_write_raw,
opt_write_behind,
opt_prefer_read_raw,
error_ptr,
smb_error_class_ptr,
smb_error_ptr,
@@ -1800,7 +1903,7 @@ smba_change_dircache_size(struct smba_server * server,int cache_size)
}
}
invalidate_dircache(server, NULL);
invalidate_dircache(server);
free_dircache(old_dircache);
+2 -2
View File
@@ -119,7 +119,7 @@ typedef int (*smba_callback_t) (void *d, int fpos, int nextpos, char *name, int
/****************************************************************************/
int smba_open(smba_server_t *s, char *name, int writable, int truncate, smba_file_t **file, int * error_ptr);
void smba_close(smba_file_t *f, int * error_ptr);
void smba_close(smba_server_t * s, smba_file_t *f);
int smba_read(smba_file_t *f, char *data, long len, const QUAD * const offset, int * error_ptr);
int smba_write(smba_file_t *f, const char *data, long len, const QUAD * const offset, int * error_ptr);
int smba_lockrec (smba_file_t *f, long offset, long len, long mode, int unlocked, long timeout, int * error_ptr);
@@ -133,7 +133,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 * error_ptr, int * smb_error_class_ptr, int * smb_error_ptr, smba_server_t **result);
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_write_raw, int opt_write_behind, int opt_prefer_read_raw, int * error_ptr, int * smb_error_class_ptr, int * smb_error_ptr, smba_server_t **result);
void smba_disconnect(smba_server_t *server);
int smba_get_dircache_size(struct smba_server * server);
int smba_change_dircache_size(struct smba_server * server,int cache_size);
+5 -5
View File
@@ -1,6 +1,6 @@
#define VERSION 1
#define REVISION 144
#define DATE "1.6.2018"
#define VERS "smbfs 1.144"
#define VSTRING "smbfs 1.144 (1.6.2018)\r\n"
#define VERSTAG "\0$VER: smbfs 1.144 (1.6.2018)"
#define REVISION 146
#define DATE "3.6.2018"
#define VERS "smbfs 1.146"
#define VSTRING "smbfs 1.146 (3.6.2018)\r\n"
#define VERSTAG "\0$VER: smbfs 1.146 (3.6.2018)"
+1 -1
View File
@@ -1 +1 @@
144
146
+135
View File
@@ -1284,3 +1284,138 @@ smb_trans2_request (struct smb_server *server, int command, int *data_len, int *
return result;
}
int
smb_request_read_raw (struct smb_server *server, unsigned char *target, int max_len, int * error_ptr)
{
unsigned char *buffer = server->transmit_buffer;
int sock_fd = server->mount_data.fd;
int len, result;
ASSERT( error_ptr != NULL );
if (server->state != CONN_VALID)
{
LOG (("Connection state is invalid\n"));
(*error_ptr) = error_server_connection_invalid;
result = -1;
goto out;
}
/* Length includes the NetBIOS session header (4 bytes), which
* is prepended to the packet to be sent.
*/
len = NETBIOS_HEADER_SIZE + smb_len (buffer);
LOG (("len = %ld cmd = 0x%02lx\n", len, buffer[8]));
LOG (("target=%lx, max_len=%ld\n", (unsigned int) target, max_len));
LOG (("buffer=%lx, sock=%lx\n", (unsigned int) buffer, (unsigned int) sock_fd));
#if defined(DUMP_SMB)
dump_netbios_header(__FILE__,__LINE__,buffer,NULL,0);
dump_smb(__FILE__,__LINE__,0,buffer+NETBIOS_HEADER_SIZE,len-NETBIOS_HEADER_SIZE,smb_packet_from_consumer,server->max_recv);
#endif /* defined(DUMP_SMB) */
/* Request that data should be read in raw mode. */
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;
}
/* Wait for the raw data to be sent by the server. */
result = smb_receive_raw (server, SMBreadbraw, sock_fd, target, max_len, NULL, 0, FALSE, error_ptr);
out:
if (result < 0)
smb_check_server_connection(server,(*error_ptr));
LOG (("result = %ld\n", result));
return result;
}
/* smb_request_write_raw assumes that the request SMBwriteBraw has been
* completed successfully, so that we can send the raw data now.
*/
int
smb_request_write_raw (struct smb_server *server, unsigned const char *source, int length, int * error_ptr)
{
byte nb_header[NETBIOS_HEADER_SIZE];
int sock_fd = server->mount_data.fd;
int result;
if (server->state != CONN_VALID)
{
LOG (("Connection state is invalid\n"));
(*error_ptr) = error_server_connection_invalid;
result = -1;
goto out;
}
ASSERT( length <= 65535 );
/* Send the NetBIOS header. */
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)
{
LOG(("send() for %ld bytes failed (errno=%ld)\n", length, errno));
(*error_ptr) = errno;
goto out;
}
/* Wait for the server to respond. */
if(!server->write_behind)
{
result = smb_receive (server, SMBwritebraw, sock_fd, NULL, 0, error_ptr);
if(result < 0)
goto out;
}
else
{
LOG(("not waiting for server to respond\n"));
}
result = length;
out:
if (result < 0)
smb_check_server_connection(server,(*error_ptr));
LOG (("result = %ld\n", result));
return result;
}