The branch, v3-3-stable has been updated via bb9f768... WHATSNEW: Update changes. via 2c935e6... WHATSNEW. Update changes since 3.3.8. via cdf190a... s3:wbc_sid: Fix build. via 42aea0d... s3: Fix a memleak reported by dmarkey (cherry picked from commit 5aeb954ba9382e1975c64ac96f1e377ed6af3ae0) via 2b40f75... s3:smbclient: Fix bug 6606 (reported as 6744) in 3.3 via 7f17f28... Correct fix for bug 6781 - Cannot rename subfolders in Explorer view with recent versions of Samba. Without this fix, renaming a directory ./a to ./b, whilst a directory ./aa was already open would fail. Jeremy. (cherry picked from commit 1f604d26d038956a6ddde892610c9b2254268160) via 0e7fbe2... Fix bug 6769 - symlink unlink does nothing. Jeremy. (cherry picked from commit fdc28f6700c97e1276e3d6ae1f242f7daa9bab9e) via 89cc728... s3:mount.cifs: make "mount.cifs -V" print the version, not usage. via d7607eb... Revert "cifs mount did not properly display version string when no other parameters passed in." from 8468e58... WHATSNEW: Add more coherent explanation for bug #6680.
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v3-3-stable - Log ----------------------------------------------------------------- commit bb9f768419b656508ba1d62e8c84be7b6037a11f Author: Karolin Seeger <ksee...@samba.org> Date: Mon Oct 12 13:45:39 2009 +0200 WHATSNEW: Update changes. Karolin (cherry picked from commit 0e52cec95a7b6040a1dd6e6bb5c5439fd3378a32) commit 2c935e618331face49a11ba3459b93d453d7092f Author: Karolin Seeger <ksee...@samba.org> Date: Mon Oct 12 13:10:29 2009 +0200 WHATSNEW. Update changes since 3.3.8. Karolin (cherry picked from commit 680e39a6795729dfa5e9a748e189f1424324434f) commit cdf190a5030291807ea30481c8fee67c6b6187d5 Author: Karolin Seeger <ksee...@samba.org> Date: Mon Oct 12 11:24:30 2009 +0200 s3:wbc_sid: Fix build. Use talloc_free instead of TALLOC_FREE. Signed-off-by: Volker Lendecke <v...@samba.org> (cherry picked from commit 95389ecdeb2e1d9d9512210a92c05c7a2d753409) commit 42aea0d90745235efc57d35b96a54a2dc834aa14 Author: Volker Lendecke <v...@samba.org> Date: Fri Oct 9 22:58:14 2009 +0200 s3: Fix a memleak reported by dmarkey (cherry picked from commit 5aeb954ba9382e1975c64ac96f1e377ed6af3ae0) Fix bug #6797. (cherry picked from commit 68c77a51410bd3a1a0fbe61d6714a9a95b4d82cd) commit 2b40f75d70b94a1213e5cd78996171b428b35b56 Author: Volker Lendecke <v...@samba.org> Date: Fri Sep 18 19:45:36 2009 +0200 s3:smbclient: Fix bug 6606 (reported as 6744) in 3.3 This is a port of 1f34ffa0ca and 24309bdb2efc to 3.3. Fix file corruption using smbclient with NT4 server. (cherry picked from commit b0fdc578fb10062c36ce2df18ab37cab57a89692) commit 7f17f286d3a4a0b864fa771f945a8fc02e45ae4d Author: Jeremy Allison <j...@samba.org> Date: Wed Oct 7 15:49:56 2009 -0700 Correct fix for bug 6781 - Cannot rename subfolders in Explorer view with recent versions of Samba. Without this fix, renaming a directory ./a to ./b, whilst a directory ./aa was already open would fail. Jeremy. (cherry picked from commit 1f604d26d038956a6ddde892610c9b2254268160) commit 0e7fbe2c0b0ffeb56fc3d2a3b2cd9f45bffb91ad Author: Jeremy Allison <j...@samba.org> Date: Thu Oct 8 15:55:35 2009 -0700 Fix bug 6769 - symlink unlink does nothing. Jeremy. (cherry picked from commit fdc28f6700c97e1276e3d6ae1f242f7daa9bab9e) commit 89cc728e44b0cec6fe122b7e650f22447d251b7a Author: Michael Adam <ob...@samba.org> Date: Thu Oct 8 10:44:48 2009 -0400 s3:mount.cifs: make "mount.cifs -V" print the version, not usage. (cherry-picked from d7ca4997017e86b6f23ced64f1f1672bfb15716b) Also make "mount.cifs -h" not exit with error exit code but with return code 0. Michael Part 2/2 of a fix for bug #6692 (mount.cifs segfault). (cherry picked from commit d41131948346619be98514331d7059d9bffecac5) commit d7607eb74658cae4856bb287242bc6f5fb27438b Author: Jeff Layton <jlay...@redhat.com> Date: Thu Oct 8 10:42:37 2009 -0400 Revert "cifs mount did not properly display version string when no other parameters passed in." This reverts commit c7bf0f4c222ae46be2a751997e03197832b494cd. Part 1/2 of a fix for bug #6692. (cherry picked from commit 2cda51b4e6fba53c04f87e4c2dd99a952a63d812) ----------------------------------------------------------------------- Summary of changes: WHATSNEW.txt | 6 + source/client/mount.cifs.c | 41 +++++--- source/libsmb/clireadwrite.c | 188 +++++++++++++++++++++++++++++---- source/modules/vfs_default.c | 6 +- source/nsswitch/libwbclient/wbc_sid.c | 4 + source/smbd/files.c | 9 ++- source/smbd/posix_acls.c | 57 ++++++++--- source/smbd/reply.c | 49 +++++++-- 8 files changed, 298 insertions(+), 62 deletions(-) Changeset truncated at 500 lines: diff --git a/WHATSNEW.txt b/WHATSNEW.txt index 81a325c..2d4262c 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -9,6 +9,7 @@ This is the latest bugfix release of the Samba 3.3 series. Major enhancements in Samba 3.3.9 include: o Fix trust relationships to windows 2008 (2008 r2) (bug #6711). + o Fix file corruption using smbclient with NT4 server (bug #6606). o Fix Windows 7 share access (which defaults to NTLMv2) (bug #6680). o Fix SAMR server for Winbind access (bug #6504). @@ -22,11 +23,14 @@ Changes since 3.3.8 o Michael Adam <ob...@samba.org> * BUG 6509: Use gid (not uid) cache in fetch_gid_from_cache(). + * BUG 6692: Fix mount.cifs segfault. o Jeremy Allison <j...@samba.org> * BUG 6504: Fix SAMR server for Winbind access. + * BUG 6769: Symlink unlink does nothing. * BUG 6776: Fix core dump when running overlapping Byte Lock test. + * BUG 6781: Fix renaming of subfolders in Explorer view. o Yannick Bergeron <burgerg...@hotmail.com> @@ -49,8 +53,10 @@ o Volker Lendecke <v...@samba.org> * BUG 5886: Fix password change propagation. * BUG 6349: Initialize domain info struct. * BUG 6585: Fix unqualified "net join". + * BUG 6606: Fix file corruption using smbclient with NT4 server. * BUG 6646: Correctly chew keepalive packets. * BUG 6785: Only ever handle one event after a select call. + * BUG 6797: Fix a memleak in libwbclient. o Derrell Lipman <derrell.lip...@unwireduniverse.com> diff --git a/source/client/mount.cifs.c b/source/client/mount.cifs.c index c78aee0..0add7a8 100644 --- a/source/client/mount.cifs.c +++ b/source/client/mount.cifs.c @@ -1036,6 +1036,14 @@ uppercase_string(char *string) return 1; } +static void print_cifs_mount_version(void) +{ + printf("mount.cifs version: %s.%s%s\n", + MOUNT_CIFS_VERSION_MAJOR, + MOUNT_CIFS_VERSION_MINOR, + MOUNT_CIFS_VENDOR_SUFFIX); +} + int main(int argc, char ** argv) { int c; @@ -1097,15 +1105,25 @@ int main(int argc, char ** argv) exit(EX_SYSERR); } mountpoint = argv[2]; - } else { - if ((strcmp (argv[1], "--version") == 0) || - ((strcmp (argv[1], "-V") == 0))) { - printf ("mount.cifs version: %s.%s%s\n", - MOUNT_CIFS_VERSION_MAJOR, - MOUNT_CIFS_VERSION_MINOR, - MOUNT_CIFS_VENDOR_SUFFIX); - exit (0); + } else if (argc == 2) { + if ((strcmp(argv[1], "-V") == 0) || + (strcmp(argv[1], "--version") == 0)) + { + print_cifs_mount_version(); + exit(0); + } + + if ((strcmp(argv[1], "-h") == 0) || + (strcmp(argv[1], "-?") == 0) || + (strcmp(argv[1], "--help") == 0)) + { + mount_cifs_usage(); + exit(0); } + + mount_cifs_usage(); + exit(EX_USAGE); + } else { mount_cifs_usage(); exit(EX_USAGE); } @@ -1161,11 +1179,8 @@ int main(int argc, char ** argv) case 'v': ++verboseflag; break; - case 'V': - printf ("mount.cifs version: %s.%s%s\n", - MOUNT_CIFS_VERSION_MAJOR, - MOUNT_CIFS_VERSION_MINOR, - MOUNT_CIFS_VENDOR_SUFFIX); + case 'V': + print_cifs_mount_version(); exit (0); case 'w': flags &= ~MS_RDONLY; diff --git a/source/libsmb/clireadwrite.c b/source/libsmb/clireadwrite.c index a57f1e0..ac59c8a 100644 --- a/source/libsmb/clireadwrite.c +++ b/source/libsmb/clireadwrite.c @@ -154,6 +154,133 @@ NTSTATUS cli_read_andx_recv(struct async_req *req, ssize_t *received, return NT_STATUS_OK; } +struct cli_readall_state { + struct cli_state *cli; + uint16_t fnum; + off_t start_offset; + size_t size; + size_t received; + uint8_t *buf; +}; + +static void cli_readall_done(struct async_req *subreq); + +static struct async_req *cli_readall_send(TALLOC_CTX *mem_ctx, + struct cli_state *cli, + uint16_t fnum, + off_t offset, size_t size) +{ + struct async_req *req, *subreq; + struct cli_readall_state *state; + + req = async_req_new(mem_ctx, cli->event_ctx); + if (req == NULL) { + return NULL; + } + state = talloc(req, struct cli_readall_state); + if (state == NULL) { + TALLOC_FREE(req); + return NULL; + } + req->private_data = state; + + state->cli = cli; + state->fnum = fnum; + state->start_offset = offset; + state->size = size; + state->received = 0; + state->buf = NULL; + + subreq = cli_read_andx_send(state, cli, fnum, offset, size); + if (subreq == NULL) { + TALLOC_FREE(req); + return NULL; + } + subreq->async.fn = cli_readall_done; + subreq->async.priv = req; + return req; +} + +static void cli_readall_done(struct async_req *subreq) +{ + struct async_req *req = talloc_get_type_abort( + subreq->async.priv, struct async_req); + struct cli_readall_state *state = talloc_get_type_abort( + req->private_data, struct cli_readall_state); + ssize_t received; + uint8_t *buf; + NTSTATUS status; + + status = cli_read_andx_recv(subreq, &received, &buf); + if (!NT_STATUS_IS_OK(status)) { + async_req_error(req, status); + return; + } + + if (received == 0) { + /* EOF */ + async_req_done(req); + return; + } + + if ((state->received == 0) && (received == state->size)) { + /* Ideal case: Got it all in one run */ + state->buf = buf; + state->received += received; + async_req_done(req); + return; + } + + /* + * We got a short read, issue a read for the + * rest. Unfortunately we have to allocate the buffer + * ourselves now, as our caller expects to receive a single + * buffer. cli_read_andx does it from the buffer received from + * the net, but with a short read we have to put it together + * from several reads. + */ + + if (state->buf == NULL) { + state->buf = talloc_array(state, uint8_t, state->size); + if (async_req_nomem(state->buf, req)) { + return; + } + } + memcpy(state->buf + state->received, buf, received); + state->received += received; + + TALLOC_FREE(subreq); + + if (state->received >= state->size) { + async_req_done(req); + return; + } + + subreq = cli_read_andx_send(state, state->cli, state->fnum, + state->start_offset + state->received, + state->size - state->received); + if (async_req_nomem(subreq, req)) { + return; + } + subreq->async.fn = cli_readall_done; + subreq->async.priv = req; +} + +static NTSTATUS cli_readall_recv(struct async_req *req, ssize_t *received, + uint8_t **rcvbuf) +{ + struct cli_readall_state *state = talloc_get_type_abort( + req->private_data, struct cli_readall_state); + + SMB_ASSERT(req->state >= ASYNC_REQ_DONE); + if (req->state == ASYNC_REQ_ERROR) { + return req->status; + } + *received = state->received; + *rcvbuf = state->buf; + return NT_STATUS_OK; +} + /* * Parallel read support. * @@ -162,6 +289,12 @@ NTSTATUS cli_read_andx_recv(struct async_req *req, ssize_t *received, * the callback function "sink" in the right order. */ +struct cli_pull_subreq { + struct async_req *req; + size_t received; + uint8_t *buf; +}; + struct cli_pull_state { struct async_req *req; @@ -179,7 +312,7 @@ struct cli_pull_state { * Outstanding requests */ int num_reqs; - struct async_req **reqs; + struct cli_pull_subreq *reqs; /* * For how many bytes did we send requests already? @@ -268,7 +401,7 @@ struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx, struct cli_state *cli, state->num_reqs = MAX(window_size/state->chunk_size, 1); state->num_reqs = MIN(state->num_reqs, cli->max_mux); - state->reqs = TALLOC_ZERO_ARRAY(state, struct async_req *, + state->reqs = TALLOC_ZERO_ARRAY(state, struct cli_pull_subreq, state->num_reqs); if (state->reqs == NULL) { goto failed; @@ -288,17 +421,17 @@ struct async_req *cli_pull_send(TALLOC_CTX *mem_ctx, struct cli_state *cli, size_left = size - state->requested; request_thistime = MIN(size_left, state->chunk_size); - state->reqs[i] = cli_read_andx_send( + state->reqs[i].req = cli_readall_send( state->reqs, cli, fnum, state->start_offset + state->requested, request_thistime); - if (state->reqs[i] == NULL) { + if (state->reqs[i].req == NULL) { goto failed; } - state->reqs[i]->async.fn = cli_pull_read_done; - state->reqs[i]->async.priv = result; + state->reqs[i].req->async.fn = cli_pull_read_done; + state->reqs[i].req->async.priv = result; state->requested += request_thistime; } @@ -320,16 +453,32 @@ static void cli_pull_read_done(struct async_req *read_req) read_req->async.priv, struct async_req); struct cli_pull_state *state = talloc_get_type_abort( pull_req->private_data, struct cli_pull_state); - struct cli_request *read_state = cli_request_get(read_req); + ssize_t received; + uint8_t *buf; NTSTATUS status; + int i; - status = cli_read_andx_recv(read_req, &read_state->data.read.received, - &read_state->data.read.rcvbuf); + status = cli_readall_recv(read_req, &received, &buf); if (!NT_STATUS_IS_OK(status)) { async_req_error(state->req, status); return; } + for (i=0; i<state->num_reqs; i++) { + if (state->reqs[i].req == read_req) { + break; + } + } + + if (i == state->num_reqs) { + /* Got something we did not send. Just drop it. */ + TALLOC_FREE(read_req); + return; + } + + state->reqs[i].received = received; + state->reqs[i].buf = buf; + /* * This loop is the one to take care of out-of-order replies. All * pending requests are in state->reqs, state->reqs[top_req] is the @@ -339,34 +488,33 @@ static void cli_pull_read_done(struct async_req *read_req) * requests. */ - while (state->reqs[state->top_req] != NULL) { - struct cli_request *top_read; + while (state->reqs[state->top_req].req != NULL) { + struct cli_pull_subreq *top_read; DEBUG(11, ("cli_pull_read_done: top_req = %d\n", state->top_req)); - if (state->reqs[state->top_req]->state < ASYNC_REQ_DONE) { + if (state->reqs[state->top_req].req->state < ASYNC_REQ_DONE) { DEBUG(11, ("cli_pull_read_done: top request not yet " "done\n")); return; } - top_read = cli_request_get(state->reqs[state->top_req]); + top_read = &state->reqs[state->top_req]; DEBUG(10, ("cli_pull_read_done: Pushing %d bytes, %d already " - "pushed\n", (int)top_read->data.read.received, + "pushed\n", (int)top_read->received, (int)state->pushed)); - status = state->sink((char *)top_read->data.read.rcvbuf, - top_read->data.read.received, + status = state->sink((char *)top_read->buf, top_read->received, state->priv); if (!NT_STATUS_IS_OK(status)) { async_req_error(state->req, status); return; } - state->pushed += top_read->data.read.received; + state->pushed += top_read->received; - TALLOC_FREE(state->reqs[state->top_req]); + TALLOC_FREE(state->reqs[state->top_req].req); if (state->requested < state->size) { struct async_req *new_req; @@ -383,7 +531,7 @@ static void cli_pull_read_done(struct async_req *read_req) + state->requested), state->top_req)); - new_req = cli_read_andx_send( + new_req = cli_readall_send( state->reqs, state->cli, state->fnum, state->start_offset + state->requested, request_thistime); @@ -395,7 +543,7 @@ static void cli_pull_read_done(struct async_req *read_req) new_req->async.fn = cli_pull_read_done; new_req->async.priv = pull_req; - state->reqs[state->top_req] = new_req; + state->reqs[state->top_req].req = new_req; state->requested += request_thistime; } diff --git a/source/modules/vfs_default.c b/source/modules/vfs_default.c index 1e95633..d8ef888 100644 --- a/source/modules/vfs_default.c +++ b/source/modules/vfs_default.c @@ -993,7 +993,11 @@ static NTSTATUS vfswrap_streaminfo(vfs_handle_struct *handle, ret = SMB_VFS_FSTAT(fsp, &sbuf); } else { - ret = SMB_VFS_STAT(handle->conn, fname, &sbuf); + if (lp_posix_pathnames()) { + ret = SMB_VFS_LSTAT(handle->conn, fname, &sbuf); + } else { + ret = SMB_VFS_STAT(handle->conn, fname, &sbuf); + } } if (ret == -1) { diff --git a/source/nsswitch/libwbclient/wbc_sid.c b/source/nsswitch/libwbclient/wbc_sid.c index 18516b6..856b8b4 100644 --- a/source/nsswitch/libwbclient/wbc_sid.c +++ b/source/nsswitch/libwbclient/wbc_sid.c @@ -281,9 +281,13 @@ wbcErr wbcLookupSid(const struct wbcDomainSid *sid, if (WBC_ERROR_IS_OK(wbc_status)) { if (pdomain != NULL) { *pdomain = domain; + } else { + talloc_free(domain); } if (pname != NULL) { *pname = name; + } else { + talloc_free(name); } if (pname_type != NULL) { *pname_type = name_type; diff --git a/source/smbd/files.c b/source/smbd/files.c index cdaa5f1..e74ad7a 100644 --- a/source/smbd/files.c +++ b/source/smbd/files.c @@ -407,13 +407,18 @@ bool file_find_subpath(files_struct *dir_fsp) fsp->conn->connectpath, fsp->fsp_name); - if (strnequal(d_fullname, d1_fullname, dlen)) { + /* + * If the open file has a path that is a longer + * component, then it's a subpath. + */ + if (strnequal(d_fullname, d1_fullname, dlen) && + (d1_fullname[dlen] == '/')) { TALLOC_FREE(d_fullname); TALLOC_FREE(d1_fullname); return true; } TALLOC_FREE(d1_fullname); - } + } TALLOC_FREE(d_fullname); return false; diff --git a/source/smbd/posix_acls.c b/source/smbd/posix_acls.c index 1afd48e..c8d9e00 100644 --- a/source/smbd/posix_acls.c +++ b/source/smbd/posix_acls.c @@ -3178,13 +3178,19 @@ NTSTATUS posix_get_nt_acl(struct connection_struct *conn, const char *name, SMB_ACL_T posix_acl = NULL; SMB_ACL_T def_acl = NULL; struct pai_val *pal; + int ret; *ppdesc = NULL; DEBUG(10,("posix_get_nt_acl: called for file %s\n", name )); /* Get the stat struct for the owner info. */ - if(SMB_VFS_STAT(conn, name, &sbuf) != 0) { + if (lp_posix_pathnames()) { + ret = SMB_VFS_LSTAT(conn, name, &sbuf); + } else { + ret = SMB_VFS_STAT(conn, name, &sbuf); + } + if(ret != 0) { return map_nt_error_from_unix(errno); } @@ -3218,6 +3224,7 @@ int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid) int ret; files_struct *fsp; SMB_STRUCT_STAT st; + bool posix_paths = lp_posix_pathnames(); if(!CAN_WRITE(conn)) { return -1; @@ -3225,7 +3232,11 @@ int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid) /* Case (1). */ /* try the direct way first */ - ret = SMB_VFS_CHOWN(conn, fname, uid, gid); + if (posix_paths) { + ret = SMB_VFS_LCHOWN(conn, fname, uid, gid); + } else { + ret = SMB_VFS_CHOWN(conn, fname, uid, gid); + } if (ret == 0) return 0; @@ -3265,7 +3276,12 @@ int try_chown(connection_struct *conn, const char *fname, uid_t uid, gid_t gid) -- Samba Shared Repository