[SCM] Samba Shared Repository - branch v3-6-test updated
Jeremy Allison
jra at samba.org
Tue Jan 25 15:57:11 MST 2011
The branch, v3-6-test has been updated
via 34952ac Fix bug #7863 - Unlink may unlink wrong file when hardlinks are involved.
via f818e57 Add uint32_t name_hash argument (currently unused) to get_file_infos().
via d2bf919 Add name_hash into the share mode entry struct (as yet only use for renames to identify a specific path). (cherry picked from commit b97f1ce68a512cb0da71ee1de9ddaa49dd466068)
via 6189fcd Add name_hash to files_struct. Set within fsp_set_smb_fname(). (cherry picked from commit 76418e23bcde1eba4dfefbc10c51c083567a52e6)
from 4d36084 s3-smbclient: Fix cli_errstr() usage (part of bug #7864)
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v3-6-test
- Log -----------------------------------------------------------------
commit 34952ac438db81d23caaf5c46a2c55d77bfcc97a
Author: Jeremy Allison <jra at samba.org>
Date: Tue Jan 25 14:23:19 2011 -0800
Fix bug #7863 - Unlink may unlink wrong file when hardlinks are involved.
Do this by keeping a linked list of delete on close tokens, one for
each filename that identifies a path to the dev/inode. Use the
jenkins hash of the pathname to identify the correct token.
(cherry picked from commit 44732734cca2328a8aceb2db9b577c923920f644)
commit f818e57efe68a4ec6a53ce0bba384c14c9f299ef
Author: Jeremy Allison <jra at samba.org>
Date: Tue Jan 25 13:57:38 2011 -0800
Add uint32_t name_hash argument (currently unused) to get_file_infos().
Will be used when we store more than one delete on close token.
(cherry picked from commit a65bce4e38d0b940286c7c93c226651e5fb45082)
commit d2bf919d7145079fbd81fd16792c11f4b6024edd
Author: Jeremy Allison <jra at samba.org>
Date: Tue Jan 25 14:01:52 2011 -0800
Add name_hash into the share mode entry struct (as yet only use for renames to identify a specific path).
(cherry picked from commit b97f1ce68a512cb0da71ee1de9ddaa49dd466068)
commit 6189fcd839b85dff7d1f4736e141114641bafee6
Author: Jeremy Allison <jra at samba.org>
Date: Tue Jan 25 13:49:01 2011 -0800
Add name_hash to files_struct. Set within fsp_set_smb_fname().
(cherry picked from commit 76418e23bcde1eba4dfefbc10c51c083567a52e6)
-----------------------------------------------------------------------
Summary of changes:
source3/include/proto.h | 13 ++-
source3/include/smb.h | 40 +++--
source3/libsmb/smb_share_modes.c | 45 ++++-
source3/locking/locking.c | 350 +++++++++++++++++++++++++++----------
source3/smbd/close.c | 59 ++++---
source3/smbd/dir.c | 2 +-
source3/smbd/filename.c | 10 +
source3/smbd/files.c | 33 ++++-
source3/smbd/nttrans.c | 4 +-
source3/smbd/open.c | 12 +-
source3/smbd/oplock.c | 2 +
source3/smbd/reply.c | 13 +-
source3/smbd/smb2_create.c | 2 +-
source3/smbd/smb2_getinfo.c | 6 +-
source3/smbd/trans2.c | 26 +++-
15 files changed, 454 insertions(+), 163 deletions(-)
Changeset truncated at 500 lines:
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 29dbcc9..4c7d4f3 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -3068,8 +3068,11 @@ struct share_mode_lock *fetch_share_mode_unlocked(TALLOC_CTX *mem_ctx,
bool rename_share_filename(struct messaging_context *msg_ctx,
struct share_mode_lock *lck,
const char *servicepath,
+ uint32_t orig_name_hash,
+ uint32_t new_name_hash,
const struct smb_filename *smb_fname);
void get_file_infos(struct file_id id,
+ uint32_t name_hash,
bool *delete_on_close,
struct timespec *write_time);
bool is_valid_share_mode_entry(const struct share_mode_entry *e);
@@ -3086,9 +3089,13 @@ void del_deferred_open_entry(struct share_mode_lock *lck, uint64_t mid,
bool remove_share_oplock(struct share_mode_lock *lck, files_struct *fsp);
bool downgrade_share_oplock(struct share_mode_lock *lck, files_struct *fsp);
NTSTATUS can_set_delete_on_close(files_struct *fsp, uint32 dosmode);
-void set_delete_on_close_token(struct share_mode_lock *lck, const UNIX_USER_TOKEN *tok);
-void set_delete_on_close_lck(struct share_mode_lock *lck, bool delete_on_close, const UNIX_USER_TOKEN *tok);
+const UNIX_USER_TOKEN *get_delete_on_close_token(struct share_mode_lock *lck, uint32_t name_hash);
+void set_delete_on_close_lck(files_struct *fsp,
+ struct share_mode_lock *lck,
+ bool delete_on_close,
+ const UNIX_USER_TOKEN *tok);
bool set_delete_on_close(files_struct *fsp, bool delete_on_close, const UNIX_USER_TOKEN *tok);
+bool is_delete_on_close_set(struct share_mode_lock *lck, uint32_t name_hash);
bool set_sticky_write_time(struct file_id fileid, struct timespec write_time);
bool set_write_time(struct file_id fileid, struct timespec write_time);
int share_mode_forall(void (*fn)(const struct share_mode_entry *, const char *,
@@ -4764,6 +4771,8 @@ files_struct *file_fsp(struct smb_request *req, uint16 fid);
NTSTATUS dup_file_fsp(struct smb_request *req, files_struct *from,
uint32 access_mask, uint32 share_access,
uint32 create_options, files_struct *to);
+NTSTATUS file_name_hash(connection_struct *conn,
+ const char *name, uint32_t *p_name_hash);
NTSTATUS fsp_set_smb_fname(struct files_struct *fsp,
const struct smb_filename *smb_fname_in);
diff --git a/source3/include/smb.h b/source3/include/smb.h
index 1a76691..95c1d62 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -346,6 +346,7 @@ typedef struct files_struct {
bool posix_open;
bool is_sparse;
struct smb_filename *fsp_name;
+ uint32_t name_hash; /* Jenkins hash of full pathname. */
struct vfs_fsp_data *vfs_extension;
struct fake_file_handle *fake_file_handle;
@@ -684,6 +685,7 @@ struct share_mode_entry {
unsigned long share_file_id;
uint32 uid; /* uid of file opener. */
uint16 flags; /* See SHARE_MODE_XX above. */
+ uint32_t name_hash; /* Jenkins hash of full pathname. */
};
/* oplock break message definition - linearization of share_mode_entry.
@@ -703,7 +705,8 @@ Offset Data length.
58 unsigned long file_id 4 bytes
62 uint32 uid 4 bytes
66 uint16 flags 2 bytes
-68
+68 uint32 name_hash 4 bytes
+72
*/
@@ -721,14 +724,21 @@ Offset Data length.
#define OP_BREAK_MSG_FILE_ID_OFFSET 58
#define OP_BREAK_MSG_UID_OFFSET 62
#define OP_BREAK_MSG_FLAGS_OFFSET 66
+#define OP_BREAK_MSG_NAME_HASH_OFFSET 68
#ifdef CLUSTER_SUPPORT
-#define OP_BREAK_MSG_VNN_OFFSET 68
-#define MSG_SMB_SHARE_MODE_ENTRY_SIZE 72
+#define OP_BREAK_MSG_VNN_OFFSET 72
+#define MSG_SMB_SHARE_MODE_ENTRY_SIZE 76
#else
-#define MSG_SMB_SHARE_MODE_ENTRY_SIZE 68
+#define MSG_SMB_SHARE_MODE_ENTRY_SIZE 72
#endif
+struct delete_token_list {
+ struct delete_token_list *next, *prev;
+ uint32_t name_hash;
+ UNIX_USER_TOKEN *delete_token;
+};
+
struct share_mode_lock {
const char *servicepath; /* canonicalized. */
const char *base_name;
@@ -736,8 +746,7 @@ struct share_mode_lock {
struct file_id id;
int num_share_modes;
struct share_mode_entry *share_modes;
- UNIX_USER_TOKEN *delete_token;
- bool delete_on_close;
+ struct delete_token_list *delete_tokens;
struct timespec old_write_time;
struct timespec changed_write_time;
bool fresh;
@@ -754,20 +763,23 @@ struct locking_data {
union {
struct {
int num_share_mode_entries;
- bool delete_on_close;
struct timespec old_write_time;
struct timespec changed_write_time;
- uint32 delete_token_size; /* Only valid if either of
- the two previous fields
- are True. */
+ uint32 num_delete_token_entries;
} s;
struct share_mode_entry dummy; /* Needed for alignment. */
} u;
/* The following four entries are implicit
- struct share_mode_entry modes[num_share_mode_entries];
- char unix_token[delete_token_size] (divisible by 4).
- char share_name[];
- char file_name[];
+
+ (1) struct share_mode_entry modes[num_share_mode_entries];
+
+ (2) A num_delete_token_entries of structs {
+ uint32_t len_delete_token;
+ char unix_token[len_delete_token] (divisible by 4).
+ };
+
+ (3) char share_name[];
+ (4) char file_name[];
*/
};
diff --git a/source3/libsmb/smb_share_modes.c b/source3/libsmb/smb_share_modes.c
index 9f98550..9392349 100644
--- a/source3/libsmb/smb_share_modes.c
+++ b/source3/libsmb/smb_share_modes.c
@@ -155,7 +155,8 @@ static int share_mode_entry_equal(const struct smb_share_mode_entry *e_entry,
*/
static void create_share_mode_entry(struct share_mode_entry *out,
- const struct smb_share_mode_entry *in)
+ const struct smb_share_mode_entry *in,
+ uint32_t name_hash)
{
memset(out, '\0', sizeof(struct share_mode_entry));
@@ -170,6 +171,7 @@ static void create_share_mode_entry(struct share_mode_entry *out,
out->id.extid = in->extid;
out->uid = (uint32)geteuid();
out->flags = 0;
+ out->name_hash = name_hash;
}
/*
@@ -255,12 +257,32 @@ int smb_get_share_mode_entries(struct smbdb_ctx *db_ctx,
return 0;
}
- *p_delete_on_close = ld->u.s.delete_on_close;
+ *p_delete_on_close = ld->u.s.num_delete_token_entries != 0;
*pp_list = list;
free(db_data.dptr);
return list_num;
}
+static uint32_t smb_name_hash(const char *sharepath, const char *filename, int *err)
+{
+ TDB_DATA key;
+ char *fullpath = NULL;
+ int ret;
+ uint32_t name_hash;
+
+ *err = 0;
+ ret = asprintf(&fullpath, "%s/%s", sharepath, filename);
+ if (ret == -1 || fullpath == NULL) {
+ *err = 1;
+ return 0;
+ }
+ key.dptr = (uint8_t *)fullpath;
+ key.dsize = strlen(fullpath);
+ name_hash = tdb_jenkins_hash(&key);
+ free(fullpath);
+ return name_hash;
+}
+
/*
* Create an entry in the Samba share mode db.
*/
@@ -281,6 +303,12 @@ int smb_create_share_mode_entry_ex(struct smbdb_ctx *db_ctx,
struct share_mode_entry *shares = NULL;
uint8 *new_data_p = NULL;
size_t new_data_size = 0;
+ int err = 0;
+ uint32_t name_hash = smb_name_hash(sharepath, filename, &err);
+
+ if (err) {
+ return -1;
+ }
db_data = tdb_fetch(db_ctx->smb_tdb, locking_key);
if (!db_data.dptr) {
@@ -296,10 +324,9 @@ int smb_create_share_mode_entry_ex(struct smbdb_ctx *db_ctx,
ld = (struct locking_data *)db_data.dptr;
memset(ld, '\0', sizeof(struct locking_data));
ld->u.s.num_share_mode_entries = 1;
- ld->u.s.delete_on_close = 0;
- ld->u.s.delete_token_size = 0;
+ ld->u.s.num_delete_token_entries = 0;
shares = (struct share_mode_entry *)(db_data.dptr + sizeof(struct locking_data));
- create_share_mode_entry(shares, new_entry);
+ create_share_mode_entry(shares, new_entry, name_hash);
memcpy(db_data.dptr + sizeof(struct locking_data) + sizeof(struct share_mode_entry),
sharepath,
@@ -338,12 +365,12 @@ int smb_create_share_mode_entry_ex(struct smbdb_ctx *db_ctx,
shares = (struct share_mode_entry *)(new_data_p + sizeof(struct locking_data) +
(orig_num_share_modes * sizeof(struct share_mode_entry)));
- create_share_mode_entry(shares, new_entry);
+ create_share_mode_entry(shares, new_entry, name_hash);
ld = (struct locking_data *)new_data_p;
ld->u.s.num_share_mode_entries++;
- /* Append the original delete_token and filenames. */
+ /* Append the original delete_tokens and filenames. */
memcpy(new_data_p + sizeof(struct locking_data) + (ld->u.s.num_share_mode_entries * sizeof(struct share_mode_entry)),
db_data.dptr + sizeof(struct locking_data) + (orig_num_share_modes * sizeof(struct share_mode_entry)),
db_data.dsize - sizeof(struct locking_data) - (orig_num_share_modes * sizeof(struct share_mode_entry)));
@@ -460,7 +487,7 @@ int smb_delete_share_mode_entry(struct smbdb_ctx *db_ctx,
return tdb_delete(db_ctx->smb_tdb, locking_key);
}
- /* Copy any delete token plus the terminating filenames. */
+ /* Copy any delete tokens plus the terminating filenames. */
remaining_ptr = db_data.dptr + sizeof(struct locking_data) + (orig_num_share_modes * sizeof(struct share_mode_entry));
remaining_size = db_data.dsize - (remaining_ptr - db_data.dptr);
@@ -521,7 +548,7 @@ int smb_change_share_mode_entry(struct smbdb_ctx *db_ctx,
}
if (share_mode_entry_equal(set_entry, share)) {
- create_share_mode_entry(share, new_entry);
+ create_share_mode_entry(share, new_entry, share->name_hash);
found_entry = 1;
break;
}
diff --git a/source3/locking/locking.c b/source3/locking/locking.c
index 4a61953..f98208f 100644
--- a/source3/locking/locking.c
+++ b/source3/locking/locking.c
@@ -492,7 +492,7 @@ char *share_mode_str(TALLOC_CTX *ctx, int num, const struct share_mode_entry *e)
return talloc_asprintf(ctx, "share_mode_entry[%d]: %s "
"pid = %s, share_access = 0x%x, private_options = 0x%x, "
"access_mask = 0x%x, mid = 0x%llx, type= 0x%x, gen_id = %lu, "
- "uid = %u, flags = %u, file_id %s",
+ "uid = %u, flags = %u, file_id %s, name_hash = 0x%x",
num,
e->op_type == UNUSED_SHARE_MODE_ENTRY ? "UNUSED" : "",
procid_str_static(&e->pid),
@@ -500,7 +500,8 @@ char *share_mode_str(TALLOC_CTX *ctx, int num, const struct share_mode_entry *e)
e->access_mask, (unsigned long long)e->op_mid,
e->op_type, e->share_file_id,
(unsigned int)e->uid, (unsigned int)e->flags,
- file_id_string_tos(&e->id));
+ file_id_string_tos(&e->id),
+ (unsigned int)e->name_hash);
}
/*******************************************************************
@@ -532,6 +533,104 @@ static void print_share_mode_table(struct locking_data *data)
}
}
+static int parse_delete_tokens_list(struct share_mode_lock *lck,
+ struct locking_data *pdata,
+ const TDB_DATA dbuf)
+{
+ uint8_t *p = dbuf.dptr + sizeof(struct locking_data) +
+ (lck->num_share_modes *
+ sizeof(struct share_mode_entry));
+ uint8_t *end_ptr = dbuf.dptr + (dbuf.dsize - 2);
+ int delete_tokens_size = 0;
+ int i;
+
+ lck->delete_tokens = NULL;
+
+ for (i = 0; i < pdata->u.s.num_delete_token_entries; i++) {
+ uint32_t token_len;
+ struct delete_token_list *pdtl;
+
+ if (end_ptr - p < (sizeof(uint32_t) + sizeof(uint32_t) +
+ sizeof(uid_t) + sizeof(gid_t))) {
+ DEBUG(0,("parse_delete_tokens_list: "
+ "corrupt token list (%u)",
+ (unsigned int)(end_ptr - p)));
+ smb_panic("corrupt token list");
+ return -1;
+ }
+
+ memcpy(&token_len, p, sizeof(token_len));
+ delete_tokens_size += token_len;
+
+ if (p + token_len > end_ptr || token_len < sizeof(token_len) +
+ sizeof(pdtl->name_hash) +
+ sizeof(uid_t) +
+ sizeof(gid_t)) {
+ DEBUG(0,("parse_delete_tokens_list: "
+ "invalid token length (%u)\n",
+ (unsigned int)token_len ));
+ smb_panic("invalid token length");
+ return -1;
+ }
+
+ p += sizeof(token_len);
+
+ pdtl = TALLOC_ZERO_P(lck, struct delete_token_list);
+ if (pdtl == NULL) {
+ DEBUG(0,("parse_delete_tokens_list: talloc failed"));
+ return -1;
+ }
+ /* Copy out the name_hash. */
+ memcpy(&pdtl->name_hash, p, sizeof(pdtl->name_hash));
+ p += sizeof(pdtl->name_hash);
+
+ pdtl->delete_token = TALLOC_ZERO_P(pdtl, UNIX_USER_TOKEN);
+ if (pdtl->delete_token == NULL) {
+ DEBUG(0,("parse_delete_tokens_list: talloc failed"));
+ return -1;
+ }
+
+ /* Copy out the uid and gid. */
+ memcpy(&pdtl->delete_token->uid, p, sizeof(uid_t));
+ p += sizeof(uid_t);
+ memcpy(&pdtl->delete_token->gid, p, sizeof(gid_t));
+ p += sizeof(gid_t);
+
+ token_len -= (sizeof(token_len) + sizeof(pdtl->name_hash) +
+ sizeof(uid_t) + sizeof(gid_t));
+
+ /* Any supplementary groups ? */
+ if (token_len) {
+ int j;
+
+ if (token_len % sizeof(gid_t) != 0) {
+ DEBUG(0,("parse_delete_tokens_list: "
+ "corrupt group list (%u)",
+ (unsigned int)(token_len % sizeof(gid_t)) ));
+ smb_panic("corrupt group list");
+ return -1;
+ }
+
+ pdtl->delete_token->ngroups = token_len / sizeof(gid_t);
+ pdtl->delete_token->groups = TALLOC_ARRAY(pdtl->delete_token, gid_t,
+ pdtl->delete_token->ngroups);
+ if (pdtl->delete_token->groups == NULL) {
+ DEBUG(0,("parse_delete_tokens_list: talloc failed"));
+ return -1;
+ }
+
+ for (j = 0; j < pdtl->delete_token->ngroups; j++) {
+ memcpy(&pdtl->delete_token->groups[j], p, sizeof(gid_t));
+ p += sizeof(gid_t);
+ }
+ }
+ /* Add to the list. */
+ DLIST_ADD(lck->delete_tokens, pdtl);
+ }
+
+ return delete_tokens_size;
+}
+
/*******************************************************************
Get all share mode entries for a dev/inode pair.
********************************************************************/
@@ -539,6 +638,7 @@ static void print_share_mode_table(struct locking_data *data)
static bool parse_share_modes(const TDB_DATA dbuf, struct share_mode_lock *lck)
{
struct locking_data data;
+ int delete_tokens_size;
int i;
if (dbuf.dsize < sizeof(struct locking_data)) {
@@ -547,20 +647,18 @@ static bool parse_share_modes(const TDB_DATA dbuf, struct share_mode_lock *lck)
memcpy(&data, dbuf.dptr, sizeof(data));
- lck->delete_on_close = data.u.s.delete_on_close;
lck->old_write_time = data.u.s.old_write_time;
lck->changed_write_time = data.u.s.changed_write_time;
lck->num_share_modes = data.u.s.num_share_mode_entries;
- DEBUG(10, ("parse_share_modes: delete_on_close: %d, owrt: %s, "
- "cwrt: %s, tok: %u, num_share_modes: %d\n",
- lck->delete_on_close,
+ DEBUG(10, ("parse_share_modes: owrt: %s, "
+ "cwrt: %s, ntok: %u, num_share_modes: %d\n",
timestring(talloc_tos(),
convert_timespec_to_time_t(lck->old_write_time)),
timestring(talloc_tos(),
convert_timespec_to_time_t(
lck->changed_write_time)),
- (unsigned int)data.u.s.delete_token_size,
+ (unsigned int)data.u.s.num_delete_token_entries,
lck->num_share_modes));
if ((lck->num_share_modes < 0) || (lck->num_share_modes > 1000000)) {
@@ -590,66 +688,25 @@ static bool parse_share_modes(const TDB_DATA dbuf, struct share_mode_lock *lck)
}
}
- /* Get any delete token. */
- if (data.u.s.delete_token_size) {
- uint8 *p = dbuf.dptr + sizeof(struct locking_data) +
- (lck->num_share_modes *
- sizeof(struct share_mode_entry));
-
- if ((data.u.s.delete_token_size < sizeof(uid_t) + sizeof(gid_t)) ||
- ((data.u.s.delete_token_size - sizeof(uid_t)) % sizeof(gid_t)) != 0) {
- DEBUG(0, ("parse_share_modes: invalid token size %d\n",
- data.u.s.delete_token_size));
- smb_panic("parse_share_modes: invalid token size");
- }
-
- lck->delete_token = TALLOC_P(lck, UNIX_USER_TOKEN);
- if (!lck->delete_token) {
- smb_panic("parse_share_modes: talloc failed");
- }
-
- /* Copy out the uid and gid. */
- memcpy(&lck->delete_token->uid, p, sizeof(uid_t));
- p += sizeof(uid_t);
- memcpy(&lck->delete_token->gid, p, sizeof(gid_t));
- p += sizeof(gid_t);
-
- /* Any supplementary groups ? */
- lck->delete_token->ngroups = (data.u.s.delete_token_size > (sizeof(uid_t) + sizeof(gid_t))) ?
- ((data.u.s.delete_token_size -
- (sizeof(uid_t) + sizeof(gid_t)))/sizeof(gid_t)) : 0;
-
- if (lck->delete_token->ngroups) {
- /* Make this a talloc child of lck->delete_token. */
- lck->delete_token->groups = TALLOC_ARRAY(lck->delete_token, gid_t,
- lck->delete_token->ngroups);
- if (!lck->delete_token) {
- smb_panic("parse_share_modes: talloc failed");
- }
-
- for (i = 0; i < lck->delete_token->ngroups; i++) {
- memcpy(&lck->delete_token->groups[i], p, sizeof(gid_t));
- p += sizeof(gid_t);
- }
- }
-
- } else {
- lck->delete_token = NULL;
+ /* Get any delete tokens. */
+ delete_tokens_size = parse_delete_tokens_list(lck, &data, dbuf);
+ if (delete_tokens_size < 0) {
+ smb_panic("parse_share_modes: parse_delete_tokens_list failed");
}
/* Save off the associated service path and filename. */
lck->servicepath = (const char *)dbuf.dptr + sizeof(struct locking_data) +
(lck->num_share_modes * sizeof(struct share_mode_entry)) +
- data.u.s.delete_token_size;
+ delete_tokens_size;
lck->base_name = (const char *)dbuf.dptr + sizeof(struct locking_data) +
(lck->num_share_modes * sizeof(struct share_mode_entry)) +
- data.u.s.delete_token_size +
+ delete_tokens_size +
strlen(lck->servicepath) + 1;
lck->stream_name = (const char *)dbuf.dptr + sizeof(struct locking_data) +
(lck->num_share_modes * sizeof(struct share_mode_entry)) +
- data.u.s.delete_token_size +
+ delete_tokens_size +
strlen(lck->servicepath) + 1 +
strlen(lck->base_name) + 1;
@@ -685,7 +742,9 @@ static TDB_DATA unparse_share_modes(const struct share_mode_lock *lck)
struct locking_data *data;
ssize_t offset;
ssize_t sp_len, bn_len, sn_len;
- uint32 delete_token_size;
+ uint32_t delete_tokens_size = 0;
+ struct delete_token_list *pdtl = NULL;
+ uint32_t num_delete_token_entries = 0;
result.dptr = NULL;
result.dsize = 0;
@@ -704,12 +763,18 @@ static TDB_DATA unparse_share_modes(const struct share_mode_lock *lck)
bn_len = strlen(lck->base_name);
--
Samba Shared Repository
More information about the samba-cvs
mailing list