diff options
author | Volker Lendecke <vl@samba.org> | 2011-11-24 14:11:28 +0100 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2011-12-02 22:43:05 +0100 |
commit | 1c46fb5c3e8a1b5ce0d61f39d934bb68074953cb (patch) | |
tree | 2369645574aa86f197911898fe21a9d397d29196 /source3/locking | |
parent | 057e4422a7c0b54f32b698f0ef9c3507084501d9 (diff) | |
download | samba-1c46fb5c3e8a1b5ce0d61f39d934bb68074953cb.tar.gz samba-1c46fb5c3e8a1b5ce0d61f39d934bb68074953cb.tar.bz2 samba-1c46fb5c3e8a1b5ce0d61f39d934bb68074953cb.zip |
s3: Use autogenerated open_files.idl
Diffstat (limited to 'source3/locking')
-rw-r--r-- | source3/locking/locking.c | 414 |
1 files changed, 65 insertions, 349 deletions
diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 611b2d2990..caa2b5aef6 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -45,6 +45,7 @@ #include "serverid.h" #include "messages.h" #include "util_tdb.h" +#include "../librpc/gen_ndr/ndr_open_files.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_LOCKING @@ -510,221 +511,35 @@ char *share_mode_str(TALLOC_CTX *ctx, int num, const struct share_mode_entry *e) } /******************************************************************* - Print out a share mode table. -********************************************************************/ - -static void print_share_mode_table(struct locking_data *data) -{ - int num_share_modes = data->u.s.num_share_mode_entries; - struct share_mode_entry *shares = - (struct share_mode_entry *)(data + 1); - int i; - - for (i = 0; i < num_share_modes; i++) { - struct share_mode_entry entry; - char *str; - - /* - * We need to memcpy the entry here due to alignment - * restrictions that are not met when directly accessing - * shares[i] - */ - - memcpy(&entry, &shares[i], sizeof(struct share_mode_entry)); - str = share_mode_str(talloc_tos(), i, &entry); - - DEBUG(10,("print_share_mode_table: %s\n", str ? str : "")); - TALLOC_FREE(str); - } -} - -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->num_delete_tokens = 0; - lck->delete_tokens = NULL; - - for (i = 0; i < pdata->u.s.num_delete_token_entries; i++) { - uint32_t token_len; - struct delete_token *pdt; - - 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(pdt->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); - - lck->delete_tokens = talloc_realloc( - lck, lck->delete_tokens, struct delete_token, - lck->num_delete_tokens+1); - - if (lck->delete_tokens == NULL) { - DEBUG(0, ("parse_delete_tokens_list: talloc failed")); - return -1; - } - pdt = &lck->delete_tokens[lck->num_delete_tokens]; - - /* Copy out the name_hash. */ - memcpy(&pdt->name_hash, p, sizeof(pdt->name_hash)); - p += sizeof(pdt->name_hash); - - pdt->delete_token = talloc_zero( - lck->delete_tokens, struct security_unix_token); - if (pdt->delete_token == NULL) { - DEBUG(0,("parse_delete_tokens_list: talloc failed")); - return -1; - } - - /* Copy out the uid and gid. */ - memcpy(&pdt->delete_token->uid, p, sizeof(uid_t)); - p += sizeof(uid_t); - memcpy(&pdt->delete_token->gid, p, sizeof(gid_t)); - p += sizeof(gid_t); - - token_len -= (sizeof(token_len) + sizeof(pdt->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; - } - - pdt->delete_token->ngroups = token_len / sizeof(gid_t); - pdt->delete_token->groups = talloc_array( - pdt->delete_token, gid_t, - pdt->delete_token->ngroups); - if (pdt->delete_token->groups == NULL) { - DEBUG(0,("parse_delete_tokens_list: talloc failed")); - return -1; - } - - for (j = 0; j < pdt->delete_token->ngroups; j++) { - memcpy(&pdt->delete_token->groups[j], p, - sizeof(gid_t)); - p += sizeof(gid_t); - } - } - lck->num_delete_tokens += 1; - } - - return delete_tokens_size; -} - -/******************************************************************* Get all share mode entries for a dev/inode pair. ********************************************************************/ static bool parse_share_modes(const TDB_DATA dbuf, struct share_mode_lock *lck) { - struct locking_data data; - int delete_tokens_size; int i; struct server_id *pids; bool *pid_exists; + enum ndr_err_code ndr_err; + DATA_BLOB blob; - if (dbuf.dsize < sizeof(struct locking_data)) { - smb_panic("parse_share_modes: buffer too short"); - } - - memcpy(&data, dbuf.dptr, sizeof(data)); - - 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; + blob.data = dbuf.dptr; + blob.length = dbuf.dsize; - 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.num_delete_token_entries, - lck->num_share_modes)); - - if ((lck->num_share_modes < 0) || (lck->num_share_modes > 1000000)) { - DEBUG(0, ("invalid number of share modes: %d\n", - lck->num_share_modes)); - smb_panic("parse_share_modes: invalid number of share modes"); + ndr_err = ndr_pull_struct_blob( + &blob, lck, lck, + (ndr_pull_flags_fn_t)ndr_pull_share_mode_lock); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + DEBUG(1, ("ndr_pull_share_mode_lock failed\n")); + return false; } - lck->share_modes = NULL; - - if (lck->num_share_modes != 0) { - - if (dbuf.dsize < (sizeof(struct locking_data) + - (lck->num_share_modes * - sizeof(struct share_mode_entry)))) { - smb_panic("parse_share_modes: buffer too short"); - } - - lck->share_modes = (struct share_mode_entry *) - talloc_memdup(lck, - dbuf.dptr+sizeof(struct locking_data), - lck->num_share_modes * - sizeof(struct share_mode_entry)); - - if (lck->share_modes == NULL) { - smb_panic("parse_share_modes: talloc failed"); - } - } + lck->modified = false; - /* 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"); + if (DEBUGLEVEL >= 10) { + DEBUG(10, ("parse_share_modes:\n")); + NDR_PRINT_DEBUG(share_mode_lock, lck); } - /* 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)) + - delete_tokens_size; - - lck->base_name = (const char *)dbuf.dptr + sizeof(struct locking_data) + - (lck->num_share_modes * sizeof(struct share_mode_entry)) + - 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)) + - delete_tokens_size + - strlen(lck->servicepath) + 1 + - strlen(lck->base_name) + 1; - /* * Ensure that each entry has a real process attached. */ @@ -749,19 +564,10 @@ static bool parse_share_modes(const TDB_DATA dbuf, struct share_mode_lock *lck) for (i = 0; i < lck->num_share_modes; i++) { struct share_mode_entry *entry_p = &lck->share_modes[i]; - char *str = NULL; - if (DEBUGLEVEL >= 10) { - str = share_mode_str(talloc_tos(), i, entry_p); - } - DEBUG(10,("parse_share_modes: %s\n", - str ? str : "")); if (!pid_exists[i]) { - DEBUG(10,("parse_share_modes: deleted %s\n", - str ? str : "")); entry_p->op_type = UNUSED_SHARE_MODE_ENTRY; lck->modified = True; } - TALLOC_FREE(str); } TALLOC_FREE(pid_exists); TALLOC_FREE(pids); @@ -769,125 +575,35 @@ static bool parse_share_modes(const TDB_DATA dbuf, struct share_mode_lock *lck) return True; } -static TDB_DATA unparse_share_modes(const struct share_mode_lock *lck) +static TDB_DATA unparse_share_modes(struct share_mode_lock *lck) { - TDB_DATA result; - int num_valid = 0; - int i; - struct locking_data *data; - ssize_t offset; - ssize_t sp_len, bn_len, sn_len; - uint32_t delete_tokens_size = 0; + DATA_BLOB blob; + enum ndr_err_code ndr_err; + uint32_t i; - result.dptr = NULL; - result.dsize = 0; + if (DEBUGLEVEL >= 10) { + DEBUG(10, ("unparse_share_modes:\n")); + NDR_PRINT_DEBUG(share_mode_lock, lck); + } for (i=0; i<lck->num_share_modes; i++) { if (!is_unused_share_mode_entry(&lck->share_modes[i])) { - num_valid += 1; + break; } } - - if (num_valid == 0) { - return result; - } - - sp_len = strlen(lck->servicepath); - bn_len = strlen(lck->base_name); - sn_len = lck->stream_name != NULL ? strlen(lck->stream_name) : 0; - - for (i=0; i<lck->num_delete_tokens; i++) { - struct delete_token *pdt = &lck->delete_tokens[i]; - delete_tokens_size += - (sizeof(uint32_t) + - sizeof(uint32_t) + - sizeof(uid_t) + - sizeof(gid_t) + - pdt->delete_token->ngroups*sizeof(gid_t)); - } - - result.dsize = sizeof(*data) + - lck->num_share_modes * sizeof(struct share_mode_entry) + - delete_tokens_size + - sp_len + 1 + - bn_len + 1 + - sn_len + 1; - result.dptr = talloc_array(lck, uint8, result.dsize); - - if (result.dptr == NULL) { - smb_panic("talloc failed"); - } - - data = (struct locking_data *)result.dptr; - ZERO_STRUCTP(data); - data->u.s.num_share_mode_entries = lck->num_share_modes; - data->u.s.old_write_time = lck->old_write_time; - data->u.s.changed_write_time = lck->changed_write_time; - data->u.s.num_delete_token_entries = lck->num_delete_tokens; - - DEBUG(10,("unparse_share_modes: owrt: %s cwrt: %s, ntok: %u, " - "num: %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.num_delete_token_entries, - data->u.s.num_share_mode_entries)); - - memcpy(result.dptr + sizeof(*data), lck->share_modes, - sizeof(struct share_mode_entry)*lck->num_share_modes); - offset = sizeof(*data) + - sizeof(struct share_mode_entry)*lck->num_share_modes; - - /* Store any delete on close tokens. */ - - for (i=0; i<lck->num_delete_tokens; i++) { - struct delete_token *pdtl = &lck->delete_tokens[i]; - struct security_unix_token *pdt = pdtl->delete_token; - uint32_t token_size = sizeof(uint32_t) + - sizeof(uint32_t) + - sizeof(uid_t) + - sizeof(gid_t) + - (pdt->ngroups * sizeof(gid_t)); - uint8_t *p = result.dptr + offset; - - memcpy(p, &token_size, sizeof(uint32_t)); - p += sizeof(uint32_t); - - memcpy(p, &pdtl->name_hash, sizeof(uint32_t)); - p += sizeof(uint32_t); - - memcpy(p, &pdt->uid, sizeof(uid_t)); - p += sizeof(uid_t); - - memcpy(p, &pdt->gid, sizeof(gid_t)); - p += sizeof(gid_t); - - for (i = 0; i < pdt->ngroups; i++) { - memcpy(p, &pdt->groups[i], sizeof(gid_t)); - p += sizeof(gid_t); - } - offset += token_size; + if (i == lck->num_share_modes) { + DEBUG(10, ("No used share mode found\n")); + return make_tdb_data(NULL, 0); } - strlcpy((char *)result.dptr + offset, - lck->servicepath ? lck->servicepath : "", - result.dsize - offset); - offset += sp_len + 1; - strlcpy((char *)result.dptr + offset, - lck->base_name ? lck->base_name : "", - result.dsize - offset); - offset += bn_len + 1; - strlcpy((char *)result.dptr + offset, - lck->stream_name ? lck->stream_name : "", - result.dsize - offset); - - if (DEBUGLEVEL >= 10) { - print_share_mode_table(data); + ndr_err = ndr_push_struct_blob( + &blob, lck, lck, + (ndr_push_flags_fn_t)ndr_push_share_mode_lock); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + smb_panic("ndr_push_share_mode_lock failed"); } - return result; + return make_tdb_data(blob.data, blob.length); } static int share_mode_lock_destructor(struct share_mode_lock *lck) @@ -949,6 +665,8 @@ static bool fill_share_mode_lock(struct share_mode_lock *lck, TDB_DATA share_mode_data, const struct timespec *old_write_time) { + bool fresh; + /* Ensure we set every field here as the destructor must be valid even if parse_share_modes fails. */ @@ -962,12 +680,10 @@ static bool fill_share_mode_lock(struct share_mode_lock *lck, lck->delete_tokens = NULL; ZERO_STRUCT(lck->old_write_time); ZERO_STRUCT(lck->changed_write_time); - lck->fresh = False; - lck->modified = False; - lck->fresh = (share_mode_data.dptr == NULL); + fresh = (share_mode_data.dptr == NULL); - if (lck->fresh) { + if (fresh) { bool has_stream; if (smb_fname == NULL || servicepath == NULL || old_write_time == NULL) { @@ -986,12 +702,14 @@ static bool fill_share_mode_lock(struct share_mode_lock *lck, return False; } lck->old_write_time = *old_write_time; + lck->modified = false; } else { if (!parse_share_modes(share_mode_data, lck)) { DEBUG(0, ("Could not parse share modes\n")); return False; } } + lck->fresh = fresh; return True; } @@ -1004,6 +722,7 @@ struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx, { struct share_mode_lock *lck; struct file_id tmp; + struct db_record *rec; TDB_DATA key = locking_key(&id, &tmp); TDB_DATA value; @@ -1012,13 +731,14 @@ struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx, return NULL; } - if (!(lck->record = dbwrap_fetch_locked(lock_db, lck, key))) { + rec = dbwrap_fetch_locked(lock_db, lck, key); + if (rec == NULL) { DEBUG(3, ("Could not lock share entry\n")); TALLOC_FREE(lck); return NULL; } - value = dbwrap_record_get_value(lck->record); + value = dbwrap_record_get_value(rec); if (!fill_share_mode_lock(lck, id, servicepath, smb_fname, value, old_write_time)) { @@ -1027,6 +747,7 @@ struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx, return NULL; } + lck->record = rec; talloc_set_destructor(lck, share_mode_lock_destructor); return lck; @@ -1743,15 +1464,12 @@ struct forall_state { static int traverse_fn(struct db_record *rec, void *_state) { struct forall_state *state = (struct forall_state *)_state; - struct locking_data *data; - struct share_mode_entry *shares; - const char *sharepath; - const char *fname; - const char *del_tokens; - uint32_t total_del_token_size = 0; - int i; + uint32_t i; TDB_DATA key; TDB_DATA value; + DATA_BLOB blob; + enum ndr_err_code ndr_err; + struct share_mode_lock *lck; key = dbwrap_record_get_key(rec); value = dbwrap_record_get_value(rec); @@ -1760,30 +1478,28 @@ static int traverse_fn(struct db_record *rec, void *_state) if (key.dsize != sizeof(struct file_id)) return 0; - data = (struct locking_data *)value.dptr; - shares = (struct share_mode_entry *)(value.dptr + sizeof(*data)); - del_tokens = (const char *)value.dptr + sizeof(*data) + - data->u.s.num_share_mode_entries*sizeof(*shares); - - for (i = 0; i < data->u.s.num_delete_token_entries; i++) { - uint32_t del_token_size; - memcpy(&del_token_size, del_tokens, sizeof(uint32_t)); - total_del_token_size += del_token_size; - del_tokens += del_token_size; + lck = talloc(talloc_tos(), struct share_mode_lock); + if (lck == NULL) { + return 0; } - sharepath = (const char *)value.dptr + sizeof(*data) + - data->u.s.num_share_mode_entries*sizeof(*shares) + - total_del_token_size; - fname = (const char *)value.dptr + sizeof(*data) + - data->u.s.num_share_mode_entries*sizeof(*shares) + - total_del_token_size + - strlen(sharepath) + 1; + blob.data = value.dptr; + blob.length = value.dsize; - for (i=0;i<data->u.s.num_share_mode_entries;i++) { - state->fn(&shares[i], sharepath, fname, + ndr_err = ndr_pull_struct_blob( + &blob, lck, lck, + (ndr_pull_flags_fn_t)ndr_pull_share_mode_lock); + if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { + DEBUG(1, ("ndr_pull_share_mode_lock failed\n")); + return 0; + } + for (i=0; i<lck->num_share_modes; i++) { + state->fn(&lck->share_modes[i], + lck->servicepath, lck->base_name, state->private_data); } + TALLOC_FREE(lck); + return 0; } |