[SCM] Samba Shared Repository - branch master updated
Volker Lendecke
vlendec at samba.org
Tue Oct 13 12:35:26 MDT 2009
The branch, master has been updated
via 94d5417... s3:torture: Add a notify-bench test
via 1302526... s3:libsmb: Add cli_notify
via f3869f9... s3:rpc: Fix is_known_pipename for dynamically loaded pipes
via 1341d45... s3: Fix some nonempty blank lines
via 6e48aad... s3: Fix vfs_shadow_copy2 to allow in-path @GMT-xxx
from 5ec557d... s3/loadparm: Fix severe HPUX compiler issue.
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master
- Log -----------------------------------------------------------------
commit 94d5417d10a9baa281a19b86d157fb856430dd13
Author: Volker Lendecke <vl at samba.org>
Date: Mon Oct 12 17:29:45 2009 +0200
s3:torture: Add a notify-bench test
This is a test that creates and deletes files in a directory as fast as the
network allows it. At the same time, it opens a filechangenotify. This test is
done to just torture handling a single directory together with the notify
infrastructure.
commit 1302526a74fe71b4cb56ff3c0ce26d6c5b71d360
Author: Volker Lendecke <vl at samba.org>
Date: Mon Oct 12 16:43:19 2009 +0200
s3:libsmb: Add cli_notify
commit f3869f90f5efeabd404cc0c61f41cc5fcaeefc61
Author: Volker Lendecke <vl at samba.org>
Date: Sat Oct 3 15:33:12 2009 +0200
s3:rpc: Fix is_known_pipename for dynamically loaded pipes
commit 1341d4509c715ab115425698c82e05ad4fc9f5f8
Author: Volker Lendecke <vl at samba.org>
Date: Sun Oct 4 16:52:08 2009 +0200
s3: Fix some nonempty blank lines
commit 6e48aad3be53f06cf75fb8278457e08c510198fc
Author: Andrew Tridgell <tridge at samba.org>
Date: Wed Sep 16 03:22:56 2009 +0200
s3: Fix vfs_shadow_copy2 to allow in-path @GMT-xxx
-----------------------------------------------------------------------
Summary of changes:
source3/include/nss_info.h | 6 +-
source3/include/proto.h | 8 +
source3/libsmb/clifile.c | 144 +++++++++++++
source3/modules/vfs_shadow_copy2.c | 147 +++++++++++--
source3/passdb/util_unixsids.c | 10 +-
source3/rpc_server/srv_pipe.c | 23 ++-
source3/torture/torture.c | 403 ++++++++++++++++++++++++++++++++++++
7 files changed, 711 insertions(+), 30 deletions(-)
Changeset truncated at 500 lines:
diff --git a/source3/include/nss_info.h b/source3/include/nss_info.h
index a60a6f0..7514289 100644
--- a/source3/include/nss_info.h
+++ b/source3/include/nss_info.h
@@ -8,12 +8,12 @@
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
-
+
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@@ -36,7 +36,7 @@
struct nss_function_entry {
struct nss_function_entry *prev, *next;
-
+
const char *name;
struct nss_info_methods *methods;
};
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 8fc4195..6475a03 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -2659,6 +2659,14 @@ struct tevent_req *cli_posix_rmdir_send(TALLOC_CTX *mem_ctx,
const char *fname);
NTSTATUS cli_posix_rmdir_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx);
NTSTATUS cli_posix_rmdir(struct cli_state *cli, const char *fname);
+struct tevent_req *cli_notify_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct cli_state *cli, uint16_t fnum,
+ uint32_t buffer_size,
+ uint32_t completion_filter, bool recursive);
+NTSTATUS cli_notify_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
+ uint32_t *pnum_changes,
+ struct notify_change **pchanges);
/* The following definitions come from libsmb/clifsinfo.c */
diff --git a/source3/libsmb/clifile.c b/source3/libsmb/clifile.c
index b15aa8d..5eb8bd4 100644
--- a/source3/libsmb/clifile.c
+++ b/source3/libsmb/clifile.c
@@ -5027,3 +5027,147 @@ NTSTATUS cli_posix_rmdir(struct cli_state *cli, const char *fname)
}
return status;
}
+
+/****************************************************************************
+ filechangenotify
+****************************************************************************/
+
+struct cli_notify_state {
+ uint8_t setup[8];
+ uint32_t num_changes;
+ struct notify_change *changes;
+};
+
+static void cli_notify_done(struct tevent_req *subreq);
+
+struct tevent_req *cli_notify_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct cli_state *cli, uint16_t fnum,
+ uint32_t buffer_size,
+ uint32_t completion_filter, bool recursive)
+{
+ struct tevent_req *req, *subreq;
+ struct cli_notify_state *state;
+
+ req = tevent_req_create(mem_ctx, &state, struct cli_notify_state);
+ if (req == NULL) {
+ return NULL;
+ }
+
+ SIVAL(state->setup, 0, completion_filter);
+ SSVAL(state->setup, 4, fnum);
+ SSVAL(state->setup, 6, recursive);
+
+ subreq = cli_trans_send(
+ state, /* mem ctx. */
+ ev, /* event ctx. */
+ cli, /* cli_state. */
+ SMBnttrans, /* cmd. */
+ NULL, /* pipe name. */
+ -1, /* fid. */
+ NT_TRANSACT_NOTIFY_CHANGE, /* function. */
+ 0, /* flags. */
+ (uint16_t *)state->setup, /* setup. */
+ 4, /* num setup uint16_t words. */
+ 0, /* max returned setup. */
+ NULL, /* param. */
+ 0, /* num param. */
+ buffer_size, /* max returned param. */
+ NULL, /* data. */
+ 0, /* num data. */
+ 0); /* max returned data. */
+
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, cli_notify_done, req);
+ return req;
+}
+
+static void cli_notify_done(struct tevent_req *subreq)
+{
+ struct tevent_req *req = tevent_req_callback_data(
+ subreq, struct tevent_req);
+ struct cli_notify_state *state = tevent_req_data(
+ req, struct cli_notify_state);
+ NTSTATUS status;
+ uint8_t *params;
+ uint32_t i, ofs, num_params;
+
+ status = cli_trans_recv(subreq, talloc_tos(), NULL, NULL,
+ ¶ms, &num_params, NULL, NULL);
+ TALLOC_FREE(subreq);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10, ("cli_trans_recv returned %s\n", nt_errstr(status)));
+ tevent_req_nterror(req, status);
+ return;
+ }
+
+ state->num_changes = 0;
+ ofs = 0;
+
+ while (num_params - ofs > 12) {
+ uint32_t len = IVAL(params, ofs);
+ state->num_changes += 1;
+
+ if ((len == 0) || (ofs+len >= num_params)) {
+ break;
+ }
+ ofs += len;
+ }
+
+ state->changes = talloc_array(state, struct notify_change,
+ state->num_changes);
+ if (tevent_req_nomem(state->changes, req)) {
+ TALLOC_FREE(params);
+ return;
+ }
+
+ ofs = 0;
+
+ for (i=0; i<state->num_changes; i++) {
+ uint32_t next = IVAL(params, ofs);
+ uint32_t len = IVAL(params, ofs+8);
+ ssize_t ret;
+ char *name;
+
+ if ((next != 0) && (len+12 != next)) {
+ TALLOC_FREE(params);
+ tevent_req_nterror(
+ req, NT_STATUS_INVALID_NETWORK_RESPONSE);
+ return;
+ }
+
+ state->changes[i].action = IVAL(params, ofs+4);
+ ret = clistr_pull_talloc(params, (char *)params, &name,
+ params+ofs+12, len,
+ STR_TERMINATE|STR_UNICODE);
+ if (ret == -1) {
+ TALLOC_FREE(params);
+ tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
+ return;
+ }
+ state->changes[i].name = name;
+ ofs += next;
+ }
+
+ TALLOC_FREE(params);
+ tevent_req_done(req);
+}
+
+NTSTATUS cli_notify_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
+ uint32_t *pnum_changes,
+ struct notify_change **pchanges)
+{
+ struct cli_notify_state *state = tevent_req_data(
+ req, struct cli_notify_state);
+ NTSTATUS status;
+
+ if (tevent_req_is_nterror(req, &status)) {
+ return status;
+ }
+
+ *pnum_changes = state->num_changes;
+ *pchanges = talloc_move(mem_ctx, &state->changes);
+ return NT_STATUS_OK;
+}
diff --git a/source3/modules/vfs_shadow_copy2.c b/source3/modules/vfs_shadow_copy2.c
index eac83fc..61f71b7 100644
--- a/source3/modules/vfs_shadow_copy2.c
+++ b/source3/modules/vfs_shadow_copy2.c
@@ -76,31 +76,99 @@ static int vfs_shadow_copy2_debug_level = DBGC_VFS;
/*
make very sure it is one of our special names
*/
-static inline bool shadow_copy2_match_name(const char *name)
+static inline bool shadow_copy2_match_name(const char *name, const char **gmt_start)
{
unsigned year, month, day, hr, min, sec;
- if (name[0] != '@') return False;
- if (strncmp(name, "@GMT-", 5) != 0) return False;
- if (sscanf(name, "@GMT-%04u.%02u.%02u-%02u.%02u.%02u", &year, &month,
+ const char *p;
+ if (gmt_start) {
+ (*gmt_start) = NULL;
+ }
+ p = strstr_m(name, "@GMT-");
+ if (p == NULL) return false;
+ if (p > name && p[-1] != '/') return False;
+ if (sscanf(p, "@GMT-%04u.%02u.%02u-%02u.%02u.%02u", &year, &month,
&day, &hr, &min, &sec) != 6) {
return False;
}
- if (name[24] != 0 && name[24] != '/') {
+ if (p[24] != 0 && p[24] != '/') {
return False;
}
+ if (gmt_start) {
+ (*gmt_start) = p;
+ }
return True;
}
/*
+ shadow copy paths can also come into the server in this form:
+
+ /foo/bar/@GMT-XXXXX/some/file
+
+ This function normalises the filename to be of the form:
+
+ @GMT-XXXX/foo/bar/some/file
+ */
+static const char *shadow_copy2_normalise_path(TALLOC_CTX *mem_ctx, const char *path, const char *gmt_start)
+{
+ char *pcopy;
+ char buf[GMT_NAME_LEN];
+ size_t prefix_len;
+
+ if (path == gmt_start) {
+ return path;
+ }
+
+ prefix_len = gmt_start - path - 1;
+
+ DEBUG(10, ("path=%s, gmt_start=%s, prefix_len=%d\n", path, gmt_start,
+ (int)prefix_len));
+
+ /*
+ * We've got a/b/c/@GMT-YYYY.MM.DD-HH.MM.SS/d/e. convert to
+ * @GMT-YYYY.MM.DD-HH.MM.SS/a/b/c/d/e before further
+ * processing. As many VFS calls provide a const char *,
+ * unfortunately we have to make a copy.
+ */
+
+ pcopy = talloc_strdup(talloc_tos(), path);
+ if (pcopy == NULL) {
+ return NULL;
+ }
+
+ gmt_start = pcopy + prefix_len;
+
+ /*
+ * Copy away "@GMT-YYYY.MM.DD-HH.MM.SS"
+ */
+ memcpy(buf, gmt_start+1, GMT_NAME_LEN);
+
+ /*
+ * Make space for it including a trailing /
+ */
+ memmove(pcopy + GMT_NAME_LEN + 1, pcopy, prefix_len);
+
+ /*
+ * Move in "@GMT-YYYY.MM.DD-HH.MM.SS/" at the beginning again
+ */
+ memcpy(pcopy, buf, GMT_NAME_LEN);
+ pcopy[GMT_NAME_LEN] = '/';
+
+ DEBUG(10, ("shadow_copy2_normalise_path: %s -> %s\n", path, pcopy));
+
+ return pcopy;
+}
+
+/*
convert a name to the shadow directory
*/
#define _SHADOW2_NEXT(op, args, rtype, eret, extra) do { \
const char *name = fname; \
- if (shadow_copy2_match_name(fname)) { \
+ const char *gmt_start; \
+ if (shadow_copy2_match_name(fname, &gmt_start)) { \
char *name2; \
rtype ret; \
- name2 = convert_shadow2_name(handle, fname); \
+ name2 = convert_shadow2_name(handle, fname, gmt_start); \
if (name2 == NULL) { \
errno = EINVAL; \
return eret; \
@@ -116,11 +184,12 @@ static inline bool shadow_copy2_match_name(const char *name)
} while (0)
#define _SHADOW2_NEXT_SMB_FNAME(op, args, rtype, eret, extra) do { \
- if (shadow_copy2_match_name(smb_fname->base_name)) { \
+ const char *gmt_start; \
+ if (shadow_copy2_match_name(smb_fname->base_name, &gmt_start)) { \
char *name2; \
char *smb_base_name_tmp = NULL; \
rtype ret; \
- name2 = convert_shadow2_name(handle, smb_fname->base_name); \
+ name2 = convert_shadow2_name(handle, smb_fname->base_name, gmt_start); \
if (name2 == NULL) { \
errno = EINVAL; \
return eret; \
@@ -143,10 +212,11 @@ static inline bool shadow_copy2_match_name(const char *name)
#define _SHADOW2_NTSTATUS_NEXT(op, args, eret, extra) do { \
const char *name = fname; \
- if (shadow_copy2_match_name(fname)) { \
+ const char *gmt_start; \
+ if (shadow_copy2_match_name(fname, &gmt_start)) { \
char *name2; \
NTSTATUS ret; \
- name2 = convert_shadow2_name(handle, fname); \
+ name2 = convert_shadow2_name(handle, fname, gmt_start); \
if (name2 == NULL) { \
errno = EINVAL; \
return eret; \
@@ -168,7 +238,9 @@ static inline bool shadow_copy2_match_name(const char *name)
#define SHADOW2_NEXT_SMB_FNAME(op, args, rtype, eret) _SHADOW2_NEXT_SMB_FNAME(op, args, rtype, eret, )
#define SHADOW2_NEXT2(op, args) do { \
- if (shadow_copy2_match_name(oldname) || shadow_copy2_match_name(newname)) { \
+ const char *gmt_start1, *gmt_start2; \
+ if (shadow_copy2_match_name(oldname, &gmt_start1) || \
+ shadow_copy2_match_name(newname, &gmt_start2)) { \
errno = EROFS; \
return -1; \
} else { \
@@ -177,8 +249,9 @@ static inline bool shadow_copy2_match_name(const char *name)
} while (0)
#define SHADOW2_NEXT2_SMB_FNAME(op, args) do { \
- if (shadow_copy2_match_name(smb_fname_src->base_name) || \
- shadow_copy2_match_name(smb_fname_dst->base_name)) { \
+ const char *gmt_start1, *gmt_start2; \
+ if (shadow_copy2_match_name(smb_fname_src->base_name, &gmt_start1) || \
+ shadow_copy2_match_name(smb_fname_dst->base_name, &gmt_start2)) { \
errno = EROFS; \
return -1; \
} else { \
@@ -267,7 +340,7 @@ static const char *shadow_copy2_find_basedir(TALLOC_CTX *mem_ctx, vfs_handle_str
convert a filename from a share relative path, to a path in the
snapshot directory
*/
-static char *convert_shadow2_name(vfs_handle_struct *handle, const char *fname)
+static char *convert_shadow2_name(vfs_handle_struct *handle, const char *fname, const char *gmt_path)
{
TALLOC_CTX *tmp_ctx = talloc_new(handle->data);
const char *snapdir, *relpath, *baseoffset, *basedir;
@@ -288,6 +361,14 @@ static char *convert_shadow2_name(vfs_handle_struct *handle, const char *fname)
return NULL;
}
+ if (strncmp(fname, "@GMT-", 5) != 0) {
+ fname = shadow_copy2_normalise_path(tmp_ctx, fname, gmt_path);
+ if (fname == NULL) {
+ talloc_free(tmp_ctx);
+ return NULL;
+ }
+ }
+
relpath = fname + GMT_NAME_LEN;
baselen = strlen(basedir);
baseoffset = handle->conn->connectpath + baselen;
@@ -406,7 +487,7 @@ static int shadow_copy2_lstat(vfs_handle_struct *handle,
static int shadow_copy2_fstat(vfs_handle_struct *handle, files_struct *fsp, SMB_STRUCT_STAT *sbuf)
{
int ret = SMB_VFS_NEXT_FSTAT(handle, fsp, sbuf);
- if (ret == 0 && shadow_copy2_match_name(fsp->fsp_name->base_name)) {
+ if (ret == 0 && shadow_copy2_match_name(fsp->fsp_name->base_name, NULL)) {
convert_sbuf(handle, fsp->fsp_name->base_name, sbuf);
}
return ret;
@@ -476,8 +557,24 @@ static int shadow_copy2_mknod(vfs_handle_struct *handle,
static char *shadow_copy2_realpath(vfs_handle_struct *handle,
const char *fname, char *resolved_path)
{
- if (shadow_copy2_match_name(fname) && (fname[GMT_NAME_LEN] == '\0')) {
- return SMB_VFS_NEXT_REALPATH(handle, ".", resolved_path);
+ const char *gmt;
+
+ if (shadow_copy2_match_name(fname, &gmt)
+ && (gmt[GMT_NAME_LEN] == '\0')) {
+ char *copy, *result;
+
+ copy = talloc_strdup(talloc_tos(), fname);
+ if (copy == NULL) {
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ copy[gmt - fname] = '.';
+
+ DEBUG(10, ("calling NEXT_REALPATH with %s\n", copy));
+ result = SMB_VFS_NEXT_REALPATH(handle, copy, resolved_path);
+ TALLOC_FREE(copy);
+ return result;
}
SHADOW2_NEXT(REALPATH, (handle, name, resolved_path), char *, NULL);
}
@@ -486,14 +583,22 @@ static const char *shadow_copy2_connectpath(struct vfs_handle_struct *handle,
const char *fname)
{
TALLOC_CTX *tmp_ctx = talloc_stackframe();
- const char *snapdir, *baseoffset, *basedir;
+ const char *snapdir, *baseoffset, *basedir, *gmt_start;
size_t baselen;
char *ret;
- if (!shadow_copy2_match_name(fname)) {
+ DEBUG(10, ("shadow_copy2_connectpath called with %s\n", fname));
+
+ if (!shadow_copy2_match_name(fname, &gmt_start)) {
return handle->conn->connectpath;
}
+ fname = shadow_copy2_normalise_path(talloc_tos(), fname, gmt_start);
+ if (fname == NULL) {
+ TALLOC_FREE(tmp_ctx);
+ return NULL;
+ }
+
snapdir = shadow_copy2_find_snapdir(tmp_ctx, handle);
if (snapdir == NULL) {
DEBUG(2,("no snapdir found for share at %s\n",
@@ -644,7 +749,7 @@ static int shadow_copy2_get_shadow_copy2_data(vfs_handle_struct *handle,
SHADOW_COPY_LABEL *tlabels;
/* ignore names not of the right form in the snapshot directory */
- if (!shadow_copy2_match_name(d->d_name)) {
+ if (!shadow_copy2_match_name(d->d_name, NULL)) {
continue;
}
diff --git a/source3/passdb/util_unixsids.c b/source3/passdb/util_unixsids.c
index ad4e702..ad51253 100644
--- a/source3/passdb/util_unixsids.c
+++ b/source3/passdb/util_unixsids.c
@@ -2,17 +2,17 @@
Unix SMB/CIFS implementation.
Translate unix-defined names to SIDs and vice versa
Copyright (C) Volker Lendecke 2005
-
+
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@@ -31,7 +31,7 @@ bool sid_check_is_in_unix_users(const DOM_SID *sid)
sid_copy(&dom_sid, sid);
sid_split_rid(&dom_sid, &rid);
-
+
return sid_check_is_unix_users(&dom_sid);
}
@@ -80,7 +80,7 @@ bool sid_check_is_in_unix_groups(const DOM_SID *sid)
sid_copy(&dom_sid, sid);
sid_split_rid(&dom_sid, &rid);
-
+
return sid_check_is_unix_groups(&dom_sid);
}
diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c
--
Samba Shared Repository
More information about the samba-cvs
mailing list