Updated to version 1.132

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-05-19 15:43:09 +02:00
parent 6b58679cd6
commit afe7b87f24
18 changed files with 2096 additions and 875 deletions
+2 -2
View File
@@ -71,7 +71,7 @@ cp850.o : cp850.c
crypt.o : crypt.c system_headers.h assert.h smbfs.h
dump_smb.o : dump_smb.c system_headers.h assert.h smbfs.h dump_smb.h quad_math.h
main.o : main.c system_headers.h assert.h smbfs.h smb_abstraction.h utf-8-iso-8859-1-conversion.h cp437.h cp850.h errors.h dump_smb.h smbfs_rev.h
proc.o : proc.c system_headers.h assert.h smbfs.h quad_math.h errors.h
proc.o : proc.c system_headers.h assert.h smbfs.h quad_math.h errors.h smbfs_rev.h
quad_math.o : quad_math.c quad_math.h
smb_abstraction.o : smb_abstraction.c system_headers.h assert.h smbfs.h smb_abstraction.h
sock.o : sock.c system_headers.h assert.h smbfs.h smb_abstraction.h dump_smb.h errors.h
@@ -80,4 +80,4 @@ utf-8-iso-8859-1-conversion.o : utf-8-iso-8859-1-conversion.c utf-8-iso-8859-1-c
###############################################################################
clean:
-delete #?.o $(PROJECT)(%|.debug)
-delete #?.o #?.map $(PROJECT)(%|.debug)
+2 -2
View File
@@ -76,7 +76,7 @@ cp850.o : cp850.c
crypt.o : crypt.c system_headers.h assert.h smbfs.h
dump_smb.o : dump_smb.c system_headers.h assert.h smbfs.h dump_smb.h quad_math.h
main.o : main.c system_headers.h assert.h smbfs.h smb_abstraction.h utf-8-iso-8859-1-conversion.h cp437.h cp850.h errors.h dump_smb.h smbfs_rev.h
proc.o : proc.c system_headers.h assert.h smbfs.h quad_math.h errors.h
proc.o : proc.c system_headers.h assert.h smbfs.h quad_math.h errors.h smbfs_rev.h
quad_math.o : quad_math.c quad_math.h
smb_abstraction.o : smb_abstraction.c system_headers.h assert.h smbfs.h smb_abstraction.h
sock.o : sock.c system_headers.h assert.h smbfs.h smb_abstraction.h dump_smb.h errors.h
@@ -85,4 +85,4 @@ utf-8-iso-8859-1-conversion.o : utf-8-iso-8859-1-conversion.c utf-8-iso-8859-1-c
###########################################################################
clean:
rm *.o $(PROJECT) $(PROJECT).debug $(PROJECT).map
-rm *.o $(PROJECT) $(PROJECT).debug $(PROJECT).map
Executable → Regular
+6 -5
View File
@@ -52,10 +52,10 @@ enum smb_conn_state
struct smb_dskattr
{
word total;
word allocblocks;
word blocksize;
word free;
dword total;
dword allocblocks;
dword blocksize;
dword free;
};
/*
@@ -65,7 +65,7 @@ struct smb_dirent
{
int opened; /* is it open on the fileserver? */
word fileid; /* What id to handle a file with? */
word attr; /* Attribute fields, DOS value */
dword attr; /* Attribute fields, DOS value */
time_t atime, mtime,
wtime, ctime; /* Times, as seen by the server, normalized */
@@ -73,6 +73,7 @@ struct smb_dirent
/* proc.c */
unsigned long size; /* File size. */
char * complete_path; /* Complete path, MS-DOS notation, with '\' */
size_t complete_path_size; /* Number of bytes allocated for name */
int len; /* Namelength. */
+7 -4
View File
@@ -47,13 +47,14 @@ int smb_len(const byte *packet);
void smb_translate_error_class_and_code(int errcls,int error,char ** class_ptr,char ** code_ptr);
int smb_errno(int errcls, int error);
int smb_payload_size(const struct smb_server *server, int wct, int bcc);
int smb_proc_open(struct smb_server *server, const char *pathname, int len, struct smb_dirent *entry, int * error_ptr);
int smb_proc_open(struct smb_server *server, const char *pathname, int len, int writable, int truncate, struct smb_dirent *entry, int * error_ptr);
int smb_proc_close(struct smb_server *server, word fileid, dword mtime, int * error_ptr);
int smb_proc_read(struct smb_server *server, struct smb_dirent *finfo, off_t offset, long count, char *data, int * error_ptr);
int smb_proc_read_raw(struct smb_server *server, struct smb_dirent *finfo, off_t offset, long count, char *data, int * error_ptr);
int smb_proc_write (struct smb_server *server, struct smb_dirent *finfo, off_t offset, long count, const char *data, int * error_ptr);
int smb_proc_write_raw(struct smb_server *server, struct smb_dirent *finfo, off_t offset, long count, const char *data, int * error_ptr);
int smb_proc_lseek (struct smb_server *server, struct smb_dirent *finfo, off_t offset, int mode, off_t * new_position_ptr, int * error_ptr);
int smb_proc_writex (struct smb_server *server, struct smb_dirent *finfo, off_t offset, long count, const char *data, int * error_ptr);
int smb_proc_readx (struct smb_server *server, struct smb_dirent *finfo, off_t offset, long count, char *data, int * error_ptr);
int smb_proc_lockingX (struct smb_server *server, struct smb_dirent *finfo, struct smb_lkrng *locks, int num_entries, int mode, long timeout, int * error_ptr);
int smb_proc_create(struct smb_server *server, const char *path, int len, struct smb_dirent *entry, int * error_ptr);
int smb_proc_mv(struct smb_server *server, const char *opath, const int olen, const char *npath, const int nlen, int * error_ptr);
@@ -64,6 +65,8 @@ int smb_proc_trunc(struct smb_server *server, word fid, dword length, int * erro
int smb_proc_readdir(struct smb_server *server, char *path, int fpos, int cache_size, struct smb_dirent *entry, int * error_ptr);
int smb_proc_getattr_core(struct smb_server *server, const char *path, int len, struct smb_dirent *entry, int * error_ptr);
int smb_proc_getattrE(struct smb_server *server, struct smb_dirent *entry, int * error_ptr);
int smb_query_path_information(struct smb_server *server, const char *path, int len, int fid, struct smb_dirent *entry, int * error_ptr);
int smb_set_file_information(struct smb_server *server, struct smb_dirent *entry, const dword * size_ptr, int * error_ptr);
int smb_proc_setattr_core(struct smb_server *server, const char *path, int len, struct smb_dirent *new_finfo, int * error_ptr);
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);
@@ -73,8 +76,8 @@ int smb_proc_connect(struct smb_server *server, int * error_ptr);
void smb_check_server_connection(struct smb_server *server, int error);
void smb_release(struct smb_server *server);
int smb_connect(struct smb_server *server, int * error_ptr);
int smb_request(struct smb_server *server,void * input_payload,const void * output_payload,int payload_size, int * error_ptr);
int smb_trans2_request(struct smb_server *server, int *data_len, int *param_len, char **data, char **param, 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);
+12
View File
@@ -65,6 +65,12 @@ struct smb_server
/* olsen (2018-05-09): Timeout for send/receive operations in seconds. */
int timeout;
/* olsen (2018-05-14): Don't retry establishing a server connection. */
int dont_retry;
/* olsen (2018-05-18): Override the "Native OS" name passed to the server. */
char * native_os;
};
#define NEGOTIATE_USER_SECURITY 0x01 /* If set, the server supports
@@ -83,4 +89,10 @@ struct smb_server
#define CAP_RAW_MODE 0x00000001 /* The server supports SMB_COM_WRITE_RAW
and SMB_COM_READ_RAW requests. */
#define CAP_LARGE_READX 0x00004000 /* The server permits SMB_COM_READ_ANDX
to read up to 65535 bytes. */
#define CAP_LARGE_WRITEX 0x00008000 /* The server permits SMB_COM_WRITE_ANDX
to write up to 65535 bytes. */
#endif
Executable → Regular
+45 -6
View File
@@ -51,6 +51,7 @@
#define ERRnoresource 89
#define ERRtoomanyuids 90
#define ERRbaduid 91
#define ERRinvalidname 123 /* Object name collision */
#define ERRbadpipe 230 /* Named pipe invalid */
#define ERRpipebusy 231 /* All instances of pipe are busy */
#define ERRpipeclosing 232 /* named pipe close in progress */
@@ -265,28 +266,66 @@
#define SMBfclose 0x84 /* find close */
#define SMBinvalid 0xFE /* invalid command */
/* Extended 2.0 protocol */
/* Extended 2.0 protocol (LAN Manager 2.0) */
#define SMBtrans2 0x32 /* TRANS2 protocol set */
#define SMBtranss2 0x33 /* TRANS2 protocol set, secondary command */
#define SMBfindclose 0x34 /* Terminate a TRANSACT2_FINDFIRST */
#define SMBfindnclose 0x35 /* Terminate a TRANSACT2_FINDNOTIFYFIRST */
#define SMBulogoffX 0x74 /* user logoff */
/* NT LAN Manager */
#define SMBntcreateX 0xA2 /* Create or open file */
/* these are the TRANS2 sub commands */
#define TRANSACT2_OPEN 0
#define TRANSACT2_FINDFIRST 1
#define TRANSACT2_FINDNEXT 2
#define TRANSACT2_QFSINFO 3
#define TRANSACT2_QFSINFO 3 /* TRANS2_QUERY_FS_INFORMATION */
#define TRANSACT2_SETFSINFO 4
#define TRANSACT2_QPATHINFO 5
#define TRANSACT2_SETPATHINFO 6
#define TRANSACT2_QPATHINFO 5 /* TRANS2_QUERY_PATH_INFORMATION */
#define TRANSACT2_SETPATHINFO 6 /* TRANS2_SET_PATH_INFORMATION */
#define TRANSACT2_QFILEINFO 7
#define TRANSACT2_SETFILEINFO 8
#define TRANSACT2_FSCTL 9
#define TRANSACT2_IOCTL 10
#define TRANSACT2_FINDNOTIFYFIRST 11
#define TRANSACT2_FINDNOTIFYNEXT 12
#define TRANSACT2_MKDIR 13
#define TRANSACT2_MKDIR 13 /* TRANS2_CREATE_DIRECTORY */
/* These are used by SMBntcreateX */
#define FILE_READ_DATA 0x00000001
#define FILE_WRITE_DATA 0x00000002
#define FILE_READ_ATTRIBUTES 0x00000080
#define FILE_WRITE_ATTRIBUTES 0x00000100
#define FILE_DELETE 0x00001000
#define GENERIC_WRITE 0x40000000
#define GENERIC_READ 0x80000000
#define FILE_SHARE_READ 0x00000001
#define FILE_SHARE_WRITE 0x00000002
#define SEC_ANONYMOUS 0x00000000
#define FILE_OPEN 0x00000001
#define FILE_CREATE 0x00000002
#define FILE_OVERWRITE_IF 0x00000005
#define NT_CREATE_REQUEST_OPBATCH 0x00000004
/* Directory entry formats supported by TRANSACT2_FINDFIRST/TRANSACT2_FINDNEXT */
#define SMB_INFO_STANDARD 0x0001 /* LAN Manager 2.0 */
#define SMB_FILE_BOTH_DIRECTORY_INFO 0x0104 /* NT LAN Manager */
/* File system information formats supported by TRANSACT2_QFSINFO (actually,
* we only need this one).
*/
#define SMB_QUERY_FS_SIZE_INFO 0x0103
/* Path information formats supported by TRANSACT2_QPATHINFO and TRANSACT2_QFILEINFO. */
#define SMB_QUERY_FILE_ALL_INFO 0x0107
/* Set information formats supported by TRANSACT2_SETFILEINFO. */
#define SMB_SET_FILE_BASIC_INFO 0x0101 /* NT LAN Manager */
#define SMB_SET_FILE_END_OF_FILE_INFO 0x0104 /* NT LAN Manager */
#endif /* _SMBNO_H_ */
+71 -180
View File
@@ -26,7 +26,7 @@
* copy "amiga:Public/Documents/Amiga Files/Shared/dir/Windows-Export/LP2NRFP.h" ram:
* smbfs.debug user=guest volume=sicherung //192.168.1.76/sicherung-smb
* smbfs maxtransmit=16600 debuglevel=2 dumpsmb dumpsmblevel=2 domain=workgroup user=olsen password=... volume=olsen //felix/olsen
* Samba 4.6.7: smbfs debuglevel=2 dumpsmb dumpsmblevel=2 volume=ubuntu-test //192.168.1.33/test
* Samba 4.6.7: smbfs debuglevel=2 dumpsmb dumpsmblevel=2 volume=ubuntu-test //ubuntu-17-olaf/test
* Samba 3.0.25: smbfs debuglevel=2 dumpsmb dumpsmblevel=1 user=olsen password=... volume=olsen //192.168.1.118/olsen
*/
@@ -49,29 +49,6 @@
/****************************************************************************/
/* A quick workaround for the timeval/timerequest->TimeVal/TimeRequest
change in the recent OS4 header files. */
#if defined(__NEW_TIMEVAL_DEFINITION_USED__)
#define timeval TimeVal
#define tv_secs Seconds
#define tv_micro Microseconds
#define timerequest TimeRequest
#define tr_node Request
#define tr_time Time
#endif /* __NEW_TIMEVAL_DEFINITION_USED__ */
/****************************************************************************/
/* This is for backwards compatibility only. */
#if defined(__amigaos4__)
#define fib_EntryType fib_Obsolete
#endif /* __amigaos4__ */
/****************************************************************************/
#include "smbfs_rev.h"
STRPTR Version = VERSTAG;
@@ -158,7 +135,7 @@ STATIC ULONG stack_usage_exit(const struct StackSwapStruct * stk);
STATIC LONG CVSPrintf(STRPTR format_string, APTR args);
STATIC VOID VSPrintf(STRPTR buffer, STRPTR formatString, APTR args);
STATIC VOID Cleanup(VOID);
STATIC BOOL Setup(STRPTR program_name, STRPTR service, STRPTR workgroup, STRPTR username, STRPTR opt_password, BOOL opt_changecase, STRPTR opt_clientname, STRPTR opt_servername, int opt_cachesize, int opt_max_transmit, int opt_timeout, LONG *opt_time_zone_offset, LONG *opt_dst_offset, BOOL opt_raw_smb, BOOL opt_write_behind, BOOL opt_prefer_write_raw, BOOL opt_disable_write_raw, BOOL opt_disable_read_raw, STRPTR device_name, STRPTR volume_name, STRPTR translation_file);
STATIC BOOL Setup(STRPTR program_name, STRPTR service, STRPTR workgroup, STRPTR username, STRPTR opt_password, BOOL opt_changecase, STRPTR opt_clientname, STRPTR opt_servername, int opt_cachesize, int opt_max_transmit, int opt_timeout, LONG *opt_time_zone_offset, LONG *opt_dst_offset, BOOL opt_raw_smb, BOOL opt_write_behind, BOOL opt_prefer_write_raw, BOOL opt_disable_write_raw, BOOL opt_disable_read_raw, STRPTR opt_native_os, STRPTR device_name, STRPTR volume_name, STRPTR translation_file);
STATIC VOID HandleFileSystem(STRPTR device_name, STRPTR volume_name, STRPTR service_name);
/****************************************************************************/
@@ -567,6 +544,7 @@ main(VOID)
SWITCH PreferWriteRaw;
SWITCH DisableWriteRaw;
SWITCH DisableReadRaw;
KEY NativeOS;
SWITCH DumpSMB;
NUMBER DumpSMBLevel;
KEY DumpSMBFile;
@@ -601,6 +579,7 @@ main(VOID)
"PREFERWRITERAW/S,"
"DISABLEWRITERAW/S,"
"DISABLEREADRAW/S,"
"NATIVEOS/K,"
"DUMPSMB/S,"
"DUMPSMBLEVEL/N/K,"
"DUMPSMBFILE/K,"
@@ -839,6 +818,10 @@ main(VOID)
if(FindToolType(Icon->do_ToolTypes,"DISABLEREADRAW") != NULL)
args.DisableReadRaw = TRUE;
str = FindToolType(Icon->do_ToolTypes,"NATIVEOS");
if(str != NULL)
args.NativeOS = str;
str = FindToolType(Icon->do_ToolTypes,"TRANSLATE");
if(str == NULL)
str = FindToolType(Icon->do_ToolTypes,"TRANSLATIONFILE");
@@ -1123,6 +1106,7 @@ main(VOID)
args.PreferWriteRaw,
args.DisableWriteRaw,
args.DisableReadRaw,
args.NativeOS,
args.DeviceName,
args.VolumeName,
args.TranslationFile))
@@ -1247,9 +1231,9 @@ posix_strerror(int error)
SocketBaseTagList(tags);
result = (STRPTR)tags[0].ti_Data;
return(result);
}
return(result);
}
/****************************************************************************/
@@ -2201,7 +2185,7 @@ MapErrnoToIoErr(int error)
*/
STATIC const LONG map_posix_to_amigados[][2] =
{
{ EPERM, ERROR_OBJECT_NOT_FOUND }, /* Operation not permitted */
{ EPERM, ERROR_READ_PROTECTED }, /* Operation not permitted */
{ ENOENT, ERROR_OBJECT_NOT_FOUND }, /* No such file or directory */
{ ESRCH, ERROR_OBJECT_NOT_FOUND }, /* No such process */
{ EINTR, ERROR_BREAK }, /* Interrupted system call */
@@ -2209,7 +2193,7 @@ MapErrnoToIoErr(int error)
{ E2BIG, ERROR_TOO_MANY_ARGS }, /* Argument list too long */
{ EBADF, ERROR_INVALID_LOCK }, /* Bad file descriptor */
{ ENOMEM, ERROR_NO_FREE_STORE }, /* Cannot allocate memory */
{ EACCES, ERROR_OBJECT_NOT_FOUND }, /* Permission denied */
{ EACCES, ERROR_READ_PROTECTED }, /* Permission denied */
{ ENOTBLK, ERROR_OBJECT_WRONG_TYPE }, /* Block device required */
{ EBUSY, ERROR_OBJECT_IN_USE }, /* Device busy */
{ EEXIST, ERROR_OBJECT_EXISTS }, /* File exists */
@@ -2233,12 +2217,12 @@ MapErrnoToIoErr(int error)
{ EPFNOSUPPORT, ERROR_NOT_IMPLEMENTED }, /* Protocol family not supported */
{ EAFNOSUPPORT, ERROR_NOT_IMPLEMENTED }, /* Address family not supported by protocol family */
{ EADDRINUSE, ERROR_OBJECT_IN_USE }, /* Address already in use */
{ EADDRNOTAVAIL, ERROR_OBJECT_NOT_FOUND }, /* Can't assign requested address */
{ ENETDOWN, ERROR_OBJECT_NOT_FOUND }, /* Network is down */
{ ENETUNREACH, ERROR_OBJECT_NOT_FOUND }, /* Network is unreachable */
{ ENETRESET, ERROR_OBJECT_NOT_FOUND }, /* Network dropped connection on reset */
{ ECONNABORTED, ERROR_OBJECT_NOT_FOUND }, /* Software caused connection abort */
{ ECONNRESET, ERROR_OBJECT_NOT_FOUND }, /* Connection reset by peer */
{ EADDRNOTAVAIL, ERROR_DIR_NOT_FOUND }, /* Can't assign requested address */
{ ENETDOWN, ERROR_DIR_NOT_FOUND }, /* Network is down */
{ ENETUNREACH, ERROR_DIR_NOT_FOUND }, /* Network is unreachable */
{ ENETRESET, ERROR_DIR_NOT_FOUND }, /* Network dropped connection on reset */
{ ECONNABORTED, ERROR_DIR_NOT_FOUND }, /* Software caused connection abort */
{ ECONNRESET, ERROR_DIR_NOT_FOUND }, /* Connection reset by peer */
{ ENOBUFS, ERROR_BUFFER_OVERFLOW }, /* No buffer space available */
{ EISCONN, ERROR_OBJECT_IN_USE }, /* Socket is already connected */
{ ENOTCONN, ERROR_OBJECT_WRONG_TYPE }, /* Socket is not connected */
@@ -2246,8 +2230,8 @@ MapErrnoToIoErr(int error)
{ ECONNREFUSED, ERROR_OBJECT_IN_USE }, /* Connection refused */
{ ELOOP, ERROR_TOO_MANY_LEVELS }, /* Too many levels of symbolic links */
{ ENAMETOOLONG, ERROR_LINE_TOO_LONG }, /* File name too long */
{ EHOSTDOWN, ERROR_OBJECT_NOT_FOUND }, /* Host is down */
{ EHOSTUNREACH, ERROR_OBJECT_NOT_FOUND }, /* No route to host */
{ EHOSTDOWN, ERROR_DIR_NOT_FOUND }, /* Host is down */
{ EHOSTUNREACH, ERROR_DIR_NOT_FOUND }, /* No route to host */
{ ENOTEMPTY, ERROR_DIRECTORY_NOT_EMPTY }, /* Directory not empty */
{ EPROCLIM, ERROR_TASK_TABLE_FULL }, /* Too many processes */
{ EUSERS, ERROR_TASK_TABLE_FULL }, /* Too many users */
@@ -2606,6 +2590,7 @@ Setup(
BOOL opt_prefer_write_raw,
BOOL opt_disable_write_raw,
BOOL opt_disable_read_raw,
STRPTR opt_native_os,
STRPTR device_name,
STRPTR volume_name,
STRPTR translation_file)
@@ -2785,6 +2770,7 @@ Setup(
opt_prefer_write_raw,
opt_disable_write_raw,
opt_disable_read_raw,
(char *)opt_native_os,
&error,
&smb_error_class,
&smb_error,
@@ -3258,7 +3244,7 @@ Action_Parent(
SHOWSTRING(full_name);
if(smba_open(ServerData,full_name,full_name_size,&ln->ln_File,&error) < 0)
if(smba_open(ServerData,full_name,full_name_size,open_read_only,open_dont_truncate,&ln->ln_File,&error) < 0)
{
error = MapErrnoToIoErr(error);
goto out;
@@ -3453,7 +3439,7 @@ Action_DeleteObject(
SHOWSTRING(full_name);
if(smba_open(ServerData,full_name,full_name_size,&file,&error) < 0)
if(smba_open(ServerData,full_name,full_name_size,open_writable,open_dont_truncate,&file,&error) < 0)
{
error = MapErrnoToIoErr(error);
goto out;
@@ -3658,7 +3644,7 @@ Action_CreateDir(
ln->ln_FileLock.fl_Volume = MKBADDR(VolumeNode);
ln->ln_FullName = full_name;
if(smba_open(ServerData,dir_name,dir_name_size,&dir,&error) < 0)
if(smba_open(ServerData,dir_name,dir_name_size,open_read_only,open_dont_truncate,&dir,&error) < 0)
{
error = MapErrnoToIoErr(error);
goto out;
@@ -3675,7 +3661,7 @@ Action_CreateDir(
SHOWSTRING(full_name);
if(smba_open(ServerData,full_name,full_name_size,&ln->ln_File,&error) < 0)
if(smba_open(ServerData,full_name,full_name_size,open_read_only,open_dont_truncate,&ln->ln_File,&error) < 0)
{
error = MapErrnoToIoErr(error);
goto out;
@@ -3805,7 +3791,7 @@ Action_LocateObject(
SHOWSTRING(full_name);
if(smba_open(ServerData,full_name,full_name_size,&ln->ln_File,&error) < 0)
if(smba_open(ServerData,full_name,full_name_size,open_read_only,open_dont_truncate,&ln->ln_File,&error) < 0)
{
error = MapErrnoToIoErr(error);
goto out;
@@ -3898,7 +3884,7 @@ Action_CopyDir(
SHOWSTRING(full_name);
if(smba_open(ServerData,full_name,full_name_size,&ln->ln_File,&error) < 0)
if(smba_open(ServerData,full_name,full_name_size,open_read_only,open_dont_truncate,&ln->ln_File,&error) < 0)
{
error = MapErrnoToIoErr(error);
goto out;
@@ -4091,7 +4077,7 @@ Action_SetProtect(
SHOWSTRING(full_name);
if(smba_open(ServerData,full_name,full_name_size,&file,&error) < 0)
if(smba_open(ServerData,full_name,full_name_size,open_read_only,open_dont_truncate,&file,&error) < 0)
{
error = MapErrnoToIoErr(error);
goto out;
@@ -4104,7 +4090,6 @@ Action_SetProtect(
st.atime = -1;
st.ctime = -1;
st.mtime = -1;
st.size = -1;
if((mask & (FIBF_WRITE|FIBF_DELETE)) != (FIBF_WRITE|FIBF_DELETE))
{
@@ -4124,7 +4109,7 @@ Action_SetProtect(
/* The 'system' attribute is associated with the 'pure' bit for now. */
st.is_system = ((mask & FIBF_PURE) != 0);
if(smba_setattr(file,&st,&error) < 0)
if(smba_setattr(file,&st,NULL,&error) < 0)
{
error = MapErrnoToIoErr(error);
goto out;
@@ -5368,7 +5353,7 @@ Action_Find(
int ignored_error;
smba_stat_t st;
if(smba_open(ServerData,full_name,full_name_size,&file,&ignored_error) == OK &&
if(smba_open(ServerData,full_name,full_name_size,open_read_only,open_dont_truncate,&file,&ignored_error) == OK &&
smba_getattr(file,&st,&ignored_error) == OK)
{
/* File apparently opens Ok and information on it
@@ -5441,7 +5426,7 @@ Action_Find(
SHOWMSG("creating a file; finding parent path first");
SHOWSTRING(parent_path);
if(smba_open(ServerData,parent_path,strlen(full_name)+3,&dir,&error) < 0)
if(smba_open(ServerData,parent_path,strlen(full_name)+3,open_read_only,open_dont_truncate,&dir,&error) < 0)
{
error = MapErrnoToIoErr(error);
goto out;
@@ -5472,7 +5457,7 @@ Action_Find(
}
/* Now for the remainder... */
if(smba_open(ServerData,full_name,full_name_size,&fn->fn_File,&error) < 0)
if(smba_open(ServerData,full_name,full_name_size,action != ACTION_FINDINPUT,create_new_file,&fn->fn_File,&error) < 0)
{
error = MapErrnoToIoErr(error);
goto out;
@@ -5513,6 +5498,8 @@ Action_Read(
ENTER();
SHOWVALUE(length);
if(length > 0)
{
result = smba_read(fn->fn_File,mem,length,fn->fn_Offset,&error);
@@ -5555,6 +5542,8 @@ Action_Write(
goto out;
}
SHOWVALUE(length);
if(length > 0)
{
result = smba_write(fn->fn_File,mem,length,fn->fn_Offset,&error);
@@ -5607,143 +5596,46 @@ Action_Seek(
{
LONG previous_position = fn->fn_Offset;
LONG result = -1;
smba_stat_t st;
LONG offset;
int error;
ENTER();
/* olsen: This doesn't really work with Microsoft SMB servers, but it works with Samba. */
#if 0
switch(mode)
{
switch(mode)
{
case OFFSET_BEGINNING:
case OFFSET_BEGINNING:
mode = 0;
break;
offset = position;
break;
case OFFSET_CURRENT:
case OFFSET_CURRENT:
mode = 1;
break;
offset = fn->fn_Offset + position;
break;
case OFFSET_END:
case OFFSET_END:
mode = 2;
break;
default:
error = ERROR_ACTION_NOT_KNOWN;
if(smba_getattr(fn->fn_File,&st,&error) < 0)
{
error = MapErrnoToIoErr(error);
goto out;
}
}
error = smba_seek (fn->fn_File, position, mode, (off_t *) &offset);
if(error < 0)
{
error = MapErrnoToIoErr(error);
offset = st.size + position;
break;
default:
error = ERROR_ACTION_NOT_KNOWN;
goto out;
}
}
#endif
/* olsen: This is the original implementation. */
#if 0
if(offset < 0)
{
smba_stat_t st;
error = smba_getattr(fn->fn_File,&st);
if(error < 0)
{
error = MapErrnoToIoErr(error);
goto out;
}
offset = fn->fn_Offset;
switch(mode)
{
case OFFSET_BEGINNING:
offset = position;
break;
case OFFSET_CURRENT:
offset += position;
break;
case OFFSET_END:
offset = st.size + position;
break;
default:
error = ERROR_ACTION_NOT_KNOWN;
goto out;
}
if(offset < 0 || offset > st.size)
{
error = ERROR_SEEK_ERROR;
goto out;
}
error = ERROR_SEEK_ERROR;
goto out;
}
#endif
/* olsen: This is a mix of the two above. First we calculate the absolute
* position, then seek to that position. The SMB server is supposed
* to do its housekeeping before the position is changed. I wish this
* worked differently, but it seems we've got the best of both worlds
* here...
*/
#if 1
{
smba_stat_t st;
switch(mode)
{
case OFFSET_BEGINNING:
offset = position;
break;
case OFFSET_CURRENT:
offset = fn->fn_Offset + position;
break;
case OFFSET_END:
if(smba_getattr(fn->fn_File,&st,&error) < 0)
{
error = MapErrnoToIoErr(error);
goto out;
}
offset = st.size + position;
break;
default:
error = ERROR_ACTION_NOT_KNOWN;
goto out;
}
if(offset < 0)
{
error = ERROR_SEEK_ERROR;
goto out;
}
if(smba_seek (fn->fn_File, offset, 0, (off_t *) &offset, &error) < 0)
{
error = MapErrnoToIoErr(error);
goto out;
}
}
#endif
error = OK;
@@ -5768,10 +5660,11 @@ Action_SetFileSize(
LONG mode,
LONG * error_ptr)
{
smba_stat_t st;
LONG result = -1;
smba_stat_t st;
int error;
long offset;
dword size;
ENTER();
@@ -5818,12 +5711,9 @@ Action_SetFileSize(
goto out;
}
st.atime = -1;
st.ctime = -1;
st.mtime = -1;
st.size = offset;
size = (dword)offset;
if(smba_setattr(fn->fn_File,&st,&error) < 0)
if(smba_setattr(fn->fn_File,NULL,&size,&error) < 0)
{
error = MapErrnoToIoErr(error);
goto out;
@@ -5923,7 +5813,7 @@ Action_SetDate(
SHOWSTRING(full_name);
if(smba_open(ServerData,full_name,full_name_size,&file,&error) < 0)
if(smba_open(ServerData,full_name,full_name_size,open_read_only,open_dont_truncate,&file,&error) < 0)
{
error = MapErrnoToIoErr(error);
goto out;
@@ -5937,12 +5827,13 @@ Action_SetDate(
seconds = (ds->ds_Days * 24 * 60 + ds->ds_Minute) * 60 + (ds->ds_Tick / TICKS_PER_SECOND);
memset(&st,0,sizeof(st));
st.atime = -1;
st.ctime = -1;
st.mtime = seconds + UNIX_TIME_OFFSET + GetTimeZoneDelta();
st.size = -1;
if(smba_setattr(file,&st,&error) < 0)
if(smba_setattr(file,&st,NULL,&error) < 0)
{
error = MapErrnoToIoErr(error);
goto out;
@@ -6144,7 +6035,7 @@ Action_ParentFH(
SHOWSTRING(full_name);
if(smba_open(ServerData,full_name,full_name_size,&ln->ln_File,&error) < 0)
if(smba_open(ServerData,full_name,full_name_size,open_read_only,open_dont_truncate,&ln->ln_File,&error) < 0)
{
error = MapErrnoToIoErr(error);
goto out;
@@ -6219,7 +6110,7 @@ Action_CopyDirFH(
SHOWSTRING(full_name);
if (smba_open(ServerData,full_name,full_name_size,&ln->ln_File,&error) < 0)
if (smba_open(ServerData,full_name,full_name_size,open_read_only,open_dont_truncate,&ln->ln_File,&error) < 0)
{
error = MapErrnoToIoErr(error);
goto out;
@@ -6636,7 +6527,7 @@ Action_SetComment(
SHOWSTRING(full_name);
if (smba_open(ServerData,full_name,full_name_size,&file,&error) < 0)
if (smba_open(ServerData,full_name,full_name_size,open_read_only,open_dont_truncate,&file,&error) < 0)
{
error = MapErrnoToIoErr(error);
goto out;
+1065 -371
View File
File diff suppressed because it is too large Load Diff
Executable → Regular
+132 -9
View File
@@ -26,8 +26,94 @@
/****************************************************************************/
/* This function comes from Harry S. Warren, Jr.'s book "Hacker's delight". */
static int
carry(ULONG x, ULONG y)
{
int result;
ULONG z;
z = (x & y) | ((x | y) & ~(x + y));
result = ((LONG)z) < 0 ? 1 : 0;
return(result);
}
/****************************************************************************/
/* This function comes from Harry S. Warren, Jr.'s book "Hacker's delight".
* Computes the high-order half of the 64-bit product, unsigned. Derived
* from Knuth's Algorithm M.
*/
static ULONG mulhu (ULONG u, ULONG v)
{
ULONG u0, u1, v0, v1, w0, w1, w2, t;
u0 = u & 0xFFFF;
u1 = u >> 16;
v0 = v & 0xFFFF;
v1 = v >> 16;
w0 = u0 * v0;
t = u1 * v0 + (w0 >> 16);
w1 = t & 0xFFFF;
w2 = t >> 16;
w1 = u0 * v1 + w1;
return u1 * v1 + w2 + (w1 >> 16);
}
/* Multiply two 32 bit numbers, yielding a 64 bit result value. */
VOID
multiply_32_by_32_to_64(ULONG ab,ULONG cd,QUAD * product)
{
product->High = mulhu(ab,cd);
product->Low = ab * cd;
}
/* Multiply an unsigned 64 bit quantity by a 32 bit quantity, yielding a 64
* bit product. Returns the most significant component of the product, which
* is effectively the 32 bit overflow from the 96 bit product.
*/
ULONG
multiply_64_by_32_to_64(const QUAD * const abcd,ULONG ef,QUAD * abcdef)
{
QUAD cdef;
QUAD abef;
ULONG ab,cd;
/* Split the factors so that the following is true:
*
* abcd = (ab * 65536 * 65536) + cd;
*/
ab = abcd->High;
cd = abcd->Low;
/* We need to calculate the following:
*
* abcd * ef = (ab * 65536 * 65536 + cd) * ef
* = (ab * 65536 * 65536) * ef + cd * ef
* = (abef) * 65536 * 65536 + cdef
*/
multiply_32_by_32_to_64(cd,ef,&cdef);
multiply_32_by_32_to_64(ab,ef,&abef);
/* Let's put it all together as: (cd+ef) * 65536 * 65536 + ef. */
abcdef->Low = cdef.Low;
abcdef->High = abef.Low + cdef.High;
return(abef.High);
}
/****************************************************************************/
/* Divide a 64 bit integer by a 32 bit integer, filling in a 64 bit quotient
and returning a 32 bit remainder. */
* and returning a 32 bit remainder.
*/
ULONG
divide_64_by_32(const QUAD * const dividend,ULONG divisor,QUAD * quotient)
{
@@ -83,27 +169,63 @@ divide_64_by_32(const QUAD * const dividend,ULONG divisor,QUAD * quotient)
/****************************************************************************/
/* Add an unsigned 64 bit quantity to a 64 bit quantity, yielding a
* 64 bit sum.
*/
ULONG
add_64_plus_64_to_64(const QUAD * const a,const QUAD * const b,QUAD * ab)
{
ULONG low,high,overflow = 0;
/* Add the first summand to the least significant
* component of the second summand and check for
* overflow.
*/
low = a->Low + b->Low;
high = carry(a->Low, b->Low);
/* Put it all together. */
ab->Low = low;
/* Add the most significant components and check
* for overflow.
*/
overflow += carry(high, a->High);
high += a->High;
overflow += carry(high, b->High);
ab->High = high + b->High;
return(overflow);
}
/****************************************************************************/
/* Subtract a 64 bit integer from another 64 bit integer, producing a
64 bit integer difference, returning a 32 bit integer that indicates
whether or not an underflow occured. */
* 64 bit integer difference, returning a 32 bit integer that indicates
* whether or not an underflow occured.
*/
ULONG
subtract_64_from_64_to_64(const QUAD * const minuend,const QUAD * const subtrahend,QUAD * difference)
{
QUAD extended_minuend;
/* We may have to borrow if the minuend is less than the
subtrahend, so we set up a local variable to track
any underflow this might produce. */
* subtrahend, so we set up a local variable to track
* any underflow this might produce.
*/
extended_minuend.High = 0;
extended_minuend.Low = minuend->High;
/* First step: take care of the least significant word. If
that produces a local underflow, borrow from the most
significant word. */
* that produces a local underflow, borrow from the most
* significant word.
*/
if(minuend->Low < subtrahend->Low)
{
/* Borrow, and if there's nothing to be borrowed,
remember that we had an underflow. */
* remember that we had an underflow.
*/
if(extended_minuend.Low-- == 0)
extended_minuend.High--;
}
@@ -111,7 +233,8 @@ subtract_64_from_64_to_64(const QUAD * const minuend,const QUAD * const subtrahe
difference->Low = minuend->Low - subtrahend->Low;
/* Second step: take care of the most significant word. If
that produces a local underflow, remember that. */
* that produces a local underflow, remember that.
*/
if(extended_minuend.Low < subtrahend->High)
extended_minuend.High--;
Executable → Regular
+3
View File
@@ -39,7 +39,10 @@ typedef struct
/****************************************************************************/
VOID multiply_32_by_32_to_64(ULONG ab,ULONG cd,QUAD * product);
ULONG multiply_64_by_32_to_64(const QUAD * const abcd,ULONG ef,QUAD * abcdef);
ULONG divide_64_by_32(const QUAD * const dividend,ULONG divisor,QUAD * quotient);
ULONG add_64_plus_64_to_64(const QUAD * const a,const QUAD * const b,QUAD * ab);
ULONG subtract_64_from_64_to_64(const QUAD * const minuend,const QUAD * const subtrahend,QUAD * difference);
/****************************************************************************/
+2 -10
View File
@@ -107,7 +107,7 @@ cp850.o : cp850.c
crypt.o : crypt.c system_headers.h assert.h smbfs.h
dump_smb.o : dump_smb.c system_headers.h assert.h smbfs.h dump_smb.h quad_math.h
main.o : main.c system_headers.h assert.h smbfs.h smb_abstraction.h utf-8-iso-8859-1-conversion.h cp437.h cp850.h errors.h dump_smb.h smbfs_rev.h
proc.o : proc.c system_headers.h assert.h smbfs.h quad_math.h errors.h
proc.o : proc.c system_headers.h assert.h smbfs.h quad_math.h errors.h smbfs_rev.h
quad_math.o : quad_math.c quad_math.h
smb_abstraction.o : smb_abstraction.c system_headers.h assert.h smbfs.h smb_abstraction.h
sock.o : sock.c system_headers.h assert.h smbfs.h smb_abstraction.h dump_smb.h errors.h
@@ -120,7 +120,7 @@ clean:
-delete \#?.o $(PROJECT)(%|.debug)
realclean: clean
-delete system_headers.gst tags tagfiles \#?.map all
-delete system_headers.gst tags tagfiles \#?.map ID all
###############################################################################
@@ -132,11 +132,3 @@ update:
version:
bumprev $(VERSION) $(PROJECT)
###############################################################################
cvs-tag:
cvs -q tag V$(VERSION)_`type $(PROJECT)_rev.rev`
cvs-update:
cvs update
+263 -100
View File
@@ -62,20 +62,6 @@ struct smba_file
/*****************************************************************************/
/* Some message size calculations include the size of the NetBIOS session
* header, which may not be necessary. The "message size" in question is not
* the same as the underlying transport layer, which in this case is
* NetBIOS over TCP.
*/
#define NETBIOS_HEADER_SIZE 4
/* The NetBIOS frame payload cannot be larger than 131071 bytes,
* which is (2^71)-1.
*/
#define MAX_NETBIOS_FRAME_SIZE 131071
/*****************************************************************************/
#include "smb_abstraction.h"
/*****************************************************************************/
@@ -99,6 +85,7 @@ smba_connect (
int opt_prefer_write_raw,
int opt_disable_write_raw,
int opt_disable_read_raw,
char * opt_native_os,
int * error_ptr,
int * smb_error_class_ptr,
int * smb_error_ptr,
@@ -152,6 +139,9 @@ smba_connect (
/* olsen (2018-05-09): Timeout for send/receive operations in seconds. */
res->server.timeout = timeout;
/* olsen (2018-05-18): Override the "Native OS" name passed to the server. */
res->server.native_os = opt_native_os;
if(smba_setup_dircache (res,cache_size,error_ptr) < 0)
{
ReportError("Directory cache initialization failed (%ld, %s).",(*error_ptr),posix_strerror(*error_ptr));
@@ -280,7 +270,7 @@ smba_disconnect (smba_server_t * server)
/*****************************************************************************/
static int
make_open (smba_file_t * f, int need_fid, int * error_ptr)
make_open (smba_file_t * f, int need_fid, int writable, int truncate, int * error_ptr)
{
smba_server_t *s;
int result;
@@ -293,17 +283,32 @@ make_open (smba_file_t * f, int need_fid, int * error_ptr)
if (!f->is_valid || f->attr_time == 0 || (now > f->attr_time && now - f->attr_time > ATTR_CACHE_TIME))
{
result = smb_proc_getattr_core (&s->server, f->dirent.complete_path, f->dirent.len, &f->dirent, error_ptr);
if (f->server->server.protocol >= PROTOCOL_LANMAN2)
result = smb_query_path_information (&s->server, f->dirent.complete_path, f->dirent.len, 0, &f->dirent, error_ptr);
else
result = smb_proc_getattr_core (&s->server, f->dirent.complete_path, f->dirent.len, &f->dirent, error_ptr);
if (result < 0)
goto out;
}
if ((f->dirent.attr & aDIR) == 0) /* a regular file */
{
if (need_fid || !s->supports_E_known || s->supports_E)
if (f->server->server.protocol >= PROTOCOL_LANMAN2)
{
if(need_fid)
{
LOG (("opening file %s\n", f->dirent.complete_path));
result = smb_proc_open (&s->server, f->dirent.complete_path, f->dirent.len, writable, truncate, &f->dirent, error_ptr);
if (result < 0)
goto out;
}
}
else if (need_fid || !s->supports_E_known || s->supports_E)
{
LOG (("opening file %s\n", f->dirent.complete_path));
result = smb_proc_open (&s->server, f->dirent.complete_path, f->dirent.len, &f->dirent, error_ptr);
result = smb_proc_open (&s->server, f->dirent.complete_path, f->dirent.len, writable, truncate, &f->dirent, error_ptr);
if (result < 0)
goto out;
@@ -350,7 +355,7 @@ make_open (smba_file_t * f, int need_fid, int * error_ptr)
/*****************************************************************************/
int
smba_open (smba_server_t * s, char *name, size_t name_size, smba_file_t ** file, int * error_ptr)
smba_open (smba_server_t * s, char *name, size_t name_size, int writable, int truncate, smba_file_t ** file, int * error_ptr)
{
smba_file_t *f;
int result;
@@ -373,7 +378,7 @@ smba_open (smba_server_t * s, char *name, size_t name_size, smba_file_t ** file,
f->dirent.len = strlen (name);
f->server = s;
result = make_open (f, 0, error_ptr);
result = make_open (f, open_dont_need_fid, writable, truncate, error_ptr);
if (result < 0)
goto out;
@@ -399,14 +404,25 @@ write_attr (smba_file_t * f, int * error_ptr)
LOG (("file %s\n", f->dirent.complete_path));
result = make_open (f, 0, error_ptr);
if (result < 0)
goto out;
if(f->server->server.protocol >= PROTOCOL_LANMAN2)
{
result = make_open (f, open_need_fid, open_writable, open_dont_truncate, error_ptr);
if (result < 0)
goto out;
if (f->dirent.opened && f->server->supports_E)
result = smb_proc_setattrE (&f->server->server, f->dirent.fileid, &f->dirent, error_ptr);
result = smb_set_file_information (&f->server->server, &f->dirent, NULL, error_ptr);
}
else
result = smb_proc_setattr_core (&f->server->server, f->dirent.complete_path, f->dirent.len, &f->dirent, error_ptr);
{
result = make_open (f, open_dont_need_fid, open_read_only, open_dont_truncate, error_ptr);
if (result < 0)
goto out;
if (f->dirent.opened && f->server->supports_E)
result = smb_proc_setattrE (&f->server->server, f->dirent.fileid, &f->dirent, error_ptr);
else
result = smb_proc_setattr_core (&f->server->server, f->dirent.complete_path, f->dirent.len, &f->dirent, error_ptr);
}
if (result < 0)
{
@@ -414,7 +430,7 @@ write_attr (smba_file_t * f, int * error_ptr)
goto out;
}
f->attr_dirty = 0;
f->attr_dirty = FALSE;
out:
@@ -460,14 +476,75 @@ smba_read (smba_file_t * f, char *data, long len, long offset, int * error_ptr)
int num_bytes_read = 0;
int result;
result = make_open (f, 1, error_ptr);
result = make_open (f, open_need_fid, open_read_only, open_dont_truncate, error_ptr);
if (result < 0)
goto out;
D(("read %ld bytes from offset %ld",len,offset));
if (f->server->server.protocol >= PROTOCOL_LANMAN1)
{
int max_readx_size;
int count;
/* Calculate maximum number of bytes that could be transferred with
* a single SMBreadX packet...
*
* 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_READ_ANDX response account for
* 1(wordcount)+1(andxcommand)+1(andxreserved)+2(andxoffset)+
* 2(available)+2(datacompactionmode)+2(reserved)+2(datalength)+
* 2(dataoffset)+10(reserved2)
* = 25 bytes
*
* The data part of a SMB_COM_READ_ANDX response account for
* 2(bytecount)+1(pad) = 3 bytes,
* not including the actual payload
*
* This leaves 'max_receive' - 60 for the payload.
*/
max_readx_size = f->server->server.max_buffer_size - 60;
if((f->server->server.capabilities & CAP_LARGE_READX) != 0)
max_readx_size = 65535;
/* ZZZ SMB_COM_READ_ANDX uses the packet buffer to receive
* the data, which is why there is another limit to how
* much data can be received.
*/
if(max_readx_size > f->server->server.transmit_buffer_size - 62)
max_readx_size = f->server->server.transmit_buffer_size - 62;
LOG (("len = %ld, max_readx_size = %ld\n", len, max_readx_size));
do
{
count = min(len, max_readx_size);
result = smb_proc_readx (&f->server->server, &f->dirent, offset, count, data, error_ptr);
if (result < 0)
goto out;
num_bytes_read += result;
len -= result;
offset += result;
data += result;
if(result < count)
{
D(("read returned fewer characters than expected (%ld < %ld)",result,count));
break;
}
}
while (len > 0);
}
/* SMB_COM_READ_RAW and SMB_COM_WRITE_RAW supported? */
if ((f->server->server.capabilities & CAP_RAW_MODE) != 0 && !f->server->server.disable_read_raw)
else if ((f->server->server.capabilities & CAP_RAW_MODE) != 0 && !f->server->server.disable_read_raw)
{
int max_raw_size = f->server->server.max_raw_size;
int n;
@@ -534,14 +611,14 @@ smba_read (smba_file_t * f, char *data, long len, long offset, int * error_ptr)
* This leaves 'max_buffer_size' - 48 for the payload.
*/
/*max_size_smb_com_read = f->server->server.max_buffer_size - SMB_HEADER_LEN - 5 * 2 - 5;*/
max_size_smb_com_read = f->server->server.max_buffer_size - 48 - NETBIOS_HEADER_SIZE;
max_size_smb_com_read = f->server->server.max_buffer_size - 48;
/* ZZZ SMB_COM_READ uses the packet buffer to receive
* the data, which is why there is another limit to how
* much data can be received.
*/
if(max_size_smb_com_read > f->server->server.transmit_buffer_size - 48 - NETBIOS_HEADER_SIZE)
max_size_smb_com_read = f->server->server.transmit_buffer_size - 48 - NETBIOS_HEADER_SIZE;
if(max_size_smb_com_read > f->server->server.transmit_buffer_size - 48)
max_size_smb_com_read = f->server->server.transmit_buffer_size - 48;
do
{
@@ -591,7 +668,7 @@ smba_write (smba_file_t * f, const char *data, long len, long offset, int * erro
int max_buffer_size;
int result;
result = make_open (f, 1, error_ptr);
result = make_open (f, open_need_fid, open_writable, open_dont_truncate, error_ptr);
if (result < 0)
goto out;
@@ -599,7 +676,68 @@ smba_write (smba_file_t * f, const char *data, long len, long offset, int * erro
max_buffer_size = f->server->server.max_buffer_size;
if ((f->server->server.capabilities & CAP_RAW_MODE) != 0 && !f->server->server.disable_write_raw)
/* SMB_COM_WRITE_ANDX supported? */
if (f->server->server.protocol >= PROTOCOL_LANMAN1)
{
int max_writex_size;
int n;
/* Calculate maximum number of bytes that could be transferred with
* a single SMB_COM_WRITE_ANDX 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_ANDX command account for
* 1(word_count)+1(and_x_command)+1(and_x_reserved)+2(and_x_offset)+
* 2(fid)+4(offset)+4(timeout)+2(write_mode)+2(remaining)+2(reserved)+
* 2(data_length)+2(data_offset)+4(offset_high)
* = 29 bytes
*
* The data part of a SMB_COM_WRITE_ANDX command account for
* 2(byte_count)+1(pad) = 3 bytes, not including
* the actual payload
*
* This leaves 'max_buffer_size' - 64 for the payload.
*/
if(f->server->server.protocol >= PROTOCOL_NT1)
max_writex_size = max_buffer_size - 64;
else
max_writex_size = max_buffer_size - 60;
if((f->server->server.capabilities & CAP_LARGE_WRITEX) != 0)
max_writex_size = 65535;
LOG (("len = %ld, max_writex_size = %ld\n", len, max_writex_size));
do
{
n = min(len, max_writex_size);
ASSERT( n > 0 );
LOG(("writing %ld bytes; offset=%lu, len=%ld\n", n, offset, len));
result = smb_proc_writex(&f->server->server, &f->dirent, offset, n, data, error_ptr);
if(result < 0)
goto out;
LOG(("number of bytes written = %ld\n", result));
data += result;
offset += result;
len -= result;
num_bytes_written += result;
}
while(len > 0);
}
else if ((f->server->server.capabilities & CAP_RAW_MODE) != 0 && !f->server->server.disable_write_raw)
{
int max_raw_size = f->server->server.max_raw_size;
int max_size_smb_com_write_raw;
@@ -624,7 +762,7 @@ smba_write (smba_file_t * f, const char *data, long len, long offset, int * erro
* 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 - NETBIOS_HEADER_SIZE;
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)
@@ -680,7 +818,7 @@ smba_write (smba_file_t * f, const char *data, long len, long offset, int * erro
* This leaves 'max_buffer_size' - 48 for the payload.
*/
/*max_size_smb_com_write = f->server->server.max_buffer_size - (SMB_HEADER_LEN + 5 * sizeof (word) + 5) - 4;*/
max_size_smb_com_write = max_buffer_size - 48 - NETBIOS_HEADER_SIZE;
max_size_smb_com_write = max_buffer_size - 48;
/* SMB_COM_WRITE cannot transmit more than 65535 bytes. */
if(max_size_smb_com_write > 65535)
@@ -708,6 +846,8 @@ smba_write (smba_file_t * f, const char *data, long len, long offset, int * erro
while (len > 0);
}
LOG(("num_bytes_written=%ld\n", num_bytes_written));
result = num_bytes_written;
out:
@@ -729,26 +869,6 @@ smba_write (smba_file_t * f, const char *data, long len, long offset, int * erro
/*****************************************************************************/
int
smba_seek (smba_file_t *f, long offset, long mode, off_t * new_position_ptr, int * error_ptr)
{
int result;
D(("seek %ld bytes from position %s",offset,mode > 0 ? (mode == 2 ? "SEEK_END" : "SEEK_CUR") : "SEEK_SET"));
result = make_open (f, 1, error_ptr);
if(result < 0)
goto out;
result = smb_proc_lseek (&f->server->server, &f->dirent, offset, mode, new_position_ptr, error_ptr);
out:
return result;
}
/*****************************************************************************/
/* perform a single record-lock */
int
smba_lockrec (smba_file_t *f, long offset, long len, long mode, int unlocked, long timeout, int * error_ptr)
@@ -756,7 +876,7 @@ smba_lockrec (smba_file_t *f, long offset, long len, long mode, int unlocked, lo
struct smb_lkrng *rec_lock = NULL;
int result;
result = make_open (f, 1, error_ptr);
result = make_open (f, open_need_fid, open_read_only, open_dont_truncate, error_ptr);
if(result < 0)
goto out;
@@ -793,7 +913,7 @@ smba_getattr (smba_file_t * f, smba_stat_t * data, int * error_ptr)
int result;
ULONG now;
result = make_open (f, 0, error_ptr);
result = make_open (f, open_dont_need_fid, open_read_only, open_dont_truncate, error_ptr);
if (result < 0)
goto out;
@@ -803,10 +923,20 @@ smba_getattr (smba_file_t * f, smba_stat_t * data, int * error_ptr)
{
LOG (("file %s\n", f->dirent.complete_path));
if (f->dirent.opened && f->server->supports_E)
result = smb_proc_getattrE (&f->server->server, &f->dirent, error_ptr);
if (f->server->server.protocol >= PROTOCOL_LANMAN2)
{
if (f->dirent.opened)
result = smb_query_path_information (&f->server->server, NULL, 0, f->dirent.fileid, &f->dirent, error_ptr);
else
result = smb_query_path_information (&f->server->server, f->dirent.complete_path, f->dirent.len, 0, &f->dirent, error_ptr);
}
else
result = smb_proc_getattr_core (&f->server->server, f->dirent.complete_path, f->dirent.len, &f->dirent, error_ptr);
{
if (f->dirent.opened && f->server->supports_E)
result = smb_proc_getattrE (&f->server->server, &f->dirent, error_ptr);
else
result = smb_proc_getattr_core (&f->server->server, f->dirent.complete_path, f->dirent.len, &f->dirent, error_ptr);
}
if (result < 0)
goto out;
@@ -833,51 +963,78 @@ smba_getattr (smba_file_t * f, smba_stat_t * data, int * error_ptr)
/*****************************************************************************/
int
smba_setattr (smba_file_t * f, smba_stat_t * data, int * error_ptr)
smba_setattr (smba_file_t * f, const smba_stat_t * data, const dword * size_ptr, int * error_ptr)
{
BOOL times_changed = FALSE;
dword attrs;
int result;
if (data->atime != -1)
f->dirent.atime = data->atime;
if (data->ctime != -1)
f->dirent.ctime = data->ctime;
if (data->mtime != -1)
f->dirent.mtime = data->mtime;
if (data->is_wp)
f->dirent.attr |= aRONLY;
else
f->dirent.attr &= ~aRONLY;
if (data->is_archive)
f->dirent.attr |= aARCH;
else
f->dirent.attr &= ~aARCH;
if (data->is_system)
f->dirent.attr |= aSYSTEM;
else
f->dirent.attr &= ~aSYSTEM;
f->attr_dirty = 1;
result = write_attr (f, error_ptr);
if (result < 0)
goto out;
if (data->size != -1 && data->size != (int)f->dirent.size)
if (data != NULL)
{
result = make_open (f, 1, error_ptr);
if (data->atime != -1 && f->dirent.atime != data->atime)
{
f->dirent.atime = data->atime;
times_changed = TRUE;
}
if (data->ctime != -1 && f->dirent.ctime != data->ctime)
{
f->dirent.ctime = data->ctime;
times_changed = TRUE;
}
if (data->mtime != -1 && f->dirent.mtime != data->mtime)
{
f->dirent.mtime = data->mtime;
times_changed = TRUE;
}
attrs = f->dirent.attr;
if (data->is_wp)
attrs |= aRONLY;
else
attrs &= ~aRONLY;
if (data->is_archive)
attrs |= aARCH;
else
attrs &= ~aARCH;
if (data->is_system)
attrs |= aSYSTEM;
else
attrs &= ~aSYSTEM;
if(f->dirent.attr != attrs)
{
f->dirent.attr = attrs;
f->attr_dirty = TRUE;
}
if(f->attr_dirty || times_changed)
{
result = write_attr (f, error_ptr);
if (result < 0)
goto out;
}
}
if (size_ptr != NULL && (*size_ptr) != f->dirent.size)
{
result = make_open (f, open_need_fid, open_writable, open_dont_truncate, error_ptr);
if(result < 0)
goto out;
result = smb_proc_trunc (&f->server->server, f->dirent.fileid, data->size, error_ptr);
if(f->server->server.protocol >= PROTOCOL_LANMAN2)
result = smb_set_file_information (&f->server->server, &f->dirent, size_ptr, error_ptr);
else
result = smb_proc_trunc (&f->server->server, f->dirent.fileid, (*size_ptr), error_ptr);
if(result < 0)
goto out;
f->dirent.size = data->size;
f->dirent.size = (*size_ptr);
}
out:
@@ -896,7 +1053,7 @@ smba_readdir (smba_file_t * f, long offs, void *d, smba_callback_t callback, int
int result;
ULONG now;
result = make_open (f, 0, error_ptr);
result = make_open (f, open_dont_need_fid, open_read_only, open_dont_truncate, error_ptr);
if (result < 0)
goto out;
@@ -1063,7 +1220,7 @@ smba_create (smba_file_t * dir, const char *name, smba_stat_t * attr, int * erro
char *path = NULL;
int result;
result = make_open (dir, 0, error_ptr);
result = make_open (dir, open_dont_need_fid, open_read_only, open_dont_truncate, error_ptr);
if (result < 0)
goto out;
@@ -1093,7 +1250,11 @@ smba_create (smba_file_t * dir, const char *name, smba_stat_t * attr, int * erro
path[dir->dirent.len] = DOS_PATHSEP;
strcpy (&path[dir->dirent.len + 1], name);
result = smb_proc_create (&dir->server->server, path, strlen (path), &entry, error_ptr);
if (dir->server->server.protocol >= PROTOCOL_LANMAN2)
result = smb_proc_open (&dir->server->server, path, strlen(path), open_writable, open_truncate, &entry, error_ptr);
else
result = smb_proc_create (&dir->server->server, path, strlen (path), &entry, error_ptr);
if(result < 0)
goto out;
@@ -1115,7 +1276,7 @@ smba_mkdir (smba_file_t * dir, const char *name, int * error_ptr)
char *path = NULL;
int result;
result = make_open (dir, 0, error_ptr);
result = make_open (dir, open_dont_need_fid, open_read_only, open_dont_truncate, error_ptr);
if (result < 0)
goto out;
@@ -1430,6 +1591,7 @@ smba_start(
int opt_prefer_write_raw,
int opt_disable_write_raw,
int opt_disable_read_raw,
char * opt_native_os,
int * error_ptr,
int * smb_error_class_ptr,
int * smb_error_ptr,
@@ -1602,6 +1764,7 @@ smba_start(
opt_prefer_write_raw,
opt_disable_write_raw,
opt_disable_read_raw,
opt_native_os,
error_ptr,
smb_error_class_ptr,
smb_error_ptr,
+18 -4
View File
@@ -21,6 +21,21 @@
struct smb_server;
#endif /* _SMB_FS_SB */
/*****************************************************************************/
/* These should make the respective purpose of each make_open()
* parameter clearer. The read/write and truncate options are
* also used by smba_open().
*/
#define open_dont_need_fid FALSE
#define open_need_fid TRUE
#define open_read_only FALSE
#define open_writable TRUE
#define open_dont_truncate FALSE
#define open_truncate TRUE
/****************************************************************************/
typedef struct smba_connect_parameters
@@ -57,14 +72,13 @@ typedef int (*smba_callback_t) (void *d, int fpos, int nextpos, char *name, int
/****************************************************************************/
int smba_open(smba_server_t *s, char *name, size_t name_size, smba_file_t **file, int * error_ptr);
int smba_open(smba_server_t *s, char *name, size_t name_size, int writable, int truncate, smba_file_t **file, int * error_ptr);
void smba_close(smba_file_t *f, int * error_ptr);
int smba_read(smba_file_t *f, char *data, long len, long offset, int * error_ptr);
int smba_write(smba_file_t *f, const char *data, long len, long offset, int * error_ptr);
int smba_seek (smba_file_t *f, long offset, long mode, off_t * new_position_ptr, int * error_ptr);
int smba_lockrec (smba_file_t *f, long offset, long len, long mode, int unlocked, long timeout, int * error_ptr);
int smba_getattr(smba_file_t *f, smba_stat_t *data, int * error_ptr);
int smba_setattr(smba_file_t *f, smba_stat_t *data, int * error_ptr);
int smba_setattr(smba_file_t *f, const smba_stat_t *data, const unsigned long * size_ptr, int * error_ptr);
int smba_readdir(smba_file_t *f, long offs, void *d, smba_callback_t callback, int * error_ptr);
int smba_create(smba_file_t *dir, const char *name, smba_stat_t *attr, int * error_ptr);
int smba_mkdir(smba_file_t *dir, const char *name, int * error_ptr);
@@ -73,7 +87,7 @@ int smba_rmdir(smba_server_t *s, char *path, int * error_ptr);
int smba_rename(smba_server_t *s, char *from, 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(char *service, char *opt_workgroup, char *opt_username, char *opt_password, char *opt_clientname, char *opt_servername, int opt_cachesize, int opt_max_transmit, int opt_timeout, int opt_raw_smb, int opt_write_behind, int opt_prefer_write_raw, int opt_disable_write_raw, int opt_disable_read_raw, int * error_ptr, int * smb_error_class_ptr, int * smb_error_ptr, smba_server_t **result);
int smba_start(char *service, char *opt_workgroup, char *opt_username, char *opt_password, char *opt_clientname, char *opt_servername, int opt_cachesize, int opt_max_transmit, int opt_timeout, int opt_raw_smb, int opt_write_behind, int opt_prefer_write_raw, int opt_disable_write_raw, int opt_disable_read_raw, char * opt_native_os, 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 130
#define DATE "13.5.2018"
#define VERS "smbfs 1.130"
#define VSTRING "smbfs 1.130 (13.5.2018)\r\n"
#define VERSTAG "\0$VER: smbfs 1.130 (13.5.2018)"
#define REVISION 132
#define DATE "19.5.2018"
#define VERS "smbfs 1.132"
#define VSTRING "smbfs 1.132 (19.5.2018)\r\n"
#define VERSTAG "\0$VER: smbfs 1.132 (19.5.2018)"
+1 -1
View File
@@ -1 +1 @@
130
132
+308 -176
View File
@@ -10,22 +10,6 @@
#include "smbfs.h"
/****************************************************************************/
/* A quick workaround for the timeval/timerequest->TimeVal/TimeRequest
change in the recent OS4 header files. */
#if defined(__NEW_TIMEVAL_DEFINITION_USED__)
#define timeval TimeVal
#define tv_secs Seconds
#define tv_micro Microseconds
#define timerequest TimeRequest
#define tr_node Request
#define tr_time Time
#endif /* __NEW_TIMEVAL_DEFINITION_USED__ */
/*****************************************************************************/
#include <smb/smb_fs.h>
@@ -113,6 +97,7 @@ receive_all(int fd, void * _data, int len, int * error_ptr)
static int
smb_receive_raw (
struct smb_server * server,
int command,
int sock_fd,
unsigned char * target,
int max_raw_length,
@@ -155,7 +140,7 @@ smb_receive_raw (
#if defined(DUMP_SMB)
{
if(netbios_session_buf[0] != 0x00 && netbios_session_payload_size > 0)
if(command != 0 && netbios_session_buf[0] != 0x00 && netbios_session_payload_size > 0)
{
/* We only want to show what's in the first few
* bytes of a session packet. Since we only support
@@ -213,12 +198,21 @@ smb_receive_raw (
/* 0x84 == retarget session response */
default:
LOG (("Invalid session header type 0x%02lx\n", netbios_session_buf[0]));
/* The session setup may need to know about the
* NetBIOS session response, but for any command
* these message types are invalid.
*/
if(command != 0)
{
LOG (("Invalid session header type 0x%02lx\n", netbios_session_buf[0]));
(*error_ptr) = error_invalid_netbios_session;
(*error_ptr) = error_invalid_netbios_session;
result = -1;
goto out;
result = -1;
goto out;
}
break;
}
/* The length in the NetBIOS header is the raw data length (17 bits) */
@@ -236,158 +230,113 @@ smb_receive_raw (
/* Prepend the NetBIOS header to what is read? */
if (want_header)
{
/* Check for buffer overflow. */
if(NETBIOS_HEADER_SIZE + len > max_raw_length)
{
LOG (("Received length (%ld) > max_xmit (%ld)!\n", len, max_raw_length));
(*error_ptr) = error_message_exceeds_buffer_size;
result = -1;
goto out;
}
memcpy (target, netbios_session_buf, NETBIOS_HEADER_SIZE);
target += NETBIOS_HEADER_SIZE;
}
/* This is an optimization for the SMB_COM_READ command, which
* tries to avoid copying the received data twice. To this end
* we receive the SMB_COM_READ response up to the point at which
/* This is an optimization for the SMB_COM_READ and SMB_COM_READ_ANDX
* commands, which tries to avoid copying the received data twice. To
* this end we receive the command response up to the point at which
* the message header ends and the data returned by the server
* begins. Then we read the data, storing it directly in the
* receive buffer rather than in the packet buffer, from which
* it would have to be retrieved later.
* it would otherwise have to be retrieved later.
*/
if(input_payload != NULL)
{
int count_of_bytes_returned;
int count_of_bytes_to_read;
int num_bytes_received = 0;
int buffer_format;
LOG(("input_payload=0x%08lx, payload_size=%ld\n", input_payload, input_payload_size));
/* We need to read the following data:
*
* 0: 32 bytes of SMB message header
* 32: 1 byte of word count
* 33: 2 bytes of 'count of bytes returned' (1 word)
* 35: 8 bytes of reserved data (4 words)
* 43: 2 bytes of 'byte count' (1 word)
* 45: 1 byte of 'buffer format'
* 46: 2 bytes of 'count of bytes to read' (1 word).
*
* This adds up to 48 bytes.
*/
LOG(("reading the first %ld bytes\n", 48));
result = receive_all (sock_fd, target, 48, error_ptr);
if (result < 0)
if(command == SMBreadX)
{
LOG (("recv error = %ld\n", (*error_ptr)));
goto out;
}
int data_length;
int data_offset;
num_bytes_received += result;
/* We need to read the following data:
*
* 0: 32 bytes of SMB message header
* 32: 1 byte of word count
* 33: 1 byte of andxcommand
* 34: 1 byte of andxreserved
* 35: 2 bytes of andxoffset
* 37: 2 bytes of available
* 39: 2 bytes of datacompactionmode
* 41: 2 bytes of reserved
* 43: 2 bytes of datalength
* 45: 2 bytes of dataoffset
* 47: 10 bytes of reserved
* 57: 2 bytes of bytecount
*
* This adds up to 59 bytes.
*/
ASSERT( num_bytes_received == 48 );
LOG(("SMBreadX: reading the first %ld bytes\n", 59));
/* End of file reached? */
if(num_bytes_received < 48)
{
/* End of file */
LOG (("EOF\n"));
(*error_ptr) = error_end_of_file;
result = -1;
goto out;
}
/* So we read the header. Now we need to figure out if the
* data is in the expected format, and how many bytes are
* waiting to be read.
*/
/* The buffer format must be 1. */
buffer_format = BVAL(target, 45);
LOG(("buffer format = %ld, should be %ld\n", buffer_format, 1));
if(buffer_format != 1)
{
LOG(("buffer format %ld not supported\n", buffer_format));
(*error_ptr) = error_invalid_buffer_format;
result = -1;
goto out;
}
count_of_bytes_returned = WVAL(target, 33);
count_of_bytes_to_read = WVAL(target, 46);
/* That should never be more data than the read buffer may hold. */
ASSERT( count_of_bytes_to_read <= input_payload_size );
ASSERT( count_of_bytes_to_read <= count_of_bytes_returned );
ASSERT( count_of_bytes_returned <= input_payload_size );
LOG(("count of bytes to read = %ld, should be <= %ld\n", count_of_bytes_to_read, input_payload_size));
if(count_of_bytes_returned > input_payload_size)
{
(*error_ptr) = error_message_exceeds_buffer_size;
result = -1;
goto out;
}
result = receive_all (sock_fd, input_payload, count_of_bytes_to_read, error_ptr);
if (result < 0)
{
LOG (("recv error = %ld\n", (*error_ptr)));
goto out;
}
if(result < count_of_bytes_to_read)
{
/* End of file */
LOG (("EOF\n"));
(*error_ptr) = error_end_of_file;
result = -1;
goto out;
}
num_bytes_received += result;
ASSERT( count_of_bytes_to_read == count_of_bytes_returned );
if(count_of_bytes_to_read < count_of_bytes_returned)
{
LOG(("fewer data available than should be delivered; setting the remainder (%ld bytes) to 0.\n", count_of_bytes_returned - count_of_bytes_to_read));
memset(&input_payload[count_of_bytes_to_read],0,count_of_bytes_returned - count_of_bytes_to_read);
}
/* This should never happen, but then we better make sure to
* read the entire message.
*/
if(num_bytes_received < len)
{
LOG(("reading the remaining %ld bytes; this should never happen\n", len - num_bytes_received ));
result = receive_all (sock_fd, &target[num_bytes_received], len - num_bytes_received, error_ptr);
result = receive_all (sock_fd, target, 59, error_ptr);
if (result < 0)
{
LOG (("recv error = %ld\n", (*error_ptr)));
goto out;
}
if(result < len - num_bytes_received)
num_bytes_received += result;
ASSERT( num_bytes_received == 59 );
/* End of file reached? */
if(num_bytes_received < 59)
{
/* End of file */
LOG (("EOF\n"));
(*error_ptr) = error_end_of_file;
result = -1;
goto out;
}
data_offset = WVAL(target, 45);
SHOWVALUE(data_offset);
/* Skip the padding bytes, if any. */
if(data_offset > 59)
{
result = receive_all (sock_fd, target + 59, data_offset - 59, error_ptr);
if (result < 0)
{
LOG (("recv error = %ld\n", (*error_ptr)));
goto out;
}
/* End of file reached? */
if(result < data_offset - 59)
{
/* End of file */
LOG (("EOF\n"));
(*error_ptr) = error_end_of_file;
result = -1;
goto out;
}
num_bytes_received += result;
}
data_length = WVAL(target, 43);
SHOWVALUE(data_length);
result = receive_all (sock_fd, input_payload, data_length, error_ptr);
if (result < 0)
{
LOG (("recv error = %ld\n", (*error_ptr)));
goto out;
}
if(result < data_length)
{
/* End of file */
LOG (("EOF\n"));
@@ -397,20 +346,187 @@ smb_receive_raw (
result = -1;
goto out;
}
}
#if defined(DUMP_SMB)
num_bytes_received += result;
/* This should never happen, but then we better make sure to
* read the entire message.
*/
if(num_bytes_received < len)
{
LOG(("reading the remaining %ld bytes; this should never happen\n", len - num_bytes_received ));
result = receive_all (sock_fd, &target[num_bytes_received], len - num_bytes_received, error_ptr);
if (result < 0)
{
LOG (("recv error = %ld\n", (*error_ptr)));
goto out;
}
if(result < len - num_bytes_received)
{
/* End of file */
LOG (("EOF\n"));
(*error_ptr) = error_end_of_file;
result = -1;
goto out;
}
}
}
else
{
/* If want_header==0 then this is the data returned by SMB_COM_READ_RAW. */
dump_smb(__FILE__,__LINE__,!want_header,target,48,smb_packet_to_consumer,server->max_recv);
int count_of_bytes_returned;
int count_of_bytes_to_read;
int buffer_format;
if(buffer_format == 1)
dump_smb(__FILE__,__LINE__,!want_header,input_payload,num_bytes_received - 48,smb_packet_to_consumer,server->max_recv);
ASSERT( command == SMBread );
if(num_bytes_received < len && result > 0)
dump_smb(__FILE__,__LINE__,!want_header,&target[num_bytes_received],result,smb_packet_to_consumer,server->max_recv);
/* We need to read the following data:
*
* 0: 32 bytes of SMB message header
* 32: 1 byte of word count
* 33: 2 bytes of 'count of bytes returned' (1 word)
* 35: 8 bytes of reserved data (4 words)
* 43: 2 bytes of 'byte count' (1 word)
* 45: 1 byte of 'buffer format'
* 46: 2 bytes of 'count of bytes to read' (1 word).
*
* This adds up to 48 bytes.
*/
LOG(("SMBread: reading the first %ld bytes\n", 48));
result = receive_all (sock_fd, target, 48, error_ptr);
if (result < 0)
{
LOG (("recv error = %ld\n", (*error_ptr)));
goto out;
}
num_bytes_received += result;
ASSERT( num_bytes_received == 48 );
/* End of file reached? */
if(num_bytes_received < 48)
{
/* End of file */
LOG (("EOF\n"));
(*error_ptr) = error_end_of_file;
result = -1;
goto out;
}
/* So we read the header. Now we need to figure out if the
* data is in the expected format, and how many bytes are
* waiting to be read.
*/
/* The buffer format must be 1. */
buffer_format = BVAL(target, 45);
LOG(("buffer format = %ld, should be %ld\n", buffer_format, 1));
if(buffer_format != 1)
{
LOG(("buffer format %ld not supported\n", buffer_format));
(*error_ptr) = error_invalid_buffer_format;
result = -1;
goto out;
}
count_of_bytes_returned = WVAL(target, 33);
count_of_bytes_to_read = WVAL(target, 46);
/* That should never be more data than the read buffer may hold. */
ASSERT( count_of_bytes_to_read <= input_payload_size );
ASSERT( count_of_bytes_to_read <= count_of_bytes_returned );
ASSERT( count_of_bytes_returned <= input_payload_size );
LOG(("count of bytes to read = %ld, should be <= %ld\n", count_of_bytes_to_read, input_payload_size));
if(count_of_bytes_returned > input_payload_size)
{
(*error_ptr) = error_message_exceeds_buffer_size;
result = -1;
goto out;
}
result = receive_all (sock_fd, input_payload, count_of_bytes_to_read, error_ptr);
if (result < 0)
{
LOG (("recv error = %ld\n", (*error_ptr)));
goto out;
}
if(result < count_of_bytes_to_read)
{
/* End of file */
LOG (("EOF\n"));
(*error_ptr) = error_end_of_file;
result = -1;
goto out;
}
num_bytes_received += result;
ASSERT( count_of_bytes_to_read == count_of_bytes_returned );
if(count_of_bytes_to_read < count_of_bytes_returned)
{
LOG(("fewer data available than should be delivered; setting the remainder (%ld bytes) to 0.\n", count_of_bytes_returned - count_of_bytes_to_read));
memset(&input_payload[count_of_bytes_to_read],0,count_of_bytes_returned - count_of_bytes_to_read);
}
/* This should never happen, but then we better make sure to
* read the entire message.
*/
if(num_bytes_received < len)
{
LOG(("reading the remaining %ld bytes; this should never happen\n", len - num_bytes_received ));
result = receive_all (sock_fd, &target[num_bytes_received], len - num_bytes_received, error_ptr);
if (result < 0)
{
LOG (("recv error = %ld\n", (*error_ptr)));
goto out;
}
if(result < len - num_bytes_received)
{
/* End of file */
LOG (("EOF\n"));
(*error_ptr) = error_end_of_file;
result = -1;
goto out;
}
}
#if defined(DUMP_SMB)
{
/* If want_header==0 then this is the data returned by SMB_COM_READ_RAW. */
dump_smb(__FILE__,__LINE__,!want_header,target,48,smb_packet_to_consumer,server->max_recv);
if(buffer_format == 1)
dump_smb(__FILE__,__LINE__,!want_header,input_payload,num_bytes_received - 48,smb_packet_to_consumer,server->max_recv);
if(num_bytes_received < len && result > 0)
dump_smb(__FILE__,__LINE__,!want_header,&target[num_bytes_received],result,smb_packet_to_consumer,server->max_recv);
}
#endif /* defined(DUMP_SMB) */
}
#endif /* defined(DUMP_SMB) */
result = num_bytes_received;
}
@@ -448,7 +564,7 @@ smb_receive_raw (
}
static int
smb_receive (struct smb_server *server, int sock_fd, void * input_payload, int payload_size, int * error_ptr)
smb_receive (struct smb_server *server, int command, int sock_fd, void * input_payload, int payload_size, int * error_ptr)
{
byte * packet = server->transmit_buffer;
int result;
@@ -456,11 +572,26 @@ smb_receive (struct smb_server *server, int sock_fd, void * input_payload, int p
ASSERT( error_ptr != NULL );
ASSERT( server->max_recv <= server->transmit_buffer_size );
result = smb_receive_raw (server, sock_fd, packet,
server->max_recv,
input_payload, payload_size,
TRUE, /* We want the NetBIOS session service header */
error_ptr);
result = smb_receive_raw (
server,
command,
sock_fd,
packet,
/* Note: Worst case, if the inbound data has to go into the buffer, with
* no separate payload buffer provided. This is a "workaround" for
* SMB_COM_READ_ANDX which can end up receiving the regular
* SMB message header plus 65535 bytes of payload data, which
* easily breaks the limit set by server->max_recv (which only
* accounts for the in-band reception limit, not the out-of-band
* limit if the "large readx" capability is in effect).
* ZZZ this merits another check in smb_receive_raw().
*/
server->transmit_buffer_allocation_size,
input_payload, payload_size,
/* We want the NetBIOS session service header */
TRUE,
error_ptr);
if (result < 0)
{
LOG (("receive error: %ld\n", (*error_ptr)));
@@ -482,6 +613,7 @@ smb_receive (struct smb_server *server, int sock_fd, void * input_payload, int p
static int
smb_receive_trans2 (
struct smb_server * server,
int command,
int sock_fd,
int * data_len_ptr,
int * param_len_ptr,
@@ -507,16 +639,12 @@ smb_receive_trans2 (
int total_param;
int result;
ASSERT( data_len_ptr != NULL );
ASSERT( param_len_ptr != NULL );
ASSERT( data_ptr != NULL );
ASSERT( param_ptr != NULL );
ASSERT( error_ptr != NULL );
(*data_len_ptr) = (*param_len_ptr) = 0;
(*param_ptr) = (*data_ptr) = NULL;
result = smb_receive (server, sock_fd, NULL, 0, error_ptr);
result = smb_receive (server, command, sock_fd, NULL, 0, error_ptr);
if (result < 0)
goto out;
@@ -641,7 +769,7 @@ smb_receive_trans2 (
if (total_data <= data_len && total_param <= param_len)
break;
result = smb_receive (server, sock_fd, NULL, 0, error_ptr);
result = smb_receive (server, command, sock_fd, NULL, 0, error_ptr);
if (result < 0)
goto out;
@@ -772,6 +900,10 @@ smb_check_server_connection(struct smb_server *server, int error)
if(close_connection)
{
/* Stop means stop: EINTR is equivalent to Ctrl+C */
if(error == EINTR)
server->dont_retry = TRUE;
server->state = CONN_INVALID;
smb_invalidate_all_inodes (server);
}
@@ -782,7 +914,7 @@ smb_check_server_connection(struct smb_server *server, int error)
* case of error.
*/
int
smb_request (struct smb_server *server, void * input_payload, const void * output_payload, int payload_size, int * error_ptr)
smb_request (struct smb_server *server, int command, void * input_payload, const void * output_payload, int payload_size, int * error_ptr)
{
unsigned char *buffer = server->transmit_buffer;
int sock_fd = server->mount_data.fd;
@@ -856,7 +988,7 @@ smb_request (struct smb_server *server, void * input_payload, const void * outpu
}
}
result = smb_receive (server, sock_fd, input_payload, payload_size, error_ptr);
result = smb_receive (server, command, sock_fd, input_payload, payload_size, error_ptr);
out:
@@ -872,7 +1004,7 @@ smb_request (struct smb_server *server, void * input_payload, const void * outpu
* one packet to send.
*/
int
smb_trans2_request (struct smb_server *server, int *data_len, int *param_len, char **data, char **param, int * error_ptr)
smb_trans2_request (struct smb_server *server, int command, int *data_len, int *param_len, char **data, char **param, int * error_ptr)
{
unsigned char *buffer = server->transmit_buffer;
int sock_fd = server->mount_data.fd;
@@ -911,7 +1043,7 @@ smb_trans2_request (struct smb_server *server, int *data_len, int *param_len, ch
goto out;
}
result = smb_receive_trans2 (server, sock_fd, data_len, param_len, data, param, error_ptr);
result = smb_receive_trans2 (server, command, sock_fd, data_len, param_len, data, param, error_ptr);
out:
@@ -968,7 +1100,7 @@ smb_request_read_raw (struct smb_server *server, unsigned char *target, int max_
}
/* Wait for the raw data to be sent by the server. */
result = smb_receive_raw (server, sock_fd, target, max_len, NULL, 0, FALSE, error_ptr);
result = smb_receive_raw (server, SMBreadbraw, sock_fd, target, max_len, NULL, 0, FALSE, error_ptr);
out:
@@ -1037,7 +1169,7 @@ smb_request_write_raw (struct smb_server *server, unsigned const char *source, i
/* Wait for the server to respond. */
if(!server->write_behind)
{
result = smb_receive (server, sock_fd, NULL, 0, error_ptr);
result = smb_receive (server, SMBwritebraw, sock_fd, NULL, 0, error_ptr);
if(result < 0)
goto out;
}
Executable → Regular
+23
View File
@@ -79,6 +79,22 @@
/*****************************************************************************/
/* A quick workaround for the timeval/timerequest->TimeVal/TimeRequest
change in the recent OS4 header files. */
#if defined(__NEW_TIMEVAL_DEFINITION_USED__)
#define timeval TimeVal
#define tv_secs Seconds
#define tv_micro Microseconds
#define timerequest TimeRequest
#define tr_node Request
#define tr_time Time
#endif /* __NEW_TIMEVAL_DEFINITION_USED__ */
/*****************************************************************************/
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/intuition.h>
@@ -90,6 +106,13 @@
/*****************************************************************************/
/* This is for backwards compatibility only. */
#if defined(__amigaos4__)
#define fib_EntryType fib_Obsolete
#endif /* __amigaos4__ */
/*****************************************************************************/
#include <time.h>
#include <stdio.h>
#include <errno.h>