mirror of
https://github.com/obarthel/amiga-smbfs.git
synced 2025-12-08 14:58:35 +00:00
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:
@@ -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.
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
+294
-53
@@ -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
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 @@
|
||||
144
|
||||
146
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user