From 145ab107b2670b3d645c6757d0a3930eaff6c4d0 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 17 Jan 2008 17:48:33 +0100 Subject: Always return nlink=1 for directories I did not test it, but it should not affect cifsfs, there are special posix calls that also return the stat information unfiltered. (This used to be commit e96cf1309e45628f4c27d03f77a4eef5e00602df) --- source3/smbd/trans2.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 23d6f12996..763b6480e3 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3745,11 +3745,6 @@ static void call_trans2qfilepathinfo(connection_struct *conn, nlink = sbuf.st_nlink; - if ((nlink > 0) && S_ISDIR(sbuf.st_mode)) { - /* NTFS does not seem to count ".." */ - nlink -= 1; - } - if ((nlink > 0) && delete_pending) { nlink -= 1; } @@ -4018,7 +4013,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd data_size = 24; SOFF_T(pdata,0,allocation_size); SOFF_T(pdata,8,file_size); - SIVAL(pdata,16,nlink); + SIVAL(pdata,16,(mode&aDIR)?1:nlink); SCVAL(pdata,20,delete_pending?1:0); SCVAL(pdata,21,(mode&aDIR)?1:0); SSVAL(pdata,22,0); /* Padding. */ @@ -4096,7 +4091,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd pdata += 40; SOFF_T(pdata,0,allocation_size); SOFF_T(pdata,8,file_size); - SIVAL(pdata,16,nlink); + SIVAL(pdata,16,(mode&aDIR)?1:nlink); SCVAL(pdata,20,delete_pending); SCVAL(pdata,21,(mode&aDIR)?1:0); SSVAL(pdata,22,0); -- cgit From ca6cf1fe94f096aac846d0111b39006bdd40b7e3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 18 Jan 2008 18:39:27 -0800 Subject: Actually test vl's new code and make it work to fix the build farm :-). Jeremy. (This used to be commit 63defd3e9d4ba3f02f36ec5ad7b73463f31962a1) --- source3/smbd/trans2.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 763b6480e3..935a881607 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -3743,12 +3743,6 @@ static void call_trans2qfilepathinfo(connection_struct *conn, } } - nlink = sbuf.st_nlink; - - if ((nlink > 0) && delete_pending) { - nlink -= 1; - } - if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) { reply_nterror(req, NT_STATUS_INVALID_LEVEL); return; @@ -3767,6 +3761,16 @@ static void call_trans2qfilepathinfo(connection_struct *conn, if (!mode) mode = FILE_ATTRIBUTE_NORMAL; + nlink = sbuf.st_nlink; + + if (nlink && (mode&aDIR)) { + nlink = 1; + } + + if ((nlink > 0) && delete_pending) { + nlink -= 1; + } + fullpathname = fname; if (!(mode & aDIR)) file_size = get_file_size(sbuf); @@ -4013,7 +4017,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd data_size = 24; SOFF_T(pdata,0,allocation_size); SOFF_T(pdata,8,file_size); - SIVAL(pdata,16,(mode&aDIR)?1:nlink); + SIVAL(pdata,16,nlink); SCVAL(pdata,20,delete_pending?1:0); SCVAL(pdata,21,(mode&aDIR)?1:0); SSVAL(pdata,22,0); /* Padding. */ @@ -4091,7 +4095,7 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd pdata += 40; SOFF_T(pdata,0,allocation_size); SOFF_T(pdata,8,file_size); - SIVAL(pdata,16,(mode&aDIR)?1:nlink); + SIVAL(pdata,16,nlink); SCVAL(pdata,20,delete_pending); SCVAL(pdata,21,(mode&aDIR)?1:0); SSVAL(pdata,22,0); -- cgit From 6d7eb2e6ecec5920fe347c5d75d8596bd289eecf Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 15 Jan 2008 13:22:39 +0100 Subject: Make get_ea_value public (This used to be commit 0aa406bbba8699063ea3758b19dca24cf42ff15a) --- source3/smbd/trans2.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 935a881607..12b0f20879 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -114,8 +114,9 @@ static bool samba_private_attr_name(const char *unix_ea_name) Get one EA value. Fill in a struct ea_struct. ****************************************************************************/ -static bool get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp, - const char *fname, char *ea_name, struct ea_struct *pea) +NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, + files_struct *fsp, const char *fname, + const char *ea_name, struct ea_struct *pea) { /* Get the value of this xattr. Max size is 64k. */ size_t attr_size = 256; @@ -126,7 +127,7 @@ static bool get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_str val = TALLOC_REALLOC_ARRAY(mem_ctx, val, char, attr_size); if (!val) { - return False; + return NT_STATUS_NO_MEMORY; } if (fsp && fsp->fh->fd != -1) { @@ -141,7 +142,7 @@ static bool get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_str } if (sizeret == -1) { - return False; + return map_nt_error_from_unix(errno); } DEBUG(10,("get_ea_value: EA %s is of length %u\n", ea_name, (unsigned int)sizeret)); @@ -149,13 +150,17 @@ static bool get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, files_str pea->flags = 0; if (strnequal(ea_name, "user.", 5)) { - pea->name = &ea_name[5]; + pea->name = talloc_strdup(mem_ctx, &ea_name[5]); } else { - pea->name = ea_name; + pea->name = talloc_strdup(mem_ctx, ea_name); + } + if (pea->name == NULL) { + TALLOC_FREE(val); + return NT_STATUS_NO_MEMORY; } pea->value.data = (unsigned char *)val; pea->value.length = (size_t)sizeret; - return True; + return NT_STATUS_OK; } /**************************************************************************** @@ -215,7 +220,9 @@ static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_str if (!listp) return NULL; - if (!get_ea_value(mem_ctx, conn, fsp, fname, p, &listp->ea)) { + if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp, + fname, p, + &listp->ea))) { return NULL; } -- cgit From 84518f1fc74437c61b79080671f3adfd809b2c32 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 19 Jan 2008 16:07:56 +0100 Subject: Add get_ea_names_from_file to sanely list posix xattrs Refactor get_ea_list_from_file to use that. (This used to be commit aec357a456798050abe565d2a744ed5f17ad5901) --- source3/smbd/trans2.c | 191 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 142 insertions(+), 49 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 12b0f20879..53eff65b54 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -163,86 +163,179 @@ NTSTATUS get_ea_value(TALLOC_CTX *mem_ctx, connection_struct *conn, return NT_STATUS_OK; } -/**************************************************************************** - Return a linked list of the total EA's. Plus the total size -****************************************************************************/ - -static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp, - const char *fname, size_t *pea_total_len) +NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, + files_struct *fsp, const char *fname, + char ***pnames, size_t *pnum_names) { /* Get a list of all xattrs. Max namesize is 64k. */ size_t ea_namelist_size = 1024; - char *ea_namelist; + char *ea_namelist = NULL; + char *p; + char **names, **tmp; + size_t num_names; ssize_t sizeret; - int i; - struct ea_list *ea_list_head = NULL; - - *pea_total_len = 0; if (!lp_ea_support(SNUM(conn))) { - return NULL; + *pnames = NULL; + *pnum_names = 0; + return NT_STATUS_OK; } - for (i = 0, ea_namelist = TALLOC_ARRAY(mem_ctx, char, ea_namelist_size); i < 6; - ea_namelist = TALLOC_REALLOC_ARRAY(mem_ctx, ea_namelist, char, ea_namelist_size), i++) { + /* + * TALLOC the result early to get the talloc hierarchy right. + */ - if (!ea_namelist) { - return NULL; + names = TALLOC_ARRAY(mem_ctx, char *, 1); + if (names == NULL) { + DEBUG(0, ("talloc failed\n")); + return NT_STATUS_NO_MEMORY; + } + + while (ea_namelist_size <= 65536) { + + ea_namelist = TALLOC_REALLOC_ARRAY( + names, ea_namelist, char, ea_namelist_size); + if (ea_namelist == NULL) { + DEBUG(0, ("talloc failed\n")); + TALLOC_FREE(names); + return NT_STATUS_NO_MEMORY; } if (fsp && fsp->fh->fd != -1) { - sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist, ea_namelist_size); + sizeret = SMB_VFS_FLISTXATTR(fsp, ea_namelist, + ea_namelist_size); } else { - sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, ea_namelist_size); + sizeret = SMB_VFS_LISTXATTR(conn, fname, ea_namelist, + ea_namelist_size); } - if (sizeret == -1 && errno == ERANGE) { + if ((sizeret == -1) && (errno = ERANGE)) { ea_namelist_size *= 2; - } else { + } + else { break; } } - if (sizeret == -1) - return NULL; + if (sizeret == -1) { + TALLOC_FREE(names); + return map_nt_error_from_unix(errno); + } - DEBUG(10,("get_ea_list_from_file: ea_namelist size = %u\n", (unsigned int)sizeret )); + DEBUG(10, ("get_ea_list_from_file: ea_namelist size = %u\n", + (unsigned int)sizeret)); - if (sizeret) { - for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p) + 1) { - struct ea_list *listp; + if (sizeret == 0) { + TALLOC_FREE(names); + *pnames = NULL; + *pnum_names = 0; + return NT_STATUS_OK; + } - if (strnequal(p, "system.", 7) || samba_private_attr_name(p)) - continue; + /* + * Ensure the result is 0-terminated + */ - listp = TALLOC_P(mem_ctx, struct ea_list); - if (!listp) - return NULL; + if (ea_namelist[sizeret-1] != '\0') { + TALLOC_FREE(names); + return NT_STATUS_INTERNAL_ERROR; + } - if (!NT_STATUS_IS_OK(get_ea_value(mem_ctx, conn, fsp, - fname, p, - &listp->ea))) { - return NULL; - } + /* + * count the names + */ + num_names = 0; - { - fstring dos_ea_name; - push_ascii_fstring(dos_ea_name, listp->ea.name); - *pea_total_len += 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length; - DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len = %u\n", - (unsigned int)*pea_total_len, dos_ea_name, - (unsigned int)listp->ea.value.length )); - } - DLIST_ADD_END(ea_list_head, listp, struct ea_list *); + for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) { + num_names += 1; + } + + tmp = TALLOC_REALLOC_ARRAY(mem_ctx, names, char *, num_names); + if (tmp == NULL) { + DEBUG(0, ("talloc failed\n")); + TALLOC_FREE(names); + return NT_STATUS_NO_MEMORY; + } + + names = tmp; + num_names = 0; + + for (p = ea_namelist; p - ea_namelist < sizeret; p += strlen(p)+1) { + names[num_names++] = p; + } + + *pnames = names; + *pnum_names = num_names; + return NT_STATUS_OK; +} + +/**************************************************************************** + Return a linked list of the total EA's. Plus the total size +****************************************************************************/ + +static struct ea_list *get_ea_list_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, files_struct *fsp, + const char *fname, size_t *pea_total_len) +{ + /* Get a list of all xattrs. Max namesize is 64k. */ + size_t i, num_names; + char **names; + struct ea_list *ea_list_head = NULL; + NTSTATUS status; + + *pea_total_len = 0; + + if (!lp_ea_support(SNUM(conn))) { + return NULL; + } + + status = get_ea_names_from_file(talloc_tos(), conn, fsp, fname, + &names, &num_names); + + if (!NT_STATUS_IS_OK(status) || (num_names == 0)) { + return NULL; + } + + for (i=0; iea))) { + return NULL; } + + push_ascii_fstring(dos_ea_name, listp->ea.name); + + *pea_total_len += + 4 + strlen(dos_ea_name) + 1 + listp->ea.value.length; + + DEBUG(10,("get_ea_list_from_file: total_len = %u, %s, val len " + "= %u\n", (unsigned int)*pea_total_len, dos_ea_name, + (unsigned int)listp->ea.value.length)); + + DLIST_ADD_END(ea_list_head, listp, struct ea_list *); + } - DEBUG(10,("get_ea_list_from_file: total_len = %u\n", (unsigned int)*pea_total_len)); + /* Add on 4 for total length. */ + if (*pea_total_len) { + *pea_total_len += 4; + } + + DEBUG(10, ("get_ea_list_from_file: total_len = %u\n", + (unsigned int)*pea_total_len)); + return ea_list_head; } -- cgit From 1b976d51928dd6fa923272d277e13e5267188869 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 19 Jan 2008 20:41:15 +0100 Subject: Add the STREAMINFO vfs call Based on jpeach's work, modified the streaminfo prototype Make use of it in trans2.c together with marshall_stream_info() (This used to be commit c34d729c7c0600a8f11bf7e489a634a4e37fe88e) --- source3/smbd/trans2.c | 112 ++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 99 insertions(+), 13 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 53eff65b54..d56a0dab09 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -5,7 +5,7 @@ Copyright (C) Stefan (metze) Metzmacher 2003 Copyright (C) Volker Lendecke 2005-2007 Copyright (C) Steve French 2005 - Copyright (C) James Peach 2007 + Copyright (C) James Peach 2006-2007 Extensively modified by Andrew Tridgell, 1995 @@ -3568,6 +3568,72 @@ static char *store_file_unix_basic_info2(connection_struct *conn, return pdata; } +static NTSTATUS marshall_stream_info(unsigned int num_streams, + const struct stream_struct *streams, + char *data, + unsigned int max_data_bytes, + unsigned int *data_size) +{ + unsigned int i; + unsigned int ofs = 0; + + for (i=0; i max_data_bytes) { + TALLOC_FREE(namebuf); + return NT_STATUS_BUFFER_TOO_SMALL; + } + + SIVAL(data, ofs+4, namelen); + SOFF_T(data, ofs+8, streams[i].size); + SOFF_T(data, ofs+16, streams[i].alloc_size); + memcpy(data+ofs+24, namebuf, namelen); + TALLOC_FREE(namebuf); + + next_offset = ofs + 24 + namelen; + + if (i == num_streams-1) { + SIVAL(data, ofs, 0); + } + else { + unsigned int align = ndr_align_size(next_offset, 8); + + if (next_offset + align > max_data_bytes) { + return NT_STATUS_BUFFER_TOO_SMALL; + } + + memset(data+next_offset, 0, align); + next_offset += align; + + SIVAL(data, ofs, next_offset - ofs); + ofs = next_offset; + } + + ofs = next_offset; + } + + *data_size = ofs; + + return NT_STATUS_OK; +} + /**************************************************************************** Reply to a TRANSACT2_QFILEINFO on a PIPE ! ****************************************************************************/ @@ -4273,20 +4339,40 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd */ case SMB_QUERY_FILE_STREAM_INFO: #endif - case SMB_FILE_STREAM_INFORMATION: - DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_STREAM_INFORMATION\n")); - if (mode & aDIR) { - data_size = 0; - } else { - size_t byte_len = dos_PutUniCode(pdata+24,"::$DATA", (size_t)0xE, False); - SIVAL(pdata,0,0); /* ??? */ - SIVAL(pdata,4,byte_len); /* Byte length of unicode string ::$DATA */ - SOFF_T(pdata,8,file_size); - SOFF_T(pdata,16,allocation_size); - data_size = 24 + byte_len; + case SMB_FILE_STREAM_INFORMATION: { + unsigned int num_streams; + struct stream_struct *streams; + NTSTATUS status; + + DEBUG(10,("call_trans2qfilepathinfo: " + "SMB_FILE_STREAM_INFORMATION\n")); + + status = SMB_VFS_STREAMINFO( + conn, fsp, fname, talloc_tos(), + &num_streams, &streams); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("could not get stream info: %s\n", + nt_errstr(status))); + reply_nterror(req, status); + return; } - break; + status = marshall_stream_info(num_streams, streams, + pdata, max_data_bytes, + &data_size); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("marshall_stream_info failed: %s\n", + nt_errstr(status))); + reply_nterror(req, status); + return; + } + + TALLOC_FREE(streams); + + break; + } case SMB_QUERY_COMPRESSION_INFO: case SMB_FILE_COMPRESSION_INFORMATION: DEBUG(10,("call_trans2qfilepathinfo: SMB_FILE_COMPRESSION_INFORMATION\n")); -- cgit From 2411c6cb90e485bd289b8b654db1c632556bfb2d Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 19 Jan 2008 23:10:09 +0100 Subject: Add "split_ntfs_stream_name()" together with a torture test (This used to be commit d813bd9e02d9baf916eb96c478be89f0c435e07c) --- source3/smbd/nttrans.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index e8df732ea2..9381174af0 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -271,6 +271,9 @@ void send_nt_replies(connection_struct *conn, /**************************************************************************** Is it an NTFS stream name ? + An NTFS file name is .:: + $DATA can be used as both a stream name and a stream type. A missing stream + name or type implies $DATA. ****************************************************************************/ bool is_ntfs_stream_name(const char *fname) -- cgit From 1069cfe4ade88a032164c1242c9480a544584655 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 19 Jan 2008 23:25:36 +0100 Subject: Add streams support This is the core of the streams support. The main change is that in files_struct there is now a base_fsp pointer that holds the main file open while a stream is open. This is necessary to get the rather strange delete semantics right: You can't delete the main file while a stream is open without FILE_SHARE_DELETE, and while a stream is open a successful unlink of the main file leads to DELETE_PENDING for all further access on the main file or any stream. (This used to be commit 6022873cc155bdbbd3fb620689715f07a24d6ed1) --- source3/smbd/close.c | 115 +++++++++++++++++++++++++- source3/smbd/filename.c | 121 +++++++++++++++++++++++++++ source3/smbd/open.c | 214 +++++++++++++++++++++++++++++++++++++++++++++--- source3/smbd/reply.c | 28 +++++-- 4 files changed, 454 insertions(+), 24 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 4c385d7611..4bd23a35fc 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -155,6 +155,75 @@ static void notify_deferred_opens(struct share_mode_lock *lck) } } +/**************************************************************************** + Delete all streams +****************************************************************************/ + +static NTSTATUS delete_all_streams(connection_struct *conn, const char *fname) +{ + struct stream_struct *stream_info; + int i; + unsigned int num_streams; + TALLOC_CTX *frame = talloc_stackframe(); + NTSTATUS status; + + status = SMB_VFS_STREAMINFO(conn, NULL, fname, talloc_tos(), + &num_streams, &stream_info); + + if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) { + DEBUG(10, ("no streams around\n")); + TALLOC_FREE(frame); + return NT_STATUS_OK; + } + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("SMB_VFS_STREAMINFO failed: %s\n", + nt_errstr(status))); + goto fail; + } + + DEBUG(10, ("delete_all_streams found %d streams\n", + num_streams)); + + if (num_streams == 0) { + TALLOC_FREE(frame); + return NT_STATUS_OK; + } + + for (i=0; ifs_capabilities & FILE_NAMED_STREAMS) + && !is_ntfs_stream_name(fsp->fsp_name)) { + + status = delete_all_streams(conn, fsp->fsp_name); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(5, ("delete_all_streams failed: %s\n", + nt_errstr(status))); + goto done; + } + } + + if (SMB_VFS_UNLINK(conn,fsp->fsp_name) != 0) { /* * This call can potentially fail as another smbd may @@ -570,12 +652,37 @@ static NTSTATUS close_stat(files_struct *fsp) NTSTATUS close_file(files_struct *fsp, enum file_close_type close_type) { + NTSTATUS status; + struct files_struct *base_fsp = fsp->base_fsp; + if(fsp->is_directory) { - return close_directory(fsp, close_type); + status = close_directory(fsp, close_type); } else if (fsp->is_stat) { - return close_stat(fsp); + status = close_stat(fsp); } else if (fsp->fake_file_handle != NULL) { - return close_fake_file(fsp); + status = close_fake_file(fsp); + } else { + status = close_normal_file(fsp, close_type); + } + + if (!NT_STATUS_IS_OK(status)) { + return status; } - return close_normal_file(fsp, close_type); + + if ((base_fsp != NULL) && (close_type != SHUTDOWN_CLOSE)) { + + /* + * fsp was a stream, the base fsp can't be a stream as well + * + * For SHUTDOWN_CLOSE this is not possible here, because + * SHUTDOWN_CLOSE only happens from files.c which walks the + * complete list of files. If we mess with more than one fsp + * those loops will become confused. + */ + + SMB_ASSERT(base_fsp->base_fsp == NULL); + close_file(base_fsp, close_type); + } + + return status; } diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index be4960cab8..1d44c7498e 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -28,6 +28,13 @@ static bool scan_directory(connection_struct *conn, const char *path, char *name, char **found_name); +static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx, + connection_struct *conn, + const char *orig_path, + const char *basepath, + const char *streamname, + SMB_STRUCT_STAT *pst, + char **path); /**************************************************************************** Mangle the 2nd name and check if it is then equal to the first name. @@ -119,6 +126,7 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, char *start, *end; char *dirpath = NULL; char *name = NULL; + char *stream = NULL; bool component_was_mangled = False; bool name_has_wildcard = False; NTSTATUS result; @@ -206,6 +214,18 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, return NT_STATUS_NO_MEMORY; } + stream = strchr_m(name, ':'); + + if (stream != NULL) { + char *tmp = talloc_strdup(ctx, stream); + if (tmp == NULL) { + TALLOC_FREE(name); + return NT_STATUS_NO_MEMORY; + } + *stream = '\0'; + stream = tmp; + } + /* * Large directory fix normalization. If we're case sensitive, and * the case preserving parameters are set to "no", normalize the case of @@ -653,6 +673,20 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, DEBUG(5,("conversion finished %s -> %s\n",orig_path, name)); done: + if (stream != NULL) { + char *tmp = NULL; + + result = build_stream_path(ctx, conn, orig_path, name, stream, + pst, &tmp); + if (!NT_STATUS_IS_OK(result)) { + goto fail; + } + + DEBUG(10, ("build_stream_path returned %s\n", tmp)); + + TALLOC_FREE(name); + name = tmp; + } *pp_conv_path = name; TALLOC_FREE(dirpath); return NT_STATUS_OK; @@ -823,3 +857,90 @@ static bool scan_directory(connection_struct *conn, const char *path, errno = ENOENT; return False; } + +static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx, + connection_struct *conn, + const char *orig_path, + const char *basepath, + const char *streamname, + SMB_STRUCT_STAT *pst, + char **path) +{ + SMB_STRUCT_STAT st; + char *result = NULL; + NTSTATUS status; + unsigned int i, num_streams; + struct stream_struct *streams = NULL; + + result = talloc_asprintf(mem_ctx, "%s%s", basepath, streamname); + if (result == NULL) { + return NT_STATUS_NO_MEMORY; + } + + if (SMB_VFS_STAT(conn, result, &st) == 0) { + *pst = st; + *path = result; + return NT_STATUS_OK; + } + + if (errno != ENOENT) { + status = map_nt_error_from_unix(errno); + DEBUG(10, ("vfs_stat failed: %s\n", nt_errstr(status))); + goto fail; + } + + status = SMB_VFS_STREAMINFO(conn, NULL, basepath, mem_ctx, + &num_streams, &streams); + + if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { + SET_STAT_INVALID(*pst); + *path = result; + return NT_STATUS_OK; + } + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("vfs_streaminfo failed: %s\n", nt_errstr(status))); + goto fail; + } + + for (i=0; icase_sensitive)) { + DEBUGADD(10, ("equal\n")); + break; + } + DEBUGADD(10, ("not equal\n")); + } + + if (i == num_streams) { + SET_STAT_INVALID(*pst); + *path = result; + TALLOC_FREE(streams); + return NT_STATUS_OK; + } + + TALLOC_FREE(result); + + result = talloc_asprintf(mem_ctx, "%s%s", basepath, streams[i].name); + if (result == NULL) { + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + SET_STAT_INVALID(*pst); + + if (SMB_VFS_STAT(conn, result, pst) == 0) { + stat_cache_add(orig_path, result, conn->case_sensitive); + } + + *path = result; + TALLOC_FREE(streams); + return NT_STATUS_OK; + + fail: + TALLOC_FREE(result); + TALLOC_FREE(streams); + return status; +} diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 9d48bcc98b..0d6e07a032 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -1842,7 +1842,9 @@ NTSTATUS open_file_ntcreate(connection_struct *conn, set_share_mode(lck, fsp, current_user.ut.uid, 0, fsp->oplock_type, new_file_created); /* Handle strange delete on close create semantics. */ - if ((create_options & FILE_DELETE_ON_CLOSE) && can_set_initial_delete_on_close(lck)) { + if ((create_options & FILE_DELETE_ON_CLOSE) + && (is_ntfs_stream_name(fname) + || can_set_initial_delete_on_close(lck))) { status = can_set_delete_on_close(fsp, True, new_dos_attributes); if (!NT_STATUS_IS_OK(status)) { @@ -2443,6 +2445,115 @@ static struct case_semantics_state *set_posix_case_semantics(TALLOC_CTX *mem_ctx return result; } +/* + * If a main file is opened for delete, all streams need to be checked for + * !FILE_SHARE_DELETE. Do this by opening with DELETE_ACCESS. + * If that works, delete them all by setting the delete on close and close. + */ + +static NTSTATUS open_streams_for_delete(connection_struct *conn, + const char *fname) +{ + struct stream_struct *stream_info; + files_struct **streams; + int i; + unsigned int num_streams; + TALLOC_CTX *frame = talloc_stackframe(); + NTSTATUS status; + + status = SMB_VFS_STREAMINFO(conn, NULL, fname, talloc_tos(), + &num_streams, &stream_info); + + if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) { + DEBUG(10, ("no streams around\n")); + TALLOC_FREE(frame); + return NT_STATUS_OK; + } + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("SMB_VFS_STREAMINFO failed: %s\n", + nt_errstr(status))); + goto fail; + } + + DEBUG(10, ("open_streams_for_delete found %d streams\n", + num_streams)); + + if (num_streams == 0) { + TALLOC_FREE(frame); + return NT_STATUS_OK; + } + + streams = TALLOC_ARRAY(talloc_tos(), files_struct *, num_streams); + if (streams == NULL) { + DEBUG(0, ("talloc failed\n")); + status = NT_STATUS_NO_MEMORY; + goto fail; + } + + for (i=0; i= 0; i--) { + if (streams[i] == NULL) { + continue; + } + + DEBUG(10, ("Closing stream # %d, %s\n", i, + streams[i]->fsp_name)); + close_file(streams[i], NORMAL_CLOSE); + } + + fail: + TALLOC_FREE(frame); + return status; +} + /* * Wrapper around open_file_ntcreate and open_directory */ @@ -2466,6 +2577,7 @@ NTSTATUS create_file_unixpath(connection_struct *conn, { SMB_STRUCT_STAT sbuf; int info = FILE_WAS_OPENED; + files_struct *base_fsp = NULL; files_struct *fsp = NULL; NTSTATUS status; @@ -2495,7 +2607,23 @@ NTSTATUS create_file_unixpath(connection_struct *conn, sbuf = *psbuf; } else { - SET_STAT_INVALID(sbuf); + if (SMB_VFS_STAT(conn, fname, &sbuf) == -1) { + SET_STAT_INVALID(sbuf); + } + } + + if ((conn->fs_capabilities & FILE_NAMED_STREAMS) + && (access_mask & DELETE_ACCESS) + && !is_ntfs_stream_name(fname)) { + /* + * We can't open a file with DELETE access if any of the + * streams is open without FILE_SHARE_DELETE + */ + status = open_streams_for_delete(conn, fname); + + if (!NT_STATUS_IS_OK(status)) { + goto fail; + } } /* This is the correct thing to do (check every time) but can_delete @@ -2528,12 +2656,61 @@ NTSTATUS create_file_unixpath(connection_struct *conn, } #endif + if ((conn->fs_capabilities & FILE_NAMED_STREAMS) + && is_ntfs_stream_name(fname) + && (!(create_options & NTCREATEX_OPTIONS_PRIVATE_STREAM_DELETE))) { + char *base; + uint32 base_create_disposition; + + if (create_options & FILE_DIRECTORY_FILE) { + status = NT_STATUS_NOT_A_DIRECTORY; + goto fail; + } + + status = split_ntfs_stream_name(talloc_tos(), fname, + &base, NULL); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("split_ntfs_stream_name failed: %s\n", + nt_errstr(status))); + goto fail; + } + + SMB_ASSERT(!is_ntfs_stream_name(base)); /* paranoia.. */ + + switch (create_disposition) { + case FILE_OPEN: + base_create_disposition = FILE_OPEN; + break; + default: + base_create_disposition = FILE_OPEN_IF; + break; + } + + status = create_file_unixpath(conn, NULL, base, 0, + FILE_SHARE_READ + | FILE_SHARE_WRITE + | FILE_SHARE_DELETE, + base_create_disposition, + 0, 0, 0, 0, NULL, NULL, + &base_fsp, NULL, NULL); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(10, ("create_file_unixpath for base %s failed: " + "%s\n", base, nt_errstr(status))); + goto fail; + } + } + /* * If it's a request for a directory open, deal with it separately. */ if (create_options & FILE_DIRECTORY_FILE) { + if (create_options & FILE_NON_DIRECTORY_FILE) { + status = NT_STATUS_INVALID_PARAMETER; + goto fail; + } + /* Can't open a temp directory. IFS kit test. */ if (file_attributes & FILE_ATTRIBUTE_TEMPORARY) { status = NT_STATUS_INVALID_PARAMETER; @@ -2664,6 +2841,16 @@ NTSTATUS create_file_unixpath(connection_struct *conn, DEBUG(10, ("create_file: info=%d\n", info)); + /* + * Set fsp->base_fsp late enough that we can't "goto fail" anymore. In + * the fail: branch we call close_file(fsp, ERROR_CLOSE) which would + * also close fsp->base_fsp which we have to also do explicitly in + * this routine here, as not in all "goto fail:" we have the fsp set + * up already to be initialized with the base_fsp. + */ + + fsp->base_fsp = base_fsp; + *result = fsp; if (pinfo != NULL) { *pinfo = info; @@ -2685,6 +2872,10 @@ NTSTATUS create_file_unixpath(connection_struct *conn, close_file(fsp, ERROR_CLOSE); fsp = NULL; } + if (base_fsp != NULL) { + close_file(base_fsp, ERROR_CLOSE); + base_fsp = NULL; + } return status; } @@ -2812,19 +3003,18 @@ NTSTATUS create_file(connection_struct *conn, status = NT_STATUS_NO_MEMORY; goto fail; } - } else { - /* - * Check to see if this is a mac fork of some kind. - */ + } + + /* + * Check to see if this is a mac fork of some kind. + */ - if (is_ntfs_stream_name(fname)) { - enum FAKE_FILE_TYPE fake_file_type; + if (is_ntfs_stream_name(fname)) { + enum FAKE_FILE_TYPE fake_file_type; - fake_file_type = is_fake_file(fname); + fake_file_type = is_fake_file(fname); - if (fake_file_type == FAKE_FILE_TYPE_NONE) { - return NT_STATUS_OBJECT_PATH_NOT_FOUND; - } + if (fake_file_type != FAKE_FILE_TYPE_NONE) { /* * Here we go! support for changing the disk quotas diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 381ddfe151..61ec611b6b 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -167,6 +167,10 @@ static NTSTATUS check_path_syntax_internal(char *path, } *d = '\0'; + + if (NT_STATUS_IS_OK(ret) && !posix_path) { + ret = split_ntfs_stream_name(NULL, path, NULL, NULL); + } return ret; } @@ -2289,14 +2293,22 @@ static NTSTATUS do_unlink(connection_struct *conn, /* On open checks the open itself will check the share mode, so don't do it here as we'll get it wrong. */ - status = open_file_ntcreate(conn, req, fname, &sbuf, - DELETE_ACCESS, - FILE_SHARE_NONE, - FILE_OPEN, - 0, - FILE_ATTRIBUTE_NORMAL, - req != NULL ? 0 : INTERNAL_OPEN_ONLY, - NULL, &fsp); + status = create_file_unixpath + (conn, /* conn */ + req, /* req */ + fname, /* fname */ + DELETE_ACCESS, /* access_mask */ + FILE_SHARE_NONE, /* share_access */ + FILE_OPEN, /* create_disposition*/ + FILE_NON_DIRECTORY_FILE, /* create_options */ + FILE_ATTRIBUTE_NORMAL, /* file_attributes */ + 0, /* oplock_request */ + 0, /* allocation_size */ + NULL, /* sd */ + NULL, /* ea_list */ + &fsp, /* result */ + NULL, /* pinfo */ + &sbuf); /* psbuf */ if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("open_file_ntcreate failed: %s\n", -- cgit From 0bb6fb7b6f8ea1c039e710f55bba779363716f2d Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 19 Jan 2008 21:53:49 -0800 Subject: Couple of minor fixes for POSIX pathname processing in the new stream code. (1) In smbd/filename, don't split the name at ':' if we know it's a posix path (this should be parameterized....). (2). When calling posix_mkdir, we get the flag FILE_FLAG_POSIX_SEMANTICS passed to open_directory(). I know for a posix client lp_posix_pathnames should be true (which is checked for in is_ntfs_stream_name() but we have an explicit flag here, so let's use it. Jeremy. (This used to be commit 7bb7a0def6518784befa75e5303289d2b4d36dd4) --- source3/smbd/filename.c | 18 ++++++++++-------- source3/smbd/open.c | 2 +- 2 files changed, 11 insertions(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/filename.c b/source3/smbd/filename.c index 1d44c7498e..10e9583049 100644 --- a/source3/smbd/filename.c +++ b/source3/smbd/filename.c @@ -214,16 +214,18 @@ NTSTATUS unix_convert(TALLOC_CTX *ctx, return NT_STATUS_NO_MEMORY; } - stream = strchr_m(name, ':'); + if (!lp_posix_pathnames()) { + stream = strchr_m(name, ':'); - if (stream != NULL) { - char *tmp = talloc_strdup(ctx, stream); - if (tmp == NULL) { - TALLOC_FREE(name); - return NT_STATUS_NO_MEMORY; + if (stream != NULL) { + char *tmp = talloc_strdup(ctx, stream); + if (tmp == NULL) { + TALLOC_FREE(name); + return NT_STATUS_NO_MEMORY; + } + *stream = '\0'; + stream = tmp; } - *stream = '\0'; - stream = tmp; } /* diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 0d6e07a032..ad221c3227 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2106,7 +2106,7 @@ NTSTATUS open_directory(connection_struct *conn, (unsigned int)create_disposition, (unsigned int)file_attributes)); - if (is_ntfs_stream_name(fname)) { + if (!(file_attributes & FILE_FLAG_POSIX_SEMANTICS) && is_ntfs_stream_name(fname)) { DEBUG(2, ("open_directory: %s is a stream name!\n", fname)); return NT_STATUS_NOT_A_DIRECTORY; } -- cgit From f87d08f6222f3e86b771c9c8ef669c1872118f6b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 20 Jan 2008 14:43:30 +0100 Subject: Don't test split_ntfs_stream_name This is a hot code path, and if it has a :, the name will be split later on anyway. (This used to be commit 9f7f6b812d89decea1456ccdc37978e645d11a63) --- source3/smbd/reply.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 61ec611b6b..5a5eb1e190 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -168,9 +168,6 @@ static NTSTATUS check_path_syntax_internal(char *path, *d = '\0'; - if (NT_STATUS_IS_OK(ret) && !posix_path) { - ret = split_ntfs_stream_name(NULL, path, NULL, NULL); - } return ret; } -- cgit From 896ec681816b38d85e3dfbb45e9df8993de42899 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 20 Jan 2008 14:44:07 +0100 Subject: NT_STATUS_OBJECT_NAME_NOT_FOUND also means "no streams around :-)" (This used to be commit 96b9a7b3eb92c9f133a3f43ffc4d57d0212e4ebd) --- source3/smbd/open.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index ad221c3227..f55728665f 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -2464,7 +2464,8 @@ static NTSTATUS open_streams_for_delete(connection_struct *conn, status = SMB_VFS_STREAMINFO(conn, NULL, fname, talloc_tos(), &num_streams, &stream_info); - if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED)) { + if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_IMPLEMENTED) + || NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { DEBUG(10, ("no streams around\n")); TALLOC_FREE(frame); return NT_STATUS_OK; -- cgit From 043a7e177476d4c281b74d6ce997219f3009744a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 20 Jan 2008 15:59:31 +0100 Subject: Activate SMB_QUERY_FILE_STREAM_INFO gcolley was right, my nt4 does not blue screen with it (This used to be commit 9f2b5dc1865ca109e1e34c91548479ad9b26f450) --- source3/smbd/trans2.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index d56a0dab09..9c48cdfbba 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -4331,14 +4331,15 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd data_size = 4; break; -#if 0 /* - * NT4 server just returns "invalid query" to this - if we try to answer - * it then NTws gets a BSOD! (tridge). - * W2K seems to want this. JRA. + * NT4 server just returns "invalid query" to this - if we try + * to answer it then NTws gets a BSOD! (tridge). W2K seems to + * want this. JRA. + */ + /* The first statement above is false - verified using Thursby + * client against NT4 -- gcolley. */ case SMB_QUERY_FILE_STREAM_INFO: -#endif case SMB_FILE_STREAM_INFORMATION: { unsigned int num_streams; struct stream_struct *streams; -- cgit From b1017bb551fd28d2f9562acb1ff7f0dde933417a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 20 Jan 2008 17:32:19 +0100 Subject: Free case_state earlier Found by a "set but never used" warning. Thanks to talloc_tos() this was not really a bug, but this way the code becomes much clearer. (This used to be commit b326f11dc39a8ce20d957aac976be0cf7108ba9d) --- source3/smbd/open.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index f55728665f..9fca38e3ed 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -3080,6 +3080,8 @@ NTSTATUS create_file(connection_struct *conn, fname = converted_fname; } + TALLOC_FREE(case_state); + /* All file access must go through check_name() */ status = check_name(conn, fname); -- cgit From 33f3eeaa00974860dfc45962d5fd34cf05396c76 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 20 Jan 2008 17:35:25 +0100 Subject: Fix some "set but never used" warnings (This used to be commit 4a6dadc5178f4861e9c032321939db3b639734b5) --- source3/smbd/reply.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 5a5eb1e190..4ea81a3819 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -3375,7 +3375,6 @@ void error_to_writebrawerr(struct smb_request *req) void reply_writebraw(struct smb_request *req) { connection_struct *conn = req->conn; - int outsize = 0; char *buf = NULL; ssize_t nwritten=0; ssize_t total_written=0; @@ -3485,8 +3484,7 @@ void reply_writebraw(struct smb_request *req) * it to send more bytes */ memcpy(buf, req->inbuf, smb_size); - outsize = srv_set_message(buf, - Protocol>PROTOCOL_COREPLUS?1:0,0,True); + srv_set_message(buf,Protocol>PROTOCOL_COREPLUS?1:0,0,True); SCVAL(buf,smb_com,SMBwritebraw); SSVALS(buf,smb_vwv0,0xFFFF); show_msg(buf); -- cgit From 9a226532221b88369b913bc9f9d6ec335620349f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 21 Jan 2008 15:10:44 +0100 Subject: Add SMB_VFS_FS_CAPABILITIES It turns out that this is a necessary operation, separate from statvfs. statvfs can fail during tcon, so conn->fs_capabilities would never see that we support streams on a particular share. James, can you check that I got the darwin variant right? Thanks! (This used to be commit 3ad798d803b3b023533bb48e6993885f22b96095) --- source3/smbd/service.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/service.c b/source3/smbd/service.c index ed8061e2f7..a8aa25405a 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -1171,16 +1171,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser, * assumes that all the filesystem mounted withing a share path have * the same characteristics, which is likely but not guaranteed. */ - { - vfs_statvfs_struct svfs; - - conn->fs_capabilities = - FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES; - if (SMB_VFS_STATVFS(conn, conn->connectpath, &svfs) == 0) { - conn->fs_capabilities = svfs.FsCapabilities; - } - } + conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn); /* * Print out the 'connected as' stuff here as we need -- cgit From 597b28b86ed99acfb488afb86b11fe48538cf169 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 22 Jan 2008 09:13:25 +0100 Subject: Fix a segfault Found by the IBM checker. Jeremy, you changed this from 'dirname == 0' which does not make sense at all in the old code to '!dirname == 0' which from my point of view makes even less sense, because the precedence of ! is according to Harbison/Steele higher than the precedence of ==. Please check that the code now actually does what it's supposed to do. Thanks! (This used to be commit c8def5564739c4c754001f84fcfb77f1093b96c3) --- source3/smbd/utmp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/utmp.c b/source3/smbd/utmp.c index e82bbea3b3..5931b2b1d0 100644 --- a/source3/smbd/utmp.c +++ b/source3/smbd/utmp.c @@ -223,7 +223,7 @@ static char *uw_pathname(TALLOC_CTX *ctx, } /* For u-files and non-explicit w-dir, look for "utmp dir" */ - if (!dirname == 0 || strlen(dirname) == 0) { + if ((dirname == NULL) || (strlen(dirname) == 0)) { dirname = talloc_strdup(ctx, lp_utmpdir()); if (!dirname) { return NULL; -- cgit From 6a69bc3ef99349edf78b5dec9a029366985f23b9 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 22 Jan 2008 09:18:40 +0100 Subject: Fix get_ea_names_from_file for many EAs Found by the IBM checker (This used to be commit 8741a9b37496e78b28d59d844aaba12f269171e0) --- source3/smbd/trans2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 9c48cdfbba..896d2dee14 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -210,7 +210,7 @@ NTSTATUS get_ea_names_from_file(TALLOC_CTX *mem_ctx, connection_struct *conn, ea_namelist_size); } - if ((sizeret == -1) && (errno = ERANGE)) { + if ((sizeret == -1) && (errno == ERANGE)) { ea_namelist_size *= 2; } else { -- cgit From 2a78eb9c0d5f82b9d893509dff3932bde9799adf Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 22 Jan 2008 09:22:14 +0100 Subject: Fix a ton of IBM checker uninitialized variable warnings SET_STAT_INVALID only sets nlink, not the other fields We might consider to change SET_STAT_INVALID to always do ZERO_STRUCT (This used to be commit 8cf8c5b2034fe093b5db7f069bc6be8d328399bf) --- source3/smbd/open.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/open.c b/source3/smbd/open.c index 9fca38e3ed..aa4bc48f3d 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -3034,8 +3034,7 @@ NTSTATUS create_file(connection_struct *conn, goto fail; } - SET_STAT_INVALID(sbuf); - + ZERO_STRUCT(sbuf); goto done; } } -- cgit From a4c2b04a2b46fd308e98cc83c26de8307f5196a5 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 21 Jan 2008 20:24:23 +0100 Subject: Hide streams from the EA API (This used to be commit e9bb3d5067b74a29beb778f85687829778e42b5b) --- source3/smbd/trans2.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 896d2dee14..b5b3ea751b 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -105,9 +105,13 @@ static bool samba_private_attr_name(const char *unix_ea_name) for (i = 0; prohibited_ea_names[i]; i++) { if (strequal( prohibited_ea_names[i], unix_ea_name)) - return True; + return true; } - return False; + if (StrnCaseCmp(unix_ea_name, SAMBA_XATTR_DOSSTREAM_PREFIX, + strlen(SAMBA_XATTR_DOSSTREAM_PREFIX)) == 0) { + return true; + } + return false; } /**************************************************************************** -- cgit From 559603ad693ede382c566cb8bbd8e6bd8d5750a6 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Tue, 22 Jan 2008 11:33:17 +0100 Subject: Get Samba version or capability information from Windows On Jan 21 16:18, Danilo Almeida wrote: > Corina wrote: > > > + time_t samba_gitcommitdate; > > And: > > > + SIVAL(pdata,28,extended_info.samba_gitcommitdate); > > + memcpy(pdata+32,extended_info.samba_version_string,32); > > Note that you are dropping bits on a system w/64-bit time_t, and that this has the 2038 problem. Right. I changed samba_gitcommitdate from time_t to NTTIME and shortened samba_version_string to 28 bytes. New patch below. Thanks, Corinna (This used to be commit 28aa1c199d3a22cda34afcaab49c0561eeb0abcb) --- source3/smbd/trans2.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index b5b3ea751b..1243bdd9d2 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2797,7 +2797,14 @@ cBytesSector=%u, cUnitTotal=%u, cUnitAvail=%d\n", (unsigned int)bsize, (unsigned case SMB_FS_OBJECTID_INFORMATION: { unsigned char objid[16]; + struct smb_extended_info extended_info; memcpy(pdata,create_volume_objectid(conn, objid),16); + samba_extended_info_version (&extended_info); + SIVAL(pdata,16,extended_info.samba_magic); + SIVAL(pdata,20,extended_info.samba_version); + SIVAL(pdata,24,extended_info.samba_subversion); + SBIG_UINT(pdata,28,extended_info.samba_gitcommitdate); + memcpy(pdata+36,extended_info.samba_version_string,28); data_len = 64; break; } -- cgit From d4d962f691d13f36226157c38f706ee4d10b9150 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 22 Jan 2008 13:00:22 +0100 Subject: Move samba_extended_info_version to smbd/trans2.c This is right now only used there, and in version.c it gave linker errors because some binaries (e.g. smbmnt) don't link in time.o (This used to be commit 1f0eaaa5911f893c822465a26fe49ab65afb0730) --- source3/smbd/trans2.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 1243bdd9d2..8b999cd8f5 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2459,6 +2459,38 @@ unsigned char *create_volume_objectid(connection_struct *conn, unsigned char obj return objid; } +static void samba_extended_info_version(struct smb_extended_info *extended_info) +{ + SMB_ASSERT(extended_info != NULL); + + extended_info->samba_magic = SAMBA_EXTENDED_INFO_MAGIC; + extended_info->samba_version = ((SAMBA_VERSION_MAJOR & 0xff) << 24) + | ((SAMBA_VERSION_MINOR & 0xff) << 16) + | ((SAMBA_VERSION_RELEASE & 0xff) << 8); +#ifdef SAMBA_VERSION_REVISION + extended_info->samba_version |= (tolower(*SAMBA_VERSION_REVISION) - 'a' + 1) & 0xff; +#endif +#ifdef SAMBA_VERSION_RC_RELEASE + extended_info->samba_subversion |= (SAMBA_VERSION_RC_RELEASE & 0xff) << 24; +#else +#ifdef SAMBA_VERSION_PRE_RELEASE + extended_info->samba_subversion |= (SAMBA_VERSION_PRE_RELEASE & 0xff) << 16; +#endif +#endif +#ifdef SAMBA_VERSION_VENDOR_PATCH + extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff); +#endif + /* FIXME: samba_gitcommitdate should contain the git commit date. */ + unix_to_nt_time(&extended_info->samba_gitcommitdate, time(NULL)); + + memset(extended_info->samba_version_string, 0, + sizeof(extended_info->samba_version_string)); + + snprintf (extended_info->samba_version_string, + sizeof(extended_info->samba_version_string), + "%s", samba_version_string()); +} + /**************************************************************************** Reply to a TRANS2_QFSINFO (query filesystem info). ****************************************************************************/ -- cgit From 9051199e40dec27d3532fbec7f5744033def1874 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Tue, 22 Jan 2008 16:38:00 +0100 Subject: Get Samba version or capability information from Windows On Jan 22 13:31, Volker Lendecke wrote: > On Tue, Jan 22, 2008 at 11:33:17AM +0100, Corinna Vinschen wrote: > > Right. I changed samba_gitcommitdate from time_t to NTTIME and shortened > > samba_version_string to 28 bytes. New patch below. > > Ok, pushed with some modifications. You might want to review > that. Reviewed and tested. Looks good, thank you! Below you'll find a tiny patch to add the git commit date. It seems I simply missed its existence in version.h :( Tested on Windows XP. Thanks, Corinna * source/smbd/trans2.c (samba_extended_info_version): Fill out samba_gitcommitdate member with GIT commit timestamp. (This used to be commit a33d0797585b5cdd304ac1eb6966b9c7c799bab6) --- source3/smbd/trans2.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 8b999cd8f5..fb845220cd 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -2481,7 +2481,9 @@ static void samba_extended_info_version(struct smb_extended_info *extended_info) extended_info->samba_subversion |= (SAMBA_VERSION_VENDOR_PATCH & 0xffff); #endif /* FIXME: samba_gitcommitdate should contain the git commit date. */ - unix_to_nt_time(&extended_info->samba_gitcommitdate, time(NULL)); +#ifdef SAMBA_VERSION_GIT_COMMIT_TIME + unix_to_nt_time(&extended_info->samba_gitcommitdate, SAMBA_VERSION_GIT_COMMIT_TIME); +#endif memset(extended_info->samba_version_string, 0, sizeof(extended_info->samba_version_string)); -- cgit From 5b35ecd930dc6267821c7a3d8b3a90c680ab71b1 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 23 Jan 2008 10:33:36 +0100 Subject: Remove two unused variables (This used to be commit f12ac1ecedd6634d8ccc54d8fce8382514e3322f) --- source3/smbd/process.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index a5bdb96650..6fd4d17d88 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -23,7 +23,6 @@ extern struct auth_context *negprot_global_auth_context; extern int smb_echo_count; -const int total_buffer_size = (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE + SAFETY_MARGIN); static enum smb_read_errors smb_read_error = SMB_READ_OK; /* -- cgit From 587cf54c61c9f1f7bcae431a82035fd942716c32 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 23 Jan 2008 11:04:10 +0100 Subject: strtok -> strtok_r (This used to be commit fd34ce437057bb34cdc37f4b066e424000d36789) --- source3/smbd/msdfs.c | 5 +++-- source3/smbd/password.c | 12 ++++++++---- 2 files changed, 11 insertions(+), 6 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c index 4ae735633b..8ffa0f7751 100644 --- a/source3/smbd/msdfs.c +++ b/source3/smbd/msdfs.c @@ -288,12 +288,13 @@ static bool parse_msdfs_symlink(TALLOC_CTX *ctx, char **alt_path = NULL; int count = 0, i; struct referral *reflist; + char *saveptr; temp = talloc_strdup(ctx, target); if (!temp) { return False; } - prot = strtok(temp,":"); + prot = strtok_r(temp, ":", &saveptr); if (!prot) { DEBUG(0,("parse_msdfs_symlink: invalid path !\n")); return False; @@ -306,7 +307,7 @@ static bool parse_msdfs_symlink(TALLOC_CTX *ctx, /* parse out the alternate paths */ while((count Date: Wed, 23 Jan 2008 16:42:31 +0100 Subject: read_socket_with_timeout has timeout=0 handling (This used to be commit 7101026061c470ed962267b43ac0aa67cc761a64) --- source3/smbd/process.c | 29 ++++++----------------------- 1 file changed, 6 insertions(+), 23 deletions(-) (limited to 'source3/smbd') diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 6fd4d17d88..d961f98cc0 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -155,16 +155,8 @@ static ssize_t read_packet_remainder(int fd, return len; } - if (timeout > 0) { - ret = read_socket_with_timeout(fd, - buffer, - len, - len, - timeout, - get_srv_read_error()); - } else { - ret = read_data(fd, buffer, len, get_srv_read_error()); - } + ret = read_socket_with_timeout(fd, buffer, len, len, timeout, + get_srv_read_error()); if (ret != len) { cond_set_smb_read_error(get_srv_read_error(), @@ -206,19 +198,10 @@ static ssize_t receive_smb_raw_talloc_partial_read(TALLOC_CTX *mem_ctx, memcpy(writeX_header, lenbuf, sizeof(lenbuf)); - if (timeout > 0) { - ret = read_socket_with_timeout(fd, - writeX_header + 4, - STANDARD_WRITE_AND_X_HEADER_SIZE, - STANDARD_WRITE_AND_X_HEADER_SIZE, - timeout, - get_srv_read_error()); - } else { - ret = read_data(fd, - writeX_header+4, - STANDARD_WRITE_AND_X_HEADER_SIZE, - get_srv_read_error()); - } + ret = read_socket_with_timeout(fd, writeX_header + 4, + STANDARD_WRITE_AND_X_HEADER_SIZE, + STANDARD_WRITE_AND_X_HEADER_SIZE, + timeout, get_srv_read_error()); if (ret != STANDARD_WRITE_AND_X_HEADER_SIZE) { cond_set_smb_read_error(get_srv_read_error(), -- cgit