*/
#include "includes.h"
+#include "system/filesys.h"
#include "librpc/gen_ndr/ndr_notify.h"
+#include "dbwrap.h"
+#include "smbd/smbd.h"
+#include "messages.h"
+#include "lib/util/tdb_wrap.h"
+#include "util_tdb.h"
struct notify_context {
struct db_context *db_recursive;
}
notify->db_recursive = db_open(notify, lock_path("notify.tdb"),
- 0, TDB_SEQNUM|TDB_CLEAR_IF_FIRST,
+ 0, TDB_SEQNUM|TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH,
O_RDWR|O_CREAT, 0644);
if (notify->db_recursive == NULL) {
talloc_free(notify);
}
notify->db_onelevel = db_open(notify, lock_path("notify_onelevel.tdb"),
- 0, TDB_SEQNUM|TDB_CLEAR_IF_FIRST,
+ 0, TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH,
O_RDWR|O_CREAT, 0644);
if (notify->db_onelevel == NULL) {
talloc_free(notify);
return notify;
}
+bool notify_internal_parent_init(TALLOC_CTX *mem_ctx)
+{
+ struct tdb_wrap *db1, *db2;
+
+ if (lp_clustering()) {
+ return true;
+ }
+
+ /*
+ * Open the tdbs in the parent process (smbd) so that our
+ * CLEAR_IF_FIRST optimization in tdb_reopen_all can properly
+ * work.
+ */
+
+ db1 = tdb_wrap_open(mem_ctx, lock_path("notify.tdb"),
+ 0, TDB_SEQNUM|TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH,
+ O_RDWR|O_CREAT, 0644);
+ if (db1 == NULL) {
+ DEBUG(1, ("could not open notify.tdb: %s\n", strerror(errno)));
+ return false;
+ }
+ db2 = tdb_wrap_open(mem_ctx, lock_path("notify_onelevel.tdb"),
+ 0, TDB_CLEAR_IF_FIRST|TDB_INCOMPATIBLE_HASH, O_RDWR|O_CREAT, 0644);
+ if (db2 == NULL) {
+ DEBUG(1, ("could not open notify_onelevel.tdb: %s\n",
+ strerror(errno)));
+ TALLOC_FREE(db1);
+ return false;
+ }
+ return true;
+}
+
/*
lock and fetch the record
*/
notify->seqnum = seqnum;
talloc_free(notify->array);
- notify->array = TALLOC_ZERO_P(notify, struct notify_array);
+ notify->array = talloc_zero(notify, struct notify_array);
NT_STATUS_HAVE_NO_MEMORY(notify->array);
if (!rec) {
status = NT_STATUS_OK;
if (blob.length > 0) {
enum ndr_err_code ndr_err;
- ndr_err = ndr_pull_struct_blob(&blob, notify->array, NULL, notify->array,
+ ndr_err = ndr_pull_struct_blob(&blob, notify->array, notify->array,
(ndr_pull_flags_fn_t)ndr_pull_notify_array);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
- status = ndr_map_error2ntstatus(ndr_err);
+ /* 1. log that we got a corrupt notify_array
+ * 2. clear the variable the garbage was stored into to not trip
+ * over it next time this method is entered with the same seqnum
+ * 3. delete it from the database */
+ DEBUG(2, ("notify_array is corrupt, discarding it\n"));
+
+ ZERO_STRUCTP(notify->array);
+ if (rec != NULL) {
+ rec->delete_rec(rec);
+ }
+
+ } else {
+ if (DEBUGLEVEL >= 10) {
+ DEBUG(10, ("notify_load:\n"));
+ NDR_PRINT_DEBUG(notify_array, notify->array);
+ }
}
}
- if (DEBUGLEVEL >= 10) {
- DEBUG(10, ("notify_load:\n"));
- NDR_PRINT_DEBUG(notify_array, notify->array);
- }
if (!rec) {
talloc_free(dbuf.dptr);
/*
compare notify entries for sorting
*/
-static int notify_compare(const void *p1, const void *p2)
+static int notify_compare(const struct notify_entry *e1, const struct notify_entry *e2)
{
- const struct notify_entry *e1 = (const struct notify_entry *)p1;
- const struct notify_entry *e2 = (const struct notify_entry *)p2;
return strcmp(e1->path, e2->path);
}
tmp_ctx = talloc_new(notify);
NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
- ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, NULL, notify->array,
+ ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, notify->array,
(ndr_push_flags_fn_t)ndr_push_notify_array);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
talloc_free(tmp_ctx);
return;
}
- ndr_err = ndr_pull_struct_blob(data, tmp_ctx, NULL, &ev,
+ ndr_err = ndr_pull_struct_blob(data, tmp_ctx, &ev,
(ndr_pull_flags_fn_t)ndr_pull_notify_event);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
talloc_free(tmp_ctx);
d->max_mask |= e->filter;
d->max_mask_subdir |= e->subdir_filter;
- if (d->num_entries > 1) {
- qsort(d->entries, d->num_entries, sizeof(d->entries[0]), notify_compare);
- }
+ TYPESAFE_QSORT(d->entries, d->num_entries, notify_compare);
/* recalculate the maximum masks */
d->max_mask = 0;
blob.length = rec->value.dsize;
if (blob.length > 0) {
- ndr_err = ndr_pull_struct_blob(
- &blob, array, NULL, array,
+ ndr_err = ndr_pull_struct_blob(&blob, array, array,
(ndr_pull_flags_fn_t)ndr_pull_notify_entry_array);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
DEBUG(10, ("ndr_pull_notify_entry_array failed: %s\n",
array->entries[array->num_entries].server = notify->server;
array->num_entries += 1;
- ndr_err = ndr_push_struct_blob(
- &blob, rec, NULL, array,
+ ndr_err = ndr_push_struct_blob(&blob, rec, array,
(ndr_push_flags_fn_t)ndr_push_notify_entry_array);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
DEBUG(10, ("ndr_push_notify_entry_array failed: %s\n",
depth = count_chars(e.path, '/');
- listel = TALLOC_ZERO_P(notify, struct notify_list);
+ listel = talloc_zero(notify, struct notify_list);
if (listel == NULL) {
status = NT_STATUS_NO_MEMORY;
goto done;
NTSTATUS status;
int i;
+ if (notify == NULL) {
+ return NT_STATUS_NOT_IMPLEMENTED;
+ }
+
array = talloc_zero(talloc_tos(), struct notify_entry_array);
if (array == NULL) {
return NT_STATUS_NO_MEMORY;
}
rec = notify->db_onelevel->fetch_locked(
- notify->db_onelevel, talloc_tos(),
- make_tdb_data((uint8_t *)fid, sizeof(*fid)));
+ notify->db_onelevel, array,
+ make_tdb_data((const uint8_t *)fid, sizeof(*fid)));
if (rec == NULL) {
DEBUG(10, ("notify_remove_onelevel: fetch_locked for %s failed"
"\n", file_id_string_tos(fid)));
blob.length = rec->value.dsize;
if (blob.length > 0) {
- ndr_err = ndr_pull_struct_blob(
- &blob, array, NULL, array,
+ ndr_err = ndr_pull_struct_blob(&blob, array, array,
(ndr_pull_flags_fn_t)ndr_pull_notify_entry_array);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
DEBUG(10, ("ndr_pull_notify_entry_array failed: %s\n",
return NT_STATUS_OK;
}
- ndr_err = ndr_push_struct_blob(
- &blob, rec, NULL, array,
+ ndr_err = ndr_push_struct_blob(&blob, rec, array,
(ndr_push_flags_fn_t)ndr_push_notify_entry_array);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
DEBUG(10, ("ndr_push_notify_entry_array failed: %s\n",
tmp_ctx = talloc_new(notify);
- ndr_err = ndr_push_struct_blob(&data, tmp_ctx, NULL, &ev,
+ ndr_err = ndr_push_struct_blob(&data, tmp_ctx, &ev,
(ndr_push_flags_fn_t)ndr_push_notify_event);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
talloc_free(tmp_ctx);
if (blob.length > 0) {
enum ndr_err_code ndr_err;
- ndr_err = ndr_pull_struct_blob(
- &blob, array, NULL, array,
+ ndr_err = ndr_pull_struct_blob(&blob, array, array,
(ndr_pull_flags_fn_t)ndr_pull_notify_entry_array);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
DEBUG(10, ("ndr_pull_notify_entry_array failed: %s\n",