diff --git a/documentation/history.doc b/documentation/history.doc index a93e83b..1aa3c9a 100644 --- a/documentation/history.doc +++ b/documentation/history.doc @@ -1779,3 +1779,35 @@ smbfs 1.139 (26.5.2018) 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. + + +smbfs 1.140 (27.5.2018) + +- When opening a file or directory for access, the access rights + required now follow the original smbfs implementation which + always required write access regardless of whether it was + needed or not. If write access was not available it would + retry using read-only access. + + The new code now starts with write access, even if only read + access was required, and will retry with read-only access if + needed. However, if write access was required, no retry with + read-only access will be made. + +- Only the directory cache needs to keep track of how much memory + is available for storing file and directory names during directory + scanning. Opening a file or directory doesn't have to bother, + which is why smbfs can now do its job without allocating a + minimum of 256 bytes per path name. This also simplified the + path name management. Incidentally, the path name management + could not reliably guarantee a NUL-terminated buffer :-( + +- Finally figured out why files or directories created through smbfs + could not be deleted again: smbfs could end up marking them as + "ready-only". Fixed! + +- Found and fixed a few utterly embarrassing "use after free" cases, + which thankfully had little impact :-/ + +- The debug code now shows which file IDs the server assigned to + opened files/directories. diff --git a/source_code/include/smb/smb.h b/source_code/include/smb/smb.h index 31d6104..40411d5 100644 --- a/source_code/include/smb/smb.h +++ b/source_code/include/smb/smb.h @@ -67,15 +67,19 @@ struct smb_dirent dword attr; /* Attribute fields, DOS value */ time_t atime, mtime, - wtime, ctime; /* Times, as seen by the server, normalized */ - /* to UTC. The ugly conversion happens in */ - /* proc.c */ + wtime, ctime; /* Times, as seen by the server, normalized + * to UTC. The ugly conversion happens in + * proc.c + */ 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 */ + size_t complete_path_size; /* Number of bytes allocated for name; this is + * used only by the directory reader and + * the cache. + */ int len; /* Name length. */ diff --git a/source_code/include/smb/smb_fs.h b/source_code/include/smb/smb_fs.h index 8ec9376..349493e 100644 --- a/source_code/include/smb/smb_fs.h +++ b/source_code/include/smb/smb_fs.h @@ -57,19 +57,19 @@ int smb_proc_read(struct smb_server *server, struct smb_dirent *finfo, off_t off 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_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_lockingX (struct smb_server *server, struct smb_dirent *finfo, const 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); int smb_proc_mkdir(struct smb_server *server, const char *path, const int len, int * error_ptr); int smb_proc_rmdir(struct smb_server *server, const char *path, const int len, int * error_ptr); int smb_proc_unlink(struct smb_server *server, const char *path, const int len, int * error_ptr); int smb_proc_trunc(struct smb_server *server, word fid, dword length, int * error_ptr); -int smb_proc_readdir(struct smb_server *server, char *path, int fpos, int cache_size, struct smb_dirent *entry, int * error_ptr); +int smb_proc_readdir(struct smb_server *server, const char *path, int fpos, int cache_size, struct smb_dirent *entry, int * error_ptr); int smb_proc_getattr_core(struct smb_server *server, const char *path, int len, struct smb_dirent *entry, int * error_ptr); int smb_proc_getattrE(struct smb_server *server, struct smb_dirent *entry, int * error_ptr); int smb_query_path_information(struct smb_server *server, const char *path, int len, int fid, struct smb_dirent *entry, int * error_ptr); int smb_set_file_information(struct smb_server *server, struct smb_dirent *entry, const 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_setattr_core(struct smb_server *server, const char *path, int len, const 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); int smb_proc_connect(struct smb_server *server, int * error_ptr); diff --git a/source_code/include/smb/smbno.h b/source_code/include/smb/smbno.h index f67a1c1..efa659c 100644 --- a/source_code/include/smb/smbno.h +++ b/source_code/include/smb/smbno.h @@ -292,6 +292,20 @@ #define TRANSACT2_FINDNOTIFYNEXT 12 #define TRANSACT2_MKDIR 13 /* TRANS2_CREATE_DIRECTORY */ +/* Basic SMB file attributes, such as used by TRANSACT2_FINDFIRST + * or SMB_COM_OPEN. + */ +#define SMB_FILE_ATTRIBUTE_NORMAL 0x0000 +#define SMB_FILE_ATTRIBUTE_READONLY 0x0001 +#define SMB_FILE_ATTRIBUTE_HIDDEN 0x0002 +#define SMB_FILE_ATTRIBUTE_SYSTEM 0x0004 +#define SMB_FILE_ATTRIBUTE_VOLUME 0x0008 +#define SMB_FILE_ATTRIBUTE_DIRECTORY 0x0010 +#define SMB_FILE_ATTRIBUTE_ARCHIVE 0x0020 +#define SMB_SEARCH_ATTRIBUTE_READONLY 0x0100 +#define SMB_SEARCH_ATTRIBUTE_HIDDEN 0x0200 +#define SMB_SEARCH_ATTRIBUTE_SYSTEM 0x0400 + /* Extended file attributes */ #define ATTR_READONLY 0x00000001 #define ATTR_HIDDEN 0x00000002 @@ -384,4 +398,21 @@ #define SMB_SET_FILE_BASIC_INFO 0x0101 /* NT LAN Manager */ #define SMB_SET_FILE_END_OF_FILE_INFO 0x0104 /* NT LAN Manager */ +/* These are used with SMBopen */ +#define SMB_OPEN_ACCESS_READ_ONLY 0x0000 +#define SMB_OPEN_ACCESS_WRITE_ONLY 0x0001 +#define SMB_OPEN_ACCESS_READ_WRITE 0x0002 +#define SMB_OPEN_ACCESS_EXECUTE 0x0003 +#define SMB_OPEN_SHARE_COMPATIBILITY_MODE 0x0000 +#define SMB_OPEN_SHARE_DENY_EVERYTHING 0x0010 +#define SMB_OPEN_SHARE_DENY_WRITE 0x0020 +#define SMB_OPEN_SHARE_DENY_READ_EXECUTE 0x0030 +#define SMB_OPEN_SHARE_DENY_NOTHING 0x0040 +#define SMB_OPEN_LOCALITY_UNKNOWN 0x0000 +#define SMB_OPEN_LOCALITY_SEQUENTIAL 0x0100 +#define SMB_OPEN_LOCALITY_RANDOM 0x0200 +#define SMB_OPEN_LOCALITY_MIXED 0x0300 +#define SMB_OPEN_CACHE_DISABLED 0x1000 +#define SMB_OPEN_WRITE_THROUGH_ENABLED 0x4000 + #endif /* _SMBNO_H_ */ diff --git a/source_code/main.c b/source_code/main.c index 149c30f..04a604f 100644 --- a/source_code/main.c +++ b/source_code/main.c @@ -935,7 +935,7 @@ main(VOID) if(args.Service != NULL) { - STRPTR name = FilePart(program_name); + const TEXT * name = FilePart(program_name); /* Set up the name of the program, as it will be * displayed in the proces status list. @@ -3170,15 +3170,25 @@ ConvertCString(void * bstring,int max_len,const TEXT * cstring,int len) * to the name of the parent directory. This takes care of all the * special cases, such as the root directory. The result will be converted * to be in a form suitable for use with the SMB file sharing service. + * + * Note that the parent directory name uses SMB path name separator + * characters ("\"), but the path name to be added ("name") uses the + * AmigaDOS path name separator characters ("/"). + * + * This function will return ERROR_NO_FREE_STORE if the memory allocation + * failed, and ERROR_INVALID_COMPONENT_NAME if the combination of the + * parent name and the name wound up referring to the root directory. */ STATIC LONG BuildFullName( const TEXT * parent_name, - STRPTR name, - STRPTR * result_ptr, - int * result_size_ptr) + const TEXT * name, + STRPTR * result_ptr) { int error = OK; + int parent_name_len; + int name_len; + int buffer_len; STRPTR buffer; int len,size; int i; @@ -3197,15 +3207,23 @@ BuildFullName( /* Throw everything left of the colon away. */ if(name != NULL) { - for(i = 0 ; i < (int)strlen(name) ; i++) + name_len = strlen(name); + + for(i = 0 ; i < name_len ; i++) { if(name[i] == ':') { name = &name[i+1]; + name_len -= i + 1; + break; } } } + else + { + name_len = 0; + } /* Now, how much room is needed for the complete * path to fit into a buffer? @@ -3213,13 +3231,24 @@ BuildFullName( len = 2; if(parent_name != NULL) - len += strlen(parent_name) + 1; + { + /* Skip any excess delimiters. */ + while((*parent_name) == SMB_PATH_SEPARATOR) + parent_name++; + + parent_name_len = strlen(parent_name); + + len += 1 + parent_name_len; + } + else + { + len += strlen(SMB_ROOT_DIR_NAME); + + parent_name_len = 0; + } if(name != NULL) - len += strlen(name) + 1; - - if(len < SMB_MAXNAMELEN) - len = SMB_MAXNAMELEN; + len += 1 + name_len; size = len + 3; @@ -3233,16 +3262,19 @@ BuildFullName( /* Start by filling in the path name. */ if(parent_name != NULL) { - /* Skip any excess separators. */ - while((*parent_name) == SMB_PATH_SEPARATOR) - parent_name++; - buffer[0] = SMB_PATH_SEPARATOR; - strcpy(&buffer[1],parent_name); + + memcpy(&buffer[1],parent_name,parent_name_len); + + buffer_len = 1 + parent_name_len; } else { + ASSERT( (int)strlen(SMB_ROOT_DIR_NAME) < size ); + strcpy(buffer,SMB_ROOT_DIR_NAME); + + buffer_len = strlen(buffer); } /* If there's a name to add, do just that. */ @@ -3250,11 +3282,6 @@ BuildFullName( { int segment_start; int segment_len; - int buffer_len; - int name_len; - - buffer_len = strlen(buffer); - name_len = strlen(name); segment_start = 0; @@ -3294,9 +3321,7 @@ BuildFullName( /* Is this already the root directory name? */ if(buffer_len <= 1) { - FreeMemory(buffer); - buffer = NULL; - + error = ERROR_INVALID_COMPONENT_NAME; goto out; } else @@ -3332,7 +3357,15 @@ BuildFullName( * necessary. */ if(buffer_len > 0 && buffer[buffer_len-1] != SMB_PATH_SEPARATOR) + { + if(buffer_len+1 > size) + { + error = ERROR_NO_FREE_STORE; + goto out; + } + buffer[buffer_len++] = SMB_PATH_SEPARATOR; + } /* Find out how many characters are in that name; this * excludes the terminating slash. @@ -3342,6 +3375,12 @@ BuildFullName( else len = segment_len; + if(buffer_len+len+1 > size) + { + error = ERROR_NO_FREE_STORE; + goto out; + } + memcpy(&buffer[buffer_len],&name[segment_start],len); buffer_len += len; } @@ -3351,14 +3390,17 @@ BuildFullName( } (*result_ptr) = buffer; - (*result_size_ptr) = size; + + ASSERT( buffer_len < size ); + + buffer[buffer_len] = '\0'; D(("buffer = '%s'",escape_name(buffer))); + buffer = NULL; out: - if(error != OK) - FreeMemory(buffer); + FreeMemory(buffer); RETURN(error); return(error); @@ -3373,9 +3415,7 @@ Action_Parent( { BPTR result = ZERO; STRPTR full_name = NULL; - int full_name_size; STRPTR parent_name; - BOOL cleanup = TRUE; struct LockNode * ln = NULL; int error; @@ -3394,16 +3434,18 @@ Action_Parent( parent_name = NULL; } - error = BuildFullName(parent_name,"/",&full_name,&full_name_size); + error = BuildFullName(parent_name,"/",&full_name); if(error != OK) - goto out; + { + /* Check if we ended up having to return the parent of + * the root directory. This is indicated by the + * error code ERROR_INVALID_COMPONENT_NAME. + */ + if(error == ERROR_INVALID_COMPONENT_NAME) + error = OK; - /* Check if we ended up having to return the parent of - * the root directory. This is indicated by a NULL - * name pointer and a zero error code. - */ - if(full_name == NULL) goto out; + } ln = AllocateMemory(sizeof(*ln)); if(ln == NULL) @@ -3422,7 +3464,7 @@ Action_Parent( 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) + if(smba_open(ServerData,full_name,open_read_only,open_dont_truncate,&ln->ln_File,&error) < 0) { error = MapErrnoToIoErr(error); goto out; @@ -3430,16 +3472,15 @@ Action_Parent( AddTail((struct List *)&LockList,(struct Node *)ln); result = MKBADDR(&ln->ln_FileLock); - cleanup = FALSE; SHOWVALUE(&ln->ln_FileLock); + full_name = NULL; + ln = NULL; + out: - if(cleanup) - { - FreeMemory(full_name); - FreeMemory(ln); - } + FreeMemory(full_name); + FreeMemory(ln); (*error_ptr) = error; @@ -3488,7 +3529,7 @@ Action_DeleteObject( { LONG result = DOSFALSE; STRPTR full_name = NULL; - int full_name_size; + int full_name_len; smba_file_t * file = NULL; STRPTR parent_name; STRPTR full_parent_name = NULL; @@ -3560,16 +3601,17 @@ Action_DeleteObject( } } - error = BuildFullName(parent_name,name,&full_name,&full_name_size); + error = BuildFullName(parent_name,name,&full_name); if(error != OK) - goto out; - - /* Trying to delete the root directory, are you kidding? */ - if(full_name == NULL) { - LOG(("cannot delete the root directory\n")); - - error = ERROR_OBJECT_IN_USE; + /* Trying to delete the root directory, are you kidding? */ + if(error == ERROR_INVALID_COMPONENT_NAME) + { + LOG(("cannot delete the root directory\n")); + + error = ERROR_OBJECT_IN_USE; + } + goto out; } @@ -3587,21 +3629,23 @@ Action_DeleteObject( * in case the directory contents are currently being * examined, that process is restarted. */ - full_parent_name = AllocateMemory(strlen(full_name)+3); + full_name_len = strlen(full_name); + + full_parent_name = AllocateMemory(full_name_len+1); if(full_parent_name == NULL) { error = ERROR_NO_FREE_STORE; goto out; } - strcpy(full_parent_name,full_name); + memcpy(full_parent_name,full_name,full_name_len+1); /* Build the parent object name - Piru */ - if (full_parent_name[0] != '\0') + if (full_name_len > 0) { int i; - i = strlen(full_parent_name) - 1; + i = full_name_len - 1; if (i >= 0 && full_parent_name[i] == SMB_PATH_SEPARATOR) i--; @@ -3629,7 +3673,7 @@ Action_DeleteObject( 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) + if(smba_open(ServerData,full_name,open_writable,open_dont_truncate,&file,&error) < 0) { error = MapErrnoToIoErr(error); goto out; @@ -3706,12 +3750,12 @@ Action_DeleteObject( out: - FreeMemory(full_name); - FreeMemory(full_parent_name); - if(file != NULL) smba_close(file,&ignored_error); + FreeMemory(full_name); + FreeMemory(full_parent_name); + (*error_ptr) = error; RETURN(result); @@ -3728,11 +3772,10 @@ Action_CreateDir( { BPTR result = ZERO; STRPTR full_name = NULL; - int full_name_size; + int full_name_len; struct LockNode * ln = NULL; STRPTR parent_name; STRPTR dir_name = NULL; - size_t dir_name_size; smba_file_t * dir = NULL; STRPTR base_name; TEXT name[MAX_FILENAME_LEN+1]; @@ -3789,33 +3832,33 @@ Action_CreateDir( } } - error = BuildFullName(parent_name,name,&full_name,&full_name_size); + error = BuildFullName(parent_name,name,&full_name); if(error != OK) - goto out; - - /* Trying to overwrite the root directory, are you kidding? */ - if(full_name == NULL) { - error = ERROR_OBJECT_IN_USE; + /* Trying to overwrite the root directory, are you kidding? */ + if(error == ERROR_INVALID_COMPONENT_NAME) + error = ERROR_OBJECT_IN_USE; + goto out; } D(("full_name = '%s'",escape_name(full_name))); - dir_name_size = strlen(full_name)+3; + full_name_len = strlen(full_name); - dir_name = AllocateMemory(dir_name_size); + /* Note: extra character needed for special case '\name'. */ + dir_name = AllocateMemory(full_name_len+2); if(dir_name == NULL) { error = ERROR_NO_FREE_STORE; goto out; } - strcpy(dir_name,full_name); + memcpy(dir_name,full_name,full_name_len+1); base_name = NULL; - for(i = strlen(dir_name)-1 ; i >= 0 ; i--) + for(i = full_name_len-1 ; i >= 0 ; i--) { if(dir_name[i] == SMB_PATH_SEPARATOR) { @@ -3824,7 +3867,7 @@ Action_CreateDir( */ if(i == 0) { - memmove(&dir_name[1],&dir_name[0],strlen(dir_name)+1); + memmove(&dir_name[1],&dir_name[0],full_name_len+1); i++; } @@ -3852,12 +3895,14 @@ Action_CreateDir( ln->ln_FileLock.fl_Volume = MKBADDR(VolumeNode); ln->ln_FullName = full_name; - if(smba_open(ServerData,dir_name,dir_name_size,open_read_only,open_dont_truncate,&dir,&error) < 0) + if(smba_open(ServerData,dir_name,open_read_only,open_dont_truncate,&dir,&error) < 0) { error = MapErrnoToIoErr(error); goto out; } + ASSERT( base_name != NULL ); + if(smba_mkdir(dir,base_name,&error) < 0) { error = MapErrnoToIoErr(error); @@ -3869,7 +3914,7 @@ Action_CreateDir( 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) + if(smba_open(ServerData,full_name,open_read_only,open_dont_truncate,&ln->ln_File,&error) < 0) { error = MapErrnoToIoErr(error); goto out; @@ -3879,18 +3924,17 @@ Action_CreateDir( result = MKBADDR(&ln->ln_FileLock); SHOWVALUE(&ln->ln_FileLock); + full_name = NULL; + ln = NULL; + out: if(dir != NULL) smba_close(dir,&ignored_error); FreeMemory(dir_name); - - if(result == ZERO) - { - FreeMemory(full_name); - FreeMemory(ln); - } + FreeMemory(full_name); + FreeMemory(ln); (*error_ptr) = error; @@ -3909,7 +3953,6 @@ Action_LocateObject( { BPTR result = ZERO; STRPTR full_name = NULL; - int full_name_size; struct LockNode * ln = NULL; STRPTR parent_name; TEXT name[MAX_FILENAME_LEN+1]; @@ -3964,15 +4007,17 @@ Action_LocateObject( goto out; } - error = BuildFullName(parent_name,name,&full_name,&full_name_size); + error = BuildFullName(parent_name,name,&full_name); if(error != OK) - goto out; + { + /* Trying to get a lock on the root directory's parent? + * My pleasure. + */ + if(error == ERROR_INVALID_COMPONENT_NAME) + error = OK; - /* Trying to get a lock on the root directory's parent? - * My pleasure. - */ - if(full_name == NULL) goto out; + } ln = AllocateMemory(sizeof(*ln)); if(ln == NULL) @@ -3995,7 +4040,7 @@ Action_LocateObject( 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) + if(smba_open(ServerData,full_name,open_read_only,open_dont_truncate,&ln->ln_File,&error) < 0) { error = MapErrnoToIoErr(error); goto out; @@ -4005,13 +4050,13 @@ Action_LocateObject( result = MKBADDR(&ln->ln_FileLock); SHOWVALUE(&ln->ln_FileLock); + full_name = NULL; + ln = NULL; + out: - if(result == ZERO) - { - FreeMemory(full_name); - FreeMemory(ln); - } + FreeMemory(full_name); + FreeMemory(ln); (*error_ptr) = error; @@ -4028,9 +4073,9 @@ Action_CopyDir( { BPTR result = ZERO; STRPTR full_name = NULL; - int full_name_size; struct LockNode * ln = NULL; - STRPTR source_name; + const TEXT * source_name; + int source_name_len; LONG source_mode; int error; @@ -4067,18 +4112,16 @@ Action_CopyDir( source_mode = SHARED_LOCK; } - full_name_size = strlen(source_name)+3; - if(full_name_size < SMB_MAXNAMELEN+1) - full_name_size = SMB_MAXNAMELEN+1; + source_name_len = strlen(source_name); - full_name = AllocateMemory(full_name_size); + full_name = AllocateMemory(source_name_len+1); if(full_name == NULL) { error = ERROR_NO_FREE_STORE; goto out; } - strcpy(full_name,source_name); + memcpy(full_name,source_name,source_name_len+1); ln->ln_FileLock.fl_Key = (LONG)ln; ln->ln_FileLock.fl_Access = source_mode; @@ -4088,7 +4131,7 @@ Action_CopyDir( 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) + if(smba_open(ServerData,full_name,open_read_only,open_dont_truncate,&ln->ln_File,&error) < 0) { error = MapErrnoToIoErr(error); goto out; @@ -4098,13 +4141,13 @@ Action_CopyDir( result = MKBADDR(&ln->ln_FileLock); SHOWVALUE(&ln->ln_FileLock); + full_name = NULL; + ln = NULL; + out: - if(result == ZERO) - { - FreeMemory(full_name); - FreeMemory(ln); - } + FreeMemory(full_name); + FreeMemory(ln); (*error_ptr) = error; @@ -4210,7 +4253,6 @@ Action_SetProtect( { LONG result = DOSFALSE; STRPTR full_name = NULL; - int full_name_size; smba_file_t * file = NULL; STRPTR parent_name; TEXT name[MAX_FILENAME_LEN+1]; @@ -4266,22 +4308,21 @@ Action_SetProtect( } } - error = BuildFullName(parent_name,name,&full_name,&full_name_size); + error = BuildFullName(parent_name,name,&full_name); if(error != OK) - goto out; - - /* Trying to change the protection bits of the root - * directory, are you kidding? - */ - if(full_name == NULL) { - error = ERROR_OBJECT_WRONG_TYPE; + /* Trying to change the protection bits of the root + * directory, are you kidding? + */ + if(error == ERROR_INVALID_COMPONENT_NAME) + error = ERROR_OBJECT_WRONG_TYPE; + goto out; } 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) + if(smba_open(ServerData,full_name,open_writable,open_dont_truncate,&file,&error) < 0) { error = MapErrnoToIoErr(error); goto out; @@ -4289,8 +4330,6 @@ Action_SetProtect( memset(&st,0,sizeof(st)); - mask ^= FIBF_READ | FIBF_WRITE | FIBF_EXECUTE | FIBF_DELETE; - st.atime = -1; st.ctime = -1; st.mtime = -1; @@ -4320,8 +4359,6 @@ Action_SetProtect( out: - FreeMemory(full_name); - if(file != NULL) { int ignored_error; @@ -4329,6 +4366,8 @@ Action_SetProtect( smba_close(file, &ignored_error); } + FreeMemory(full_name); + (*error_ptr) = error; RETURN(result); @@ -4348,9 +4387,7 @@ Action_RenameObject( struct LockNode * ln; LONG result = DOSFALSE; STRPTR full_source_name = NULL; - int full_source_name_size; STRPTR full_destination_name = NULL; - int full_destination_name_size; TEXT name[MAX_FILENAME_LEN+1]; STRPTR parent_name; int error; @@ -4405,14 +4442,13 @@ Action_RenameObject( } } - error = BuildFullName(parent_name,name,&full_source_name,&full_source_name_size); + error = BuildFullName(parent_name,name,&full_source_name); if(error != OK) - goto out; - - /* Trying to rename the root directory, are you kidding? */ - if(full_source_name == NULL) { - error = ERROR_OBJECT_IN_USE; + /* Trying to rename the root directory, are you kidding? */ + if(error == ERROR_INVALID_COMPONENT_NAME) + error = ERROR_OBJECT_IN_USE; + goto out; } @@ -4455,17 +4491,20 @@ Action_RenameObject( } } - error = BuildFullName(parent_name,name,&full_destination_name,&full_destination_name_size); + error = BuildFullName(parent_name,name,&full_destination_name); if(error != OK) - goto out; - - /* Trying to rename the root directory, are you kidding? */ - if(full_destination_name == NULL) { - error = ERROR_OBJECT_IN_USE; + /* Trying to rename the root directory, are you kidding? */ + if(error == ERROR_INVALID_COMPONENT_NAME) + error = ERROR_OBJECT_IN_USE; + goto out; } + /* Is this object still in use? If so, renaming it would require + * updating the names in all the file locks and file handles which + * use it. + */ error = NameAlreadyInUse(full_source_name); if(error != OK) goto out; @@ -4474,8 +4513,8 @@ Action_RenameObject( if(error != OK) goto out; - D(("full_source_name = '%s'",escape_name(full_source_name))); - D(("full_destination_name = '%s'",escape_name(full_destination_name))); + D(("source name = '%s'",escape_name(full_source_name))); + D(("destination name = '%s'",escape_name(full_destination_name))); if(smba_rename(ServerData,full_source_name,full_destination_name,&error) < 0) { @@ -4483,6 +4522,8 @@ Action_RenameObject( goto out; } + /* ZZZ purge the caches of source and destination parent directories. */ + result = DOSTRUE; out: @@ -4809,7 +4850,10 @@ Action_ExamineObject( FIBF_GRP_READ|FIBF_GRP_EXECUTE|FIBF_GRP_WRITE|FIBF_GRP_DELETE; if(st.is_read_only) - fib->fib_Protection ^= (FIBF_OTR_DELETE|FIBF_GRP_DELETE|FIBF_DELETE); + { + fib->fib_Protection &= ~(FIBF_OTR_DELETE|FIBF_GRP_DELETE); + fib->fib_Protection |= FIBF_DELETE; + } /* Careful: the 'archive' attribute has exactly the opposite * meaning in the Amiga and the SMB worlds. @@ -5651,7 +5695,6 @@ Action_Find( LONG result = DOSFALSE; STRPTR parent_path = NULL; STRPTR full_name = NULL; - int full_name_size; struct FileNode * fn = NULL; STRPTR parent_name; TEXT name[MAX_FILENAME_LEN+1]; @@ -5722,14 +5765,13 @@ Action_Find( goto out; } - error = BuildFullName(parent_name,name,&full_name,&full_name_size); + error = BuildFullName(parent_name,name,&full_name); if(error != OK) - goto out; - - /* Trying to open the root directory? */ - if(full_name == NULL) { - error = ERROR_OBJECT_WRONG_TYPE; + /* Trying to open the root directory? */ + if(error == ERROR_INVALID_COMPONENT_NAME) + error = ERROR_OBJECT_WRONG_TYPE; + goto out; } @@ -5768,10 +5810,10 @@ Action_Find( int ignored_error; smba_stat_t st; - if(smba_open(ServerData,full_name,full_name_size,open_read_only,open_dont_truncate,&file,&ignored_error) == OK && + if(smba_open(ServerData,full_name,open_read_only,open_dont_truncate,&file,&ignored_error) == OK && smba_getattr(file,&st,&ignored_error) == OK) { - /* File apparently opens Ok and information on it + /* File apparently opens OK and information on it * is available, don't try to replace it. */ create_new_file = FALSE; @@ -5802,6 +5844,7 @@ Action_Find( { int ignored_error; smba_file_t * dir; + int full_name_len; STRPTR base_name; int i; @@ -5811,22 +5854,27 @@ Action_Find( goto out; } - parent_path = AllocateMemory(strlen(full_name)+3); + full_name_len = strlen(full_name); + + /* Note: extra character required for special case below. */ + parent_path = AllocateMemory(full_name_len+2); if(parent_path == NULL) { error = ERROR_NO_FREE_STORE; goto out; } - strcpy(parent_path,full_name); + memcpy(parent_path,full_name,full_name_len+1); + base_name = NULL; - for(i = strlen(parent_path)-1 ; i >= 0 ; i--) + + for(i = full_name_len-1 ; i >= 0 ; i--) { if(parent_path[i] == SMB_PATH_SEPARATOR) { if(i == 0) { - memmove(&parent_path[1],&parent_path[0],strlen(parent_path)+1); + memmove(&parent_path[1],&parent_path[0],full_name_len+1); i++; } @@ -5840,7 +5888,7 @@ Action_Find( SHOWMSG("creating a file; finding parent path first"); 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) + if(smba_open(ServerData,parent_path,open_read_only,open_dont_truncate,&dir,&error) < 0) { error = MapErrnoToIoErr(error); goto out; @@ -5868,7 +5916,7 @@ Action_Find( } /* Now for the remainder... */ - if(smba_open(ServerData,full_name,full_name_size,action != ACTION_FINDINPUT,create_new_file,&fn->fn_File,&error) < 0) + if(smba_open(ServerData,full_name,action != ACTION_FINDINPUT,create_new_file,&fn->fn_File,&error) < 0) { error = MapErrnoToIoErr(error); goto out; @@ -5879,14 +5927,13 @@ Action_Find( AddTail((struct List *)&FileList,(struct Node *)fn); result = DOSTRUE; + full_name = NULL; + fn = NULL; + out: - if(result == DOSFALSE) - { - FreeMemory(full_name); - FreeMemory(fn); - } - + FreeMemory(full_name); + FreeMemory(fn); FreeMemory(parent_path); (*error_ptr) = error; @@ -5989,6 +6036,7 @@ Action_End( Remove((struct Node *)fn); smba_close(fn->fn_File,&ignored_error); + FreeMemory(fn->fn_FullName); FreeMemory(fn); @@ -6202,7 +6250,6 @@ Action_SetDate( { LONG result = DOSFALSE; STRPTR full_name = NULL; - int full_name_size; smba_file_t * file = NULL; STRPTR parent_name; TEXT name[MAX_FILENAME_LEN+1]; @@ -6259,20 +6306,19 @@ Action_SetDate( } } - error = BuildFullName(parent_name,name,&full_name,&full_name_size); + error = BuildFullName(parent_name,name,&full_name); if(error != OK) - goto out; - - /* Trying to change the date of the root directory? */ - if(full_name == NULL) { - error = ERROR_OBJECT_IN_USE; + /* Trying to change the date of the root directory? */ + if(error == ERROR_INVALID_COMPONENT_NAME) + error = ERROR_OBJECT_IN_USE; + goto out; } 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) + if(smba_open(ServerData,full_name,open_writable,open_dont_truncate,&file,&error) < 0) { error = MapErrnoToIoErr(error); goto out; @@ -6302,8 +6348,6 @@ Action_SetDate( out: - FreeMemory(full_name); - if(file != NULL) { int ignored_error; @@ -6311,6 +6355,8 @@ Action_SetDate( smba_close(file,&ignored_error); } + FreeMemory(full_name); + (*error_ptr) = error; RETURN(result); @@ -6478,25 +6524,25 @@ Action_ParentFH( struct LockNode * ln = NULL; int error; STRPTR full_name; - int full_name_size; + int full_name_len; int i; ENTER(); - full_name_size = strlen(fn->fn_FullName)+3; - if(full_name_size < SMB_MAXNAMELEN+1) - full_name_size = SMB_MAXNAMELEN+1; + full_name_len = strlen(fn->fn_FullName); + if(full_name_len < 2) /* Must be large enough to hold SMB_ROOT_DIR_NAME. */ + full_name_len = 2; - full_name = AllocateMemory(full_name_size); + full_name = AllocateMemory(full_name_len+1); if(full_name == NULL) { error = ERROR_NO_FREE_STORE; goto out; } - strcpy(full_name,fn->fn_FullName); + memcpy(full_name,fn->fn_FullName,full_name_len+1); - for(i = strlen(full_name)-1 ; i >= 0 ; i--) + for(i = full_name_len-1 ; i >= 0 ; i--) { if(i == 0) { @@ -6527,7 +6573,7 @@ Action_ParentFH( 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) + if(smba_open(ServerData,full_name,open_read_only,open_dont_truncate,&ln->ln_File,&error) < 0) { error = MapErrnoToIoErr(error); goto out; @@ -6537,13 +6583,13 @@ Action_ParentFH( result = MKBADDR(&ln->ln_FileLock); SHOWVALUE(&ln->ln_FileLock); + full_name = NULL; + ln = NULL; + out: - if(result == ZERO) - { - FreeMemory(ln); - FreeMemory(full_name); - } + FreeMemory(ln); + FreeMemory(full_name); (*error_ptr) = error; @@ -6561,7 +6607,7 @@ Action_CopyDirFH( BPTR result = ZERO; struct LockNode * ln = NULL; STRPTR full_name = NULL; - int full_name_size; + int full_name_len; int error; ENTER(); @@ -6572,18 +6618,16 @@ Action_CopyDirFH( goto out; } - full_name_size = strlen(fn->fn_FullName)+3; - if(full_name_size < SMB_MAXNAMELEN+1) - full_name_size = SMB_MAXNAMELEN+1; + full_name_len = strlen(fn->fn_FullName); - full_name = AllocateMemory(full_name_size); + full_name = AllocateMemory(full_name_len+1); if(full_name == NULL) { error = ERROR_NO_FREE_STORE; goto out; } - strcpy(full_name,fn->fn_FullName); + memcpy(full_name,fn->fn_FullName,full_name_len+1); ln = AllocateMemory(sizeof(*ln)); if(ln == NULL) @@ -6602,7 +6646,7 @@ Action_CopyDirFH( 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) + if (smba_open(ServerData,full_name,open_read_only,open_dont_truncate,&ln->ln_File,&error) < 0) { error = MapErrnoToIoErr(error); goto out; @@ -6612,13 +6656,13 @@ Action_CopyDirFH( result = MKBADDR(&ln->ln_FileLock); SHOWVALUE(&ln->ln_FileLock); + full_name = NULL; + ln = NULL; + out: - if(result == ZERO) - { - FreeMemory(ln); - FreeMemory(full_name); - } + FreeMemory(ln); + FreeMemory(full_name); (*error_ptr) = error; @@ -6950,7 +6994,6 @@ Action_SetComment( { LONG result = DOSFALSE; STRPTR full_name = NULL; - int full_name_size; smba_file_t * file = NULL; STRPTR parent_name; TEXT name[MAX_FILENAME_LEN+1]; @@ -7006,20 +7049,19 @@ Action_SetComment( } } - error = BuildFullName(parent_name,name,&full_name,&full_name_size); + error = BuildFullName(parent_name,name,&full_name); if(error != OK) - goto out; - - /* Trying to change the comment of the root directory? */ - if(full_name == NULL) { - error = ERROR_OBJECT_IN_USE; + /* Trying to change the comment of the root directory? */ + if(error == ERROR_INVALID_COMPONENT_NAME) + error = ERROR_OBJECT_IN_USE; + goto out; } 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) + if (smba_open(ServerData,full_name,open_writable,open_dont_truncate,&file,&error) < 0) { error = MapErrnoToIoErr(error); goto out; @@ -7040,8 +7082,6 @@ Action_SetComment( out: - FreeMemory(full_name); - if(file != NULL) { int ignored_error; @@ -7049,6 +7089,8 @@ Action_SetComment( smba_close(file, &ignored_error); } + FreeMemory(full_name); + (*error_ptr) = error; RETURN(result); diff --git a/source_code/proc.c b/source_code/proc.c index 34cd842..7ff2560 100644 --- a/source_code/proc.c +++ b/source_code/proc.c @@ -997,12 +997,35 @@ smb_proc_open (struct smb_server *server, const char *pathname, int len, int wri int result; char *p; char *buf = server->transmit_buffer; - const word o_attr = aSYSTEM | aHIDDEN | aDIR; + int retry_read_only; ENTER(); D(("pathname = '%s'", escape_name(pathname))); + /* Because the original code opened every file/directory in + * read/write mode, we emulate the same behaviour. Why this + * is done is hard to tell. Presumably, some directories need + * to be writable for modifications to take place within. + * + * If read access is requested, we start with write access + * and disable truncation just to be safe. If that attempt + * fails due to access rights issues, we try again with read + * access. + */ + if(writable) + { + retry_read_only = FALSE; + } + else + { + writable = TRUE; + + retry_read_only = TRUE; + + truncate_file = FALSE; + } + if (server->protocol >= PROTOCOL_NT1) { dword desired_access; @@ -1019,41 +1042,41 @@ smb_proc_open (struct smb_server *server, const char *pathname, int len, int wri ASSERT( smb_payload_size(server, 24, len+1) >= 0 ); - if(writable) - { - SHOWMSG("write access required"); - // desired_access = FILE_READ_DATA|FILE_WRITE_DATA|FILE_DELETE; - desired_access = GENERIC_READ|GENERIC_WRITE; - } - else - { - SHOWMSG("read access is sufficient"); - // desired_access = FILE_READ_DATA; - desired_access = GENERIC_READ; - } - - // desired_access |= FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES; - - /* Allows others to read, write and delete the file just created. - * This may be useful if smbfs hangs or you need to restart your - * System and you need to clean up after the file you just - * created. - */ - share_access = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE; - - if(writable && truncate_file) - { - create_disposition = FILE_OVERWRITE_IF; - create_options = FILE_NON_DIRECTORY_FILE | FILE_RANDOM_ACCESS; - } - else - { - create_disposition = FILE_OPEN; - create_options = 0; - } - while(TRUE) { + if(writable) + { + SHOWMSG("write access required"); + // desired_access = FILE_READ_DATA|FILE_WRITE_DATA|FILE_DELETE; + desired_access = GENERIC_READ|GENERIC_WRITE; + } + else + { + SHOWMSG("read access is sufficient"); + // desired_access = FILE_READ_DATA; + desired_access = GENERIC_READ; + } + + // desired_access |= FILE_READ_ATTRIBUTES|FILE_WRITE_ATTRIBUTES; + + /* Allows others to read, write and delete the file just created. + * This may be useful if smbfs hangs or you need to restart your + * System and you need to clean up after the file you just + * created. + */ + share_access = FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE; + + if(writable && truncate_file) + { + create_disposition = FILE_OVERWRITE_IF; + create_options = FILE_NON_DIRECTORY_FILE | FILE_RANDOM_ACCESS; + } + else + { + create_disposition = FILE_OPEN; + create_options = 0; + } + data = smb_setup_header (server, SMBntcreateX, 24, len+1); params = SMB_VWV (server->transmit_buffer); @@ -1085,6 +1108,25 @@ smb_proc_open (struct smb_server *server, const char *pathname, int len, int wri { SHOWMSG("that didn't work; retrying"); + /* Try again in read-only mode? */ + if ((*error_ptr) == EACCES || ((*error_ptr) == error_check_smb_error && smb_errno(server->rcls,server->err) == EACCES)) + { + if(retry_read_only) + { + SHOWMSG("retrying with read-only access"); + + retry_read_only = FALSE; + + writable = FALSE; + + continue; + } + else + { + goto out; + } + } + if (smb_retry (server)) continue; else @@ -1123,62 +1165,69 @@ smb_proc_open (struct smb_server *server, const char *pathname, int len, int wri goto out; } - - ASSERT( smb_payload_size(server, 2, 2 + len) >= 0 ); - - SHOWMSG("using the old SMB_COM_OPEN"); - - retry: - - p = smb_setup_header (server, SMBopen, 2, 2 + len); - WSET (buf, smb_vwv0, 0x42); /* read/write */ - WSET (buf, smb_vwv1, o_attr); - smb_encode_ascii (p, pathname, len); - - result = smb_request_ok (server, SMBopen, 7, 0, error_ptr); - if (result < 0) + else { - if (smb_retry (server)) - goto retry; + word access_and_share_modes; - if ((*error_ptr) == EACCES || ((*error_ptr) == error_check_smb_error && smb_errno(server->rcls,server->err) == EACCES)) + ASSERT( smb_payload_size(server, 2, 2 + len) >= 0 ); + + SHOWMSG("using the old SMB_COM_OPEN"); + + while(TRUE) { - /* Don't retry in read-only mode. */ if(writable) - goto out; - - ASSERT( smb_payload_size(server, 2, 2 + len) >= 0 ); - - retry_read_only: + access_and_share_modes = SMB_OPEN_SHARE_DENY_NOTHING|SMB_OPEN_ACCESS_READ_WRITE; + else + access_and_share_modes = SMB_OPEN_SHARE_DENY_NOTHING|SMB_OPEN_ACCESS_READ_ONLY; p = smb_setup_header (server, SMBopen, 2, 2 + len); - WSET (buf, smb_vwv0, 0x40); /* read only */ - WSET (buf, smb_vwv1, o_attr); + WSET (buf, smb_vwv0, access_and_share_modes); + WSET (buf, smb_vwv1, SMB_FILE_ATTRIBUTE_HIDDEN|SMB_FILE_ATTRIBUTE_SYSTEM|SMB_FILE_ATTRIBUTE_DIRECTORY); smb_encode_ascii (p, pathname, len); result = smb_request_ok (server, SMBopen, 7, 0, error_ptr); if (result < 0) { + /* Try again in read-only mode? */ + if ((*error_ptr) == EACCES || ((*error_ptr) == error_check_smb_error && smb_errno(server->rcls,server->err) == EACCES)) + { + if(retry_read_only) + { + SHOWMSG("retrying with read-only access"); + + retry_read_only = FALSE; + + writable = FALSE; + + continue; + } + else + { + goto out; + } + } + if (smb_retry (server)) - goto retry_read_only; - - goto out; + continue; + else + goto out; } - } - else - { - goto out; - } - } - /* We should now have data in vwv[0..6]. */ - 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_low = DVAL (buf, smb_vwv4); - entry->size_high = 0; - entry->opened = TRUE; - entry->writable = writable; + break; + } + + /* We should now have data in vwv[0..6]. */ + 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_low = DVAL (buf, smb_vwv4); + entry->size_high = 0; + + entry->opened = TRUE; + entry->writable = writable; + } out: @@ -1440,13 +1489,13 @@ smb_proc_readx (struct smb_server *server, struct smb_dirent *finfo, const QUAD /* smb_proc_lockingX: We don't chain any further packets to the initial one */ 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) +smb_proc_lockingX (struct smb_server *server, struct smb_dirent *finfo, const struct smb_lkrng *locks, int num_entries, int mode, long timeout, int * error_ptr) { int result; int num_locks, num_unlocks; char *buf = server->transmit_buffer; char *data; - struct smb_lkrng *p; + const struct smb_lkrng *p; int i; num_locks = num_unlocks = 0; @@ -1692,7 +1741,7 @@ smb_proc_unlink (struct smb_server *server, const char *path, const int len, int /* Allow for system and hidden files to be deleted, too. After * all, we show these in the directory lists. */ - WSET (buf, smb_vwv0, aSYSTEM | aHIDDEN); + WSET (buf, smb_vwv0, SMB_FILE_ATTRIBUTE_SYSTEM | SMB_FILE_ATTRIBUTE_HIDDEN); smb_encode_ascii (p, path, len); @@ -1738,8 +1787,8 @@ smb_proc_trunc (struct smb_server *server, word fid, dword length, int * error_p return result; } -static char * -smb_decode_dirent (char *p, struct smb_dirent *entry) +static int +smb_decode_dirent (const char *p, struct smb_dirent *entry) { size_t name_size; @@ -1753,7 +1802,7 @@ smb_decode_dirent (char *p, struct smb_dirent *entry) name_size = 13; if(name_size > entry->complete_path_size-1) - name_size = entry->complete_path_size-1; + return(-1); memcpy (entry->complete_path, p + 9, name_size); @@ -1770,13 +1819,13 @@ smb_decode_dirent (char *p, struct smb_dirent *entry) } #endif /* DEBUG */ - return p + 22; + return(0); } /* This routine is used to read in directory entries from the network. Note that it is for short directory name seeks, i.e.: protocol < PROTOCOL_LANMAN2 */ static int -smb_proc_readdir_short (struct smb_server *server, char *path, int fpos, int cache_size, struct smb_dirent *entry, int * error_ptr) +smb_proc_readdir_short (struct smb_server *server, const char *path, int fpos, int cache_size, struct smb_dirent *entry, int * error_ptr) { char *p; char *buf; @@ -1822,7 +1871,7 @@ smb_proc_readdir_short (struct smb_server *server, char *path, int fpos, int cac p = smb_setup_header (server, SMBsearch, 2, 5 + strlen (mask)); WSET (buf, smb_vwv0, entries_asked); - WSET (buf, smb_vwv1, aDIR); + WSET (buf, smb_vwv1, SMB_FILE_ATTRIBUTE_DIRECTORY); p = smb_encode_ascii (p, mask, strlen (mask)); (*p++) = 5; (void) smb_encode_word (p, 0); @@ -1833,7 +1882,7 @@ smb_proc_readdir_short (struct smb_server *server, char *path, int fpos, int cac p = smb_setup_header (server, SMBsearch, 2, 5 + SMB_STATUS_SIZE); WSET (buf, smb_vwv0, entries_asked); - WSET (buf, smb_vwv1, aDIR); + WSET (buf, smb_vwv1, SMB_FILE_ATTRIBUTE_DIRECTORY); p = smb_encode_ascii (p, "", 0); (void) smb_encode_vblock (p, status, SMB_STATUS_SIZE); } @@ -1901,9 +1950,16 @@ smb_proc_readdir_short (struct smb_server *server, char *path, int fpos, int cac } else { - p = smb_decode_dirent (p, current_entry); + if(smb_decode_dirent (p, current_entry) == 0) + { + current_entry += 1; + } + else + { + p += SMB_DIRINFO_SIZE; - current_entry += 1; + LOG (("skipped entry because name is too long; total_count = %ld, i = %ld, fpos = %ld\n", total_count, i, fpos)); + } } total_count += 1; @@ -2020,7 +2076,7 @@ smb_get_dirent_name(char *p,int level,char ** name_ptr,int * len_ptr) /* interpret a long filename structure */ static int -smb_decode_long_dirent (char *p, struct smb_dirent *finfo, int level, int * entry_length_ptr) +smb_decode_long_dirent (const char *p, struct smb_dirent *finfo, int level, int * entry_length_ptr) { int success = TRUE; @@ -2074,6 +2130,8 @@ smb_decode_long_dirent (char *p, struct smb_dirent *finfo, int level, int * entr memcpy(finfo->complete_path, name, name_len); finfo->complete_path[name_len] = '\0'; + + D(("name = '%s', length=%ld",escape_name(finfo->complete_path),name_len)); } break; @@ -2177,6 +2235,8 @@ smb_decode_long_dirent (char *p, struct smb_dirent *finfo, int level, int * entr memcpy (finfo->complete_path, p, name_len); finfo->complete_path[name_len] = '\0'; finfo->len = name_len; + + D(("name = '%s', length=%ld",escape_name(finfo->complete_path),name_len)); } break; @@ -2197,7 +2257,7 @@ smb_decode_long_dirent (char *p, struct smb_dirent *finfo, int level, int * entr } static int -smb_proc_readdir_long (struct smb_server *server, char *path, int fpos, int cache_size, struct smb_dirent *entry, int * error_ptr) +smb_proc_readdir_long (struct smb_server *server, const char *path, int fpos, int cache_size, struct smb_dirent *entry, int * error_ptr) { int max_matches = 512; /* this should actually be based on the max_recv value */ @@ -2214,7 +2274,7 @@ smb_proc_readdir_long (struct smb_server *server, char *path, int fpos, int cach int resp_data_len = 0; int resp_param_len = 0; - int attribute = aSYSTEM | aHIDDEN | aDIR; + int attribute = SMB_FILE_ATTRIBUTE_SYSTEM | SMB_FILE_ATTRIBUTE_HIDDEN | SMB_FILE_ATTRIBUTE_DIRECTORY; int result = 0; int ff_searchcount; @@ -2543,7 +2603,7 @@ smb_proc_readdir_long (struct smb_server *server, char *path, int fpos, int cach } int -smb_proc_readdir (struct smb_server *server, char *path, int fpos, int cache_size, struct smb_dirent *entry, int * error_ptr) +smb_proc_readdir (struct smb_server *server, const char *path, int fpos, int cache_size, struct smb_dirent *entry, int * error_ptr) { int result; @@ -2903,7 +2963,7 @@ smb_set_file_information(struct smb_server *server, struct smb_dirent *entry, co * entry->mtime, to make touch work. */ int -smb_proc_setattr_core (struct smb_server *server, const char *path, int len, struct smb_dirent *new_finfo, int * error_ptr) +smb_proc_setattr_core (struct smb_server *server, const char *path, int len, const struct smb_dirent *new_finfo, int * error_ptr) { char *p; char *buf = server->transmit_buffer; diff --git a/source_code/smb_abstraction.c b/source_code/smb_abstraction.c index 3e3ffe3..8d7c089 100644 --- a/source_code/smb_abstraction.c +++ b/source_code/smb_abstraction.c @@ -270,7 +270,7 @@ make_open (smba_file_t * f, int need_fid, int writable, int truncate, int * erro goto out; } - if ((f->dirent.attr & aDIR) == 0) /* a regular file */ + if ((f->dirent.attr & SMB_FILE_ATTRIBUTE_DIRECTORY) == 0) /* a regular file */ { if (f->server->server.protocol >= PROTOCOL_LANMAN2) { @@ -286,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", escape_name(f->dirent.complete_path))); + LOG (("file '%s' is already open (fileid=0x%04lx)\n", escape_name(f->dirent.complete_path), f->dirent.fileid)); } } } @@ -302,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", escape_name(f->dirent.complete_path))); + LOG (("file '%s' is already open (fileid=0x%04lx)\n", escape_name(f->dirent.complete_path), f->dirent.fileid)); } if (s->supports_E || !s->supports_E_known) @@ -348,7 +348,7 @@ make_open (smba_file_t * f, int need_fid, int writable, int truncate, int * erro /*****************************************************************************/ int -smba_open (smba_server_t * s, char *name, size_t name_size, int writable, int truncate, smba_file_t ** file, int * error_ptr) +smba_open (smba_server_t * s, char *name, int writable, int truncate, smba_file_t ** file, int * error_ptr) { smba_file_t *f; int result; @@ -367,7 +367,6 @@ smba_open (smba_server_t * s, char *name, size_t name_size, int writable, int tr memset(f,0,sizeof(*f)); f->dirent.complete_path = name; - f->dirent.complete_path_size = name_size; f->dirent.len = strlen (name); f->server = s; @@ -383,7 +382,7 @@ smba_open (smba_server_t * s, char *name, size_t name_size, int writable, int tr AddTail ((struct List *)&s->open_files, (struct Node *)f); s->num_open_files++; - LOG(("open succeeded, number of open files = %ld\n",s->num_open_files)); + LOG(("file is ready (but hasn't actually been opened yet), number of open files = %ld\n",s->num_open_files)); (*file) = f; f = NULL; @@ -415,7 +414,7 @@ write_attr (smba_file_t * f, int * error_ptr) } else { - result = make_open (f, open_dont_need_fid, open_read_only, open_dont_truncate, error_ptr); + result = make_open (f, open_dont_need_fid, open_writable, open_dont_truncate, error_ptr); if (result < 0) goto out; @@ -445,8 +444,6 @@ smba_close (smba_file_t * f, int * error_ptr) { if(f != NULL) { - 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); @@ -455,7 +452,8 @@ smba_close (smba_file_t * f, int * error_ptr) if (f->dirent.opened) { - LOG(("notifying the server that the file was closed")); + LOG (("closing file '%s' (fileid=0x%04lx)\n", escape_name(f->dirent.complete_path), f->dirent.fileid)); + smb_proc_close (&f->server->server, f->dirent.fileid, f->dirent.mtime, error_ptr); } @@ -873,11 +871,11 @@ smba_getattr (smba_file_t * f, smba_stat_t * data, int * error_ptr) f->attr_time = now; } - data->is_dir = (f->dirent.attr & aDIR) != 0; - data->is_read_only = (f->dirent.attr & aRONLY) != 0; - data->is_hidden = (f->dirent.attr & aHIDDEN) != 0; - data->is_system = (f->dirent.attr & aSYSTEM) != 0; - data->is_changed_since_last_archive = (f->dirent.attr & aARCH) != 0; + data->is_dir = (f->dirent.attr & SMB_FILE_ATTRIBUTE_DIRECTORY) != 0; + data->is_read_only = (f->dirent.attr & SMB_FILE_ATTRIBUTE_READONLY) != 0; + data->is_hidden = (f->dirent.attr & SMB_FILE_ATTRIBUTE_HIDDEN) != 0; + data->is_system = (f->dirent.attr & SMB_FILE_ATTRIBUTE_SYSTEM) != 0; + data->is_changed_since_last_archive = (f->dirent.attr & SMB_FILE_ATTRIBUTE_ARCHIVE) != 0; data->size_low = f->dirent.size_low; data->size_high = f->dirent.size_high; @@ -923,14 +921,14 @@ smba_setattr (smba_file_t * f, const smba_stat_t * data, const QUAD * const size attrs = f->dirent.attr; if (data->is_read_only) - attrs |= aRONLY; + attrs |= SMB_FILE_ATTRIBUTE_READONLY; else - attrs &= ~aRONLY; + attrs &= ~SMB_FILE_ATTRIBUTE_READONLY; if (data->is_changed_since_last_archive) - attrs |= aARCH; + attrs |= SMB_FILE_ATTRIBUTE_ARCHIVE; else - attrs &= ~aARCH; + attrs &= ~SMB_FILE_ATTRIBUTE_ARCHIVE; if(f->dirent.attr != attrs) { @@ -1059,11 +1057,11 @@ smba_readdir (smba_file_t * f, long offs, void *d, smba_callback_t callback, int 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.is_dir = (f->dircache->cache[o].attr & SMB_FILE_ATTRIBUTE_DIRECTORY) != 0; + data.is_read_only = (f->dircache->cache[o].attr & SMB_FILE_ATTRIBUTE_READONLY) != 0; + data.is_hidden = (f->dircache->cache[o].attr & SMB_FILE_ATTRIBUTE_HIDDEN) != 0; + data.is_system = (f->dircache->cache[o].attr & SMB_FILE_ATTRIBUTE_SYSTEM) != 0; + data.is_changed_since_last_archive = (f->dircache->cache[o].attr & SMB_FILE_ATTRIBUTE_ARCHIVE) != 0; 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; @@ -1149,7 +1147,7 @@ smba_create (smba_file_t * dir, const char *name, int * error_ptr) size_t len; int result; - result = make_open (dir, open_dont_need_fid, open_read_only, open_dont_truncate, error_ptr); + result = make_open (dir, open_dont_need_fid, open_writable, open_dont_truncate, error_ptr); if (result < 0) goto out; @@ -1208,7 +1206,7 @@ smba_mkdir (smba_file_t * dir, const char *name, int * error_ptr) char *path = NULL; int result; - result = make_open (dir, open_dont_need_fid, open_read_only, open_dont_truncate, error_ptr); + result = make_open (dir, open_dont_need_fid, open_writable, open_dont_truncate, error_ptr); if (result < 0) goto out; @@ -1409,6 +1407,7 @@ smba_cleanup_dircache(struct smba_server * server) static int smba_setup_dircache (struct smba_server * server,int cache_size, int * error_ptr) { + const int complete_path_size = SMB_MAXNAMELEN + 1; dircache_t * the_dircache; int result = -1; int i; @@ -1425,14 +1424,14 @@ smba_setup_dircache (struct smba_server * server,int cache_size, int * error_ptr for (i = 0; i < the_dircache->cache_size; i++) { - the_dircache->cache[i].complete_path = malloc (SMB_MAXNAMELEN + 1); + the_dircache->cache[i].complete_path = malloc (complete_path_size); if(the_dircache->cache[i].complete_path == NULL) { (*error_ptr) = ENOMEM; goto out; } - the_dircache->cache[i].complete_path_size = SMB_MAXNAMELEN + 1; + the_dircache->cache[i].complete_path_size = complete_path_size; } server->dircache = the_dircache; @@ -1754,6 +1753,7 @@ smba_get_dircache_size(struct smba_server * server) int smba_change_dircache_size(struct smba_server * server,int cache_size) { + const int complete_path_size = SMB_MAXNAMELEN + 1; dircache_t * new_cache; dircache_t * old_dircache = server->dircache; int result; @@ -1791,14 +1791,14 @@ smba_change_dircache_size(struct smba_server * server,int cache_size) /* Allocate memory for the file names. */ for(i = old_dircache->cache_size ; i < cache_size ; i++) { - new_cache->cache[i].complete_path = malloc (SMB_MAXNAMELEN + 1); + new_cache->cache[i].complete_path = malloc (complete_path_size); if(new_cache->cache[i].complete_path == NULL) { free_dircache(new_cache); goto out; } - new_cache->cache[i].complete_path_size = SMB_MAXNAMELEN + 1; + new_cache->cache[i].complete_path_size = complete_path_size; } /* Reuse the file name buffers allocated for the old cache. */ diff --git a/source_code/smb_abstraction.h b/source_code/smb_abstraction.h index dc1be3f..f90856f 100644 --- a/source_code/smb_abstraction.h +++ b/source_code/smb_abstraction.h @@ -85,7 +85,7 @@ 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); +int smba_open(smba_server_t *s, char *name, int writable, int truncate, smba_file_t **file, int * error_ptr); void smba_close(smba_file_t *f, int * error_ptr); 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); diff --git a/source_code/smbfs_rev.h b/source_code/smbfs_rev.h index c74f163..451d29b 100644 --- a/source_code/smbfs_rev.h +++ b/source_code/smbfs_rev.h @@ -1,6 +1,6 @@ #define VERSION 1 -#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)" +#define REVISION 140 +#define DATE "27.5.2018" +#define VERS "smbfs 1.140" +#define VSTRING "smbfs 1.140 (27.5.2018)\r\n" +#define VERSTAG "\0$VER: smbfs 1.140 (27.5.2018)" diff --git a/source_code/smbfs_rev.rev b/source_code/smbfs_rev.rev index 897bdc8..dee261d 100644 --- a/source_code/smbfs_rev.rev +++ b/source_code/smbfs_rev.rev @@ -1 +1 @@ -139 +140