diff --git a/documentation/history.doc b/documentation/history.doc index 91d2f8a..a93e83b 100644 --- a/documentation/history.doc +++ b/documentation/history.doc @@ -1665,8 +1665,8 @@ smbfs 1.136 (22.5.2018) smbfs 1.137 (24.5.2018) - Updated the table of error codes which eventually get translated - into AmigaDOS error codes. Quite a number of error codes were - still not properly covered. + into AmigaDOS error codes. Quite a number of error codes were not + properly covered. - We now show how much memory smbfs has used (in debug mode), and how much memory has not been released yet. @@ -1703,3 +1703,79 @@ smbfs 1.137 (24.5.2018) - Added further tests to figure out if a directory could not be deleted because it was not empty. However, it's difficult to tell all three cases apart which share the same error code. We'll try anyway... + + +smbfs 1.138 (25.5.2018) + +- The name translation performed by the directory scanning code is now + a bit more paranoid than before. They will check if the names can + be translated into something suitable for use on the Amiga. This rules + out control characters, for example. If a name is unsuitable, an + explanation why it is unsuitable will be printed in the debug output. + +- The SBM directory scanning code which uses the TRANSACT2_FINDFIRST2 + and TRANSACT2_FINDNEXT2 commands now uses the correct flag codes instead + of naked numeric constants. + +- Removed support for the "write raw" and "read raw" commands, which extends + to the command line parameters and tool types which could be used to + disable them or adjust how they would be used. + + +smbfs 1.139 (26.5.2018) + +- Added more const qualifiers to pointers, so that unintended changes + are more easily detected. + +- Text that uses 8 bit characters now uses type TEXT rather than UBYTE, + and TEXT * replaces STRPTR where it makes sense. + +- Text buffer size and maximum size (without terminating NUL byte) of + the string that may be stored in there are now distinct. + +- Building the error message list for display in an error requester + is now more efficient, as it no longer resorts to strcat(). + +- Removed the last traces of the SMB "system" file attribute and its + mapping to the "pure" protection bit on the Amiga. + +- File sizes returned (through the Examine(), ExNext() and ExAll() + functions) now refer to the original SMB file size information + which may be a 64 bit integer. Same goes for the file sizes + referenced by Seek() and SetFileSize(). Note that for now the + sizes returned will be truncated, which means that if they + exceed what an unsigned 32 bit integer may represent, then + the number 4294967295 will be used instead. There could be + hilarious consequences: watch out! + +- When scanning directory contents, names which end up containing + unprintable names (not "#$@&%*!") after conversion to Amiga format + are now ignored. + +- Reading/writing files updates the internal seek position of the + respective file, which is now a 64 bit integer. You can actually + read from files > 4 Gigabytes (and write to them, too) as long + as you do not use Seek(file, ..., OFFSET_BEGINNING) because that + will box you into the first 4 Gigabytes of the file. Note that the + result of Seek() and SetFileSize() will be a truncated position + (4294967295) if the position happens to be beyond what can be + represented by an unsigned 32 bit integer. Because "4294967295" + is also known as the signed 32 bit integer "-1" you probably + won't be able to tell it apart from a seek error (unless you + check the IoErr() value, of course, but who does?). This + used to be a problem with "normal" Amiga file systems, and now + it's a problem again :-( + +- When decoding directory entry data, we no longer replace the + "last change" time with the "last write access" time, and then + swap both time records again (who ordered that?). The + "last change" time now stays the last change time, and this + is what goes into the Amiga FileInfoBlock/ExAllData records. + +- The debug output for the directory scanner now prints the original + untranslated name in 'C' style escaped form, in case this might + reveal further insights into why the directory entry names look + like they do. Note that all file, directory and path names used + by the SMB file system layer now appear only in escaped form, which + means for example that all backslash characters which serve as + path delimiters show up twice as much. diff --git a/source_code/GNUmakefile.68k b/source_code/GNUmakefile.68k index b4dc072..42b55d1 100644 --- a/source_code/GNUmakefile.68k +++ b/source_code/GNUmakefile.68k @@ -68,13 +68,13 @@ $(PROJECT): $(OBJS) assert.o : assert.c cp437.o : cp437.c 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 smbfs_rev.h +crypt.o : crypt.c system_headers.h assert.h quad_math.h smbfs.h +dump_smb.o : dump_smb.c system_headers.h assert.h quad_math.h smbfs.h dump_smb.h +main.o : main.c system_headers.h assert.h quad_math.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 quad_math.h smbfs.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 +smb_abstraction.o : smb_abstraction.c system_headers.h assert.h quad_math.h smbfs.h errors.h smb_abstraction.h +sock.o : sock.c system_headers.h assert.h quad_math.h smbfs.h smb_abstraction.h dump_smb.h errors.h utf-8-iso-8859-1-conversion.o : utf-8-iso-8859-1-conversion.c utf-8-iso-8859-1-conversion.h ############################################################################### diff --git a/source_code/GNUmakefile.os4 b/source_code/GNUmakefile.os4 index c9e9a9a..40d19dd 100644 --- a/source_code/GNUmakefile.os4 +++ b/source_code/GNUmakefile.os4 @@ -73,13 +73,13 @@ $(PROJECT): $(OBJS) assert.o : assert.c cp437.o : cp437.c 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 smbfs_rev.h +crypt.o : crypt.c system_headers.h assert.h quad_math.h smbfs.h +dump_smb.o : dump_smb.c system_headers.h assert.h quad_math.h smbfs.h dump_smb.h +main.o : main.c system_headers.h assert.h quad_math.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 quad_math.h smbfs.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 +smb_abstraction.o : smb_abstraction.c system_headers.h assert.h quad_math.h smbfs.h errors.h smb_abstraction.h +sock.o : sock.c system_headers.h assert.h quad_math.h smbfs.h smb_abstraction.h dump_smb.h errors.h utf-8-iso-8859-1-conversion.o : utf-8-iso-8859-1-conversion.c utf-8-iso-8859-1-conversion.h ########################################################################### diff --git a/source_code/dump_smb.c b/source_code/dump_smb.c index ef683f2..8f780f4 100644 --- a/source_code/dump_smb.c +++ b/source_code/dump_smb.c @@ -40,10 +40,6 @@ /*****************************************************************************/ -extern VOID VARARGS68K SPrintf(STRPTR buffer, STRPTR formatString,...); - -/*****************************************************************************/ - /* This can be used to enable or disable the SMB packet dump output. */ static int dump_smb_enabled; diff --git a/source_code/include/smb/smb.h b/source_code/include/smb/smb.h index 08405e8..31d6104 100644 --- a/source_code/include/smb/smb.h +++ b/source_code/include/smb/smb.h @@ -71,11 +71,13 @@ struct smb_dirent /* to UTC. The ugly conversion happens in */ /* proc.c */ - unsigned long size; /* File size. */ + dword size_low; /* File size (least significant 32 bits). */ + dword size_high; /* File size (most significant 32 bits). */ char * complete_path; /* Complete path, MS-DOS notation, with '\' */ size_t complete_path_size; /* Number of bytes allocated for name */ - int len; /* Namelength. */ + + int len; /* Name length. */ unsigned opened:1; /* is it open on the fileserver? */ unsigned writable:1; /* was opened for read/write access? */ diff --git a/source_code/include/smb/smb_fs.h b/source_code/include/smb/smb_fs.h index 86d428a..8ec9376 100644 --- a/source_code/include/smb/smb_fs.h +++ b/source_code/include/smb/smb_fs.h @@ -18,6 +18,10 @@ #include +#ifndef _QUAD_MATH_H +#include "quad_math.h" +#endif /* _QUAD_MATH_H */ + /* This structure is used to pass the arguments to smb_proc_lockingX */ struct smb_lkrng @@ -50,11 +54,9 @@ 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, 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_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_writex (struct smb_server *server, struct smb_dirent *finfo, const QUAD * const offset, long count, const char *data, int * error_ptr); +int smb_proc_readx (struct smb_server *server, struct smb_dirent *finfo, const QUAD * const 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); @@ -66,7 +68,7 @@ int smb_proc_readdir(struct smb_server *server, char *path, int fpos, int cache_ 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_set_file_information(struct smb_server *server, struct smb_dirent *entry, const QUAD * const size, 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); @@ -78,7 +80,5 @@ 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 /* _LINUX_SMB_FS_H */ diff --git a/source_code/include/smb/smb_fs_sb.h b/source_code/include/smb/smb_fs_sb.h index d38c924..df67834 100644 --- a/source_code/include/smb/smb_fs_sb.h +++ b/source_code/include/smb/smb_fs_sb.h @@ -51,18 +51,6 @@ struct smb_server /* olsen (2012-12-10): raw SMB over TCP instead of NBT transport? */ int raw_smb; - /* olsen (2016-04-20): Use write-behind with SMB_COM_WRITE_RAW? */ - int write_behind; - - /* olsen (2016-04-20): Prefer SMB_COM_WRITE_RAW to SMB_COM_WRITE? */ - int prefer_write_raw; - - /* olsen (2018-05-08): Always use SMB_COM_WRITE, even if SMB_COM_WRITE_RAW were possible. */ - int disable_write_raw; - - /* olsen (2018-05-08): Always use SMB_COM_READ, even if SMB_COM_READ_RAW were possible. */ - int disable_read_raw; - /* olsen (2018-05-09): Timeout for send/receive operations in seconds. */ int timeout; diff --git a/source_code/include/smb/smbno.h b/source_code/include/smb/smbno.h index a8e390e..f67a1c1 100644 --- a/source_code/include/smb/smbno.h +++ b/source_code/include/smb/smbno.h @@ -365,6 +365,13 @@ #define SMB_INFO_STANDARD 0x0001 /* LAN Manager 2.0 */ #define SMB_FILE_BOTH_DIRECTORY_INFO 0x0104 /* NT LAN Manager */ +/* Flags used by TRANSACT2_FINDFIRST */ +#define SMB_FIND_CLOSE_AFTER_REQUEST 0x0001 /* Close the request after this search */ +#define SMB_FIND_CLOSE_AT_EOS 0x0002 /* Close search when end of search is reached */ +#define SMB_FIND_RETURN_RESUME_KEYS 0x0004 /* Return resume keys for each entry found */ +#define SMB_FIND_CONTINUE_FROM_LAST 0x0008 /* Continue search from previous ending place */ +#define SMB_FIND_WITH_BACKUP_INTENT 0x0010 /* Find with backup intent */ + /* File system information formats supported by TRANSACT2_QFSINFO (actually, * we only need this one). */ diff --git a/source_code/main.c b/source_code/main.c index cbbe1a7..149c30f 100644 --- a/source_code/main.c +++ b/source_code/main.c @@ -40,6 +40,7 @@ #include "cp437.h" #include "cp850.h" #include "errors.h" +#include "quad_math.h" #include "dump_smb.h" /****************************************************************************/ @@ -56,7 +57,7 @@ STRPTR Version = VERSTAG; /****************************************************************************/ #define UNIX_TIME_OFFSET 252460800 -#define MAX_FILENAME_LEN 256 +#define MAX_FILENAME_LEN 255 /****************************************************************************/ @@ -75,7 +76,7 @@ struct FileNode { struct MinNode fn_MinNode; struct FileHandle * fn_Handle; - LONG fn_Offset; + QUAD fn_OffsetQuad; LONG fn_Mode; smba_file_t * fn_File; STRPTR fn_FullName; @@ -133,10 +134,10 @@ STATIC LONG main(VOID); STATIC ULONG get_stack_size(VOID); STATIC VOID stack_usage_init(struct StackSwapStruct * stk); 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 LONG CVSPrintf(const TEXT * format_string, APTR args); +STATIC VOID VSPrintf(STRPTR buffer, const TEXT * 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 opt_native_os, STRPTR device_name, STRPTR volume_name, STRPTR translation_file); +STATIC BOOL Setup(const TEXT * 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, 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); /****************************************************************************/ @@ -222,8 +223,8 @@ STATIC struct MinList ErrorList; STATIC STRPTR NewProgramName; STATIC BOOL TranslateNames; -STATIC UBYTE A2M[256]; -STATIC UBYTE M2A[256]; +STATIC TEXT A2M[256]; +STATIC TEXT M2A[256]; /****************************************************************************/ @@ -543,10 +544,6 @@ main(VOID) NUMBER TimeZoneOffset; NUMBER DSTOffset; SWITCH NetBIOSTransport; - SWITCH WriteBehind; - SWITCH PreferWriteRaw; - SWITCH DisableWriteRaw; - SWITCH DisableReadRaw; KEY NativeOS; SWITCH DumpSMB; NUMBER DumpSMBLevel; @@ -578,10 +575,6 @@ main(VOID) "TZ=TIMEZONEOFFSET/N/K," "DST=DSTOFFSET/N/K," "NETBIOS/S," - "WRITEBEHIND/S," - "PREFERWRITERAW/S," - "DISABLEWRITERAW/S," - "DISABLEREADRAW/S," "NATIVEOS/K," "DUMPSMB/S," "DUMPSMBLEVEL/N/K," @@ -594,7 +587,7 @@ main(VOID) BPTR debug_file = (BPTR)NULL; BOOL close_debug_file = FALSE; - UBYTE program_name[MAX_FILENAME_LEN]; + TEXT program_name[MAX_FILENAME_LEN+1]; LONG result = RETURN_FAIL; LONG number; LONG other_number; @@ -809,18 +802,6 @@ main(VOID) if(FindToolType(Icon->do_ToolTypes,"NETBIOS") != NULL) args.NetBIOSTransport = TRUE; - if(FindToolType(Icon->do_ToolTypes,"WRITEBEHIND") != NULL) - args.WriteBehind = TRUE; - - if(FindToolType(Icon->do_ToolTypes,"PREFERWRITERAW") != NULL) - args.PreferWriteRaw = TRUE; - - if(FindToolType(Icon->do_ToolTypes,"DISABLEWRITERAW") != NULL) - args.DisableWriteRaw = TRUE; - - if(FindToolType(Icon->do_ToolTypes,"DISABLEREADRAW") != NULL) - args.DisableReadRaw = TRUE; - str = FindToolType(Icon->do_ToolTypes,"NATIVEOS"); if(str != NULL) args.NativeOS = str; @@ -1056,7 +1037,7 @@ main(VOID) if(args.DebugLevel != NULL) { - #if !defined(DEBUG) + #if !DEBUG { if(WBStartup == NULL) ReportError("This version of smbfs cannot create debug output."); @@ -1105,10 +1086,6 @@ main(VOID) args.TimeZoneOffset, args.DSTOffset, !args.NetBIOSTransport, /* Use raw SMB transport instead of NetBIOS transport? */ - args.WriteBehind, - args.PreferWriteRaw, - args.DisableWriteRaw, - args.DisableReadRaw, args.NativeOS, args.DeviceName, args.VolumeName, @@ -1155,7 +1132,7 @@ main(VOID) /****************************************************************************/ static LONG VARARGS68K -LocalFPrintf(BPTR output, const UBYTE * format, ...) +LocalFPrintf(BPTR output, const TEXT * format, ...) { va_list args; LONG result; @@ -1275,7 +1252,7 @@ host_strerror(int error) * to be compared. */ LONG -CompareNames(STRPTR a,STRPTR b) +CompareNames(const TEXT * a,const TEXT * b) { LONG result; @@ -1293,7 +1270,7 @@ CompareNames(STRPTR a,STRPTR b) VOID StringToUpper(STRPTR s) { - UBYTE c; + TEXT c; while((c = (*s)) != '\0') (*s++) = ToUpper(c); @@ -1309,15 +1286,15 @@ DisplayErrorList(VOID) { struct MinNode * last = NULL; struct MinNode * mn; - STRPTR str = NULL; - STRPTR msg; - LONG len; + TEXT * message = NULL; + const TEXT * str; + int size; /* Determine how much memory will have to be * allocated to hold all the accumulated * error messages. */ - len = 0; + size = 0; for(mn = ErrorList.mlh_Head ; mn->mln_Succ != NULL ; @@ -1325,31 +1302,39 @@ DisplayErrorList(VOID) { last = mn; - msg = (STRPTR)(mn + 1); + str = (TEXT *)(mn + 1); - len += strlen(msg)+1; + size += strlen(str)+1; } /* Allocate the memory for the messages, then * copy them there. */ - if(len > 0) + if(size > 0) { - str = AllocVec(len,MEMF_ANY); - if(str != NULL) + message = AllocVec(size,MEMF_ANY); + if(message != NULL) { - str[0] = '\0'; + int message_len; + int len; + + message_len = 0; for(mn = ErrorList.mlh_Head ; mn->mln_Succ != NULL ; mn = mn->mln_Succ) { - msg = (STRPTR)(mn + 1); + str = (TEXT *)(mn + 1); + len = strlen(str); + + memcpy(&message[message_len], str, len); + message_len += len; - strcat(str,msg); if(mn != last) - strcat(str,"\n"); + message[message_len++] = '\n'; } + + message[message_len] = '\0'; } } @@ -1358,7 +1343,7 @@ DisplayErrorList(VOID) FreeVec(mn); /* Display the error messages. */ - if(str != NULL) + if(message != NULL) { IntuitionBase = OpenLibrary("intuition.library",37); @@ -1390,13 +1375,13 @@ DisplayErrorList(VOID) es.es_StructSize = sizeof(es); es.es_Title = title; - es.es_TextFormat = str; - es.es_GadgetFormat = "Ok"; + es.es_TextFormat = message; + es.es_GadgetFormat = "OK"; EasyRequestArgs(NULL,&es,NULL,NULL); } - FreeVec(str); + FreeVec(message); } #if defined(__amigaos4__) @@ -1418,16 +1403,16 @@ DisplayErrorList(VOID) * necessary. */ STATIC VOID -AddError(STRPTR fmt,APTR args) +AddError(const TEXT * fmt,APTR args) { - LONG len; + int size; - len = CVSPrintf(fmt,args); - if(len > 0) + size = CVSPrintf(fmt,args); + if(size > 0) { struct MinNode * mn; - mn = AllocVec(sizeof(*mn) + len,MEMF_ANY|MEMF_PUBLIC); + mn = AllocVec(sizeof(*mn) + size,MEMF_ANY|MEMF_PUBLIC); if(mn != NULL) { STRPTR msg = (STRPTR)(mn + 1); @@ -1445,7 +1430,7 @@ AddError(STRPTR fmt,APTR args) * from Shell, error messages will be accumulated for later display. */ VOID VARARGS68K -ReportError(STRPTR fmt,...) +ReportError(const TEXT * fmt,...) { if(NOT Quiet) { @@ -1470,7 +1455,7 @@ ReportError(STRPTR fmt,...) else { struct Process * this_process = (struct Process *)FindTask(NULL); - UBYTE program_name[MAX_FILENAME_LEN]; + TEXT program_name[MAX_FILENAME_LEN+1]; BPTR output; GetProgramName(program_name,sizeof(program_name)); @@ -1662,8 +1647,8 @@ MakeTime(const struct tm * const tm) struct FormatContext { - UBYTE * fc_Buffer; - LONG fc_Size; + TEXT * fc_Buffer; + int fc_Size; }; /****************************************************************************/ @@ -1676,7 +1661,7 @@ CountChar(REG(a3,struct FormatContext * fc)) /* Count the number of characters SPrintf() would put into a string. */ STATIC LONG -CVSPrintf(STRPTR format_string,APTR args) +CVSPrintf(const TEXT * format_string,APTR args) { struct FormatContext fc; @@ -1690,13 +1675,13 @@ CVSPrintf(STRPTR format_string,APTR args) /****************************************************************************/ STATIC VOID ASM -StuffChar(REG(d0,UBYTE c),REG(a3,struct FormatContext * fc)) +StuffChar(REG(d0,TEXT c),REG(a3,struct FormatContext * fc)) { (*fc->fc_Buffer++) = c; } STATIC VOID -VSPrintf(STRPTR buffer, STRPTR formatString, APTR args) +VSPrintf(STRPTR buffer, const TEXT * formatString, APTR args) { struct FormatContext fc; @@ -1709,7 +1694,7 @@ VSPrintf(STRPTR buffer, STRPTR formatString, APTR args) /* Format a string for output. */ VOID VARARGS68K -SPrintf(STRPTR buffer, STRPTR formatString,...) +SPrintf(STRPTR buffer, const TEXT * formatString,...) { va_list varArgs; @@ -2101,7 +2086,8 @@ CheckAccessModeCollision(STRPTR name,LONG mode) int error = OK; ENTER(); - SHOWSTRING(name); + + D(("name = '%s'", escape_name(name))); fn = FindFileNode(name,NULL); if(fn != NULL) @@ -2163,30 +2149,26 @@ NameAlreadyInUse(STRPTR name) * should be avoided when used with the SMB file sharing protocol. */ STATIC BOOL -IsReservedName(STRPTR name) +is_reserved_name(const TEXT * name) { - BOOL result = FALSE; + BOOL result = TRUE; + TEXT c; /* Disallow "." and "..". */ if(name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0'))) - { - result = TRUE; - } - else - { - UBYTE c; + goto out; - /* Disallow the use of the backslash in file names. */ - while((c = (*name++)) != '\0') - { - if(c == SMB_PATH_SEPARATOR) - { - result = TRUE; - break; - } - } + /* Disallow the use of the backslash in file names. */ + while((c = (*name++)) != '\0') + { + if(c == SMB_PATH_SEPARATOR) + goto out; } + result = FALSE; + + out: + return(result); } @@ -2200,7 +2182,7 @@ MapErrnoToIoErr(int error) * POSIX covers more than a hundred different error codes * whereas with AmigaDOS we're stranded with a measly 48... */ - STATIC const LONG map_posix_to_amigados[][2] = + STATIC const int map_posix_to_amigados[][2] = { { E2BIG, ERROR_TOO_MANY_ARGS }, /* Argument list too long */ { EACCES, ERROR_READ_PROTECTED }, /* Permission denied */ @@ -2312,7 +2294,7 @@ MapErrnoToIoErr(int error) #if DEBUG { - UBYTE amigados_error_text[256]; + TEXT amigados_error_text[256]; Fault(result,NULL,amigados_error_text,sizeof(amigados_error_text)); @@ -2345,10 +2327,10 @@ MapErrnoToIoErr(int error) * and FALSE if at least one character cannot be translated. */ STATIC BOOL -TranslateBName(UBYTE * name,const UBYTE * map) +TranslateBName(TEXT * name,const TEXT * map) { BOOL success = TRUE; - UBYTE c; + TEXT c; int len; len = (*name++); @@ -2377,10 +2359,10 @@ TranslateBName(UBYTE * name,const UBYTE * map) * cannot be translated. */ STATIC BOOL -TranslateCName(UBYTE * name,const UBYTE * map) +TranslateCName(TEXT * name,const TEXT * map) { BOOL success = TRUE; - UBYTE c; + TEXT c; while((c = (*name)) != '\0') { @@ -2413,7 +2395,7 @@ ReallyRemoveDosEntry(struct DosList * entry) struct MsgPort * port; struct DosList * dl; BOOL result = FALSE; - LONG kind,i; + int kind,i; if(entry->dol_Type == DLT_DEVICE) kind = LDF_DEVICES; @@ -2616,38 +2598,34 @@ Cleanup(VOID) /* Allocate all the necessary resources to get going. */ 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) + const TEXT * 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, + STRPTR opt_native_os, + STRPTR device_name, + STRPTR volume_name, + STRPTR translation_file) { BOOL result = FALSE; struct DosList * dl; int error = 0; int smb_error_class = 0, smb_error = 0; STRPTR actual_volume_name; - LONG actual_volume_name_len; - UBYTE name[MAX_FILENAME_LEN]; + int actual_volume_name_len; + TEXT name[MAX_FILENAME_LEN+1]; BOOL device_exists = FALSE; - LONG len,i; + int len,i; ENTER(); @@ -2749,7 +2727,7 @@ Setup( if(opt_changecase) { - for(i = 0 ; i < (LONG)strlen(opt_password) ; i++) + for(i = 0 ; i < (int)strlen(opt_password) ; i++) opt_password[i] = ToUpper(opt_password[i]); } @@ -2785,7 +2763,7 @@ Setup( } else { - UBYTE description[100]; + TEXT description[100]; Fault(error,NULL,description,sizeof(description)); for(i = ((int)strlen(description)) - 1 ; i >= 0 ; i--) @@ -2810,10 +2788,6 @@ Setup( opt_max_transmit, opt_timeout, opt_raw_smb, - opt_write_behind, - opt_prefer_write_raw, - opt_disable_write_raw, - opt_disable_read_raw, (char *)opt_native_os, &error, &smb_error_class, @@ -3005,12 +2979,168 @@ Setup( /****************************************************************************/ +/* Truncate an file size or position which cannot be represented by a + * single 32 bit integer and substitute it with something vaguely more + * sensible (which probably isn't so sensible in the first place, but + * we keep trying). + */ +static ULONG +truncate_64_bit_position(const QUAD * position_quad) +{ + ULONG result; + + if(position_quad->High == 0) + result = position_quad->Low; + else + result = 0xFFFFFFFFUL; + + return(result); +} + +/****************************************************************************/ + +#if DEBUG + +/* Create a form of the given file/directory name which shows unprintable + * characters through the use of 'C' style escape sequences. Returns a + * pointer to a local static buffer which contains the escaped string. + * If the escape form of the name is too long to fit into the buffer, + * the text " [...]" will be appended to contents of the buffer, to indicate + * that the name was truncated. + */ +TEXT * +escape_name(const TEXT * name) +{ + static const TEXT truncated_suffix[] = " [...]"; + static TEXT buffer[4 * 256 + sizeof(truncated_suffix)]; + + const int buffer_size = (int)sizeof(buffer) - sizeof(truncated_suffix); + BOOL truncated = FALSE; + TEXT hex_code[6]; + TEXT * str; + int len; + TEXT c; + + len = 0; + + while((c = (*name++)) != '\0') + { + if (c < ' ') + { + int l = 2; + + switch(c) + { + case '\a': + + str = "\\a"; + break; + + case '\b': + + str = "\\b"; + break; + + case '\f': + + str = "\\f"; + break; + + case '\n': + + str = "\\n"; + break; + + case '\r': + + str = "\\r"; + break; + + case '\t': + + str = "\\t"; + break; + + case '\v': + + str = "\\v"; + break; + + default: + + SPrintf(hex_code,"\\x%02lx",c); + str = hex_code; + + l = 4; + break; + } + + if(len + l >= buffer_size) + { + truncated = TRUE; + break; + } + + memcpy(&buffer[len],str,l); + len += l; + } + else if (127 <= c && c <= 160) + { + if(len + 4 >= buffer_size) + { + truncated = TRUE; + break; + } + + SPrintf(hex_code,"\\x%02lx",c); + + memcpy(&buffer[len],hex_code,4); + len += 4; + } + else if (c == '\\') + { + if(len + 2 >= buffer_size) + { + truncated = TRUE; + break; + } + + buffer[len++] = c; + buffer[len++] = c; + } + else + { + if(len + 1 >= buffer_size) + { + truncated = TRUE; + break; + } + + buffer[len++] = c; + } + } + + if(truncated) + { + memcpy(&buffer[len],truncated_suffix,sizeof(truncated_suffix)-1); + len += sizeof(truncated_suffix)-1; + } + + buffer[len] = '\0'; + + return(buffer); +} + +#endif /* DEBUG */ + +/****************************************************************************/ + /* Convert a BCPL string into a standard NUL terminated 'C' string. */ STATIC VOID -ConvertBString(LONG max_len,STRPTR cstring,const void * bstring) +ConvertBString(int max_len,STRPTR cstring,const void * bstring) { - const UBYTE * from = bstring; - LONG len = from[0]; + const TEXT * from = bstring; + int len = from[0]; if(len > max_len-1) len = max_len-1; @@ -3023,9 +3153,9 @@ ConvertBString(LONG max_len,STRPTR cstring,const void * bstring) /* Convert a NUL terminated 'C' string into a BCPL string. */ STATIC VOID -ConvertCString(void * bstring,LONG max_len,const UBYTE * cstring,LONG len) +ConvertCString(void * bstring,int max_len,const TEXT * cstring,int len) { - UBYTE * to = bstring; + TEXT * to = bstring; if(len > max_len-1) len = max_len-1; @@ -3043,27 +3173,31 @@ ConvertCString(void * bstring,LONG max_len,const UBYTE * cstring,LONG len) */ STATIC LONG BuildFullName( - const UBYTE * parent_name, + const TEXT * parent_name, STRPTR name, STRPTR * result_ptr, - LONG * result_size_ptr) + int * result_size_ptr) { int error = OK; STRPTR buffer; - LONG len,size; - LONG i; + int len,size; + int i; ENTER(); - SHOWSTRING(parent_name); - SHOWSTRING(name); + if(parent_name == NULL) + D(("parent_name = NULL")); + else + D(("parent_name = '%s'",escape_name(parent_name))); + + D(("name = '%s'",escape_name(name))); (*result_ptr) = NULL; /* Throw everything left of the colon away. */ if(name != NULL) { - for(i = 0 ; i < (LONG)strlen(name) ; i++) + for(i = 0 ; i < (int)strlen(name) ; i++) { if(name[i] == ':') { @@ -3114,10 +3248,10 @@ BuildFullName( /* If there's a name to add, do just that. */ if(name != NULL) { - LONG segment_start; - LONG segment_len; - LONG buffer_len; - LONG name_len; + int segment_start; + int segment_len; + int buffer_len; + int name_len; buffer_len = strlen(buffer); name_len = strlen(name); @@ -3219,7 +3353,7 @@ BuildFullName( (*result_ptr) = buffer; (*result_size_ptr) = size; - SHOWSTRING(buffer); + D(("buffer = '%s'",escape_name(buffer))); out: @@ -3239,7 +3373,7 @@ Action_Parent( { BPTR result = ZERO; STRPTR full_name = NULL; - LONG full_name_size; + int full_name_size; STRPTR parent_name; BOOL cleanup = TRUE; struct LockNode * ln = NULL; @@ -3286,7 +3420,7 @@ Action_Parent( ln->ln_FileLock.fl_Volume = MKBADDR(VolumeNode); ln->ln_FullName = full_name; - SHOWSTRING(full_name); + D(("full_name = '%s'",escape_name(full_name))); if(smba_open(ServerData,full_name,full_name_size,open_read_only,open_dont_truncate,&ln->ln_File,&error) < 0) { @@ -3354,11 +3488,11 @@ Action_DeleteObject( { LONG result = DOSFALSE; STRPTR full_name = NULL; - LONG full_name_size; + int full_name_size; smba_file_t * file = NULL; STRPTR parent_name; STRPTR full_parent_name = NULL; - UBYTE name[MAX_FILENAME_LEN]; + TEXT name[MAX_FILENAME_LEN+1]; struct LockNode * ln; int ignored_error; smba_stat_t st; @@ -3394,15 +3528,15 @@ Action_DeleteObject( /* Translate the Amiga file name into UTF-8 encoded form? */ if (TranslateUTF8) { - UBYTE encoded_name[MAX_FILENAME_LEN]; + TEXT encoded_name[MAX_FILENAME_LEN+1]; int encoded_name_len; - LONG name_len = strlen(name); + int name_len = strlen(name); /* Figure out how long the UTF-8 version will become. */ encoded_name_len = encode_iso8859_1_as_utf8_string(name,name_len,NULL,0); /* Encoding error occured, or the resulting name is longer than the buffer will hold? */ - if(encoded_name_len < 0 || encoded_name_len >= sizeof(name)) + if(encoded_name_len < 0 || encoded_name_len >= (int)sizeof(name)) { error = ERROR_INVALID_COMPONENT_NAME; goto out; @@ -3493,7 +3627,7 @@ Action_DeleteObject( FreeMemory(full_parent_name); full_parent_name = NULL; - SHOWSTRING(full_name); + D(("full_name = '%s'",escape_name(full_name))); if(smba_open(ServerData,full_name,full_name_size,open_writable,open_dont_truncate,&file,&error) < 0) { @@ -3594,17 +3728,17 @@ Action_CreateDir( { BPTR result = ZERO; STRPTR full_name = NULL; - LONG full_name_size; + int full_name_size; struct LockNode * ln = NULL; STRPTR parent_name; STRPTR dir_name = NULL; size_t dir_name_size; smba_file_t * dir = NULL; STRPTR base_name; - UBYTE name[MAX_FILENAME_LEN]; + TEXT name[MAX_FILENAME_LEN+1]; int ignored_error; int error; - LONG i; + int i; ENTER(); @@ -3631,12 +3765,12 @@ Action_CreateDir( if (TranslateUTF8) { - UBYTE encoded_name[MAX_FILENAME_LEN]; + TEXT encoded_name[MAX_FILENAME_LEN+1]; int encoded_name_len; - LONG name_len = strlen(name); + int name_len = strlen(name); encoded_name_len = encode_iso8859_1_as_utf8_string(name,name_len,NULL,0); - if(encoded_name_len < 0 || encoded_name_len >= sizeof(name)) + if(encoded_name_len < 0 || encoded_name_len >= (int)sizeof(name)) { error = ERROR_INVALID_COMPONENT_NAME; goto out; @@ -3666,7 +3800,7 @@ Action_CreateDir( goto out; } - SHOWSTRING(full_name); + D(("full_name = '%s'",escape_name(full_name))); dir_name_size = strlen(full_name)+3; @@ -3733,7 +3867,7 @@ Action_CreateDir( smba_close(dir,&ignored_error); dir = NULL; - SHOWSTRING(full_name); + D(("full_name = '%s'",escape_name(full_name))); if(smba_open(ServerData,full_name,full_name_size,open_read_only,open_dont_truncate,&ln->ln_File,&error) < 0) { @@ -3775,10 +3909,10 @@ Action_LocateObject( { BPTR result = ZERO; STRPTR full_name = NULL; - LONG full_name_size; + int full_name_size; struct LockNode * ln = NULL; STRPTR parent_name; - UBYTE name[MAX_FILENAME_LEN]; + TEXT name[MAX_FILENAME_LEN+1]; int error; ENTER(); @@ -3800,12 +3934,12 @@ Action_LocateObject( if (TranslateUTF8) { - UBYTE encoded_name[MAX_FILENAME_LEN]; + TEXT encoded_name[MAX_FILENAME_LEN+1]; int encoded_name_len; - LONG name_len = strlen(name); + int name_len = strlen(name); encoded_name_len = encode_iso8859_1_as_utf8_string(name,name_len,NULL,0); - if(encoded_name_len < 0 || encoded_name_len >= sizeof(name)) + if(encoded_name_len < 0 || encoded_name_len >= (int)sizeof(name)) { error = ERROR_INVALID_COMPONENT_NAME; goto out; @@ -3824,7 +3958,7 @@ Action_LocateObject( } } - if(IsReservedName(FilePart(name))) + if(is_reserved_name(FilePart(name))) { error = ERROR_OBJECT_NOT_FOUND; goto out; @@ -3859,7 +3993,7 @@ Action_LocateObject( if(error != OK) goto out; - SHOWSTRING(full_name); + D(("full_name = '%s'",escape_name(full_name))); if(smba_open(ServerData,full_name,full_name_size,open_read_only,open_dont_truncate,&ln->ln_File,&error) < 0) { @@ -3894,7 +4028,7 @@ Action_CopyDir( { BPTR result = ZERO; STRPTR full_name = NULL; - LONG full_name_size; + int full_name_size; struct LockNode * ln = NULL; STRPTR source_name; LONG source_mode; @@ -3952,7 +4086,7 @@ Action_CopyDir( ln->ln_FileLock.fl_Volume = MKBADDR(VolumeNode); ln->ln_FullName = full_name; - SHOWSTRING(full_name); + D(("full_name = '%s'",escape_name(full_name))); if(smba_open(ServerData,full_name,full_name_size,open_read_only,open_dont_truncate,&ln->ln_File,&error) < 0) { @@ -4053,8 +4187,8 @@ Action_SameLock( name2 = SMB_ROOT_DIR_NAME; } - SHOWSTRING(name1); - SHOWSTRING(name2); + D(("name1 = '%s'",escape_name(name1))); + D(("name2 = '%s'",escape_name(name2))); if(Stricmp(name1,name2) == SAME) result = DOSTRUE; @@ -4076,10 +4210,10 @@ Action_SetProtect( { LONG result = DOSFALSE; STRPTR full_name = NULL; - LONG full_name_size; + int full_name_size; smba_file_t * file = NULL; STRPTR parent_name; - UBYTE name[MAX_FILENAME_LEN]; + TEXT name[MAX_FILENAME_LEN+1]; smba_stat_t st; int error; @@ -4108,12 +4242,12 @@ Action_SetProtect( if (TranslateUTF8) { - UBYTE encoded_name[MAX_FILENAME_LEN]; + TEXT encoded_name[MAX_FILENAME_LEN+1]; int encoded_name_len; - LONG name_len = strlen(name); + int name_len = strlen(name); encoded_name_len = encode_iso8859_1_as_utf8_string(name,name_len,NULL,0); - if(encoded_name_len < 0 || encoded_name_len >= sizeof(name)) + if(encoded_name_len < 0 || encoded_name_len >= (int)sizeof(name)) { error = ERROR_INVALID_COMPONENT_NAME; goto out; @@ -4145,7 +4279,7 @@ Action_SetProtect( goto out; } - SHOWSTRING(full_name); + D(("full_name = '%s'",escape_name(full_name))); if(smba_open(ServerData,full_name,full_name_size,open_writable,open_dont_truncate,&file,&error) < 0) { @@ -4176,11 +4310,6 @@ Action_SetProtect( */ st.is_changed_since_last_archive = ((mask & FIBF_ARCHIVE) == 0); - /* The 'system' attribute is associated with the 'pure' bit for now. */ - /* - st.is_system = ((mask & FIBF_PURE) != 0); - */ - if(smba_setattr(file,&st,NULL,&error) < 0) { error = MapErrnoToIoErr(error); @@ -4219,10 +4348,10 @@ Action_RenameObject( struct LockNode * ln; LONG result = DOSFALSE; STRPTR full_source_name = NULL; - LONG full_source_name_size; + int full_source_name_size; STRPTR full_destination_name = NULL; - LONG full_destination_name_size; - UBYTE name[MAX_FILENAME_LEN]; + int full_destination_name_size; + TEXT name[MAX_FILENAME_LEN+1]; STRPTR parent_name; int error; @@ -4252,12 +4381,12 @@ Action_RenameObject( if (TranslateUTF8) { - UBYTE encoded_name[MAX_FILENAME_LEN]; + TEXT encoded_name[MAX_FILENAME_LEN+1]; int encoded_name_len; - LONG name_len = strlen(name); + int name_len = strlen(name); encoded_name_len = encode_iso8859_1_as_utf8_string(name,name_len,NULL,0); - if(encoded_name_len < 0 || encoded_name_len >= sizeof(name)) + if(encoded_name_len < 0 || encoded_name_len >= (int)sizeof(name)) { error = ERROR_INVALID_COMPONENT_NAME; goto out; @@ -4302,12 +4431,12 @@ Action_RenameObject( if (TranslateUTF8) { - UBYTE encoded_name[MAX_FILENAME_LEN]; + TEXT encoded_name[MAX_FILENAME_LEN+1]; int encoded_name_len; - LONG name_len = strlen(name); + int name_len = strlen(name); encoded_name_len = encode_iso8859_1_as_utf8_string(name,name_len,NULL,0); - if(encoded_name_len < 0 || encoded_name_len >= sizeof(name)) + if(encoded_name_len < 0 || encoded_name_len >= (int)sizeof(name)) { error = ERROR_INVALID_COMPONENT_NAME; goto out; @@ -4345,8 +4474,8 @@ Action_RenameObject( if(error != OK) goto out; - SHOWSTRING(full_source_name); - SHOWSTRING(full_destination_name); + D(("full_source_name = '%s'",escape_name(full_source_name))); + D(("full_destination_name = '%s'",escape_name(full_destination_name))); if(smba_rename(ServerData,full_source_name,full_destination_name,&error) < 0) { @@ -4500,12 +4629,12 @@ Action_ExamineObject( if(lock == NULL) { - const UBYTE * volume_name = BADDR(VolumeNode->dol_Name); - LONG len = volume_name[0]; + const TEXT * volume_name = BADDR(VolumeNode->dol_Name); + int len = volume_name[0]; SHOWMSG("ZERO root lock"); - ASSERT( len < sizeof(fib->fib_FileName) ); + ASSERT( len < (int)sizeof(fib->fib_FileName) ); memcpy(&fib->fib_FileName[1],&volume_name[1],len); fib->fib_FileName[0] = len; @@ -4514,7 +4643,7 @@ Action_ExamineObject( fib->fib_EntryType = ST_ROOT; fib->fib_NumBlocks = 1; fib->fib_Date = VolumeNode->dol_misc.dol_volume.dol_VolumeDate; - fib->fib_DiskKey = -1; + fib->fib_DiskKey = -1; /* The ZERO lock cannot be used for directory scanning... */ fib->fib_Protection = FIBF_OTR_READ|FIBF_OTR_EXECUTE|FIBF_OTR_WRITE|FIBF_OTR_DELETE| FIBF_GRP_READ|FIBF_GRP_EXECUTE|FIBF_GRP_WRITE|FIBF_GRP_DELETE; } @@ -4540,16 +4669,16 @@ Action_ExamineObject( fib->fib_Date.ds_Minute = (seconds % (24 * 60 * 60)) / 60; fib->fib_Date.ds_Tick = (seconds % 60) * TICKS_PER_SECOND; - SHOWSTRING(ln->ln_FullName); + D(("ln->ln_FullName = '%s'",escape_name(ln->ln_FullName))); if(strcmp(ln->ln_FullName,SMB_ROOT_DIR_NAME) == SAME) { - const UBYTE * volume_name = BADDR(VolumeNode->dol_Name); - LONG len = volume_name[0]; + const TEXT * volume_name = BADDR(VolumeNode->dol_Name); + int len = volume_name[0]; SHOWMSG("root lock"); - ASSERT( len < sizeof(fib->fib_FileName) ); + ASSERT( len < (int)sizeof(fib->fib_FileName) ); memcpy(&fib->fib_FileName[1],&volume_name[1],len); fib->fib_FileName[0] = len; @@ -4562,7 +4691,11 @@ Action_ExamineObject( } else { - const UBYTE * name; + QUAD size_quad; + QUAD num_blocks_quad; + const TEXT * name; + const TEXT * final_name; + TEXT c; int name_len; int i; @@ -4587,7 +4720,7 @@ Action_ExamineObject( */ if(TranslateUTF8) { - UBYTE decoded_name[MAX_FILENAME_LEN]; + TEXT decoded_name[MAX_FILENAME_LEN+1]; int decoded_name_len; /* Try to decode the file name, translating it into ISO 8859-1 format. */ @@ -4596,7 +4729,7 @@ Action_ExamineObject( /* Decoding error occured, or the decoded name would be longer than * buffer would allow? */ - if(decoded_name_len < 0 || decoded_name_len >= sizeof(fib->fib_FileName)) + if(decoded_name_len < 0 || decoded_name_len >= (int)sizeof(fib->fib_FileName)) { error = ERROR_INVALID_COMPONENT_NAME; goto out; @@ -4614,7 +4747,7 @@ Action_ExamineObject( else { /* Will the name fit? */ - if(name_len >= sizeof(fib->fib_FileName)) + if(name_len >= (int)sizeof(fib->fib_FileName)) { error = ERROR_INVALID_COMPONENT_NAME; goto out; @@ -4630,16 +4763,48 @@ Action_ExamineObject( { if(!TranslateBName(fib->fib_FileName,M2A)) { + D(("name contains unacceptable characters")); + error = ERROR_INVALID_COMPONENT_NAME; goto out; } } } + /* Check if this is a usable Amiga file or directory name. */ + for(i = 0, final_name = &fib->fib_FileName[1] ; i < name_len ; i++) + { + c = final_name[i]; + + /* This should be a printable character and none of + * the characters reserved by the file system which + * should not appear in a file/directory name. + */ + if((c < ' ' && c != '\t') || (128 <= c && c < 160) || c == '/' || c == ':' || c == SMB_PATH_SEPARATOR) + { + D(("name contains unacceptable characters")); + + error = ERROR_INVALID_COMPONENT_NAME; + goto out; + } + } + + /* We pretend that the volume uses 512 bytes per + * block (or in SMB terms: the sector size is + * 512 bytes). The conversion is a bit elaborate + * here... + */ + size_quad.Low = st.size_low; + size_quad.High = st.size_high; + + /* Round up when dividing by 512. */ + add_64_plus_32_to_64(&size_quad,511,&num_blocks_quad); + divide_64_by_32(&num_blocks_quad,512,&num_blocks_quad); + fib->fib_DirEntryType = st.is_dir ? ST_USERDIR : ST_FILE; fib->fib_EntryType = fib->fib_DirEntryType; - fib->fib_NumBlocks = (st.size + 511) / 512; - fib->fib_Size = st.size; + fib->fib_NumBlocks = num_blocks_quad.Low; + fib->fib_Size = truncate_64_bit_position(&size_quad); fib->fib_Protection = FIBF_OTR_READ|FIBF_OTR_EXECUTE|FIBF_OTR_WRITE|FIBF_OTR_DELETE| FIBF_GRP_READ|FIBF_GRP_EXECUTE|FIBF_GRP_WRITE|FIBF_GRP_DELETE; @@ -4652,11 +4817,6 @@ Action_ExamineObject( if(NOT st.is_changed_since_last_archive) fib->fib_Protection |= FIBF_ARCHIVE; - /* - if(st.is_system) - fib->fib_Protection |= FIBF_PURE; - */ - if(NOT st.is_dir) fib->fib_DiskKey = -1; } @@ -4683,23 +4843,27 @@ Action_ExamineObject( /****************************************************************************/ +/* Check if the name is acceptable as an Amiga file name. */ STATIC BOOL -NameIsAcceptable(const UBYTE * name,LONG max_len) +name_is_acceptable(const TEXT * name) { BOOL result = FALSE; - UBYTE c; + TEXT c; - /* This takes care of "." and "..". */ - if(name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0'))) + c = name[0]; + + /* Empty names are not acceptable. */ + if(c == '\0') goto out; - /* Now for embedded '/', ':' and '\' characters and - * names that just don't want to fit. - */ + /* This takes care of "." and "..". */ + if(c == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0'))) + goto out; + + /* Now for embedded '/', ':' and '\' characters. */ while((c = (*name++)) != '\0') { - max_len--; - if(max_len == 0 || c == '/' || c == ':' || c == SMB_PATH_SEPARATOR) + if(c == '/' || c == ':' || c == SMB_PATH_SEPARATOR) goto out; } @@ -4717,64 +4881,129 @@ dir_scan_callback_func_exnext( struct FileInfoBlock * fib, int unused_fpos, int nextpos, - const UBYTE * name, + const TEXT * name, int eof, smba_stat_t * st) { + TEXT * final_file_name; int result = 0; - LONG name_len; + int name_len; + int i; LONG seconds; + TEXT c; + QUAD size_quad; + QUAD num_blocks_quad; ENTER(); - D((" '%s'",name)); - D((" is_dir=%ld is_read_only=%ld is_hidden=%ld size=%ld", - st->is_dir,st->is_read_only,st->is_hidden,st->size)); - D((" nextpos=%ld eof=%ld",nextpos,eof)); + #if DEBUG + { + QUAD st_size_quad; + + st_size_quad.Low = st->size_low; + st_size_quad.High = st->size_high; + + D((" '%s'",escape_name(name))); + D((" is_dir=%ld is_read_only=%ld is_hidden=%ld size=%s", st->is_dir,st->is_read_only,st->is_hidden,convert_quad_to_string(&st_size_quad))); + D((" nextpos=%ld eof=%ld",nextpos,eof)); + } + #endif /* DEBUG */ /* Skip file and drawer names that we wouldn't be * able to handle in the first place. */ - if(!NameIsAcceptable(name,sizeof(fib->fib_FileName)) || (st->is_hidden && OmitHidden)) + if(!name_is_acceptable(name)) + { + D((" name is not acceptable")); goto out; + } + + if(st->is_hidden && OmitHidden) + { + D((" ignoring hidden directory entry")); + goto out; + } name_len = strlen(name); if(TranslateUTF8) { - UBYTE decoded_name[MAX_FILENAME_LEN]; + TEXT decoded_name[MAX_FILENAME_LEN+1]; int decoded_name_len; decoded_name_len = decode_utf8_as_iso8859_1_string(name,name_len,NULL,0); /* Skip file names which we could not represent. */ - if(decoded_name_len < 0 || decoded_name_len >= (int)sizeof(fib->fib_FileName)) + if(decoded_name_len < 0) + { + D((" name cannot be decoded")); goto out; + } + + if(decoded_name_len >= (int)sizeof(fib->fib_FileName)) + { + D((" decoded name is too long (%ld >= %ld)",decoded_name_len, sizeof(fib->fib_FileName))); + goto out; + } decoded_name_len = decode_utf8_as_iso8859_1_string(name,name_len,decoded_name,sizeof(decoded_name)); fib->fib_FileName[0] = decoded_name_len; memcpy(&fib->fib_FileName[1],decoded_name,decoded_name_len); + + name_len = decoded_name_len; } else { /* Skip file names which we could not represent. */ if(name_len >= (int)sizeof(fib->fib_FileName)) + { + D((" name is too long (%ld >= %ld)",name_len, sizeof(fib->fib_FileName))); goto out; + } ConvertCString(fib->fib_FileName,sizeof(fib->fib_FileName),name,name_len); if(TranslateNames) { if(!TranslateBName(fib->fib_FileName,M2A)) + { + D((" name cannot be translated")); goto out; + } } } + /* Check if this is a usable Amiga file or directory name. */ + for(i = 0, final_file_name = &fib->fib_FileName[1] ; i < name_len ; i++) + { + c = final_file_name[i]; + + /* This should be a printable character and none of + * the characters reserved by the file system which + * should not appear in a file/directory name. + */ + if((c < ' ' && c != '\t') || (128 <= c && c < 160) || c == '/' || c == ':' || c == SMB_PATH_SEPARATOR) + { + D((" final name contains unacceptable characters")); + goto out; + } + } + + D((" final name = '%b'", MKBADDR(fib->fib_FileName))); + + /* Convert the size of the file into blocks, with 512 bytes per block. */ + size_quad.Low = st->size_low; + size_quad.High = st->size_high; + + /* Round up when dividing by 512. */ + add_64_plus_32_to_64(&size_quad,511,&num_blocks_quad); + divide_64_by_32(&num_blocks_quad,512,&num_blocks_quad); + fib->fib_DirEntryType = st->is_dir ? ST_USERDIR : ST_FILE; fib->fib_EntryType = fib->fib_DirEntryType; - fib->fib_NumBlocks = (st->size + 511) / 512; - fib->fib_Size = st->size; + fib->fib_NumBlocks = num_blocks_quad.Low; + fib->fib_Size = truncate_64_bit_position(&size_quad); fib->fib_Protection = FIBF_OTR_READ|FIBF_OTR_EXECUTE|FIBF_OTR_WRITE|FIBF_OTR_DELETE| FIBF_GRP_READ|FIBF_GRP_EXECUTE|FIBF_GRP_WRITE|FIBF_GRP_DELETE; @@ -4782,16 +5011,12 @@ dir_scan_callback_func_exnext( fib->fib_Protection ^= (FIBF_OTR_DELETE|FIBF_GRP_DELETE|FIBF_DELETE); /* Careful: the 'archive' attribute has exactly the opposite - * meaning in the Amiga and the SMB worlds. + * meaning in the Amiga (= was archived) and the SMB + * worlds (= needs to be archived), respectively. */ if(NOT st->is_changed_since_last_archive) fib->fib_Protection |= FIBF_ARCHIVE; - /* - if(st->is_system) - fib->fib_Protection |= FIBF_PURE; - */ - /* If modification time is 0 use creation time instead (cyfm 2009-03-18). */ seconds = (st->mtime == 0 ? st->ctime : st->mtime) - UNIX_TIME_OFFSET - GetTimeZoneDelta(); if(seconds < 0) @@ -4899,8 +5124,8 @@ struct ExAllContext { struct ExAllData * ec_Last; struct ExAllData * ec_Next; - ULONG ec_BytesLeft; - ULONG ec_MinSize; + int ec_BytesLeft; + int ec_MinSize; struct ExAllControl * ec_Control; ULONG ec_Type; LONG ec_Error; @@ -4912,61 +5137,156 @@ dir_scan_callback_func_exall( struct ExAllContext * ec, int unused_fpos, int nextpos, - const UBYTE * name, + const TEXT * name, int eof, smba_stat_t * st) { - UBYTE decoded_name[MAX_FILENAME_LEN]; + TEXT decoded_name[MAX_FILENAME_LEN+1]; BOOL ignore_this_entry = FALSE; + int name_len = -1; int result = 0; ENTER(); - D((" '%s'",name)); - D((" is_dir=%ld is_read_only=%ld is_hidden=%ld size=%ld", - st->is_dir,st->is_read_only,st->is_hidden,st->size)); - D((" nextpos=%ld eof=%ld",nextpos,eof)); - - /* If necessary, translate the name of the file first, so that we - * can decide early on whether or not it should show up in a - * directory listing. This filters out, for example, files using - * characters which are not usable on the Amiga because they fall - * outside the 8 bit character set used. - */ - if(TranslateUTF8) + #if DEBUG { - LONG name_len = strlen(name); - int decoded_name_len; + QUAD st_size_quad; - decoded_name_len = decode_utf8_as_iso8859_1_string(name,name_len,NULL,0); - if(decoded_name_len < 0 || decoded_name_len >= MAX_FILENAME_LEN) + st_size_quad.Low = st->size_low; + st_size_quad.High = st->size_high; + + D((" '%s'",escape_name(name))); + D((" is_dir=%ld is_read_only=%ld is_hidden=%ld size=%s", st->is_dir,st->is_read_only,st->is_hidden,convert_quad_to_string(&st_size_quad))); + D((" nextpos=%ld eof=%ld",nextpos,eof)); + } + #endif /* DEBUG */ + + /* Skip file and drawer names that we wouldn't be + * able to handle in the first place. + */ + if (!name_is_acceptable(name)) + { + D((" name is not acceptable")); + ignore_this_entry = TRUE; + } + else if (st->is_hidden && OmitHidden) + { + D((" ignoring hidden directory entry")); + ignore_this_entry = TRUE; + } + else + { + /* If necessary, translate the name of the file first, so that we + * can decide early on whether or not it should show up in a + * directory listing. This filters out, for example, files using + * characters which are not usable on the Amiga because they fall + * outside the 8 bit character set used. + */ + if(TranslateUTF8) { - ignore_this_entry = TRUE; + int decoded_name_len; + + name_len = strlen(name); + + decoded_name_len = decode_utf8_as_iso8859_1_string(name,name_len,NULL,0); + + /* Skip file names which we could not represent. */ + if(decoded_name_len < 0) + { + D((" name cannot be decoded")); + ignore_this_entry = TRUE; + } + else if (decoded_name_len > MAX_FILENAME_LEN) + { + D((" decoded name is too long (%ld > %ld)",decoded_name_len, MAX_FILENAME_LEN)); + ignore_this_entry = TRUE; + } + else + { + decode_utf8_as_iso8859_1_string(name,name_len,decoded_name,sizeof(decoded_name)); + + /* Use the decoded replacement name. */ + name = decoded_name; + name_len = decoded_name_len; + } } - else + else if (TranslateNames) { - decode_utf8_as_iso8859_1_string(name,name_len,decoded_name,sizeof(decoded_name)); + name_len = strlen(name); + if (name_len > MAX_FILENAME_LEN) + { + D((" name is too long (%ld > %ld)",name_len, MAX_FILENAME_LEN)); + ignore_this_entry = TRUE; + } + else + { + /* We need to make a copy of the original name, because + * the translation will modify what is passed to it. + */ + memcpy(decoded_name,name,name_len+1); - /* Use the decoded replacement name. */ - name = decoded_name; + if(TranslateCName(decoded_name,M2A)) + { + /* Use the translated replacement name. */ + name = decoded_name; + } + else + { + D((" name cannot be translated")); + ignore_this_entry = TRUE; + } + } + } + } + + /* Check if this is a usable Amiga file or directory name. */ + if(!ignore_this_entry) + { + TEXT c; + int i; + + if(name_len == -1) + name_len = strlen(name); + + for(i = 0 ; i < name_len ; i++) + { + c = name[i]; + + /* This should be a printable character and none of + * the characters reserved by the file system which + * should not appear in a file/directory name. + */ + if((c < ' ' && c != '\t') || (128 <= c && c < 160) || c == '/' || c == ':' || c == SMB_PATH_SEPARATOR) + { + D((" final name contains unacceptable characters")); + + ignore_this_entry = TRUE; + break; + } } } /* Skip file and drawer names that we wouldn't be * able to handle in the first place. */ - if(!ignore_this_entry && NameIsAcceptable((STRPTR)name,MAX_FILENAME_LEN) && NOT (st->is_hidden && OmitHidden)) + if(!ignore_this_entry) { ULONG type = ec->ec_Type; struct ExAllData * ed; - BOOL take_it = TRUE; - ULONG size; + int ed_size; - size = (ec->ec_MinSize + strlen(name)+1 + 3) & ~3UL; - SHOWVALUE(size); - if(size > ec->ec_BytesLeft) + if(name_len == -1) + name_len = strlen(name); + + /* Figure out how large this entry needs to be, and + * if necessary stop processing if there is not enough + * room left to store it. + */ + ed_size = ec->ec_MinSize + name_len+1; + + if(ec->ec_Next == NULL || ed_size > ec->ec_BytesLeft) { - D(("size %ld > ec->ec_BytesLeft %ld",size,ec->ec_BytesLeft)); + D(("Not enough room to return this entry: size %ld > ec->ec_BytesLeft %ld",ed_size,ec->ec_BytesLeft)); /* If this is the first directory entry, * stop the entire process before it has @@ -4974,13 +5294,13 @@ dir_scan_callback_func_exall( */ if(ec->ec_FirstAttempt) { - SHOWMSG("this was the first read attempt."); + SHOWMSG("this was the first read attempt -- aborting"); ec->ec_Control->eac_Entries = 0; ec->ec_Error = ERROR_NO_FREE_STORE; } else { - SHOWMSG("try again"); + SHOWMSG("the caller should try again"); ec->ec_Error = 0; } @@ -4988,23 +5308,31 @@ dir_scan_callback_func_exall( goto out; } + /* Fill in this entry. */ ed = ec->ec_Next; + /* Until we know better, assume that this will be + * the last list entry. + */ ed->ed_Next = NULL; + + /* Copy the name, including the terminating NUL byte. */ ed->ed_Name = (STRPTR)(((ULONG)ed) + ec->ec_MinSize); - strcpy(ed->ed_Name,name); - - if(!TranslateUTF8 && TranslateNames) - { - if(!TranslateCName(ed->ed_Name,M2A)) - take_it = FALSE; - } + memcpy(ed->ed_Name,name,name_len+1); + /* Fill in as many records as were requested. */ if(type >= ED_TYPE) ed->ed_Type = st->is_dir ? ST_USERDIR : ST_FILE; if(type >= ED_SIZE) - ed->ed_Size = st->size; + { + QUAD size_quad; + + size_quad.Low = st->size_low; + size_quad.High = st->size_high; + + ed->ed_Size = truncate_64_bit_position(&size_quad); + } if(type >= ED_PROTECTION) { @@ -5019,11 +5347,6 @@ dir_scan_callback_func_exall( */ if(NOT st->is_changed_since_last_archive) ed->ed_Prot |= FIBF_ARCHIVE; - - /* - if(st->is_system) - ed->ed_Prot |= FIBF_PURE; - */ } if(type >= ED_DATE) @@ -5048,17 +5371,18 @@ dir_scan_callback_func_exall( if(ec->ec_Control->eac_MatchString != NULL) { - SHOWMSG("checking against match string"); + D(("checking name against match string '%s'", ec->ec_Control->eac_MatchString)); + if(NOT MatchPatternNoCase(ec->ec_Control->eac_MatchString,ed->ed_Name)) { - SHOWMSG("does not match"); - take_it = FALSE; + SHOWMSG("name does not match"); + ignore_this_entry = TRUE; } } - if(take_it && ec->ec_Control->eac_MatchFunc != NULL) + if(!ignore_this_entry && ec->ec_Control->eac_MatchFunc != NULL) { - SHOWMSG("calling match func"); + SHOWMSG("checking if match function accepts the entry"); /* NOTE: the order of the parameters passed to the match hook * function can be somewhat confusing. For standard @@ -5071,26 +5395,39 @@ dir_scan_callback_func_exall( */ if(NOT CallHookPkt(ec->ec_Control->eac_MatchFunc,&type,ed)) { - SHOWMSG("does not match"); - take_it = FALSE; + SHOWMSG("match function rejected the entry"); + + ignore_this_entry = TRUE; } } - if(take_it) + if(!ignore_this_entry) { SHOWMSG("registering new entry"); + /* Link the previous entry to the current one. */ if(ec->ec_Last != NULL) ec->ec_Last->ed_Next = ed; + /* All entries need to begin on a word-aligned address, + * which means that we need to pad the entry size to + * a multiple of 2. + */ + if((ed_size % 2) > 0) + ed_size++; + + /* Note: due to the padding byte the number of bytes + * left may become negative. + */ + ec->ec_BytesLeft -= ed_size; + + ec->ec_Next = ec->ec_BytesLeft > 0 ? (struct ExAllData *)(((ULONG)ed) + ed_size) : NULL; ec->ec_Last = ed; - ec->ec_Next = (struct ExAllData *)(((ULONG)ed) + size); - ec->ec_BytesLeft -= size; + ec->ec_Control->eac_Entries++; SHOWVALUE(ec->ec_Last->ed_Next); - SHOWVALUE(ed->ed_Name); - SHOWVALUE(ed->ed_Comment); + D(("ed->ed_Name = '%s'", ed->ed_Name)); } } @@ -5108,7 +5445,7 @@ STATIC LONG Action_ExamineAll( struct FileLock * lock, struct ExAllData * ed, - ULONG size, + LONG size, ULONG type, struct ExAllControl * eac, LONG * error_ptr) @@ -5128,7 +5465,7 @@ Action_ExamineAll( eac->eac_Entries = 0; - if(size < sizeof(ed->ed_Next)) + if(size < (LONG)sizeof(ed->ed_Next)) { SHOWMSG("buffer is far too short."); error = ERROR_NO_FREE_STORE; @@ -5314,10 +5651,10 @@ Action_Find( LONG result = DOSFALSE; STRPTR parent_path = NULL; STRPTR full_name = NULL; - LONG full_name_size; + int full_name_size; struct FileNode * fn = NULL; STRPTR parent_name; - UBYTE name[MAX_FILENAME_LEN]; + TEXT name[MAX_FILENAME_LEN+1]; BOOL create_new_file; int error; @@ -5355,12 +5692,12 @@ Action_Find( if (TranslateUTF8) { - UBYTE encoded_name[MAX_FILENAME_LEN]; + TEXT encoded_name[MAX_FILENAME_LEN+1]; int encoded_name_len; - LONG name_len = strlen(name); + int name_len = strlen(name); encoded_name_len = encode_iso8859_1_as_utf8_string(name,name_len,NULL,0); - if(encoded_name_len < 0 || encoded_name_len >= sizeof(name)) + if(encoded_name_len < 0 || encoded_name_len >= (int)sizeof(name)) { error = ERROR_INVALID_COMPONENT_NAME; goto out; @@ -5379,7 +5716,7 @@ Action_Find( } } - if(IsReservedName(FilePart(name))) + if(is_reserved_name(FilePart(name))) { error = ERROR_OBJECT_NOT_FOUND; goto out; @@ -5413,7 +5750,7 @@ Action_Find( if(error != OK) goto out; - SHOWSTRING(full_name); + D(("full_name = '%s'",escape_name(full_name))); if(action == ACTION_FINDOUTPUT) { @@ -5464,10 +5801,9 @@ Action_Find( if(create_new_file) { int ignored_error; - smba_stat_t st; smba_file_t * dir; STRPTR base_name; - LONG i; + int i; if(WriteProtected) { @@ -5502,7 +5838,7 @@ Action_Find( } SHOWMSG("creating a file; finding parent path first"); - SHOWSTRING(parent_path); + D(("parent_path = '%s'",escape_name(parent_path))); if(smba_open(ServerData,parent_path,strlen(full_name)+3,open_read_only,open_dont_truncate,&dir,&error) < 0) { @@ -5510,13 +5846,10 @@ Action_Find( goto out; } - /* Only one attribute counts: the file should not be write protected. */ - memset(&st,0,sizeof(st)); - SHOWMSG("now trying to create the file"); - SHOWSTRING(base_name); + D(("base_name = '%s'",escape_name(base_name))); - if(smba_create(dir,base_name,&st,&error) < 0) + if(smba_create(dir,base_name,&error) < 0) { SHOWMSG("didn't work."); SHOWVALUE(error); @@ -5580,7 +5913,7 @@ Action_Read( if(length > 0) { - result = smba_read(fn->fn_File,mem,length,fn->fn_Offset,&error); + result = smba_read(fn->fn_File,mem,length,&fn->fn_OffsetQuad,&error); if(result < 0) { error = MapErrnoToIoErr(result); @@ -5589,7 +5922,7 @@ Action_Read( goto out; } - fn->fn_Offset += result; + add_64_plus_32_to_64(&fn->fn_OffsetQuad, result, &fn->fn_OffsetQuad); } out: @@ -5624,7 +5957,7 @@ Action_Write( if(length > 0) { - result = smba_write(fn->fn_File,mem,length,fn->fn_Offset,&error); + result = smba_write(fn->fn_File,mem,length,&fn->fn_OffsetQuad,&error); if(result < 0) { error = MapErrnoToIoErr(error); @@ -5633,7 +5966,7 @@ Action_Write( goto out; } - fn->fn_Offset += result; + add_64_plus_32_to_64(&fn->fn_OffsetQuad, result, &fn->fn_OffsetQuad); } out: @@ -5673,10 +6006,11 @@ Action_Seek( LONG mode, LONG * error_ptr) { - LONG previous_position = fn->fn_Offset; + QUAD previous_position_quad = fn->fn_OffsetQuad; + QUAD reference_position_quad; + QUAD new_position_quad; LONG result = -1; smba_stat_t st; - LONG offset; int error; ENTER(); @@ -5685,12 +6019,15 @@ Action_Seek( { case OFFSET_BEGINNING: - offset = position; + reference_position_quad.Low = 0; + reference_position_quad.High = 0; + break; case OFFSET_CURRENT: - offset = fn->fn_Offset + position; + reference_position_quad = fn->fn_OffsetQuad; + break; case OFFSET_END: @@ -5701,7 +6038,9 @@ Action_Seek( goto out; } - offset = st.size + position; + reference_position_quad.Low = st.size_low; + reference_position_quad.High = st.size_high; + break; default: @@ -5710,17 +6049,37 @@ Action_Seek( goto out; } - if(offset < 0) + if(position < 0) { - error = ERROR_SEEK_ERROR; - goto out; + QUAD position_quad; + + position_quad.Low = -position; + position_quad.High = 0; + + /* We cannot seek back beyond the beginning of the file. */ + if(compare_64_to_64(&reference_position_quad,&position_quad) < 0) + { + error = ERROR_SEEK_ERROR; + goto out; + } + + subtract_64_from_64_to_64(&reference_position_quad,&position_quad,&new_position_quad); + } + else + { + /* Careful, we need to check for overflow, too. */ + if(add_64_plus_32_to_64(&reference_position_quad,position,&new_position_quad) > 0) + { + error = ERROR_SEEK_ERROR; + goto out; + } } error = OK; - fn->fn_Offset = offset; + fn->fn_OffsetQuad = new_position_quad; - result = previous_position; + result = truncate_64_bit_position(&previous_position_quad); out: @@ -5739,43 +6098,41 @@ Action_SetFileSize( LONG mode, LONG * error_ptr) { + QUAD previous_position_quad = fn->fn_OffsetQuad; + QUAD reference_position_quad; + QUAD new_position_quad; LONG result = -1; smba_stat_t st; int error; - long offset; - dword size; ENTER(); - if(WriteProtected) - { - error = ERROR_DISK_WRITE_PROTECTED; - goto out; - } - - if(smba_getattr(fn->fn_File,&st,&error) < 0) - { - error = MapErrnoToIoErr(error); - goto out; - } - - offset = fn->fn_Offset; - switch(mode) { case OFFSET_BEGINNING: - offset = position; + reference_position_quad.Low = 0; + reference_position_quad.High = 0; + break; case OFFSET_CURRENT: - offset += position; + reference_position_quad = fn->fn_OffsetQuad; + break; case OFFSET_END: - offset = st.size + position; + if(smba_getattr(fn->fn_File,&st,&error) < 0) + { + error = MapErrnoToIoErr(error); + goto out; + } + + reference_position_quad.Low = st.size_low; + reference_position_quad.High = st.size_high; + break; default: @@ -5784,24 +6141,47 @@ Action_SetFileSize( goto out; } - if(offset < 0) + if(position < 0) { - error = ERROR_SEEK_ERROR; - goto out; + QUAD position_quad; + + position_quad.Low = -position; + position_quad.High = 0; + + /* We cannot seek back beyond the beginning of the file. */ + if(compare_64_to_64(&reference_position_quad,&position_quad) < 0) + { + error = ERROR_SEEK_ERROR; + goto out; + } + + subtract_64_from_64_to_64(&reference_position_quad,&position_quad,&new_position_quad); + } + else + { + /* Careful, we need to check for overflow, too. */ + if(add_64_plus_32_to_64(&reference_position_quad,position,&new_position_quad) > 0) + { + error = ERROR_SEEK_ERROR; + goto out; + } } - size = (dword)offset; - - if(smba_setattr(fn->fn_File,NULL,&size,&error) < 0) + if(smba_setattr(fn->fn_File,NULL,&new_position_quad,&error) < 0) { error = MapErrnoToIoErr(error); goto out; } - if(fn->fn_Offset > offset) - fn->fn_Offset = offset; + error = OK; - result = offset; + /* If the current seek position reaches beyond the new + * size of the file, move it to the end of the file. + */ + if(compare_64_to_64(&fn->fn_OffsetQuad,&new_position_quad) > 0) + fn->fn_OffsetQuad = new_position_quad; + + result = truncate_64_bit_position(&previous_position_quad); out: @@ -5822,10 +6202,10 @@ Action_SetDate( { LONG result = DOSFALSE; STRPTR full_name = NULL; - LONG full_name_size; + int full_name_size; smba_file_t * file = NULL; STRPTR parent_name; - UBYTE name[MAX_FILENAME_LEN]; + TEXT name[MAX_FILENAME_LEN+1]; smba_stat_t st; LONG seconds; int error; @@ -5855,12 +6235,12 @@ Action_SetDate( if (TranslateUTF8) { - UBYTE encoded_name[MAX_FILENAME_LEN]; + TEXT encoded_name[MAX_FILENAME_LEN+1]; int encoded_name_len; - LONG name_len = strlen(name); + int name_len = strlen(name); encoded_name_len = encode_iso8859_1_as_utf8_string(name,name_len,NULL,0); - if(encoded_name_len < 0 || encoded_name_len >= sizeof(name)) + if(encoded_name_len < 0 || encoded_name_len >= (int)sizeof(name)) { error = ERROR_INVALID_COMPONENT_NAME; goto out; @@ -5890,7 +6270,7 @@ Action_SetDate( goto out; } - SHOWSTRING(full_name); + D(("full_name = '%s'",escape_name(full_name))); if(smba_open(ServerData,full_name,full_name_size,open_writable,open_dont_truncate,&file,&error) < 0) { @@ -5945,13 +6325,17 @@ Action_ExamineFH( struct FileInfoBlock * fib, LONG * error_ptr) { + QUAD size_quad; + QUAD num_blocks_quad; LONG result = DOSFALSE; + const TEXT * final_name; + TEXT c; smba_stat_t st; int error; LONG seconds; STRPTR name; - LONG name_len; - LONG i; + int name_len; + int i; ENTER(); @@ -5978,11 +6362,11 @@ Action_ExamineFH( if(TranslateUTF8) { - UBYTE decoded_name[MAX_FILENAME_LEN]; + TEXT decoded_name[MAX_FILENAME_LEN+1]; int decoded_name_len; decoded_name_len = decode_utf8_as_iso8859_1_string(name,name_len,NULL,0); - if(decoded_name_len < 0 || decoded_name_len >= sizeof(fib->fib_FileName)) + if(decoded_name_len < 0 || decoded_name_len >= (int)sizeof(fib->fib_FileName)) { error = ERROR_INVALID_COMPONENT_NAME; goto out; @@ -5992,12 +6376,16 @@ Action_ExamineFH( fib->fib_FileName[0] = decoded_name_len; memcpy(&fib->fib_FileName[1],decoded_name,decoded_name_len); + + name_len = decoded_name_len; } else { /* Will the name fit? */ - if(name_len >= sizeof(fib->fib_FileName)) + if(name_len >= (int)sizeof(fib->fib_FileName)) { + D(("name contains unacceptable characters")); + error = ERROR_INVALID_COMPONENT_NAME; goto out; } @@ -6008,16 +6396,44 @@ Action_ExamineFH( { if(!TranslateBName(fib->fib_FileName,M2A)) { + D(("name contains unacceptable characters")); + error = ERROR_INVALID_COMPONENT_NAME; goto out; } } } + /* Check if this is a usable Amiga file or directory name. */ + for(i = 0, final_name = &fib->fib_FileName[1] ; i < name_len ; i++) + { + c = final_name[i]; + + /* This should be a printable character and none of + * the characters reserved by the file system which + * should not appear in a file/directory name. + */ + if((c < ' ' && c != '\t') || (128 <= c && c < 160) || c == '/' || c == ':' || c == SMB_PATH_SEPARATOR) + { + D(("name contains unacceptable characters")); + + error = ERROR_INVALID_COMPONENT_NAME; + goto out; + } + } + + /* Convert the size of the file into blocks, with 512 bytes per block. */ + size_quad.Low = st.size_low; + size_quad.High = st.size_high; + + /* Round up when dividing by 512. */ + add_64_plus_32_to_64(&size_quad,511,&num_blocks_quad); + divide_64_by_32(&num_blocks_quad,512,&num_blocks_quad); + fib->fib_DirEntryType = ST_FILE; fib->fib_EntryType = ST_FILE; - fib->fib_NumBlocks = (st.size + 511) / 512; - fib->fib_Size = st.size; + fib->fib_NumBlocks = num_blocks_quad.Low; + fib->fib_Size = truncate_64_bit_position(&size_quad); fib->fib_DiskKey = -1; fib->fib_Protection = FIBF_OTR_READ|FIBF_OTR_EXECUTE|FIBF_OTR_WRITE|FIBF_OTR_DELETE| @@ -6032,11 +6448,6 @@ Action_ExamineFH( if(NOT st.is_changed_since_last_archive) fib->fib_Protection |= FIBF_ARCHIVE; - /* - if(st.is_system) - fib->fib_Protection |= FIBF_PURE; - */ - /* If modification time is 0 use creation time instead (cyfm 2009-03-18). */ seconds = (st.mtime == 0 ? st.ctime : st.mtime) - UNIX_TIME_OFFSET - GetTimeZoneDelta(); if(seconds < 0) @@ -6067,8 +6478,8 @@ Action_ParentFH( struct LockNode * ln = NULL; int error; STRPTR full_name; - LONG full_name_size; - LONG i; + int full_name_size; + int i; ENTER(); @@ -6114,7 +6525,7 @@ Action_ParentFH( ln->ln_FileLock.fl_Volume = MKBADDR(VolumeNode); ln->ln_FullName = full_name; - SHOWSTRING(full_name); + D(("full_name = '%s'",escape_name(full_name))); if(smba_open(ServerData,full_name,full_name_size,open_read_only,open_dont_truncate,&ln->ln_File,&error) < 0) { @@ -6150,7 +6561,7 @@ Action_CopyDirFH( BPTR result = ZERO; struct LockNode * ln = NULL; STRPTR full_name = NULL; - LONG full_name_size; + int full_name_size; int error; ENTER(); @@ -6189,7 +6600,7 @@ Action_CopyDirFH( ln->ln_FileLock.fl_Volume = MKBADDR(VolumeNode); ln->ln_FullName = full_name; - SHOWSTRING(full_name); + D(("full_name = '%s'",escape_name(full_name))); if (smba_open(ServerData,full_name,full_name_size,open_read_only,open_dont_truncate,&ln->ln_File,&error) < 0) { @@ -6275,8 +6686,8 @@ Action_RenameDisk( int error = OK; STRPTR old_name; STRPTR new_name; - const UBYTE * name; - LONG len; + const TEXT * name; + int len; ENTER(); @@ -6539,11 +6950,11 @@ Action_SetComment( { LONG result = DOSFALSE; STRPTR full_name = NULL; - LONG full_name_size; + int full_name_size; smba_file_t * file = NULL; STRPTR parent_name; - UBYTE name[MAX_FILENAME_LEN]; - UBYTE comment[80]; + TEXT name[MAX_FILENAME_LEN+1]; + TEXT comment[80]; int error; ENTER(); @@ -6571,12 +6982,12 @@ Action_SetComment( if (TranslateUTF8) { - UBYTE encoded_name[MAX_FILENAME_LEN]; + TEXT encoded_name[MAX_FILENAME_LEN+1]; int encoded_name_len; - LONG name_len = strlen(name); + int name_len = strlen(name); encoded_name_len = encode_iso8859_1_as_utf8_string(name,name_len,NULL,0); - if(encoded_name_len < 0 || encoded_name_len >= sizeof(name)) + if(encoded_name_len < 0 || encoded_name_len >= (int)sizeof(name)) { error = ERROR_INVALID_COMPONENT_NAME; goto out; @@ -6606,7 +7017,7 @@ Action_SetComment( goto out; } - SHOWSTRING(full_name); + D(("full_name = '%s'",escape_name(full_name))); if (smba_open(ServerData,full_name,full_name_size,open_writable,open_dont_truncate,&file,&error) < 0) { @@ -6762,7 +7173,7 @@ HandleFileSystem(STRPTR device_name,STRPTR volume_name,STRPTR service_name) cli = Cli(); if(NOT cli->cli_Background) { - UBYTE name[MAX_FILENAME_LEN]; + TEXT name[MAX_FILENAME_LEN+1]; LONG max_cli; LONG which; LONG i; @@ -6804,6 +7215,11 @@ HandleFileSystem(STRPTR device_name,STRPTR volume_name,STRPTR service_name) } } + /* Don't show any further error message in the shell, and + * certainly don't allocate memory for error messages which + * would have to be displayed in an error requester (which + * doesn't happen). + */ Quiet = TRUE; done = FALSE; @@ -6868,13 +7284,13 @@ HandleFileSystem(STRPTR device_name,STRPTR volume_name,STRPTR service_name) case ACTION_LOCATE_OBJECT: /* Lock,Name,Mode -> Lock */ - res1 = Action_LocateObject((struct FileLock *)BADDR(dp->dp_Arg1),(APTR)BADDR(dp->dp_Arg2),dp->dp_Arg3,&res2); + res1 = Action_LocateObject((struct FileLock *)BADDR(dp->dp_Arg1),BADDR(dp->dp_Arg2),dp->dp_Arg3,&res2); break; case ACTION_RENAME_DISK: /* Name -> Bool */ - res1 = Action_RenameDisk((UBYTE *)BADDR(dp->dp_Arg1),&res2); + res1 = Action_RenameDisk(BADDR(dp->dp_Arg1),&res2); break; case ACTION_FREE_LOCK: @@ -6886,7 +7302,7 @@ HandleFileSystem(STRPTR device_name,STRPTR volume_name,STRPTR service_name) case ACTION_DELETE_OBJECT: /* Lock,Name -> Bool */ - res1 = Action_DeleteObject((struct FileLock *)BADDR(dp->dp_Arg1),(APTR)BADDR(dp->dp_Arg2),&res2); + res1 = Action_DeleteObject((struct FileLock *)BADDR(dp->dp_Arg1),BADDR(dp->dp_Arg2),&res2); break; case ACTION_RENAME_OBJECT: @@ -6932,7 +7348,7 @@ HandleFileSystem(STRPTR device_name,STRPTR volume_name,STRPTR service_name) case ACTION_CREATE_DIR: /* Lock,Name -> Lock */ - res1 = Action_CreateDir((struct FileLock *)BADDR(dp->dp_Arg1),(APTR)BADDR(dp->dp_Arg2),&res2); + res1 = Action_CreateDir((struct FileLock *)BADDR(dp->dp_Arg1),BADDR(dp->dp_Arg2),&res2); break; case ACTION_EXAMINE_OBJECT: @@ -6982,7 +7398,7 @@ HandleFileSystem(STRPTR device_name,STRPTR volume_name,STRPTR service_name) case ACTION_SET_DATE: /* (Ignore),FileLock,Name,DateStamp(APTR) -> Bool */ - res1 = Action_SetDate((struct FileLock *)BADDR(dp->dp_Arg2),(APTR)BADDR(dp->dp_Arg3),(struct DateStamp *)dp->dp_Arg4,&res2); + res1 = Action_SetDate((struct FileLock *)BADDR(dp->dp_Arg2),BADDR(dp->dp_Arg3),(struct DateStamp *)dp->dp_Arg4,&res2); break; case ACTION_SAME_LOCK: @@ -7008,7 +7424,7 @@ HandleFileSystem(STRPTR device_name,STRPTR volume_name,STRPTR service_name) case ACTION_FINDOUTPUT: /* FileHandle,FileLock,Name -> Bool */ - res1 = Action_Find(dp->dp_Action,(struct FileHandle *)BADDR(dp->dp_Arg1),(struct FileLock *)BADDR(dp->dp_Arg2),(APTR)BADDR(dp->dp_Arg3),&res2); + res1 = Action_Find(dp->dp_Action,(struct FileHandle *)BADDR(dp->dp_Arg1),(struct FileLock *)BADDR(dp->dp_Arg2),BADDR(dp->dp_Arg3),&res2); break; case ACTION_END: @@ -7050,7 +7466,7 @@ HandleFileSystem(STRPTR device_name,STRPTR volume_name,STRPTR service_name) case ACTION_CHANGE_MODE: /* Type,Object,Mode -> Bool */ - res1 = Action_ChangeMode(dp->dp_Arg1,(APTR)BADDR(dp->dp_Arg2),dp->dp_Arg3,&res2); + res1 = Action_ChangeMode(dp->dp_Arg1,BADDR(dp->dp_Arg2),dp->dp_Arg3,&res2); break; case ACTION_COPY_DIR_FH: @@ -7139,7 +7555,7 @@ HandleFileSystem(STRPTR device_name,STRPTR volume_name,STRPTR service_name) fn = (struct FileNode *)fn->fn_MinNode.mln_Succ) { D((" name='%s'",fn->fn_FullName)); - D((" mode=%ld, offset=%ld",fn->fn_Mode,fn->fn_Offset)); + D((" mode=%ld, offset=%s",fn->fn_Mode,convert_quad_to_string(&fn->fn_OffsetQuad))); D(("")); } @@ -7193,6 +7609,36 @@ HandleFileSystem(STRPTR device_name,STRPTR volume_name,STRPTR service_name) /****************************************************************************/ +/* Convert an unsigned 64 bit integer into a string. The + * conversion uses a local static buffer and returns a pointer + * to the first digit of the string. + */ +const char * +convert_quad_to_string(const QUAD * const number) +{ + static char string[22]; /* 21 bytes should be sufficient. */ + + QUAD m = (*number); + ULONG n; + int len; + + memset(string,'\0',sizeof(string)); + + for(len = sizeof(string) - 2 ; len >= 0 ; ) + { + n = divide_64_by_32(&m,10,&m); + + string[len--] = '0' + n; + + if(m.High == 0 && m.Low == 0) + break; + } + + return(&string[len+1]); +} + +/****************************************************************************/ + /* * Copy src to string dst of size siz. At most siz-1 characters * will be copied. Always NUL terminates (unless siz == 0). diff --git a/source_code/proc.c b/source_code/proc.c index 86f62f1..34cd842 100644 --- a/source_code/proc.c +++ b/source_code/proc.c @@ -801,7 +801,7 @@ smb_request_ok_with_payload ( else if ((error = smb_valid_packet (server->transmit_buffer)) != 0) { LOG (("not a valid packet!\n")); - + (*error_ptr) = error; result = -1; } @@ -854,7 +854,7 @@ reopen_entry(struct smb_server *server, struct smb_dirent *entry,int * error_ptr { int ignored_error; - LOG (("trying to reopen file %s\n", entry->complete_path)); + LOG (("trying to reopen file '%s'\n", escape_name(entry->complete_path))); result = smb_proc_open (server, entry->complete_path, entry->len, entry->writable, FALSE, entry, error_ptr != NULL ? error_ptr : &ignored_error); } @@ -1001,7 +1001,7 @@ smb_proc_open (struct smb_server *server, const char *pathname, int len, int wri ENTER(); - SHOWSTRING(pathname); + D(("pathname = '%s'", escape_name(pathname))); if (server->protocol >= PROTOCOL_NT1) { @@ -1115,7 +1115,8 @@ smb_proc_open (struct smb_server *server, const char *pathname, int len, int wri params = smb_decode_dword(params, &end_of_file_low); (void) smb_decode_dword(params, &end_of_file_high); - entry->size = end_of_file_low; + entry->size_low = end_of_file_low; + entry->size_high = end_of_file_high; entry->opened = TRUE; entry->writable = writable; @@ -1174,7 +1175,8 @@ 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); entry->ctime = entry->atime = entry->mtime = entry->wtime = local2utc (DVAL (buf, smb_vwv2)); - entry->size = DVAL (buf, smb_vwv4); + entry->size_low = DVAL (buf, smb_vwv4); + entry->size_high = 0; entry->opened = TRUE; entry->writable = writable; @@ -1269,43 +1271,6 @@ 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, off_t offset, long count, char *data, int * error_ptr) -{ - char *buf = server->transmit_buffer; - int result; - - ASSERT( count <= 65535 ); - - retry: - - smb_setup_header (server, SMBreadbraw, 8, 0); - - WSET (buf, smb_vwv0, finfo->fileid); - DSET (buf, smb_vwv1, offset); - WSET (buf, smb_vwv3, count); /* maxcnt */ - WSET (buf, smb_vwv4, 0); /* mincnt */ - DSET (buf, smb_vwv5, 0); /* timeout */ - WSET (buf, smb_vwv7, 0); /* reserved */ - - result = smb_request_read_raw (server, data, count, error_ptr); - if (result < 0) - { - if (smb_retry (server)) - { - if(reopen_entry(server,finfo,NULL) < 0) - LOG(("that didn't work.\n")); - else - 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) { @@ -1346,201 +1311,7 @@ smb_proc_write (struct smb_server *server, struct smb_dirent *finfo, off_t offse } int -smb_proc_write_raw (struct smb_server *server, struct smb_dirent *finfo, off_t offset, 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) - * = 25 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' - 59 for the payload. - */ - max_len = server->max_buffer_size; - if(max_len > 65535) - max_len = 65535; - - max_len -= 59; - - 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, server->protocol > PROTOCOL_COREPLUS ? 12 : 11, len); - - WSET (buf, smb_vwv0, finfo->fileid); - DSET (buf, smb_vwv1, count); - DSET (buf, smb_vwv3, offset); - 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)); - } - 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)) - { - if(reopen_entry(server,finfo,NULL) < 0) - { - LOG(("that didn't work.\n")); - goto out; - } - else - { - 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)) - { - if(reopen_entry(server,finfo,NULL) < 0) - { - LOG(("that didn't work.\n")); - goto out; - } - else - { - 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, off_t offset, long count, const char *data, int * error_ptr) +smb_proc_writex (struct smb_server *server, struct smb_dirent *finfo, const QUAD * const offset_quad, long count, const char *data, int * error_ptr) { char *buf = server->transmit_buffer; int result; @@ -1557,17 +1328,17 @@ smb_proc_writex (struct smb_server *server, struct smb_dirent *finfo, off_t offs BSET (buf, smb_vwv0, 0xFF); /* AndXCommand/AndXReserved - no additional SMB commands provided */ WSET (buf, smb_vwv1, 0); /* AndXOffset */ WSET (buf, smb_vwv2, finfo->fileid); /* fid */ - DSET (buf, smb_vwv3, offset); /* offset */ + DSET (buf, smb_vwv3, offset_quad->Low); /* offset */ DSET (buf, smb_vwv5, 0); /* timeout */ WSET (buf, smb_vwv7, 0); /* write mode */ WSET (buf, smb_vwv8, 0); /* remaining */ WSET (buf, smb_vwv9, 0); /* reserved */ WSET (buf, smb_vwv10, count); /* data length */ - + if(server->protocol >= PROTOCOL_NT1) { WSET (buf, smb_vwv11, 64+2); /* data offset */ - DSET (buf, smb_vwv12, 0); /* high offset */ + DSET (buf, smb_vwv12, offset_quad->High); /* high offset */ } else { @@ -1579,7 +1350,8 @@ smb_proc_writex (struct smb_server *server, struct smb_dirent *finfo, off_t offs WSET (p, 0, 1+count); p += 2; /* Byte count (1 pad byte + data bytes) */ (*p) = 0; /* Padding byte that must be ignored */ - LOG(("requesting SMBwriteX\n")); + + LOG(("requesting SMBwriteX: offset=%s, count=%ld\n", convert_quad_to_string(offset_quad), count)); result = smb_request_ok_with_payload (server, SMBwriteX, 6, 0, NULL, data, count, error_ptr); if (result < 0) @@ -1608,7 +1380,7 @@ smb_proc_writex (struct smb_server *server, struct smb_dirent *finfo, off_t offs } int -smb_proc_readx (struct smb_server *server, struct smb_dirent *finfo, off_t offset, long count, char *data, int * error_ptr) +smb_proc_readx (struct smb_server *server, struct smb_dirent *finfo, const QUAD * const offset_quad, long count, char *data, int * error_ptr) { char *buf = server->transmit_buffer; int result; @@ -1625,20 +1397,20 @@ smb_proc_readx (struct smb_server *server, struct smb_dirent *finfo, off_t offse BSET (buf, smb_vwv0, 0xFF); /* AndXCommand/AndXReserved - no additional SMB commands provided */ WSET (buf, smb_vwv1, 0); /* AndXOffset */ WSET (buf, smb_vwv2, finfo->fileid); /* fid */ - DSET (buf, smb_vwv3, offset); /* offset */ + DSET (buf, smb_vwv3, offset_quad->Low); /* offset */ WSET (buf, smb_vwv5, count); /* MaxCountOfBytesToReturn */ WSET (buf, smb_vwv6, 0); /* MinCountOfBytesToReturn */ DSET (buf, smb_vwv7, 0); /* timeout */ WSET (buf, smb_vwv9, 0); /* remaining */ if(server->protocol >= PROTOCOL_NT1) - DSET (buf, smb_vwv10, 0); /* OffsetHigh */ + DSET (buf, smb_vwv10, offset_quad->High); /* OffsetHigh */ /* Now for the data portion of the message */ WSET (p, 0, 0); /* Byte count */ - LOG(("requesting SMBreadX: offset=%ld, count=%ld\n", offset, count)); + LOG(("requesting SMBreadX: offset=%s, count=%ld\n", convert_quad_to_string(offset_quad), count)); result = smb_request_ok_with_payload (server, SMBreadX, 7, 0, data, NULL, count, error_ptr); if (result < 0) @@ -1654,12 +1426,12 @@ smb_proc_readx (struct smb_server *server, struct smb_dirent *finfo, off_t offse else { word data_length; - + p = SMB_VWV (server->transmit_buffer); smb_decode_word (p + 10, &data_length); - + LOG(("number of bytes read = %ld\n", data_length)); - + result = data_length; } @@ -1820,7 +1592,7 @@ smb_proc_mkdir (struct smb_server *server, const char *path, const int len, int WSET (outbuf, smb_msrcnt, 0); /* MaxSetupCount+Reserved1 */ WSET (outbuf, smb_flags, 0); /* Flags */ DSET (outbuf, smb_timeout, 0); /* Timeout */ - /* Reserved2 */ + /* Reserved2 */ WSET (outbuf, smb_pscnt, WVAL (outbuf, smb_tpscnt)); /* ParameterCount */ WSET (outbuf, smb_psoff, ((SMB_BUF (outbuf) + 3) - outbuf) - NETBIOS_HEADER_SIZE); /* ParameterOffset */ WSET (outbuf, smb_dscnt, 0); /* DataCount */ @@ -1975,7 +1747,8 @@ smb_decode_dirent (char *p, struct smb_dirent *entry) entry->attr = BVAL (p, 0); entry->mtime = entry->atime = entry->ctime = entry->wtime = date_dos2unix (WVAL (p, 1), WVAL (p, 3)); - entry->size = DVAL (p, 5); + entry->size_low = DVAL (p, 5); + entry->size_high = 0; name_size = 13; @@ -1986,7 +1759,7 @@ smb_decode_dirent (char *p, struct smb_dirent *entry) entry->complete_path[name_size] = '\0'; - LOG (("path = %s\n", entry->complete_path)); + LOG (("path = '%s'\n", escape_name(entry->complete_path))); #if DEBUG { @@ -2031,7 +1804,7 @@ smb_proc_readdir_short (struct smb_server *server, char *path, int fpos, int cac strcat (mask, "\\*.*"); LOG (("SMB call readdir %ld @ %ld\n", cache_size, fpos)); - LOG ((" mask = %s\n", mask)); + LOG ((" mask = '%s'\n", escape_name(mask))); buf = server->transmit_buffer; @@ -2265,8 +2038,10 @@ smb_decode_long_dirent (char *p, struct smb_dirent *finfo, int level, int * entr if (finfo != NULL) { + const char * name; int name_len; - + + name = &p[27]; name_len = BVAL (p, 26); SHOWVALUE(name_len); @@ -2280,24 +2055,24 @@ smb_decode_long_dirent (char *p, struct smb_dirent *finfo, int level, int * entr break; } - finfo->ctime = date_dos2unix (WVAL (p, 6), WVAL (p, 4)); - finfo->atime = date_dos2unix (WVAL (p, 10), WVAL (p, 8)); - finfo->mtime = date_dos2unix (WVAL (p, 14), WVAL (p, 12)); - finfo->wtime = finfo->mtime; - finfo->size = DVAL (p, 16); - finfo->attr = WVAL (p, 24); - finfo->len = name_len; - - /* Don't return names with NUL bytes. */ - if(memchr(&p[27], '\0', name_len) != NULL) + if(name_len == 0) { - SHOWMSG("name contains NUL bytes (skipping it)"); + D(("name length == 0 (skipping it)")); success = FALSE; break; } - memcpy(finfo->complete_path, &p[27], name_len); + finfo->ctime = date_dos2unix (WVAL (p, 6), WVAL (p, 4)); + finfo->atime = date_dos2unix (WVAL (p, 10), WVAL (p, 8)); + finfo->mtime = date_dos2unix (WVAL (p, 14), WVAL (p, 12)); + finfo->wtime = finfo->mtime; + finfo->size_low = DVAL (p, 16); + finfo->size_high = DVAL (p, 16); + finfo->attr = WVAL (p, 24); + finfo->len = name_len; + + memcpy(finfo->complete_path, name, name_len); finfo->complete_path[name_len] = '\0'; } @@ -2311,51 +2086,51 @@ smb_decode_long_dirent (char *p, struct smb_dirent *finfo, int level, int * entr if (finfo != NULL) { + dword size_low,size_high; int name_len; - time_t swap; p += 4; /* next entry offset */ - + p += 4; /* fileindex */ - + finfo->ctime = convert_long_date_to_time_t(p); p += 8; - + finfo->atime = convert_long_date_to_time_t(p); p += 8; - + finfo->wtime = convert_long_date_to_time_t(p); p += 8; - + finfo->mtime = convert_long_date_to_time_t(p); p += 8; - + /* If the modification time is not set, try to * substitute the write time for it. */ if(finfo->mtime == 0) finfo->mtime = finfo->wtime; - /* Swap last modification time and last write time. */ - swap = finfo->mtime; - finfo->mtime = finfo->wtime; - finfo->wtime = swap; - - /* Note: size is a 64 bit integer, we only use the least significant 32 bits. */ - finfo->size = DVAL (p, 0); + size_low = DVAL (p, 0); + size_high = DVAL (p, 4); p += 8; - + + finfo->size_low = size_low; + finfo->size_high = size_high; + p += 8; /* alloc size */ - + finfo->attr = DVAL (p, 0); p += 4; - + name_len = DVAL (p, 0); p += 4; /* Skip directory entries whose names we cannot store. */ if(name_len == 0) { + SHOWMSG("name is empty"); + success = FALSE; break; } @@ -2363,21 +2138,32 @@ smb_decode_long_dirent (char *p, struct smb_dirent *finfo, int level, int * entr SHOWVALUE(name_len); p += 4; /* EA size */ - + p += 1; /* short name length */ p += 1; /* reserved */ - + p += 12*2; /* short name (12 WCHAR characters) */ - /* Skip directory entries whose names we cannot store. */ - if(name_len == 0) + /* Just in case, try to remove any trailing NUL bytes from the name. */ + if(p[name_len - 1] == '\0') { - success = FALSE; - break; - } + SHOWMSG("removing trailing NUL bytes from name"); - if(p[name_len-1] == '\0') - name_len--; + do + { + name_len--; + } + while(name_len > 0 && p[name_len - 1] == '\0'); + + /* This shouldn't become an empty name. */ + if(name_len == 0) + { + SHOWMSG("name is empty"); + + success = FALSE; + break; + } + } /* Skip directory entries whose names we cannot store. */ if(name_len >= (int)finfo->complete_path_size) @@ -2388,15 +2174,6 @@ smb_decode_long_dirent (char *p, struct smb_dirent *finfo, int level, int * entr break; } - /* Don't return names with NUL bytes. */ - if(memchr(p, '\0', name_len) != NULL) - { - SHOWMSG("name contains NUL bytes (skipping it)"); - - success = FALSE; - break; - } - memcpy (finfo->complete_path, p, name_len); finfo->complete_path[name_len] = '\0'; finfo->len = name_len; @@ -2408,7 +2185,7 @@ smb_decode_long_dirent (char *p, struct smb_dirent *finfo, int level, int * entr default: (*entry_length_ptr) = 0; - + success = FALSE; break; } @@ -2441,7 +2218,7 @@ smb_proc_readdir_long (struct smb_server *server, char *path, int fpos, int cach int result = 0; int ff_searchcount; - int ff_eos = 0; + int ff_end_of_search = 0; int ff_dir_handle = 0; int ff_resume_key = 0; int loop_count = 0; @@ -2451,9 +2228,9 @@ smb_proc_readdir_long (struct smb_server *server, char *path, int fpos, int cach int dirlen = strlen (path) + 2 + 1; char *mask; int masklen; - + int entry_length; - + ENTER(); /* ZZZ experimental 'max_matches' adjustment */ @@ -2483,7 +2260,7 @@ smb_proc_readdir_long (struct smb_server *server, char *path, int fpos, int cach masklen = strlen (mask); LOG (("SMB call lreaddir %ld @ %ld\n", cache_size, fpos)); - LOG ((" mask = %s\n", mask)); + LOG ((" mask = '%s'\n", escape_name(mask))); resp_param = NULL; resp_data = NULL; @@ -2494,7 +2271,7 @@ smb_proc_readdir_long (struct smb_server *server, char *path, int fpos, int cach total_count = 0; current_entry = entry; - while (ff_eos == 0) + while (ff_end_of_search == 0) { loop_count++; if (loop_count > 200) @@ -2520,7 +2297,7 @@ smb_proc_readdir_long (struct smb_server *server, char *path, int fpos, int cach WSET (outbuf, smb_msrcnt, 0); /* MaxSetupCount+Reserved1 */ WSET (outbuf, smb_flags, 0); /* Flags */ DSET (outbuf, smb_timeout, 0); /* Timeout */ - /* Reserved2 */ + /* Reserved2 */ WSET (outbuf, smb_pscnt, WVAL (outbuf, smb_tpscnt)); /* ParameterCount */ WSET (outbuf, smb_psoff, ((SMB_BUF (outbuf) + 3) - outbuf) - NETBIOS_HEADER_SIZE); /* ParameterOffset */ WSET (outbuf, smb_dscnt, 0); /* DataCount */ @@ -2540,18 +2317,18 @@ smb_proc_readdir_long (struct smb_server *server, char *path, int fpos, int cach LOG (("first match\n")); WSET (p, 0, attribute); /* attribute */ WSET (p, 2, max_matches); /* max count */ - WSET (p, 4, 8 + 4 + 2); /* resume required + close on end + continue */ + WSET (p, 4, SMB_FIND_CLOSE_AT_EOS|SMB_FIND_RETURN_RESUME_KEYS|SMB_FIND_CONTINUE_FROM_LAST); WSET (p, 6, info_level); - DSET (p, 8, 0); + DSET (p, 8, 0); /* return every entry there is */ } else { - LOG (("next match; ff_dir_handle=0x%lx ff_resume_key=%ld mask='%s'\n", ff_dir_handle, ff_resume_key, mask)); + LOG (("next match; ff_dir_handle=0x%lx ff_resume_key=%ld mask='%s'\n", ff_dir_handle, ff_resume_key, escape_name(mask))); WSET (p, 0, ff_dir_handle); WSET (p, 2, max_matches); /* max count */ WSET (p, 4, info_level); DSET (p, 6, ff_resume_key); - WSET (p, 10, 8 + 4 + 2); /* resume required + close on end + continue */ + WSET (p, 10, SMB_FIND_CLOSE_AT_EOS|SMB_FIND_RETURN_RESUME_KEYS|SMB_FIND_CONTINUE_FROM_LAST); } p += 12; @@ -2615,15 +2392,15 @@ smb_proc_readdir_long (struct smb_server *server, char *path, int fpos, int cach ff_dir_handle = WVAL (p, 0); ff_searchcount = WVAL (p, 2); - ff_eos = WVAL (p, 4); + ff_end_of_search = WVAL (p, 4); } else { ff_searchcount = WVAL (p, 0); - ff_eos = WVAL (p, 2); + ff_end_of_search = WVAL (p, 2); } - LOG (("received %ld entries (eos=%ld)\n",ff_searchcount, ff_eos)); + LOG (("received %ld entries (end_of_search=%ld)\n",ff_searchcount, ff_end_of_search)); if (ff_searchcount == 0) break; @@ -2785,7 +2562,7 @@ smb_proc_getattr_core (struct smb_server *server, const char *path, int len, str char *p; char *buf = server->transmit_buffer; - LOG (("path=%s\n", path)); + LOG (("path='%s'\n", escape_name(path))); ASSERT( smb_payload_size(server, 0, 2 + len) >= 0 ); @@ -2808,7 +2585,8 @@ smb_proc_getattr_core (struct smb_server *server, const char *path, int len, str /* The server only tells us 1 time */ entry->ctime = entry->atime = entry->mtime = entry->wtime = local2utc (DVAL (buf, smb_vwv1)); - entry->size = DVAL (buf, smb_vwv3); + entry->size_low = DVAL (buf, smb_vwv3); + entry->size_high = 0; #if DEBUG { @@ -2855,7 +2633,7 @@ smb_query_path_information(struct smb_server *server, const char *path, int len, WSET (outbuf, smb_msrcnt, 0); /* MaxSetupCount+Reserved1 */ WSET (outbuf, smb_flags, 0); /* Flags */ DSET (outbuf, smb_timeout, 0); /* Timeout */ - /* Reserved2 */ + /* Reserved2 */ WSET (outbuf, smb_pscnt, WVAL (outbuf, smb_tpscnt)); /* ParameterCount */ WSET (outbuf, smb_psoff, ((SMB_BUF (outbuf) + 3) - outbuf) - NETBIOS_HEADER_SIZE); /* ParameterOffset */ WSET (outbuf, smb_dscnt, 0); /* DataCount */ @@ -2927,15 +2705,20 @@ smb_query_path_information(struct smb_server *server, const char *path, int len, p = smb_decode_dword(p, &end_of_file_low); (void) smb_decode_dword(p, &end_of_file_high); - entry->size = end_of_file_low; + entry->size_low = end_of_file_low; + entry->size_high = end_of_file_high; #if DEBUG { struct tm tm; + QUAD entry_size_quad; + + entry_size_quad.Low = entry->size_low; + entry_size_quad.High = entry->size_high; GMTime(entry->mtime,&tm); LOG(("mtime = %ld-%02ld-%02ld %ld:%02ld:%02ld\n",tm.tm_year + 1900,tm.tm_mon+1,tm.tm_mday,tm.tm_hour,tm.tm_min,tm.tm_sec)); - LOG(("size = %lu (0x%08lx)\n",entry->size,entry->size)); + LOG(("size = %s (0x%08lx:0x%08lx)\n",convert_quad_to_string(&entry_size_quad),entry->size_high,entry->size_low)); LOG(("attr = 0x%08lx\n",entry->attr)); } #endif /* DEBUG */ @@ -2969,12 +2752,13 @@ smb_proc_getattrE (struct smb_server *server, struct smb_dirent *entry, int * er goto out; } - entry->ctime = date_dos2unix (WVAL (buf, smb_vwv1), WVAL (buf, smb_vwv0)); - entry->atime = date_dos2unix (WVAL (buf, smb_vwv3), WVAL (buf, smb_vwv2)); - entry->mtime = date_dos2unix (WVAL (buf, smb_vwv5), WVAL (buf, smb_vwv4)); - entry->wtime = entry->mtime; - entry->size = DVAL (buf, smb_vwv6); - entry->attr = WVAL (buf, smb_vwv10); + entry->ctime = date_dos2unix (WVAL (buf, smb_vwv1), WVAL (buf, smb_vwv0)); + entry->atime = date_dos2unix (WVAL (buf, smb_vwv3), WVAL (buf, smb_vwv2)); + entry->mtime = date_dos2unix (WVAL (buf, smb_vwv5), WVAL (buf, smb_vwv4)); + entry->wtime = entry->mtime; + entry->size_low = DVAL (buf, smb_vwv6); + entry->size_high = 0; + entry->attr = WVAL (buf, smb_vwv10); #if DEBUG { @@ -3000,17 +2784,17 @@ smb_proc_getattrE (struct smb_server *server, struct smb_dirent *entry, int * er } int -smb_set_file_information(struct smb_server *server, struct smb_dirent *entry, const dword * size_ptr, int * error_ptr) +smb_set_file_information(struct smb_server *server, struct smb_dirent *entry, const QUAD * const size_quad, int * error_ptr) { unsigned char *outbuf = server->transmit_buffer; int data_size; char * p; int result; - QUAD change_time; + QUAD change_time_quad; retry: - data_size = (size_ptr == NULL) ? 40 : 8; + data_size = (size_quad == NULL) ? 40 : 8; ASSERT( smb_payload_size(server, 15, 3 + 6 + 2 + data_size) >= 0 ); @@ -3023,7 +2807,7 @@ smb_set_file_information(struct smb_server *server, struct smb_dirent *entry, co WSET (outbuf, smb_msrcnt, 0); /* MaxSetupCount+Reserved1 */ WSET (outbuf, smb_flags, 0); /* Flags */ DSET (outbuf, smb_timeout, 0); /* Timeout */ - /* Reserved2 */ + /* Reserved2 */ WSET (outbuf, smb_pscnt, WVAL (outbuf, smb_tpscnt)); /* ParameterCount */ WSET (outbuf, smb_psoff, ((SMB_BUF (outbuf) + 3) - outbuf) - NETBIOS_HEADER_SIZE); /* ParameterOffset */ WSET (outbuf, smb_dscnt, WVAL (outbuf, smb_tdscnt)); /* DataCount */ @@ -3039,7 +2823,7 @@ smb_set_file_information(struct smb_server *server, struct smb_dirent *entry, co (*p++) = '\0'; WSET (p, 0, entry->fileid); - WSET (p, 2, size_ptr == NULL ? SMB_SET_FILE_BASIC_INFO : SMB_SET_FILE_END_OF_FILE_INFO); + WSET (p, 2, size_quad == NULL ? SMB_SET_FILE_BASIC_INFO : SMB_SET_FILE_END_OF_FILE_INFO); WSET (p, 4, 0); p += 6; @@ -3048,7 +2832,7 @@ smb_set_file_information(struct smb_server *server, struct smb_dirent *entry, co (*p++) = '\0'; (*p++) = '\0'; - if(size_ptr == NULL) + if(size_quad == NULL) { /* Creation time (no change) */ DSET(p, 0, 0); @@ -3058,15 +2842,15 @@ smb_set_file_information(struct smb_server *server, struct smb_dirent *entry, co DSET(p, 8, 0); DSET(p, 12, 0); - convert_time_t_to_long_date(entry->mtime,&change_time); + convert_time_t_to_long_date(entry->mtime,&change_time_quad); /* Last write time */ - DSET(p, 16, change_time.Low); - DSET(p, 20, change_time.High); + DSET(p, 16, change_time_quad.Low); + DSET(p, 20, change_time_quad.High); /* Change time */ - DSET(p, 24, change_time.Low); - DSET(p, 28, change_time.High); + DSET(p, 24, change_time_quad.Low); + DSET(p, 28, change_time_quad.High); /* Extended file attributes */ DSET(p, 32, entry->attr); @@ -3077,8 +2861,8 @@ smb_set_file_information(struct smb_server *server, struct smb_dirent *entry, co else { /* End of file */ - DSET(p, 0, (*size_ptr)); - DSET(p, 4, 0); + DSET(p, 0, size_quad->Low); + DSET(p, 4, size_quad->High); } result = smb_trans2_request (server, SMBtrans2, NULL, NULL, NULL, NULL, error_ptr); @@ -3220,7 +3004,7 @@ smb_proc_dskattr (struct smb_server *server, struct smb_dskattr *attr, int * err WSET (outbuf, smb_msrcnt, 0); /* MaxSetupCount+Reserved1 */ WSET (outbuf, smb_flags, 0); /* Flags */ DSET (outbuf, smb_timeout, 0); /* Timeout */ - /* Reserved2 */ + /* Reserved2 */ WSET (outbuf, smb_pscnt, WVAL (outbuf, smb_tpscnt)); /* ParameterCount */ WSET (outbuf, smb_psoff, ((SMB_BUF (outbuf) + 3) - outbuf) - NETBIOS_HEADER_SIZE); /* ParameterOffset */ WSET (outbuf, smb_dscnt, 0); /* DataCount */ @@ -3686,7 +3470,7 @@ smb_proc_reconnect (struct smb_server *server, int * error_ptr) smb_setup_header (server, SMBsesssetupX, 13, user_len + password_len + nt_password_len + strlen (server->mount_data.workgroup_name)+1 + strlen (native_os)+1 + strlen (native_lanman)+1); - capabilities = CAP_RAW_MODE|CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_NT_FIND|CAP_LARGE_FILES; + capabilities = CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_NT_FIND|CAP_LARGE_FILES; WSET (packet, smb_vwv0, 0xff); /* AndXCommand+AndXReserved */ WSET (packet, smb_vwv1, 0); /* AndXOffset */ @@ -3797,7 +3581,7 @@ smb_proc_reconnect (struct smb_server *server, int * error_ptr) StringToUpper(full_share); - SHOWSTRING(full_share); + D(("full_share = '%s'", escape_name(full_share))); ASSERT( smb_payload_size(server, 4, password_len + full_share_len+1 + strlen(dev)+1) >= 0 ); diff --git a/source_code/quad_math.c b/source_code/quad_math.c index 1b0ce89..a9f1316 100644 --- a/source_code/quad_math.c +++ b/source_code/quad_math.c @@ -119,7 +119,7 @@ divide_64_by_32(const QUAD * const dividend,ULONG divisor,QUAD * quotient) { QUAD dividend_cdef = (*dividend); ULONG dividend_ab = 0; - LONG i; + int i; quotient->High = quotient->Low = 0; @@ -169,6 +169,22 @@ divide_64_by_32(const QUAD * const dividend,ULONG divisor,QUAD * quotient) /****************************************************************************/ +/* Add an unsigned 32 bit quantity to a 64 bit quantity, yielding a + * 64 bit sum. + */ +ULONG +add_64_plus_32_to_64(const QUAD * const a,ULONG b,QUAD * ab) +{ + QUAD b_quad; + + b_quad.Low = b; + b_quad.High = 0; + + return(add_64_plus_64_to_64(a,&b_quad,ab)); +} + +/****************************************************************************/ + /* Add an unsigned 64 bit quantity to a 64 bit quantity, yielding a * 64 bit sum. */ @@ -243,3 +259,32 @@ subtract_64_from_64_to_64(const QUAD * const minuend,const QUAD * const subtrahe /* Return the underflow, if any. */ return(extended_minuend.High); } + +/****************************************************************************/ + +/* Compare two unsigned 64 bit integers in the manner of strcmp(). */ +int +compare_64_to_64(const QUAD * const a,const QUAD * const b) +{ + int result; + + if(a->High < b->High) + { + result = -1; + } + else if (a->High == b->High) + { + if (a->Low < b->Low) + result = -1; + else if (a->Low == b->Low) + result = 0; + else + result = 1; + } + else + { + result = 1; + } + + return(result); +} diff --git a/source_code/quad_math.h b/source_code/quad_math.h index 5e6f85c..b932ac2 100644 --- a/source_code/quad_math.h +++ b/source_code/quad_math.h @@ -42,8 +42,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_32_to_64(const QUAD * const a,ULONG b,QUAD * ab); 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); +int compare_64_to_64(const QUAD * const a,const QUAD * const b); /****************************************************************************/ diff --git a/source_code/smakefile b/source_code/smakefile index acee14c..4a91bfc 100644 --- a/source_code/smakefile +++ b/source_code/smakefile @@ -104,13 +104,13 @@ system_headers.gst: system_headers.h system_headers.c assert.o : assert.c cp437.o : cp437.c 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 smbfs_rev.h +crypt.o : crypt.c system_headers.h assert.h quad_math.h smbfs.h +dump_smb.o : dump_smb.c system_headers.h assert.h quad_math.h smbfs.h dump_smb.h +main.o : main.c system_headers.h assert.h quad_math.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 quad_math.h smbfs.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 +smb_abstraction.o : smb_abstraction.c system_headers.h assert.h quad_math.h smbfs.h errors.h smb_abstraction.h +sock.o : sock.c system_headers.h assert.h quad_math.h smbfs.h smb_abstraction.h dump_smb.h errors.h swap_stack_and_call.o : swap_stack_and_call.asm utf-8-iso-8859-1-conversion.o : utf-8-iso-8859-1-conversion.c utf-8-iso-8859-1-conversion.h diff --git a/source_code/smb_abstraction.c b/source_code/smb_abstraction.c index 93366ff..3e3ffe3 100644 --- a/source_code/smb_abstraction.c +++ b/source_code/smb_abstraction.c @@ -12,6 +12,7 @@ #include "smbfs.h" #include "errors.h" +#include "quad_math.h" /*****************************************************************************/ @@ -82,10 +83,6 @@ smba_connect ( int max_transmit, int 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, @@ -117,26 +114,6 @@ smba_connect ( if(opt_raw_smb) res->server.raw_smb = TRUE; - /* olsen (2016-04-20): Use write-behind with SMB_COM_WRITE_RAW. */ - if(opt_write_behind) - res->server.write_behind = TRUE; - - /* olsen (2018-05-08): Always use SMB_COM_WRITE, even if SMB_COM_WRITE_RAW were possible. */ - if(opt_disable_write_raw) - { - res->server.disable_write_raw = TRUE; - } - else - { - /* olsen (2016-04-20): Prefer the use of SMB_COM_WRITE_RAW over SMB_COM_WRITE. */ - if(opt_prefer_write_raw) - res->server.prefer_write_raw = TRUE; - } - - /* olsen (2018-05-08): Always use SMB_COM_READ, even if SMB_COM_READ_RAW were possible. */ - if(opt_disable_read_raw) - res->server.disable_read_raw = TRUE; - /* olsen (2018-05-09): Timeout for send/receive operations in seconds. */ res->server.timeout = timeout; @@ -301,7 +278,7 @@ make_open (smba_file_t * f, int need_fid, int writable, int truncate, int * erro { if(!f->dirent.opened) { - LOG (("opening file %s\n", f->dirent.complete_path)); + LOG (("opening file '%s'\n", escape_name(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) @@ -309,7 +286,7 @@ make_open (smba_file_t * f, int need_fid, int writable, int truncate, int * erro } else { - LOG (("file %s is already open\n", f->dirent.complete_path)); + LOG (("file '%s' is already open\n", escape_name(f->dirent.complete_path))); } } } @@ -317,7 +294,7 @@ make_open (smba_file_t * f, int need_fid, int writable, int truncate, int * erro { if(!f->dirent.opened) { - LOG (("opening file %s\n", f->dirent.complete_path)); + LOG (("opening file '%s'\n", escape_name(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) @@ -325,7 +302,7 @@ make_open (smba_file_t * f, int need_fid, int writable, int truncate, int * erro } else { - LOG (("file %s is already open\n", f->dirent.complete_path)); + LOG (("file '%s' is already open\n", escape_name(f->dirent.complete_path))); } if (s->supports_E || !s->supports_E_known) @@ -394,7 +371,7 @@ smba_open (smba_server_t * s, char *name, size_t name_size, int writable, int tr f->dirent.len = strlen (name); f->server = s; - LOG(("open '%s' (writable=%s, truncate=%s)\n", name, writable ? "yes" : "no", truncate ? "yes" : "no")); + LOG(("open '%s' (writable=%s, truncate=%s)\n", escape_name(name), writable ? "yes" : "no", truncate ? "yes" : "no")); result = make_open (f, open_dont_need_fid, writable, truncate, error_ptr); if (result < 0) @@ -426,7 +403,7 @@ write_attr (smba_file_t * f, int * error_ptr) { int result; - LOG (("file %s\n", f->dirent.complete_path)); + LOG (("file '%s'\n", escape_name(f->dirent.complete_path))); if(f->server->server.protocol >= PROTOCOL_LANMAN2) { @@ -468,7 +445,7 @@ smba_close (smba_file_t * f, int * error_ptr) { if(f != NULL) { - LOG (("closing file '%s'\n", f->dirent.complete_path)); + LOG (("closing file '%s'\n", escape_name(f->dirent.complete_path))); if(f->node.mln_Succ != NULL || f->node.mln_Pred != NULL) Remove((struct Node *)f); @@ -500,7 +477,7 @@ 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) +smba_read (smba_file_t * f, char *data, long len, const QUAD * const offset, int * error_ptr) { int max_receive = f->server->server.max_recv; int num_bytes_read = 0; @@ -514,6 +491,7 @@ smba_read (smba_file_t * f, char *data, long len, long offset, int * error_ptr) if (f->server->server.protocol >= PROTOCOL_LANMAN1) { + QUAD position_quad = (*offset); int max_readx_size; int count; @@ -556,13 +534,13 @@ smba_read (smba_file_t * f, char *data, long len, long offset, int * error_ptr) { count = min(len, max_readx_size); - result = smb_proc_readx (&f->server->server, &f->dirent, offset, count, data, error_ptr); + result = smb_proc_readx (&f->server->server, &f->dirent, &position_quad, count, data, error_ptr); if (result < 0) goto out; num_bytes_read += result; len -= result; - offset += result; + add_64_plus_32_to_64(&position_quad,result,&position_quad); data += result; if(result < count) @@ -573,50 +551,10 @@ smba_read (smba_file_t * f, char *data, long len, long offset, int * error_ptr) } while (len > 0); } - /* SMB_COM_READ_RAW and SMB_COM_WRITE_RAW supported? */ - 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; - - 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, offset, n, data, error_ptr); - if(result <= 0) - { - D(("!!! wanted to read %ld bytes, got %ld",n,result)); - break; - } - - num_bytes_read += result; - len -= result; - offset += result; - 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; + off_t position = offset->Low; int count; /* Calculate maximum number of bytes that could be transferred with @@ -664,13 +602,13 @@ smba_read (smba_file_t * f, char *data, long len, long offset, int * error_ptr) if(count > max_receive) count = max_receive; - result = smb_proc_read (&f->server->server, &f->dirent, offset, count, data, error_ptr); + result = smb_proc_read (&f->server->server, &f->dirent, position, count, data, error_ptr); if (result < 0) goto out; num_bytes_read += result; len -= result; - offset += result; + position += result; data += result; if(result < count) @@ -692,7 +630,7 @@ 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) +smba_write (smba_file_t * f, const char *data, long len, const QUAD * const offset, int * error_ptr) { int num_bytes_written = 0; int max_buffer_size; @@ -709,6 +647,7 @@ smba_write (smba_file_t * f, const char *data, long len, long offset, int * erro /* SMB_COM_WRITE_ANDX supported? */ if (f->server->server.protocol >= PROTOCOL_LANMAN1) { + QUAD position_quad = (*offset); int max_writex_size; int n; @@ -754,69 +693,14 @@ smba_write (smba_file_t * f, const char *data, long len, long offset, int * erro 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); + result = smb_proc_writex(&f->server->server, &f->dirent, &position_quad, 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; - 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, offset, n, data, error_ptr); - if(result < 0) - goto out; - - data += result; - offset += result; + add_64_plus_32_to_64(&position_quad,result,&position_quad); len -= result; num_bytes_written += result; } @@ -825,6 +709,7 @@ smba_write (smba_file_t * f, const char *data, long len, long offset, int * erro else { int max_size_smb_com_write, count; + off_t position = offset->Low; /* Calculate maximum number of bytes that could be transferred with * a single SMBwrite packet... @@ -864,12 +749,12 @@ smba_write (smba_file_t * f, const char *data, long len, long offset, int * erro ASSERT( count <= 65535 ); - result = smb_proc_write (&f->server->server, &f->dirent, offset, count, data, error_ptr); + result = smb_proc_write (&f->server->server, &f->dirent, position, count, data, error_ptr); if (result < 0) goto out; len -= result; - offset += result; + position += result; data += result; num_bytes_written += result; } @@ -891,8 +776,22 @@ smba_write (smba_file_t * f, const char *data, long len, long offset, int * erro * at writing some data. Hence we update the cached file * size here. */ - if (offset + num_bytes_written > (int)f->dirent.size) /* ZZZ overflow check needed? */ - f->dirent.size = offset + num_bytes_written; + if(num_bytes_written > 0) + { + QUAD size_quad; + QUAD new_position_quad; + + size_quad.Low = f->dirent.size_low; + size_quad.High = f->dirent.size_high; + + add_64_plus_32_to_64(offset,num_bytes_written,&new_position_quad); + + if(compare_64_to_64(&new_position_quad,&size_quad) > 0) + { + f->dirent.size_low = new_position_quad.Low; + f->dirent.size_high = new_position_quad.High; + } + } return result; } @@ -951,7 +850,7 @@ smba_getattr (smba_file_t * f, smba_stat_t * data, int * error_ptr) if (f->attr_time == 0 || (now > f->attr_time && now - f->attr_time > ATTR_CACHE_TIME)) { - LOG (("file %s\n", f->dirent.complete_path)); + LOG (("file '%s'\n", escape_name(f->dirent.complete_path))); if (f->server->server.protocol >= PROTOCOL_LANMAN2) { @@ -980,7 +879,9 @@ smba_getattr (smba_file_t * f, smba_stat_t * data, int * error_ptr) data->is_system = (f->dirent.attr & aSYSTEM) != 0; data->is_changed_since_last_archive = (f->dirent.attr & aARCH) != 0; - data->size = f->dirent.size; + data->size_low = f->dirent.size_low; + data->size_high = f->dirent.size_high; + data->atime = f->dirent.atime; data->ctime = f->dirent.ctime; data->mtime = f->dirent.mtime; @@ -993,7 +894,7 @@ smba_getattr (smba_file_t * f, smba_stat_t * data, int * error_ptr) /*****************************************************************************/ int -smba_setattr (smba_file_t * f, const smba_stat_t * data, const dword * size_ptr, int * error_ptr) +smba_setattr (smba_file_t * f, const smba_stat_t * data, const QUAD * const size, int * error_ptr) { BOOL times_changed = FALSE; int result = 0; @@ -1001,19 +902,19 @@ smba_setattr (smba_file_t * f, const smba_stat_t * data, const dword * size_ptr, if (data != NULL) { - if (data->atime != -1 && f->dirent.atime != data->atime) + if (data->atime != (time_t)-1 && f->dirent.atime != data->atime) { f->dirent.atime = data->atime; times_changed = TRUE; } - if (data->ctime != -1 && f->dirent.ctime != data->ctime) + if (data->ctime != (time_t)-1 && f->dirent.ctime != data->ctime) { f->dirent.ctime = data->ctime; times_changed = TRUE; } - if (data->mtime != -1 && f->dirent.mtime != data->mtime) + if (data->mtime != (time_t)-1 && f->dirent.mtime != data->mtime) { f->dirent.mtime = data->mtime; times_changed = TRUE; @@ -1031,13 +932,6 @@ smba_setattr (smba_file_t * f, const smba_stat_t * data, const dword * size_ptr, else attrs &= ~aARCH; - /* - if (data->is_system) - attrs |= aSYSTEM; - else - attrs &= ~aSYSTEM; - */ - if(f->dirent.attr != attrs) { f->dirent.attr = attrs; @@ -1052,21 +946,22 @@ smba_setattr (smba_file_t * f, const smba_stat_t * data, const dword * size_ptr, } } - if (size_ptr != NULL && (*size_ptr) != f->dirent.size) + if (size != NULL && (size->Low != f->dirent.size_low || size->High != f->dirent.size_high)) { result = make_open (f, open_need_fid, open_writable, open_dont_truncate, error_ptr); if(result < 0) goto out; if(f->server->server.protocol >= PROTOCOL_LANMAN2) - result = smb_set_file_information (&f->server->server, &f->dirent, size_ptr, error_ptr); + result = smb_set_file_information (&f->server->server, &f->dirent, size, error_ptr); else - result = smb_proc_trunc (&f->server->server, f->dirent.fileid, (*size_ptr), error_ptr); + result = smb_proc_trunc (&f->server->server, f->dirent.fileid, size->Low, error_ptr); if(result < 0) goto out; - f->dirent.size = (*size_ptr); + f->dirent.size_low = size->Low; + f->dirent.size_high = size->High; } out: @@ -1123,7 +1018,7 @@ smba_readdir (smba_file_t * f, long offs, void *d, smba_callback_t callback, int if (cache_index >= f->dircache->base + f->dircache->len && f->dircache->eof) break; /* nothing more to read */ - LOG (("cachefill for %s\n", f->dirent.complete_path)); + LOG (("cachefill for '%s'\n", escape_name(f->dirent.complete_path))); LOG (("\tbase was: %ld, len was: %ld, newbase=%ld\n", f->dircache->base, f->dircache->len, cache_index)); f->dircache->len = 0; @@ -1162,14 +1057,15 @@ smba_readdir (smba_file_t * f, long offs, void *d, smba_callback_t callback, int eof = (o >= (f->dircache->len - 1) && f->dircache->eof); count++; - LOG (("delivering '%s', cache_index=%ld, eof=%ld\n", f->dircache->cache[o].complete_path, cache_index, eof)); + LOG (("delivering '%s', cache_index=%ld, eof=%ld\n", escape_name(f->dircache->cache[o].complete_path), cache_index, eof)); data.is_dir = (f->dircache->cache[o].attr & aDIR) != 0; data.is_read_only = (f->dircache->cache[o].attr & aRONLY) != 0; data.is_hidden = (f->dircache->cache[o].attr & aHIDDEN) != 0; data.is_system = (f->dircache->cache[o].attr & aSYSTEM) != 0; data.is_changed_since_last_archive = (f->dircache->cache[o].attr & aARCH) != 0; - data.size = f->dircache->cache[o].size; + data.size_low = f->dircache->cache[o].size_low; + data.size_high = f->dircache->cache[o].size_high; data.atime = f->dircache->cache[o].atime; data.ctime = f->dircache->cache[o].ctime; data.mtime = f->dircache->cache[o].mtime; @@ -1221,10 +1117,10 @@ invalidate_dircache (struct smba_server * server, char * path) other_path[0] = '\0'; } - SHOWSTRING(other_path); + D(("other_path = '%s'", escape_name(other_path))); if(dircache->cache_for != NULL) - SHOWSTRING(dircache->cache_for->dirent.complete_path); + D(("dircache->cache_for->dirent.complete_path = '%s'", escape_name(dircache->cache_for->dirent.complete_path))); else SHOWMSG("-- directory cache is empty --"); @@ -1246,7 +1142,7 @@ invalidate_dircache (struct smba_server * server, char * path) /*****************************************************************************/ int -smba_create (smba_file_t * dir, const char *name, smba_stat_t * attr, int * error_ptr) +smba_create (smba_file_t * dir, const char *name, int * error_ptr) { struct smb_dirent entry; char *path = NULL; @@ -1362,7 +1258,7 @@ close_path (smba_server_t * s, char *path, int * error_ptr) result = smb_proc_close (&s->server, p->dirent.fileid, p->dirent.mtime, error_ptr); if(result < 0) { - LOG(("closing %s with file id %ld failed\n", path, p->dirent.fileid)); + LOG(("closing '%s' with file id %ld failed\n", escape_name(path), p->dirent.fileid)); break; } @@ -1638,10 +1534,6 @@ smba_start( 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, @@ -1813,10 +1705,6 @@ smba_start( opt_max_transmit, opt_timeout, opt_raw_smb, - opt_write_behind, - opt_prefer_write_raw, - opt_disable_write_raw, - opt_disable_read_raw, opt_native_os, error_ptr, smb_error_class_ptr, diff --git a/source_code/smb_abstraction.h b/source_code/smb_abstraction.h index 9e853d6..dc1be3f 100644 --- a/source_code/smb_abstraction.h +++ b/source_code/smb_abstraction.h @@ -16,6 +16,16 @@ /****************************************************************************/ +#include + +/****************************************************************************/ + +#ifndef _QUAD_MATH_H +#include "quad_math.h" +#endif /* _QUAD_MATH_H */ + +/****************************************************************************/ + /* Forward declaration to keep the compiler happy. */ #ifndef _SMB_FS_SB struct smb_server; @@ -55,10 +65,13 @@ typedef struct smba_stat unsigned is_hidden:1; unsigned is_system:1; unsigned is_changed_since_last_archive:1; - int size; - long atime; - long ctime; - long mtime; + + unsigned long size_low; + unsigned long size_high; + + time_t atime; + time_t ctime; + time_t mtime; } smba_stat_t; /****************************************************************************/ @@ -74,20 +87,20 @@ 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, 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_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); int smba_getattr(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_setattr(smba_file_t *f, const smba_stat_t *data, const QUAD * const size, 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_create(smba_file_t *dir, const char *name, int * error_ptr); int smba_mkdir(smba_file_t *dir, const char *name, int * error_ptr); int smba_remove(smba_server_t *s, char *path, int * error_ptr); 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, char * opt_native_os, 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, 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); diff --git a/source_code/smbfs.h b/source_code/smbfs.h index e59e63f..5c25c61 100644 --- a/source_code/smbfs.h +++ b/source_code/smbfs.h @@ -33,6 +33,10 @@ #include "assert.h" #endif /* _ASSERT_H */ +#ifndef _QUAD_MATH_H +#include "quad_math.h" +#endif /* _QUAD_MATH_H */ + /****************************************************************************/ #define SAME (0) @@ -131,16 +135,18 @@ extern int h_errno; /****************************************************************************/ extern int BroadcastNameQuery(const char *name, const char *scope, UBYTE *address); -extern LONG CompareNames(STRPTR a,STRPTR b); +extern LONG CompareNames(const TEXT * a,const TEXT * b); extern LONG GetTimeZoneDelta(VOID); extern STRPTR posix_strerror(int error); extern STRPTR host_strerror(int error); extern time_t MakeTime(const struct tm * const tm); extern ULONG GetCurrentTime(VOID); extern VOID GMTime(time_t seconds,struct tm * tm); -extern VOID VARARGS68K ReportError(STRPTR fmt,...); +extern VOID VARARGS68K ReportError(const TEXT * fmt,...); extern VOID StringToUpper(STRPTR s); -extern VOID VARARGS68K SPrintf(STRPTR buffer, STRPTR formatString,...); +extern VOID VARARGS68K SPrintf(STRPTR buffer, const TEXT * formatString,...); +extern TEXT * escape_name(const TEXT * name); +extern const char * convert_quad_to_string(const QUAD * const number); /****************************************************************************/ diff --git a/source_code/smbfs_rev.h b/source_code/smbfs_rev.h index 940bdef..c74f163 100644 --- a/source_code/smbfs_rev.h +++ b/source_code/smbfs_rev.h @@ -1,6 +1,6 @@ #define VERSION 1 -#define REVISION 137 -#define DATE "24.5.2018" -#define VERS "smbfs 1.137" -#define VSTRING "smbfs 1.137 (24.5.2018)\r\n" -#define VERSTAG "\0$VER: smbfs 1.137 (24.5.2018)" +#define REVISION 139 +#define DATE "26.5.2018" +#define VERS "smbfs 1.139" +#define VSTRING "smbfs 1.139 (26.5.2018)\r\n" +#define VERSTAG "\0$VER: smbfs 1.139 (26.5.2018)" diff --git a/source_code/smbfs_rev.rev b/source_code/smbfs_rev.rev index 065fd3e..897bdc8 100644 --- a/source_code/smbfs_rev.rev +++ b/source_code/smbfs_rev.rev @@ -1 +1 @@ -137 +139 diff --git a/source_code/sock.c b/source_code/sock.c index 59dad41..b3ec8de 100644 --- a/source_code/sock.c +++ b/source_code/sock.c @@ -994,6 +994,9 @@ smb_connect (struct smb_server *server, int * error_ptr) /* If there was a network error, or data was left unread, * the best option is to the close server connection and * reopen it again. + * + * Here's where we decide whether closing the connection + * makes sense, and then close it if necessary. */ void smb_check_server_connection(struct smb_server *server, int error) @@ -1185,138 +1188,3 @@ 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; -}